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

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

HIGHLIGHTS:

  • add proper exception passing between communication sides:

if exception occur during handling client request, it is
automatically passed as comment to error response.

it may be used to snoop communication between peers

  • fix algorithm choosing text controls in GUI
  • allow GUI testing in virtual frame buffer (xvfb)

FEST had some problem with xvfb but workaround was found

supports tab-completion based on requests history

CHANGELOG:
Further improve handling of exceptions in GUI.

Add StatusBar? implementing ExceptionResultHandler?.

Make completion processing asynchronous.

Minor changes.

Improve completion in console.

Improve history in InteractiveConsole?.

First working version of DirectConsole?.

Minor changes.

Make Connection.address non final.

It is more suitable to use in configuration.

Improvement of consoles.

Improve PopupMenu? and closing of FrameJoinable?.

Fix BrowserTest?.

Found bug with FEST running under xvfb.

JButtonFixture.click() is not working under xvfb.
GuiTest? has wrapper which uses JButton.doClick() directly.

Store CompositeParam? param in TreeNode?.

Simplify ClientSideManagedConnection? connecting.

There is now connectedFunctor needed, ApplicationRequests? can be
send right after creation. They are buffered until the version
and features are negotiated.

Narow down interface of ClientSideManagedConnection?.

Allow that connection specialization send only
ApplicationRequests?.

Improve policy of text control choosing.

Change name of Genotype in BrowserTest?.

Make BrowserTest? change name of Genotype.

Minor change.

First working draft of TrackConsole?.

Simplify Consoles.

More improvements with gui joinables.

Unify initialization on gui joinables.

More rework of Frame based entities.

Refactorize structure of JFrames based entities.

Extract GuiTest? from BrowserBaseTest?.

Reorganize Console classes structure.

Add Collection view to JoinableCollection?.

Configure timeout in testing.

Minor changes.

Rework connections hierarchy.

Add Mode to the get operation.

Make get and set in Tree take PrimitiveParam?.

Unify naming of operations.

Make RunAt? use the given ExceptionHandler?.

It wraps the virtual runAt() method call with
try-catch passing exception to handler.

Force RunAt? to include ExceptionHandler?.

Improve ClientAtServer?.

Minor change.

Another sweep with FindBugs?.

Rename Instance to Tree.

Minor changes.

Minor changes.

Further clarify semantics of Futures.

Add FutureHandler?.

FutureHandler? is refinement of Future, that proxifies
exception handling to ExceptionResultHandler? given
at construction time.

Remove StateFunctor? (use Future<Void> instead).

Make Connection use Future<Void>.

Unparametrize *ResponseFuture?.

Remove StateCallback? not needed anymore.

Distinguish between sides of ResponseFuture?.

Base ResponseCallback? on Future (now ResponseFuture?).

Make asynchronous store taking Future for flags.

Implement storeValue in ObjectInstance?.

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