source: java/main/src/main/java/com/framsticks/gui/Frame.java @ 84

Last change on this file since 84 was 84, checked in by psniegowski, 11 years ago

HIGHLIGHTS:

  • simplification of entities management model
  • cleanup around params (improve hierarchy)
  • migrate from JUnit to TestNG
  • introduce FEST to automatically test GUI
  • improve slider control
  • loosen synchronization between gui tree and backend representation
  • and many other bug fixes

NOTICE:

  • a great many of lines is changed only because of substituting spaces with tabs

CHANGELOG (oldest changes at the bottom):

Some cleaning after fix found.

Fix bug with tree.

More changes with TreeNodes?.

Finally fix issue with tree.

Improve gui tree management.

Decouple update of values from fetch request in gui.

Minor changes.

Minor changes.

Minor change.

Change Path construction wording.

More fixes to SliderControl?.

Fix SliderControl?.

Fix SliderControl?.

Minor improvement.

Several changes.

Make NumberParam? a generic class.

Add robot to the gui test.

Setup common testing logging configuration.

Remove Parameters class.

Remove entityOwner from Parameters.

Move name out from Parameters class.

Move configuration to after the construction.

Simplify observers and endpoints.

Remove superfluous configureEntity overrides.

Add dependency on fest-swing-testng.

Use FEST for final print test.

Use FEST for more concise and readable assertions.

Divide test of F0Parser into multiple methods.

Migrate to TestNG

Minor change.

Change convention from LOGGER to log.

Fix reporting of errors during controls filling.

Bound maximal height of SliderControl?.

Minor improvements.

Improve tooltips for controls.

Also use Delimeted in more places.

Move static control utilities to Gui.

Rename package gui.components to controls.

Some cleaning in controls.

Improve Param classes placing.

Move ValueParam?, PrimitiveParam? and CompositeParam? one package up.

Improve ParamBuilder?.

Move getDef to ValueParam? and PrimitiveParam?.

Move getMax and getDef to ValueParam?.

Move getMin to ValueParam?.

Upgrade to laters apache commons versions.

Use filterInstanceof extensively.

Add instanceof filters.

Make ValueParam? in many places of Param.

Place assertions about ValueParam?.

Add ValueParam?

Rename ValueParam? to PrimitiveParam?

Minor changes.

Several improvements to params types.

Add NumberParam?.

Add TextControl? component.

Add .swp files to .gitignore

Greatly improved slider component.

Some improvements.

Make Param.reassign return also a state.

Add IterableIterator?.

Several changes.

  • Move util classes to better packages.
  • Remove warnings from eclim.

Several improvements.

Fix bug with BooleanParam?.

Some experiments with visualization.

Another fix to panel management.

Improve panel management.

Some refactorization around panels.

Add root class for panel.

