3
* This file is part of jReality. jReality is open source software, made
4
* available under a BSD license:
6
* Copyright (c) 2003-2006, jReality Group: Charles Gunn, Tim Hoffmann, Markus
7
* Schmies, Steffen Weissmann.
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions are met:
14
* - Redistributions of source code must retain the above copyright notice, this
15
* list of conditions and the following disclaimer.
17
* - Redistributions in binary form must reproduce the above copyright notice,
18
* this list of conditions and the following disclaimer in the documentation
19
* and/or other materials provided with the distribution.
21
* - Neither the name of jReality nor the names of its contributors nor the
22
* names of their associated organizations may be used to endorse or promote
23
* products derived from this software without specific prior written
26
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36
* POSSIBILITY OF SUCH DAMAGE.
41
package opencog.spacetime.ui.viewerapp;
43
import java.awt.Component;
44
import java.awt.Container;
45
import java.awt.Dimension;
46
import java.awt.GridBagConstraints;
47
import java.awt.GridBagLayout;
48
import java.awt.GridLayout;
49
import java.awt.event.ActionEvent;
50
import java.awt.event.MouseAdapter;
51
import java.awt.event.MouseEvent;
53
import javax.swing.AbstractAction;
54
import javax.swing.Action;
55
import javax.swing.ActionMap;
56
import javax.swing.BorderFactory;
57
import javax.swing.JCheckBox;
58
import javax.swing.JMenu;
59
import javax.swing.JPanel;
60
import javax.swing.JPopupMenu;
61
import javax.swing.JScrollPane;
62
import javax.swing.JSeparator;
63
import javax.swing.JSplitPane;
64
import javax.swing.JTree;
65
import javax.swing.KeyStroke;
66
import javax.swing.event.TreeSelectionEvent;
67
import javax.swing.event.TreeSelectionListener;
68
import javax.swing.tree.TreePath;
69
import javax.swing.tree.TreeSelectionModel;
71
import opencog.spacetime.scene.SceneGraphComponent;
72
import opencog.spacetime.scene.Viewer;
73
import opencog.spacetime.scene.proxy.tree.SceneTreeNode;
74
import opencog.spacetime.ui.treeview.JTreeRenderer;
75
import opencog.spacetime.ui.treeview.SceneTreeModel;
76
import opencog.spacetime.ui.treeview.SceneTreeModel.TreeTool;
78
import de.jtem.beans.BooleanEditor;
79
import de.jtem.beans.EditorSpawner;
80
import de.jtem.beans.InspectorPanel;
81
import de.jtem.beans.NumberSpinnerEditor;
85
* Scene tree and inspector panel for a given scene graph.
89
public class Navigator implements SelectionListener {
91
private InspectorPanel inspector;
92
private JTree sceneTree;
93
private SceneTreeModel treeModel;
94
private TreeSelectionModel tsm;
96
private SelectionManager selectionManager;
97
private SelectionManager externalSelectionManager;
98
private Viewer viewer; //the underlying viewer
100
private Container navigator;
101
private Component parentComp;
103
private Component toolBar;
104
private JCheckBox receiveCheckBox;
105
private JCheckBox propagateCheckBox;
109
* @param sceneRoot the scene root
110
* @param selectionManager the underlying selection manager
112
public Navigator(Viewer viewer) {
118
* @param sceneRoot the scene root
119
* @param selectionManager the underlying selection manager
120
* @param parentComp used by dialogs from the context menu (<code>null</code> allowed)
122
public Navigator(Viewer viewer, Component parentComp) {
124
externalSelectionManager = SelectionManagerImpl.selectionManagerForViewer(viewer);
125
selectionManager = new SelectionManagerImpl(externalSelectionManager.getDefaultSelection());
126
//selectionManager.addSelectionListener(this);
127
toolBar = createToolBar();
128
// setPropagateSelections(true);
129
setReceiveSelections(true);
131
this.parentComp = parentComp;
133
inspector = new InspectorPanel(false);
134
BooleanEditor.setNameOfNull("inherit");
135
EditorSpawner.setNameOfNull("inherit");
136
EditorSpawner.setNameOfCreation("inherited");
137
NumberSpinnerEditor.setNameOfNull("inherit");
138
NumberSpinnerEditor.setNameOfCreation("inherited");
139
//EditorManager.registerEditor(Texture2D.class, ObjectEditor.class);
141
sceneTree = new JTree();
142
treeModel = new SceneTreeModel(viewer.getSceneRoot());
144
sceneTree.setModel(treeModel);
145
//set default (anchor) selection (use the selection manager's default)
146
sceneTree.setAnchorSelectionPath(new TreePath(treeModel.convertSelection(selectionManager.getDefaultSelection())));
147
sceneTree.setCellRenderer(new JTreeRenderer());
148
sceneTree.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "toggle"); //collaps/expand nodes with ENTER
150
tsm = sceneTree.getSelectionModel();
151
tsm.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
153
tsm.addTreeSelectionListener(new SelectionListener(){
155
public void selectionChanged(SelectionEvent e) {
157
Selection currentSelection = e.getSelection();
159
inspector.setObject(currentSelection.getLastElement());
162
//update selection managers
163
selectionManager.setSelection(currentSelection);
164
if (isPropagateSelections()) externalSelectionManager.setSelection(currentSelection); //does nothing if already selected
168
try { //set default selection
169
tsm.setSelectionPath(new TreePath(treeModel.convertSelection(selectionManager.getDefaultSelection()))); //select current selection
170
} catch (Exception e) {
171
//no valid default selection
174
// SceneGraphPath sgp = sm.getSelectionPath();
175
// if (sgp != null && sgp.isValid())
176
// tsm.setSelectionPath(new TreePath(treeModel.convertSelection(sm.getSelection()))); //select current selection
182
public void selectionChanged(opencog.spacetime.ui.viewerapp.SelectionEvent e) {
183
//convert selection of manager into TreePath
184
Object[] selection = null;
186
selection = treeModel.convertSelection(e.getSelection());
187
TreePath path = new TreePath(selection);
189
if (e.nodeSelected() && !path.equals(tsm.getSelectionPath())) //compare paths only if a node is selected
190
tsm.setSelectionPath(path);
192
} catch (NullPointerException npe) {
193
//SelectionManager's selection is not valid,
194
//i.e. has no representation in tree view (scene graph)
199
public InspectorPanel getInspector() {
204
public JTree getSceneTree() {
209
public TreeSelectionModel getTreeSelectionModel() {
214
public SceneGraphComponent getSceneRoot() {
215
return viewer.getSceneRoot();
219
public Selection getSelection() {
220
return selectionManager.getSelection();
224
private void setupContextMenu() {
226
final JPopupMenu cm = new JPopupMenu();
227
cm.setLightWeightPopupEnabled(false);
229
//create content of context menu
230
JMenu editMenu = null;
231
ActionMap editActions = null;
233
editMenu = ViewerAppMenu.createEditMenu(parentComp, selectionManager);
234
editActions = ViewerAppMenu.updateActionMap(editMenu.getActionMap(), editMenu);
235
} catch (Exception e) {
236
return; //menu or actions not in classpath
238
for (Component c : editMenu.getMenuComponents()) cm.add(c);
240
//add listener to the navigator's tree
241
sceneTree.addMouseListener(new MouseAdapter() {
243
public void mousePressed( MouseEvent e ) {
247
public void mouseReleased( MouseEvent e ) {
251
private void handlePopup( MouseEvent e ) {
252
if ( e.isPopupTrigger() ) {
253
TreePath path = sceneTree.getPathForLocation( e.getX(), e.getY() );
254
if ( path != null ) {
255
tsm.clearSelection(); //ensures that SelectionListeners are notified even if path did not change
256
tsm.setSelectionPath( path );
257
cm.show( e.getComponent(), e.getX(), e.getY()+10 );
263
//set up input and action map to match actions of context menu instead of viewers menu bar
265
Object[] keys = editActions.keys();
266
for (int i = 0; i < keys.length; i++) {
267
KeyStroke key = (KeyStroke) keys[i];
268
sceneTree.getInputMap().put(key, key);
269
sceneTree.getActionMap().put(key, editActions.get(key));
271
} catch (Exception e) {
272
//e.printStackTrace();
278
* Get the navigator as a Component.
279
* @return the navigator
281
public Component getComponent() {
283
if (navigator == null) {
284
sceneTree.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
285
JScrollPane top = new JScrollPane(sceneTree);
286
top.setPreferredSize(new Dimension(1, 1));
287
top.setBorder(BorderFactory.createEmptyBorder());
289
inspector.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
290
JScrollPane bottom = new JScrollPane(inspector);
291
bottom.setPreferredSize(new Dimension(1, 1));
292
bottom.setBorder(BorderFactory.createEmptyBorder());
294
JSplitPane navigator = new JSplitPane(JSplitPane.VERTICAL_SPLIT, top, bottom);
295
navigator.setResizeWeight(0.6);
296
navigator.setContinuousLayout(true);
297
navigator.setOneTouchExpandable(true);
299
this.navigator = new JPanel();
300
this.navigator.setLayout(new GridBagLayout());
301
GridBagConstraints c = new GridBagConstraints();
302
c.fill = GridBagConstraints.BOTH;
303
c.gridwidth = GridBagConstraints.REMAINDER;
306
this.navigator.add(toolBar, c);
307
this.navigator.add(new JSeparator(), c);
309
this.navigator.add(navigator, c);
316
private Component createToolBar() {
318
JPanel checkerPanel = new JPanel();
319
checkerPanel.setLayout(new GridLayout(1, 2));
320
// JToolBar jtb = new JToolBar(SwingConstants.HORIZONTAL);
321
// jtb.setFloatable(false);
324
propagateCheckBox = new JCheckBox();
325
// final URL propagateImg = Navigator.class.getResource("propagate.png");
326
a = new AbstractAction("Propagate"){
328
private static final long serialVersionUID = 1L;
330
putValue(Action.SHORT_DESCRIPTION, "Propagate selections to the SelectionManager");
332
public void actionPerformed(ActionEvent e) {
336
propagateCheckBox.setAction(a);
337
checkerPanel.add(propagateCheckBox);
338
receiveCheckBox = new JCheckBox();
339
a = new AbstractAction("Receive"){
340
private static final long serialVersionUID = 1L;
342
putValue(Action.SHORT_DESCRIPTION, "Receive selections from the SelectionManager");
344
public void actionPerformed(ActionEvent e) {
345
updateReceiveSelections();
348
receiveCheckBox.setAction(a);
349
checkerPanel.add(receiveCheckBox);
355
* Receive selections from the underlying viewer's selection manager.
357
public void setReceiveSelections(boolean receive) {
358
receiveCheckBox.setSelected(receive);
361
public boolean isReceiveSelections() {
362
return receiveCheckBox.isSelected();
365
private void updateReceiveSelections() {
366
if (receiveCheckBox.isSelected()) {
367
externalSelectionManager.addSelectionListener(Navigator.this);
369
externalSelectionManager.removeSelectionListener(Navigator.this);
373
public boolean isPropagateSelections() {
374
return propagateCheckBox.isSelected();
378
* Propagate selections to the underlying viewer's selection manager.
380
public void setPropagateSelections(boolean propagate) {
381
propagateCheckBox.setSelected(propagate);
384
// -- INNER CLASSES -----------------------------------
388
public static abstract class SelectionListener implements TreeSelectionListener {
390
public abstract void selectionChanged(SelectionEvent e);
392
public void valueChanged(TreeSelectionEvent e) {
394
boolean[] areNew = new boolean[e.getPaths().length];
395
for (int i = 0; i < areNew.length; i++)
396
areNew[i] = e.isAddedPath(i);
398
SelectionEvent se = new SelectionEvent(e.getSource(), e.getPaths(),
399
areNew, e.getOldLeadSelectionPath(), e.getNewLeadSelectionPath());
401
selectionChanged(se);
404
} //end of class SelectionListener
407
public static class SelectionEvent extends TreeSelectionEvent {
409
private static final long serialVersionUID = 1L;
411
/** calls TreeSelectionEvent(...) */
412
public SelectionEvent(Object source, TreePath[] paths, boolean[] areNew, TreePath oldLeadSelectionPath, TreePath newLeadSelectionPath) {
413
super(source, paths, areNew, oldLeadSelectionPath, newLeadSelectionPath);
416
private Object convert(Object o) {
417
if (o instanceof SceneTreeNode)
418
return ((SceneTreeNode) o).getNode();
419
else if (o instanceof TreeTool)
420
return ((TreeTool) o).getTool();
426
* Converts the TreePath of the current selection into a Selection object.
427
* @return the current selection
429
public Selection getSelection() {
430
Selection selection = new Selection();
431
Object[] treePath = getPath().getPath();
432
for (int i = 0; i < treePath.length; i++)
433
selection.push( convert(treePath[i]) );
437
} //end of class SelectionEvent
b'\\ No newline at end of file'