Source code: org/bdgp/apps/dagedit/gui/DETermPanel.java
1 package org.bdgp.apps.dagedit.gui;
2
3 import org.bdgp.swing.*;
4 import org.bdgp.cv.gui.*;
5 import org.bdgp.cv.datamodel.*;
6
7 import org.bdgp.apps.dagedit.datamodel.*;
8 import org.bdgp.apps.dagedit.gui.event.*;
9 import javax.swing.tree.*;
10 import javax.swing.event.*;
11 import javax.swing.*;
12 import java.util.*;
13 import java.awt.event.*;
14 import java.awt.*;
15
16 public class DETermPanel extends DAGComponent {
17
18 private static int staticTreeID = 1;
19 private int treeID;
20
21 protected boolean scrollOnSelection = true;
22 protected Controller controller;
23
24 TreeSelectionListener selectionListener = new TreeSelectionListener() {
25 public void valueChanged(TreeSelectionEvent e) {
26 controller.
27 fireTermSelect(new
28 DETermSelectEvent(DETermPanel.this,
29 getSelectionPaths()));
30 }
31 };
32 /*
33 RootChangeListener rootChangeListener = new RootChangeListener() {
34 public void changeRoot(RootChangeEvent e) {
35 if (e.getSource() != DETermPanel.this)
36 setModel(new TermModel(controller.getRoot(),
37 controller));
38 }
39 };
40 */
41 DETermSelectListener termSelectListener = new DETermSelectListener () {
42 public void selectTerms(DETermSelectEvent e) {
43 setSelectionPaths(controller.getSelectedPaths());
44 }
45 };
46 /*
47 DETermReloadListener reloadListener = new DETermReloadListener () {
48 public void reload(DETermReloadEvent e) {
49 try {
50 throw new Exception("reloading "+DETermPanel.this+" based on event");
51 } catch (Exception ex) {
52 ex.printStackTrace();
53 }
54 DETermPanel.this.reload();
55 }
56 };
57
58 public DETermReloadListener getReloadListener() {
59 return reloadListener;
60 }
61 */
62
63 public DETermPanel(Controller controller, boolean editable) {
64 // super(controller.getDragController(), new TermModel(controller.getRoot(), controller), editable);
65 super(controller.getDragController(), null, editable);
66 treeID = staticTreeID++;
67 setUndoManager(controller.getUndoManager());
68 setCellRenderer(new DECellRenderer(controller));
69 this.controller = controller;
70 attachListeners();
71 }
72
73 public String toString() {
74 return "DETermPanel "+treeID;
75 }
76
77 public boolean getScrollOnSelection() {
78 return scrollOnSelection;
79 }
80
81 public void setScrollOnSelection(boolean scrollOnSelection) {
82 this.scrollOnSelection = scrollOnSelection;
83 }
84
85 public Controller getController() {
86 return controller;
87 }
88
89 public void cleanUp() {
90 setDragController(null);
91 controller.removeListener(termSelectListener);
92 }
93
94 public void addNotify() {
95 super.addNotify();
96 spec.setInsets(new Insets(15,15,15,15));
97 spec.setScrollInterval(25);
98 }
99
100
101 public void attachListeners() {
102 addTreeSelectionListener(selectionListener);
103 controller.addListener(termSelectListener);
104 }
105
106 public void setSelectionPaths(TreePath [] paths) {
107 setSelectionPaths(paths, true);
108 }
109
110 public void setSelectionPaths(TreePath [] paths, boolean supressEvent) {
111 if (supressEvent)
112 removeTreeSelectionListener(selectionListener);
113
114 super.setSelectionPaths(paths);
115
116 if (supressEvent)
117 addTreeSelectionListener(selectionListener);
118
119 if (paths != null && paths.length > 0 && scrollOnSelection)
120 scrollPathToVisible(paths[0]);
121 }
122
123 public void expandRow(int row) {
124 expandPath(getPathForRow(row));
125 }
126
127 public void expandPath(TreePath path) {
128 if (TermRelationship.pathIsCircular(path))
129 path = TermRelationship.trimCircularPath(path);
130
131 super.expandPath(path);
132 }
133
134 protected boolean isSelfTargeted(TreePath [] source, TreePath dest) {
135 for(int i=0; i < source.length; i++) {
136 if (source[i].getLastPathComponent().equals(dest.getLastPathComponent()))
137 return true;
138 }
139 return false;
140 }
141
142 protected boolean wouldDisconnectSubgraph(TreePath [] sources,
143 TreePath dest) {
144 for(int i=0; i < sources.length; i++) {
145 TreePath source = sources[i];
146 if (wouldDisconnectSubgraph(source, dest))
147 return true;
148 }
149 return false;
150 }
151
152 protected boolean wouldDisconnectSubgraph(TreePath source, TreePath dest) {
153 TermRelationship destRel = (TermRelationship) dest.getLastPathComponent();
154 Term sourceTerm = ((TermRelationship) source.getLastPathComponent()).getChild();
155
156 Vector destPaths = destRel.getPathsAsVector();
157 boolean found = false;
158 for(int i=0; i < destPaths.size(); i++) {
159 TreePath path = (TreePath) destPaths.elementAt(i);
160 if (!source.isDescendant(path)) {
161 found = true;
162 break;
163 }
164 }
165 return !found;
166 }
167
168 protected boolean wouldCreateCycle(TreePath [] sources, TreePath dest) {
169 Term destTerm = ((TermRelationship) dest.getLastPathComponent()).
170 getChild();
171 for(int i=0; i < sources.length; i++) {
172 TreePath source = sources[i];
173 Term sourceTerm = ((TermRelationship) source.
174 getLastPathComponent()).getChild();
175 if (destTerm.hasAncestor(sourceTerm))
176 return true;
177 }
178 return false;
179 }
180
181 protected boolean allowCopy(TreePath [] source, TreePath dest) {
182 if (controller.allowCycles())
183 return true;
184 else
185 return super.allowCopy(source, dest);
186 }
187
188 protected boolean allowMove(TreePath [] source, TreePath dest) {
189 if (controller.allowCycles())
190 return !wouldDisconnectSubgraph(source, dest);
191 else
192 return super.allowMove(source, dest);
193 }
194
195 protected boolean allowMerge(TreePath source, TreePath dest) {
196 if (controller.allowCycles())
197 return !source.getLastPathComponent().
198 equals(dest.getLastPathComponent());
199 else
200 return super.allowMerge(source, dest);
201 }
202
203 protected boolean allowSplit(TreePath target) {
204 TermRelationship tr = (TermRelationship) target.getLastPathComponent();
205 return tr.getParent() != null;
206 }
207
208 public void restorePaths(TreePath [] expanded) {
209 for(int i=0; i < expanded.length; i++) {
210 TreePath current = (TreePath) expanded[i];
211 Object [] objects = current.getPath();
212
213 // only expand paths that are actually in the model
214 // otherwise some JTree implementations will become corrupted
215 boolean allowExpand = true;
216 for(int j=0; j < objects.length; j++) {
217 TermRelationship old = (TermRelationship) objects[j];
218 Term parent = old.getParent();
219 Term child = old.getChild();
220 if (parent == null)
221 continue;
222 Vector relationships = parent.
223 getRelationshipsForChild(child);
224 if (relationships == null || relationships.size() == 0) {
225 allowExpand = false;
226 break;
227 }
228 }
229 if (allowExpand) {
230 makeVisible(current);
231 }
232 }
233 }
234
235 public void reload() {
236 TreePath [] expanded = getExpandedPaths();
237 TreeModel model = getModel();
238
239 if (model instanceof TermModel) {
240 ((TermModel) model).reload();
241 } else
242 System.err.println("Can't reload");
243
244 restorePaths(expanded);
245 }
246 /*
247 public void delete() {
248 super.delete();
249 reload();
250 }
251 */
252 public boolean allowDelete(TreePath [] paths) {
253 for(int i=0; i < paths.length; i++) {
254 TermRelationship tr = (TermRelationship) paths[i].
255 getLastPathComponent();
256 if (tr.getParent() == null)
257 return false;
258 Term parent = tr.getParent();
259 Term child = tr.getChild();
260 if (child.getParents().size() <= 1 &&
261 controller.warnBeforeDelete()) {
262 if (JOptionPane.
263 showConfirmDialog(this,
264 "This is the last instance of "+
265 child.getTerm()+" ("+child.getID()+")."+
266 "\n"+
267 "Are you sure you want to permanently "+
268 "remove this term from the ontology?",
269 "Delete warning",
270 JOptionPane.YES_NO_OPTION) !=
271 JOptionPane.YES_OPTION)
272 return false;
273 }
274 }
275 return true;
276 }
277
278 public boolean allowChangeRelationship(TreePath [] paths, TermRelationshipType type) {
279 return true;
280 }
281
282 public void changeRelationship(TermRelationshipType type) {
283 Component baseComponent = SwingUtilities.getRoot(this);
284 Cursor originalCursor = baseComponent.getCursor();
285 baseComponent.setCursor(new Cursor(Cursor.WAIT_CURSOR));
286 changeRelationship(getSelectionPaths(), type);
287 baseComponent.setCursor(originalCursor);
288 }
289
290 public void changeRelationship(TreePath [] source, TermRelationshipType type) {
291 if (source.length == 0)
292 return;
293 if (!allowChangeRelationship(source, type))
294 return;
295 ((TermModel) getModel()).changeTermRelationship(source, type);
296
297 repaint();
298 }
299
300
301 protected JMenu getTypeChangeMenu() {
302 JMenu changeMenu = new JMenu("Change relationship type to");
303 changeMenu.setFont(menuFont);
304 Vector types = controller.getHistory().getRelationshipTypes();
305 for(int i=0; i < types.size(); i++) {
306 final TermRelationshipType type = (TermRelationshipType) types.
307 elementAt(i);
308 JMenuItem item = new JMenuItem();
309 Icon icon = controller.getIconForRelationshipType(type);
310 String itemText = type.getDesc();
311 if (icon != null)
312 item.setIcon(icon);
313 else
314 itemText = "("+type.getName()+") "+type.getDesc();
315 item.setText(itemText);
316 item.setFont(menuFont);
317
318 item.addActionListener(new ActionListener() {
319 public void actionPerformed(ActionEvent e) {
320 changeRelationship(type);
321 }
322 });
323 changeMenu.add(item);
324 }
325 return changeMenu;
326 }
327
328 protected JPopupMenu getRightClickMenu() {
329 JPopupMenu menu = super.getRightClickMenu();
330 menu.add(getTypeChangeMenu());
331 menu.addSeparator();
332 JMenuItem collapseItem = new JMenuItem("Collapse all nodes");
333 collapseItem.addActionListener(new ActionListener() {
334 public void actionPerformed(ActionEvent e) {
335 TreePath [] selectedPaths = controller.getSelectedPaths();
336 for(int i=0; i < selectedPaths.length; i++)
337 SwingUtil.collapseTree(DETermPanel.this,
338 selectedPaths[i]);
339
340 TreePath rootPath = new TreePath(getModel().getRoot());
341 expandPath(rootPath);
342 }
343 });
344 collapseItem.setFont(controller.getDefaultFont());
345 menu.add(collapseItem);
346 return menu;
347 }
348 }
349
350
351
352
353