View Javadoc

1   /*
2   * The contents of this file are subject to the BT "ZEUS" Open Source 
3   * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file 
4   * except in compliance with the Licence. You may obtain a copy of the Licence
5   * from $ZEUS_INSTALL/licence.html or alternatively from
6   * http://www.labs.bt.com/projects/agents/zeus/licence.htm
7   * 
8   * Except as stated in Clause 7 of the Licence, software distributed under the
9   * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or 
10  * implied. See the Licence for the specific language governing rights and 
11  * limitations under the Licence.
12  * 
13  * The Original Code is within the package zeus.*.
14  * The Initial Developer of the Original Code is British Telecommunications
15  * public limited company, whose registered office is at 81 Newgate Street, 
16  * London, EC1A 7AJ, England. Portions created by British Telecommunications 
17  * public limited company are Copyright 1996-9. All Rights Reserved.
18  * 
19  * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20  */
21  
22  
23  
24  /*****************************************************************************
25  * NodesPanel.java
26  *
27  * Panel through which summary task nodes are entered
28  ***************************************************************************/
29  
30  package zeus.generator.task;
31  
32  import java.awt.*;
33  import java.awt.event.*;
34  import java.util.*;
35  import javax.swing.*;
36  import javax.swing.border.*;
37  import javax.swing.text.*;
38  import javax.swing.event.*;
39  
40  import zeus.util.*;
41  import zeus.concepts.*;
42  import zeus.concepts.fn.*;
43  import zeus.generator.*;
44  import zeus.generator.util.*;
45  import zeus.generator.event.*;
46  import zeus.gui.graph.*;
47  import zeus.gui.fields.*;
48  import zeus.gui.help.*;
49  
50  public class NodesPanel extends JPanel {
51    protected SummaryTask      task;
52    protected Graph            graph;
53    protected GraphNode[]      clipboard;
54    protected SummaryTaskModel model;
55    protected JCheckBox        autorun;
56    protected LargeTextField   costfield;
57    protected LargeTextField   timefield;
58    protected BasicFactModel   preconditionsModel;
59    protected BasicFactModel   postconditionsModel;
60  
61    public NodesPanel(AgentGenerator generator, GeneratorModel genmodel,
62                      OntologyDb ontologyDb, TaskEditor editor,
63                      SummaryTask task)  {
64  
65      this.task = task;
66  
67      model = new SummaryTaskModel(ontologyDb,task.getNodes(),task.getLinks());
68      model.addChangeListener(editor);
69      graph = new Graph(model);
70      graph.setNodeRenderer(new SummaryTaskNodeRenderer());
71      graph.setNodeEditor(new SummaryTaskNodeEditor(ontologyDb,model));
72  
73      preconditionsModel =
74         new SymBasicFactModel(SummaryTaskModel.PRECONDITION,model);
75      postconditionsModel =
76         new SymBasicFactModel(SummaryTaskModel.POSTCONDITION,model);
77  
78      GridBagLayout gridBagLayout = new GridBagLayout();
79      GridBagConstraints gbc = new GridBagConstraints();
80      setLayout(gridBagLayout);
81      setBackground(Color.lightGray);
82      setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
83  
84      // Add the control panel
85      ControlPanel controlPane =
86         new ControlPanel(editor,"Task Decomposition Graph",true,false);
87      gbc.gridwidth = GridBagConstraints.REMAINDER;
88      gbc.anchor = GridBagConstraints.NORTHWEST;
89      gbc.fill = GridBagConstraints.HORIZONTAL;
90      gbc.insets = new Insets(8,8,8,8);
91      gbc.weightx = gbc.weighty = 0;
92      gridBagLayout.setConstraints(controlPane,gbc);
93      add(controlPane);
94  
95      // Add the panel that will contain the task's nodes
96      JPanel dataPanel = new JPanel();
97      gbc.gridwidth = GridBagConstraints.REMAINDER;
98      gbc.anchor = GridBagConstraints.NORTHWEST;
99      gbc.fill = GridBagConstraints.BOTH;
100     gbc.weightx = gbc.weighty = 1;
101     gbc.insets = new Insets(8,8,8,8);
102     gridBagLayout.setConstraints(dataPanel,gbc);
103     add(dataPanel);
104 
105     // Add the panel that will contain the task's cost and time fields
106     JPanel costPanel = new JPanel();
107     gbc.gridwidth = GridBagConstraints.REMAINDER;
108     gbc.anchor = GridBagConstraints.WEST;
109     gbc.fill = GridBagConstraints.HORIZONTAL;
110     gbc.insets = new Insets(8,8,8,8);
111     gbc.weightx = gbc.weighty = 0;
112     gridBagLayout.setConstraints(costPanel,gbc);
113     add(costPanel);
114 
115     // Cost/Time panel info
116 
117     String title = task.isScript() ? "Task Mode, Cost and Time" :
118        "Task Cost and Time";
119 
120     TitledBorder border =
121        BorderFactory.createTitledBorder(title);
122     border.setTitlePosition(TitledBorder.TOP);
123     border.setTitleJustification(TitledBorder.RIGHT);
124     border.setTitleFont(new Font("Helvetica", Font.BOLD, 14));
125     border.setTitleColor(Color.blue);
126     costPanel.setBorder(border);
127 
128     gridBagLayout = new GridBagLayout();
129     costPanel.setLayout(gridBagLayout);
130     costPanel.setBackground(Color.lightGray);
131 
132     JLabel label;
133 
134     if ( task.isScript() ) {
135        label = new JLabel("Autorun:");
136        label.setToolTipText("Set autorun on if task is invoked automatically");
137        gbc = new GridBagConstraints();
138        gbc.anchor = GridBagConstraints.WEST;
139        gbc.fill = GridBagConstraints.NONE;
140        gbc.gridwidth = 1;
141        gbc.insets = new Insets(0,8,8,0);
142        gridBagLayout.setConstraints(label,gbc);
143        costPanel.add(label);
144 
145        autorun = new JCheckBox();
146        autorun.setBackground(Color.lightGray);
147        autorun.setSelected(((PlanScript)task).isAutorun());
148        autorun.setEnabled(false); // REM for now
149        autorun.addChangeListener(editor);
150 
151        gbc = new GridBagConstraints();
152        gbc.gridwidth = GridBagConstraints.REMAINDER;
153        gbc.anchor = GridBagConstraints.WEST;
154        gbc.fill = GridBagConstraints.NONE;
155        gbc.insets = new Insets(0,8,8,8);
156        gridBagLayout.setConstraints(autorun,gbc);
157        costPanel.add(autorun);
158     }
159 
160 
161     label = new JLabel("Cost:");
162     label.setToolTipText("Default cost of performing this task");
163     gbc = new GridBagConstraints();
164     gbc.anchor = GridBagConstraints.WEST;
165     gbc.fill = GridBagConstraints.NONE;
166     gbc.gridwidth = 1;
167     gbc.insets = new Insets(0,8,0,0);
168     gridBagLayout.setConstraints(label,gbc);
169     costPanel.add(label);
170 
171     costfield = new LargeTextField(2,15);
172     costfield.setLineWrap(true);
173     costfield.setText(task.getCostFn().toString());
174     costfield.addChangeListener(editor);
175 
176     gbc = new GridBagConstraints();
177     gbc.gridwidth = GridBagConstraints.REMAINDER;
178     gbc.anchor = GridBagConstraints.WEST;
179     gbc.fill = GridBagConstraints.HORIZONTAL;
180     gbc.weightx = gbc.weighty = 1;
181     gbc.insets = new Insets(0,8,0,8);
182     gridBagLayout.setConstraints(costfield,gbc);
183     costPanel.add(costfield);
184 
185     label = new JLabel("Time:");
186     label.setToolTipText("Default duration of this task");
187     gbc = new GridBagConstraints();
188     gbc.anchor = GridBagConstraints.WEST;
189     gbc.fill = GridBagConstraints.NONE;
190     gbc.gridwidth = 1;
191     gbc.insets = new Insets(8,8,8,0);
192     gridBagLayout.setConstraints(label,gbc);
193     costPanel.add(label);
194 
195     timefield = new LargeTextField(2,15);
196     timefield.setLineWrap(true);
197     timefield.setText(task.getTimeFn().toString());
198     timefield.addChangeListener(editor);
199 
200     gbc = new GridBagConstraints();
201     gbc.gridwidth = GridBagConstraints.REMAINDER;
202     gbc.anchor = GridBagConstraints.WEST;
203     gbc.fill = GridBagConstraints.HORIZONTAL;
204     gbc.weightx = gbc.weighty = 1;
205     gbc.insets = new Insets(8,8,8,8);
206     gridBagLayout.setConstraints(timefield,gbc);
207     costPanel.add(timefield);
208 
209     // Data panel info
210     gridBagLayout = new GridBagLayout();
211     dataPanel.setLayout(gridBagLayout);
212     dataPanel.setBackground(Color.lightGray);
213 
214     JScrollPane scrollPane = new JScrollPane(graph);
215     scrollPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
216     scrollPane.setPreferredSize(new Dimension(600,400));
217     graph.setPreferredSize(new Dimension(2000,2000));
218     graph.setBackground(Color.white);
219 
220     border = (BorderFactory.createTitledBorder("Task Decomposition Graph"));
221     border.setTitlePosition(TitledBorder.TOP);
222     border.setTitleJustification(TitledBorder.RIGHT);
223     border.setTitleFont(new Font("Helvetica", Font.BOLD, 14));
224     border.setTitleColor(Color.blue);
225     dataPanel.setBorder(border);
226 
227     JToolBar toolbar = new NodesToolBar(task.isScript());
228 
229     gbc = new GridBagConstraints();
230     gbc.gridwidth = GridBagConstraints.REMAINDER;
231     gbc.anchor = GridBagConstraints.WEST;
232     gbc.fill = GridBagConstraints.NONE;
233     gbc.weightx = gbc.weighty = 0;
234     gbc.insets = new Insets(0,8,0,0);
235     gridBagLayout.setConstraints(toolbar,gbc);
236     dataPanel.add(toolbar);
237 
238     gbc.gridwidth = GridBagConstraints.REMAINDER;
239     gbc.anchor = GridBagConstraints.WEST;
240     gbc.fill = GridBagConstraints.BOTH;
241     gbc.weightx = gbc.weighty = 1;
242     gbc.insets = new Insets(8,8,8,8);
243     gridBagLayout.setConstraints(scrollPane,gbc);
244     dataPanel.add(scrollPane);
245 
246     // Initialisation Information
247     // for renaming cost/time expressions
248     SymRenameAction rs = new SymRenameAction();
249     preconditionsModel.addRenameListener(rs);
250     postconditionsModel.addRenameListener(rs);
251 
252     // for validating cost/time expressions
253     SymFocusAction fs = new SymFocusAction();
254     costfield.addFocusListener(fs);
255     timefield.addFocusListener(fs);
256 
257     // for supporting attribute tree creation for cost and time fields
258     SymMouseAction ms  = new SymMouseAction();
259     costfield.addMouseListener(ms);
260     timefield.addMouseListener(ms);
261 
262   }
263 
264   protected class SymFocusAction implements FocusListener {
265     public void focusLost(FocusEvent e) {
266        LargeTextField field = (LargeTextField)e.getSource();
267        validate(field);
268     }
269     public void focusGained(FocusEvent e) {
270        LargeTextField field = (LargeTextField)e.getSource();
271        field.setForeground(Color.black);
272     }
273     protected void validate(LargeTextField field) {
274        String s = field.getText();
275        ValueFunction fn = ZeusParser.Expression(s);
276        if ( fn != null && (fn instanceof NumericFn || fn instanceof ElseFn) )
277           field.setForeground(Color.black);
278        else
279           field.setForeground(Color.red);
280     }
281   }
282 
283   protected class SymMouseAction extends MouseAdapter 
284                                  implements AttributeSelector {
285      protected JTextComponent field = null;
286      protected AttributeDialog dialog = null;
287      protected AttributeTreeModel attributeTreeModel = null;
288 
289      public SymMouseAction() {
290         attributeTreeModel = new AttributeTreeModel();
291         attributeTreeModel.setFactModels(preconditionsModel,
292 	                                 postconditionsModel);
293      }
294      public void mouseClicked(MouseEvent e) {
295         if ( SwingUtilities.isRightMouseButton(e) ) {
296            field = (JTextComponent)e.getSource();
297            if ( dialog == null )
298               dialog = new AttributeDialog(
299 	         (Frame)SwingUtilities.getRoot(field),attributeTreeModel);
300            field = (JTextComponent)e.getSource();
301            dialog.setLocationRelativeTo(field);
302            dialog.display(this);
303         }
304      }
305      public void attributeSelected(String attribute) {
306         try {
307 	   Document doc = field.getDocument();
308            int length = doc.getLength();
309            AttributeSet a = doc.getDefaultRootElement().getAttributes();
310            doc.insertString(length,attribute,a);
311 	}
312 	catch(BadLocationException e) {
313 	}
314      }
315   }
316 
317   protected class SymRenameAction implements RenameListener {
318     public void nameChanged(RenameEvent e) {
319        String prev = (String)e.getOriginal();
320        String curr = (String)e.getCurrent();
321 
322        String s;
323        s = costfield.getText();
324        costfield.setText(Misc.substitute(s,prev,curr));
325        s = timefield.getText();
326        timefield.setText(Misc.substitute(s,prev,curr));
327     }
328   }
329 
330   protected class SummaryTaskNodeRenderer implements GraphNodeRenderer {
331      public Component getNodeRendererComponent(Graph g, GraphNode node) {
332         TaskNode obj = (TaskNode)node.getUserObject();
333         return new JLabel(obj.getName(),JLabel.CENTER);
334      }
335   }
336 
337   protected class NodesToolBar extends JToolBar implements ActionListener {
338      protected HelpWindow    helpWin;
339      protected JToggleButton helpBtn;
340      protected JButton       nodeBtn;
341      protected JButton       guardBtn;
342      protected JButton       selectBtn;
343      protected JButton       selectAllBtn;
344      protected JButton       hideBtn;
345      protected JButton       showBtn;
346      protected JButton       collapseBtn;
347      protected JButton       expandBtn;
348      protected JButton       deleteBtn;
349      protected JButton       cutBtn;
350      protected JButton       copyBtn;
351      protected JButton       pasteBtn;
352      protected JButton       recomputeBtn;
353      protected JButton       redrawBtn;
354 
355      public NodesToolBar(boolean is_script) {
356 
357         setBackground(Color.lightGray);
358         setBorder(new BevelBorder(BevelBorder.LOWERED));
359         setFloatable(false);
360 
361         String sep = System.getProperty("file.separator");
362         String path = SystemProps.getProperty("gif.dir") + "generator" + sep;
363 
364         // Node Buttons
365         nodeBtn = new JButton("Node"); // new ImageIcon(path + "node.gif"));
366 	nodeBtn.setMargin(new Insets(0,0,0,0));
367         add(nodeBtn);
368         nodeBtn.setToolTipText("New task node");
369         nodeBtn.addActionListener(this);
370 
371         if ( is_script ) {
372            guardBtn = new JButton("Guard"); // new ImageIcon(path + "guard.gif"));
373 	   guardBtn.setMargin(new Insets(0,0,0,0));
374            add(guardBtn);
375            guardBtn.setToolTipText("New conditional node");
376            guardBtn.addActionListener(this);
377         }
378 
379         addSeparator();
380 
381         // Draw Buttons
382         recomputeBtn = new JButton(new ImageIcon(path + "recompute.gif"));
383 	recomputeBtn.setMargin(new Insets(0,0,0,0));
384         add(recomputeBtn);
385         recomputeBtn.setToolTipText("Recompute node positions");
386         recomputeBtn.addActionListener(this);
387 
388         redrawBtn = new JButton(new ImageIcon(path + "redraw.gif"));
389 	redrawBtn.setMargin(new Insets(0,0,0,0));
390         add(redrawBtn);
391         redrawBtn.setToolTipText("Redraw");
392         redrawBtn.addActionListener(this);
393 
394 	addSeparator();
395 
396         selectBtn = new JButton(new ImageIcon(path + "select.gif"));
397 	selectBtn.setMargin(new Insets(0,0,0,0));
398         add(selectBtn);
399         selectBtn.setToolTipText("Select nodes");
400         selectBtn.addActionListener(this);
401 
402         selectAllBtn = new JButton(new ImageIcon(path + "selectAll.gif"));
403 	selectAllBtn.setMargin(new Insets(0,0,0,0));
404         add(selectAllBtn);
405         selectAllBtn.setToolTipText("Select all nodes");
406         selectAllBtn.addActionListener(this);
407 
408         addSeparator();
409 
410         collapseBtn = new JButton(new ImageIcon(path + "collapse.gif"));
411 	collapseBtn.setMargin(new Insets(0,0,0,0));
412         add(collapseBtn);
413         collapseBtn.setToolTipText("Collapse nodes");
414         collapseBtn.addActionListener(this);
415 
416         expandBtn = new JButton(new ImageIcon(path + "expand.gif"));
417 	expandBtn.setMargin(new Insets(0,0,0,0));
418         add(expandBtn);
419         expandBtn.setToolTipText("Expand nodes");
420         expandBtn.addActionListener(this);
421 
422         addSeparator();
423 
424         hideBtn = new JButton(new ImageIcon(path + "hide.gif"));
425 	hideBtn.setMargin(new Insets(0,0,0,0));
426         add(hideBtn);
427         hideBtn.setToolTipText("Hide nodes");
428         hideBtn.addActionListener(this);
429 
430         showBtn = new JButton(new ImageIcon(path + "show.gif"));
431 	showBtn.setMargin(new Insets(0,0,0,0));
432         add(showBtn);
433         showBtn.setToolTipText("Show nodes");
434         showBtn.addActionListener(this);
435 
436         addSeparator();
437 
438         // Delete Button
439         deleteBtn = new JButton(new ImageIcon(path + "delete1.gif"));
440 	deleteBtn.setMargin(new Insets(0,0,0,0));
441         add(deleteBtn);
442         deleteBtn.setToolTipText("Delete");
443         deleteBtn.addActionListener(this);
444 
445         addSeparator();
446 
447         // Cut Button
448         cutBtn = new JButton(new ImageIcon(path + "cut.gif"));
449 	cutBtn.setMargin(new Insets(0,0,0,0));
450         add(cutBtn);
451         cutBtn.setToolTipText("Cut");
452         cutBtn.addActionListener(this);
453 
454         // Copy Button
455         copyBtn = new JButton(new ImageIcon(path + "copy.gif"));
456 	copyBtn.setMargin(new Insets(0,0,0,0));
457         add(copyBtn);
458         copyBtn.setToolTipText("Copy");
459         copyBtn.addActionListener(this);
460 
461         // Paste Button
462         pasteBtn = new JButton(new ImageIcon(path + "paste.gif"));
463 	pasteBtn.setMargin(new Insets(0,0,0,0));
464         add(pasteBtn);
465         pasteBtn.setToolTipText("Paste");
466         pasteBtn.addActionListener(this);
467 
468         addSeparator();
469 
470         // Help Button
471         helpBtn = new JToggleButton(new ImageIcon(path + "help.gif"));
472 	helpBtn.setMargin(new Insets(0,0,0,0));
473         add(helpBtn);
474         helpBtn.setToolTipText("Help");
475         helpBtn.addActionListener(this);
476      }
477 
478      public void actionPerformed(ActionEvent e)  {
479         Object src = e.getSource();
480         if ( src == nodeBtn )
481            model.addNewNode(SummaryTaskModel.BASIC_NODE);
482         else if ( src == guardBtn )
483            model.addNewNode(SummaryTaskModel.GUARD_NODE);
484         else if ( src == recomputeBtn )
485            graph.recompute();
486         else if ( src == redrawBtn )
487            graph.redraw();
488         else if ( src == selectBtn )
489            graph.select();
490         else if ( src == selectAllBtn )
491            graph.selectAll();
492         else if ( src == collapseBtn )
493            graph.collapse();
494         else if ( src == expandBtn )
495            graph.expand();
496         else if ( src == hideBtn )
497            graph.hide();
498         else if ( src == showBtn )
499            graph.show();
500         else if ( src == deleteBtn )
501            deleteSelectedNodes();
502         else if ( src == copyBtn )
503            clipboard = graph.getSelectedNodes();
504         else if ( src == pasteBtn )
505            model.addNodes(clipboard);
506         else if ( src == cutBtn )
507            clipboard = cutSelectedNodes();
508         else if ( src == helpBtn ) {
509           if ( helpBtn.isSelected() ) {
510               helpWin = new HelpWindow(SwingUtilities.getRoot(this),
511                  getLocation(),"generator","Summary Task Decomposition Graph");
512               helpWin.setSource(helpBtn);
513           }
514           else
515               helpWin.dispose();
516         }
517      }
518   }
519 
520   BasicFactModel getPreconditionsModel() {
521      return preconditionsModel;
522   }
523   BasicFactModel getPostconditionsModel() {
524      return postconditionsModel;
525   }
526 
527   void save() {
528      task.setNodes(model.getNodes());
529      task.setLinks(model.getLinks());
530      task.setCostFn(costfield.getText());
531      task.setTimeFn(timefield.getText());
532 
533      if ( task.isScript() )
534         ((PlanScript)task).setAutorun(autorun.isSelected());
535   }
536 
537   protected void deleteSelectedNodes() {
538      model.removeNodes(graph.getSelectedNodes());
539      graph.redraw();
540   }
541   protected GraphNode[] cutSelectedNodes() {
542      GraphNode[] out = graph.getSelectedNodes();
543      model.removeNodes(out);
544      graph.redraw();
545      return out;
546   }
547 }