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  * SocietyPanel.java
26  *
27  ***************************************************************************/
28  
29  package zeus.generator;
30  
31  import java.awt.*;
32  import java.awt.event.*;
33  import java.util.*;
34  import javax.swing.*;
35  import javax.swing.border.*;
36  import javax.swing.text.*;
37  import javax.swing.event.*;
38  import java.io.File;
39  
40  import zeus.util.*;
41  import zeus.concepts.*;
42  import zeus.generator.util.*;
43  import zeus.generator.event.*;
44  import zeus.generator.agent.AcquaintanceModel;
45  import zeus.gui.graph.*;
46  import zeus.gui.help.*;
47  
48  public class SocietyPanel extends JPanel {
49    protected Graph            graph;
50    protected GraphNode[]      clipboard;
51    protected SocietyModel     model;
52    protected GeneratorModel   genmodel;
53    protected AgentGenerator   generator;
54  
55    public SocietyPanel(AgentGenerator generator, GeneratorModel genmodel)  {
56      this.generator = generator;
57      this.genmodel = genmodel;
58      model = new SocietyModel(genmodel,true);
59      graph = new Graph(Graph.VERTICAL_PARENT_CHILD,model,true,false);
60      graph.setNodeRenderer(new SocietyNodeRenderer());
61      graph.setNodeEditor(new SocietyNodeEditor());
62  
63      GridBagLayout gridBagLayout = new GridBagLayout();
64      GridBagConstraints gbc = new GridBagConstraints();
65  
66      JPanel lhsPanel = new JPanel();
67      lhsPanel.setLayout(gridBagLayout);
68      lhsPanel.setBackground(Color.lightGray);
69  
70      // Add the lhs panel
71      SoceityControlPanel controlPane = new SoceityControlPanel();
72      gbc.gridwidth = GridBagConstraints.REMAINDER;
73      gbc.anchor = GridBagConstraints.NORTHWEST;
74      gbc.fill = GridBagConstraints.NONE;
75      gbc.insets = new Insets(8,8,8,8);
76      gbc.weightx = gbc.weighty = 0;
77      gridBagLayout.setConstraints(controlPane,gbc);
78      lhsPanel.add(controlPane);
79      lhsPanel.setBackground(Color.lightGray);
80  
81  
82      gridBagLayout = new GridBagLayout();
83      gbc = new GridBagConstraints();
84      setLayout(gridBagLayout);
85      setBackground(Color.lightGray);
86      setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
87  
88      gbc.gridwidth = 1;
89      gbc.anchor = GridBagConstraints.NORTHWEST;
90      gbc.fill = GridBagConstraints.NONE;
91      gbc.insets = new Insets(0,0,0,0);
92      gbc.weightx = gbc.weighty = 0;
93      gridBagLayout.setConstraints(lhsPanel,gbc);
94      add(lhsPanel);
95  
96      // Add the panel that will contain the nodes
97      JPanel dataPanel = new JPanel();
98      gbc.gridwidth = GridBagConstraints.REMAINDER;
99      gbc.anchor = GridBagConstraints.NORTHWEST;
100     gbc.fill = GridBagConstraints.BOTH;
101     gbc.weightx = gbc.weighty = 1;
102     gbc.insets = new Insets(8,8,8,8);
103     gridBagLayout.setConstraints(dataPanel,gbc);
104     add(dataPanel);
105 
106     // Data panel info
107     gridBagLayout = new GridBagLayout();
108     dataPanel.setLayout(gridBagLayout);
109     dataPanel.setBackground(Color.lightGray);
110 
111     JScrollPane scrollPane = new JScrollPane(graph);
112     scrollPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
113     scrollPane.setPreferredSize(new Dimension(600,600));
114     graph.setPreferredSize(new Dimension(2000,2000));
115     graph.setBackground(Color.white);
116 
117     TitledBorder border = (BorderFactory.createTitledBorder("Agent Society"));
118     border.setTitlePosition(TitledBorder.TOP);
119     border.setTitleJustification(TitledBorder.RIGHT);
120     border.setTitleFont(new Font("Helvetica", Font.BOLD, 14));
121     border.setTitleColor(Color.blue);
122     dataPanel.setBorder(border);
123 
124     JToolBar toolbar = new NodesToolBar();
125 
126     gbc = new GridBagConstraints();
127     gbc.gridwidth = GridBagConstraints.REMAINDER;
128     gbc.anchor = GridBagConstraints.WEST;
129     gbc.fill = GridBagConstraints.NONE;
130     gbc.weightx = gbc.weighty = 0;
131     gbc.insets = new Insets(0,8,0,0);
132     gridBagLayout.setConstraints(toolbar,gbc);
133     dataPanel.add(toolbar);
134 
135     gbc.gridwidth = GridBagConstraints.REMAINDER;
136     gbc.anchor = GridBagConstraints.WEST;
137     gbc.fill = GridBagConstraints.BOTH;
138     gbc.weightx = gbc.weighty = 1;
139     gbc.insets = new Insets(8,8,8,8);
140     gridBagLayout.setConstraints(scrollPane,gbc);
141     dataPanel.add(scrollPane);
142   }
143 
144   protected class SocietyNodeRenderer implements GraphNodeRenderer {
145      public Component getNodeRendererComponent(Graph g, GraphNode node) {
146         AgentDescription obj = (AgentDescription)node.getUserObject();
147         String agentId = obj.getName();
148         String name = genmodel.getAgentName(agentId);
149         String icon_file = genmodel.getAgentIcon(agentId);
150         if ( icon_file == null )
151 	   return new JLabel(name,JLabel.CENTER);
152         else {
153            JLabel label = new JLabel(name,new ImageIcon(icon_file),JLabel.CENTER);
154            label.setVerticalTextPosition(JLabel.BOTTOM);
155            label.setHorizontalTextPosition(JLabel.CENTER);
156            return label;
157         }
158      }
159   }
160 
161   protected class NodesToolBar extends JToolBar implements ActionListener {
162      protected HelpWindow    helpWin;
163      protected JToggleButton helpBtn;
164      protected JButton       newBtn;
165      protected JButton       selectBtn;
166      protected JButton       selectAllBtn;
167      protected JButton       hideBtn;
168      protected JButton       showBtn;
169      protected JButton       collapseBtn;
170      protected JButton       expandBtn;
171      protected JButton       deleteBtn;
172      protected JButton       cutBtn;
173      protected JButton       copyBtn;
174      protected JButton       pasteBtn;
175      protected JButton       recomputeBtn;
176      protected JButton       redrawBtn;
177 
178      public NodesToolBar() {
179         setBackground(Color.lightGray);
180         setBorder(new BevelBorder(BevelBorder.LOWERED));
181         setFloatable(false);
182 
183         String sep = System.getProperty("file.separator");
184         String path = SystemProps.getProperty("gif.dir") + "generator" + sep;
185 
186         // New Button
187         newBtn = new JButton(new ImageIcon(path + "new1.gif"));
188 	newBtn.setMargin(new Insets(0,0,0,0));
189         add(newBtn);
190         newBtn.setToolTipText("New node");
191         newBtn.addActionListener(this);
192 
193         addSeparator();
194 
195         // Draw Buttons
196         recomputeBtn = new JButton(new ImageIcon(path + "recompute.gif"));
197 	recomputeBtn.setMargin(new Insets(0,0,0,0));
198         add(recomputeBtn);
199         recomputeBtn.setToolTipText("Recompute node positions");
200         recomputeBtn.addActionListener(this);
201 
202         redrawBtn = new JButton(new ImageIcon(path + "redraw.gif"));
203 	redrawBtn.setMargin(new Insets(0,0,0,0));
204         add(redrawBtn);
205         redrawBtn.setToolTipText("Redraw");
206         redrawBtn.addActionListener(this);
207 
208 	addSeparator();
209 
210         selectBtn = new JButton(new ImageIcon(path + "select.gif"));
211 	selectBtn.setMargin(new Insets(0,0,0,0));
212         add(selectBtn);
213         selectBtn.setToolTipText("Select nodes");
214         selectBtn.addActionListener(this);
215 
216         selectAllBtn = new JButton(new ImageIcon(path + "selectAll.gif"));
217 	selectAllBtn.setMargin(new Insets(0,0,0,0));
218         add(selectAllBtn);
219         selectAllBtn.setToolTipText("Select all nodes");
220         selectAllBtn.addActionListener(this);
221 
222         addSeparator();
223 
224         collapseBtn = new JButton(new ImageIcon(path + "collapse.gif"));
225 	collapseBtn.setMargin(new Insets(0,0,0,0));
226         add(collapseBtn);
227         collapseBtn.setToolTipText("Collapse nodes");
228         collapseBtn.addActionListener(this);
229 
230         expandBtn = new JButton(new ImageIcon(path + "expand.gif"));
231 	expandBtn.setMargin(new Insets(0,0,0,0));
232         add(expandBtn);
233         expandBtn.setToolTipText("Expand nodes");
234         expandBtn.addActionListener(this);
235 
236         addSeparator();
237 
238         hideBtn = new JButton(new ImageIcon(path + "hide.gif"));
239 	hideBtn.setMargin(new Insets(0,0,0,0));
240         add(hideBtn);
241         hideBtn.setToolTipText("Hide nodes");
242         hideBtn.addActionListener(this);
243 
244         showBtn = new JButton(new ImageIcon(path + "show.gif"));
245 	showBtn.setMargin(new Insets(0,0,0,0));
246         add(showBtn);
247         showBtn.setToolTipText("Show nodes");
248         showBtn.addActionListener(this);
249 
250         addSeparator();
251 
252         // Delete Button
253         deleteBtn = new JButton(new ImageIcon(path + "delete1.gif"));
254 	deleteBtn.setMargin(new Insets(0,0,0,0));
255         add(deleteBtn);
256         deleteBtn.setToolTipText("Delete");
257         deleteBtn.addActionListener(this);
258 
259         addSeparator();
260 
261         // Cut Button
262         cutBtn = new JButton(new ImageIcon(path + "cut.gif"));
263 	cutBtn.setMargin(new Insets(0,0,0,0));
264         add(cutBtn);
265         cutBtn.setToolTipText("Cut");
266         cutBtn.addActionListener(this);
267 
268         // Copy Button
269         copyBtn = new JButton(new ImageIcon(path + "copy.gif"));
270 	copyBtn.setMargin(new Insets(0,0,0,0));
271         add(copyBtn);
272         copyBtn.setToolTipText("Copy");
273         copyBtn.addActionListener(this);
274 
275         // Paste Button
276         pasteBtn = new JButton(new ImageIcon(path + "paste.gif"));
277 	pasteBtn.setMargin(new Insets(0,0,0,0));
278         add(pasteBtn);
279         pasteBtn.setToolTipText("Paste");
280         pasteBtn.addActionListener(this);
281 
282         addSeparator();
283 
284         // Help Button
285         helpBtn = new JToggleButton(new ImageIcon(path + "help.gif"));
286 	helpBtn.setMargin(new Insets(0,0,0,0));
287         add(helpBtn);
288         helpBtn.setToolTipText("Help");
289         helpBtn.addActionListener(this);
290      }
291 
292      public void actionPerformed(ActionEvent e)  {
293         Object src = e.getSource();
294         if ( src == newBtn )
295            model.addNewNode();
296         else if ( src == recomputeBtn )
297            graph.recompute();
298         else if ( src == redrawBtn )
299            graph.redraw();
300         else if ( src == selectBtn )
301            graph.select();
302         else if ( src == selectAllBtn )
303            graph.selectAll();
304         else if ( src == collapseBtn )
305            graph.collapse();
306         else if ( src == expandBtn )
307            graph.expand();
308         else if ( src == hideBtn )
309            graph.hide();
310         else if ( src == showBtn )
311            graph.show();
312         else if ( src == deleteBtn )
313            deleteSelectedNodes();
314         else if ( src == copyBtn )
315            clipboard = graph.getSelectedNodes();
316         else if ( src == pasteBtn )
317            model.addNodes(clipboard);
318         else if ( src == cutBtn )
319            clipboard = cutSelectedNodes();
320         else if ( src == helpBtn ) {
321           if ( helpBtn.isSelected() ) {
322               helpWin = new HelpWindow(SwingUtilities.getRoot(this),
323                  getLocation(), "generator", "Society Viewer");
324               helpWin.setSource(helpBtn);
325           }
326           else
327               helpWin.dispose();
328         }
329      }
330   }
331 
332   protected void deleteSelectedNodes() {
333      model.removeNodes(graph.getSelectedNodes());
334      graph.redraw();
335   }
336   protected GraphNode[] cutSelectedNodes() {
337      GraphNode[] out = graph.getSelectedNodes();
338      model.removeNodes(out);
339      graph.redraw();
340      return out;
341   }
342 
343 
344   class SocietyNodeEditor extends AbstractGraphNodeEditor
345                           implements ActionListener {
346 
347      protected JButton button = new JButton("Click to edit");
348      protected GraphNode node;
349      protected Graph graph;
350      protected FileDialog dialog = null;
351  
352      public SocietyNodeEditor() {
353         button.setBackground(Color.lightGray);
354         button.setHorizontalAlignment(JButton.CENTER);
355         button.setBorderPainted(true);
356         button.addActionListener(this);
357         button.setOpaque(true);
358         button.setMinimumSize(new Dimension(120,30));
359         button.setPreferredSize(new Dimension(120,30));
360         button.setSize(120,30);
361      }
362  
363      public void actionPerformed(ActionEvent e) {
364         Object src = e.getSource();
365         if ( src == button ) {
366            // Note: create dialog (using button) before stopping editing
367            // which will remove the button from the visible component hierachy
368            if ( dialog == null )
369               dialog = new FileDialog((Frame)SwingUtilities.getRoot(button),
370   	       "Select Icon File",FileDialog.LOAD);
371   
372            AgentDescription agent = (AgentDescription)node.getUserObject();
373            String icon_file = genmodel.getAgentIcon(agent.getName());
374   
375            if ( icon_file != null ) {
376   	    File f1 = new File(icon_file);
377               dialog.setFile(f1.getName());
378               dialog.setDirectory(f1.getParent());
379            }
380            else
381               dialog.setFile("*.gif");
382   
383            dialog.pack();
384            dialog.setVisible(true);
385   
386            String path = (dialog.getFile() == null) ? null 
387               : dialog.getDirectory() + File.separator + dialog.getFile();
388            if ( path == null )
389               fireEditAction(EDITING_CANCELLED,this.node,null);
390            else
391               fireEditAction(EDITING_STOPPED,this.node,path);
392         }
393      }
394      public Component getNodeEditorComponent(Graph graph, GraphNode gnode) {
395         this.graph = graph;
396         this.node = gnode;
397         return button;
398      }
399   }
400 
401 
402   protected class SoceityControlPanel extends JPanel implements ItemListener {
403      protected JCheckBox[]    checkbox;
404      protected JRadioButton[] view;
405 
406      public SoceityControlPanel()  {
407        String[] RELATIONS = Misc.stringArray(AcquaintanceModel.RELATIONS_LIST);
408 
409        checkbox = new JCheckBox[RELATIONS.length];
410        view = new JRadioButton[RELATIONS.length];
411 
412        JPanel topPanel = new JPanel();
413        TitledBorder border = (BorderFactory.createTitledBorder("View Style"));
414        border.setTitlePosition(TitledBorder.TOP);
415        border.setTitleJustification(TitledBorder.RIGHT);
416        border.setTitleFont(new Font("Helvetica", Font.BOLD, 12));
417        border.setTitleColor(Color.blue);
418        topPanel.setBorder(border);
419        topPanel.setBackground(Color.lightGray);
420 
421        GridBagLayout gb = new GridBagLayout();
422        GridBagConstraints gbc = new GridBagConstraints();
423        gbc.insets = new Insets(4,4,0,4);
424        gbc.gridwidth = GridBagConstraints.REMAINDER;
425        gbc.anchor = GridBagConstraints.NORTHWEST;
426        topPanel.setLayout(gb);
427 
428        ButtonGroup alignGroup = new ButtonGroup();
429        for(int i = 0; i < view.length; i++ ) {
430           if ( i == 0 )
431              view[i] = new JRadioButton("vertical",model.getView() == i);
432           else if ( i == 1 )
433              view[i] = new JRadioButton("centered",model.getView() == i);
434           else
435              view[i] = new JRadioButton(RELATIONS[i],model.getView() == i);
436           view[i].setBackground(Color.lightGray);
437           alignGroup.add(view[i]);
438           gb.setConstraints(view[i], gbc);
439           topPanel.add(view[i]);
440        }
441 
442        JPanel bottomPanel = new JPanel();
443        border = (BorderFactory.createTitledBorder("Relational Links"));
444        border.setTitlePosition(TitledBorder.TOP);
445        border.setTitleJustification(TitledBorder.RIGHT);
446        border.setTitleFont(new Font("Helvetica", Font.BOLD, 12));
447        border.setTitleColor(Color.blue);
448        bottomPanel.setBorder(border);
449        bottomPanel.setBackground(Color.lightGray);
450 
451        gb = new GridBagLayout();
452        gbc = new GridBagConstraints();
453        bottomPanel.setLayout(gb);
454 
455        JPanel colorPanel;
456        for(int i = 0; i < checkbox.length; i++ ) {
457           checkbox[i] = new JCheckBox(RELATIONS[i]);
458           checkbox[i].setBackground(Color.lightGray);
459           colorPanel = new JPanel();
460           colorPanel.setSize(10,10);
461           colorPanel.setBackground(model.getColor(i));
462 
463           gbc.fill = GridBagConstraints.NONE;
464           gbc.weightx = 0;
465           gbc.anchor = GridBagConstraints.NORTHWEST;
466           gbc.insets = new Insets(4,4,0,0);
467           gbc.gridwidth = 1;
468           gb.setConstraints(checkbox[i],gbc);
469           bottomPanel.add(checkbox[i]);
470 
471           gbc.anchor = GridBagConstraints.EAST;
472           gbc.insets = new Insets(4,0,0,4);
473           gbc.gridwidth = GridBagConstraints.REMAINDER;
474           gb.setConstraints(colorPanel,gbc);
475           bottomPanel.add(colorPanel);
476        }
477 
478        gb = new GridBagLayout();
479        gbc = new GridBagConstraints();
480        setLayout(gb);
481        gbc.insets = new Insets(0,0,0,0);
482        gbc.gridwidth = GridBagConstraints.REMAINDER;
483        gbc.anchor = GridBagConstraints.NORTHWEST;
484        gbc.fill = GridBagConstraints.BOTH;
485        gbc.weightx = gbc.weighty = 0;
486        gb.setConstraints(topPanel,gbc);
487        add(topPanel);
488 
489        gbc.weightx = gbc.weighty = 0;
490        gb.setConstraints(bottomPanel,gbc);
491        add(bottomPanel);
492 
493        for(int i = 0; i < checkbox.length; i++ ) {
494           checkbox[i].setSelected(model.isLinkVisible(i));
495           checkbox[i].addItemListener(this);
496           view[i].addItemListener(this);
497        }
498      }
499 
500      public void itemStateChanged(ItemEvent evt) {
501        Object source = evt.getSource();
502 
503        for(int i = 0; i < checkbox.length; i++ ) {
504           if ( source == checkbox[i] ) {
505              model.showLinks(i,checkbox[i].isSelected());
506              graph.redraw();
507              return;
508           }
509           if ( source == view[i] ) {
510              switch( i ) {
511                 case 0:
512                      graph.setViewMode(Graph.VERTICAL_PARENT_CHILD);
513                      break;
514                 case 1:
515                      graph.setViewMode(Graph.CENTRED);
516                      break;
517                 default:
518                      graph.setViewMode(Graph.CIRCLES);
519                      break;
520              }
521              model.setView(i);
522              graph.recompute();
523              return;
524           }
525        }
526      }
527   }
528 
529 }