File size: 11.1 KB
Line 
1package com.framsticks.gui;
2
3import com.framsticks.core.Instance;
4import com.framsticks.core.Path;
5import com.framsticks.gui.view.*;
6import com.framsticks.gui.view.TreeCellRenderer;
7import com.framsticks.util.dispatching.Dispatcher;
8import com.framsticks.util.swing.KeyboardModifier;
9import org.apache.log4j.Logger;
10
11import javax.swing.*;
12import javax.swing.event.TreeModelEvent;
13import javax.swing.event.TreeModelListener;
14import javax.swing.event.TreeSelectionEvent;
15import javax.swing.event.TreeSelectionListener;
16import javax.swing.tree.*;
17
18import java.awt.*;
19import java.awt.datatransfer.StringSelection;
20import java.awt.event.*;
21import java.util.HashMap;
22import java.util.Map;
23
24/**
25 * @author Piotr Sniegowski
26 */
27@SuppressWarnings("serial")
28public class Frame extends JFrame implements Dispatcher {
29
30        private static final Logger log = Logger.getLogger(Frame.class.getName());
31
32        protected final Browser browser;
33
34        protected final Dimension screenDimension = Toolkit.getDefaultToolkit()
35                        .getScreenSize();
36
37        final protected CardLayout cardPanelLayout = new CardLayout();
38        protected final JPanel cardPanel = new JPanel();
39
40        protected JScrollPane treeScrollPane;
41        protected JTree tree;
42        protected DefaultTreeModel treeModel;
43        protected javax.swing.tree.MutableTreeNode rootNode;
44        //final Instance instance;
45        protected JPanel treePanel;
46        protected JPopupMenu treePopupMenu;
47        protected JMenuItem treePopupMenuHeader;
48
49        TreeNode currentlyPoppedTreeNode;
50        protected JLabel statusBar;
51        protected JPanel mainPanel;
52        protected JPanel leftPanel;
53        protected JPanel normalWorkPanel;
54        protected CardLayout mainPanelLayout;
55
56        protected JMenuBar menuBar;
57        protected JMenu fileMenu;
58        protected JMenu editMenu;
59        protected JMenu viewMenu;
60        protected JMenu windowMenu;
61        protected JMenu helpMenu;
62
63        protected final Map<BrowserEndpoint, EndpointAtFrame> endpoints = new HashMap<BrowserEndpoint, EndpointAtFrame>();
64        protected final Map<Instance, EndpointAtFrame> endpointsByInstance = new HashMap<Instance, EndpointAtFrame>();
65
66        public Frame(String title, Browser browser) {
67                super(title);
68                /** this is done to remove the current value label from above the slider,
69                 * because it cannot put to work properly with floating-point value sliders,
70                 * nor it can be removed in normal way through JSlider methods  */
71                UIManager.put("Slider.paintValue", false);
72                this.browser = browser;
73                log.debug("creating " + this);
74        }
75
76        public void configure() {
77
78                Container contentPane = this.getContentPane();
79                contentPane.setLayout(new BorderLayout());
80
81                treePopupMenu = new JPopupMenu("title");
82                treePopupMenu.setName("popup");
83                treePopupMenuHeader = new JMenuItem();
84                treePopupMenuHeader.setForeground(Color.BLUE);
85                treePopupMenu.add(treePopupMenuHeader);
86                treePopupMenu.addSeparator();
87                //TODO: add to favourites
88                //TODO: remove from favourites
89                //TODO: open in new window as root
90                //TODO: refresh
91                //TODO: open in console
92
93                treePopupMenu.add(new JMenuItem("Refresh"));
94                treePopupMenu.add(new JMenuItem("Open in new frame as root"));
95                addNodeActionToTreePopupMenu("Copy path to clipboard",
96                                new NodeAction() {
97                                        @Override
98                                        public void actionPerformed(TreeNode treeNode) {
99                                                Path path = treeNode.getInstancePath();
100                                                StringSelection selection = new StringSelection(path
101                                                                .toString());
102                                                getToolkit().getSystemClipboard().setContents(
103                                                                selection, selection);
104                                        }
105                                });
106                //this.add(createMenuItem("Add to favourites", null));
107                //this.add(createMenuItem("Remove from favourites", null));
108
109                treePanel = new JPanel();
110                treePanel.setLayout(new BorderLayout());
111
112                treeModel = new DefaultTreeModel(null);
113                treeModel.addTreeModelListener(new TreeModelListener() {
114
115                        @Override
116                        public void treeNodesChanged(TreeModelEvent arg0) {
117                                log.trace("treeNodesChanged: " + arg0);
118                        }
119
120                        @Override
121                        public void treeNodesInserted(TreeModelEvent arg0) {
122                                // log.trace("treeNodesInserted: " + arg0);
123                        }
124
125                        @Override
126                        public void treeNodesRemoved(TreeModelEvent arg0) {
127                                log.trace("treeNodesRemoved: " + arg0);
128                        }
129
130                        @Override
131                        public void treeStructureChanged(TreeModelEvent arg0) {
132                                log.trace("treeStructureChanged: " + arg0);
133                        }
134                });
135
136                tree = new JTree(treeModel);
137                tree.setName("tree");
138                tree.setRootVisible(false);
139                tree.setExpandsSelectedPaths(true);
140                tree.setSelectionModel(new DefaultTreeSelectionModel());
141                ToolTipManager.sharedInstance().registerComponent(tree);
142
143                tree.addTreeSelectionListener(new TreeSelectionListener() {
144                        @Override
145                        public void valueChanged(TreeSelectionEvent e) {
146                                chooseTreeNode(e.getNewLeadSelectionPath());
147                        }
148                });
149
150                tree.setExpandsSelectedPaths(true);
151                tree.setEditable(false);
152                tree.setDoubleBuffered(true);
153                tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
154                tree.setShowsRootHandles(true);
155                tree.setRowHeight(26);
156                tree.setDoubleBuffered(true);
157                tree.addMouseListener(new MouseAdapter() {
158                        @Override
159                        public void mousePressed(MouseEvent e) {
160                                assert isActive();
161                                showPopup(e);
162                        }
163
164                        @Override
165                        public void mouseReleased(MouseEvent e) {
166                                assert isActive();
167                                showPopup(e);
168                        }
169                });
170
171                new KeyboardModifier(tree, JComponent.WHEN_FOCUSED)
172                        .join(KeyStroke.getKeyStroke('h'), KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0))
173                        .join(KeyStroke.getKeyStroke('j'), KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0))
174                        .join(KeyStroke.getKeyStroke('k'), KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0))
175                        .join(KeyStroke.getKeyStroke('l'), KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0))
176                        ;
177
178                tree.setCellRenderer(new TreeCellRenderer());
179
180                treeScrollPane = new JScrollPane(tree);
181                treeScrollPane.setBorder(BorderFactory.createEmptyBorder());
182
183                treePanel.add(treeScrollPane);
184
185                rootNode = new DefaultMutableTreeNode();
186                rootNode.setUserObject("root");
187                treeModel.setRoot(rootNode);
188
189                normalWorkPanel = new JPanel();
190                normalWorkPanel.setLayout(new BorderLayout());
191                normalWorkPanel.setName("browser");
192
193                mainPanel = new JPanel();
194                mainPanel.setName("main");
195                mainPanelLayout = new CardLayout();
196                mainPanel.setLayout(mainPanelLayout);
197                mainPanel.add(normalWorkPanel, "browser");
198
199                menuBar = new JMenuBar();
200
201                fileMenu = menuBar.add(new JMenu("File"));
202                editMenu = menuBar.add(new JMenu("Edit"));
203                viewMenu = menuBar.add(new JMenu("View"));
204                windowMenu = menuBar.add(new JMenu("Window"));
205                helpMenu = menuBar.add(new JMenu("Help"));
206
207                contentPane.add(menuBar, BorderLayout.NORTH);
208                contentPane.add(mainPanel, BorderLayout.CENTER);
209                contentPane.add(statusBar, BorderLayout.SOUTH);
210
211                leftPanel = new JPanel();
212                leftPanel.setLayout(new BorderLayout());
213                //leftPanel.add(new ViewerTest(), BorderLayout.PAGE_START);
214//        JPanel leftTopPanel = createLeftTopPanel();
215//        if (leftTopPanel != null) {
216//            leftPanel.add(leftTopPanel, BorderLayout.PAGE_START);
217//        }
218                leftPanel.add(treePanel, BorderLayout.CENTER);
219                leftPanel.setBackground(Color.WHITE);
220                leftPanel.setForeground(Color.WHITE);
221
222                cardPanel.setName("card");
223                JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, cardPanel);
224                split.setPreferredSize(browser.defaultFrameDimension);
225                split.setMaximumSize(screenDimension);
226                split.setOneTouchExpandable(true);
227                split.setDividerLocation(250);
228                split.setDividerSize(5);
229                split.setName("split");
230
231                normalWorkPanel.add(split);
232
233                //this.setVisible(true);
234                mainPanelLayout.show(mainPanel, "browser");
235
236                cardPanel.setLayout(cardPanelLayout);
237
238                this.pack();
239                tree.requestFocusInWindow();
240
241                log.debug("frame configured");
242
243        }
244
245        protected JPanel createLeftTopPanel() {
246                return null;
247        }
248
249        public void addRootPath(BrowserEndpoint endpoint, Path path) {
250                assert isActive();
251                assert !endpoints.containsKey(endpoint);
252
253                EndpointAtFrame e = new EndpointAtFrame(endpoint, this);
254                endpoint.getInstance().addListener(e);
255                endpoints.put(endpoint, e);
256                endpointsByInstance.put(endpoint.getInstance(), e);
257                TreeNode node = new TreeNode(e, path);
258                e.rootTreeNode = node;
259                treeModel.insertNodeInto(node, rootNode, rootNode.getChildCount());
260                tree.expandPath(new TreePath(rootNode));
261        }
262
263        @Override
264        public boolean isActive() {
265                return SwingDispatcher.instance.isActive();
266        }
267
268        @Override
269        public void invokeLater(Runnable runnable) {
270                SwingDispatcher.instance.invokeLater(runnable);
271        }
272
273        public Action addActionToTreePopupMenu(Action action) {
274                assert isActive();
275                treePopupMenu.add(action);
276                return action;
277        }
278
279        public Action addNodeActionToTreePopupMenu(String title, final NodeAction nodeAction) {
280                assert isActive();
281                return addActionToTreePopupMenu(new AbstractAction(title) {
282                        @Override
283                        public void actionPerformed(ActionEvent e) {
284                                TreeNode treeNode = getCurrentlyPoppedTreeNode();
285                                if (treeNode == null) {
286                                        return;
287                                }
288                                nodeAction.actionPerformed(treeNode);
289                        }
290                });
291        }
292
293        public void showPanel(Panel panel) {
294                assert isActive();
295                assert panel != null;
296                cardPanelLayout.show(cardPanel, panel.getUniqueName());
297        }
298
299
300        private void showPopup(MouseEvent e) {
301                assert isActive();
302                if (!e.isPopupTrigger()) {
303                        return;
304                }
305                currentlyPoppedTreeNode = findTreeNodeByTreePath(tree.getPathForLocation(e.getX(), e.getY()));
306                if (currentlyPoppedTreeNode == null) {
307                        return;
308                }
309                treePopupMenu.show(e.getComponent(), e.getX(), e.getY());
310                //currentlyPoppedPanel.getNode().getFramsClass().getName()
311                //treePopupMenuHeader.setText(currentlyPoppedTreeNode.getNode().getPath());
312        }
313
314        public TreeNode getCurrentlyPoppedTreeNode() {
315                assert isActive();
316                return currentlyPoppedTreeNode;
317        }
318
319
320        public void clear() {
321                treeModel.setRoot(null);
322                cardPanel.removeAll();
323                cardPanel.updateUI();
324                tree.setEnabled(false);
325        }
326
327        public Runnable startChange(final DefaultMutableTreeNode node) {
328                assert isActive();
329                final TreePath selection = tree.getSelectionPath();
330                return new Runnable() {
331                        @Override
332                        public void run() {
333                                assert isActive();
334                                treeModel.nodeChanged(node);
335                                tree.setSelectionPath(selection);
336                        }
337                };
338        }
339
340        public void selectTreeNode(final TreeNode treeNode) {
341                assert isActive();
342/*              final Panel panel = treeNode.getOrCreatePanel();
343                if (panel == null) {
344                        return;
345                }
346                panel.setCurrentTreeNode(treeNode);
347                treeNode.updateData();
348                showPanel(panel);*/
349        }
350
351        public TreeNode findTreeNodeByTreePath(TreePath treePath) {
352                assert isActive();
353                if (treePath == null) {
354                        return null;
355                }
356                if (!(treePath.getLastPathComponent() instanceof TreeNode)) {
357                        return null;
358                }
359                return (TreeNode)treePath.getLastPathComponent();
360        }
361
362        public void chooseTreeNode(TreePath treePath) {
363                assert isActive();
364                final TreeNode treeNode = findTreeNodeByTreePath(treePath);
365                if (treeNode == null) {
366                        return;
367                }
368                treeNode.select();
369        }
370
371        public void goTo(Path path) {
372                assert isActive();
373                final TreePath treePath = endpointsByInstance.get(path.getInstance()).getTreePath(path, false);
374                log.info("go to path: " + path + "(" + treePath + ")");
375                invokeLater(new Runnable() {
376                        @Override
377                        public void run() {
378                                tree.setSelectionPath(treePath);
379                                tree.makeVisible(treePath);
380                                assert tree.isVisible(treePath);
381                        }
382
383                });
384        }
385
386
387        public void addNode(TreeNode child, DefaultMutableTreeNode parent) {
388                assert isActive();
389                Runnable r = startChange(parent);
390                treeModel.insertNodeInto(child, parent, parent.getChildCount());
391                r.run();
392        }
393
394        @Override
395        public String toString() {
396                return getTitle() + "@" + browser.getName();
397        }
398
399}
Note: See TracBrowser for help on using the repository browser.