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

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

HIGHLIGHTS:

  • loading f0 schema with XmlLoader?
  • use XmlLoader? to load configuration
  • introduce unified fork-join model of various entities

(Instances, Connections, GUI Frames, etc.),
all those entities clean up gracefully on
shutdown, which may be initialized by user
or by some entity

  • basing on above, simplify several organizing classes

(Observer, main class)

(to host native frams server process from Java level)

CHANGELOG:
Remove redundant Observer class.

Clean up in AbstractJoinable?.

Update ExternalProcess? class to changes in joining model.

Another sweep through code with FindBugs?.

Find bug with not joining RemoteInstance?.

Joining almost works.

Much improved joining model.

More improvement to joining model.

Add logging messages around joinable operations.

Rename methods in AbstractJoinable?.

Improve Joinable.

Rewrite of entity structure.

More simplifications with entities.

Further improve joinables.

Let Frame compose from JFrame instead of inheriting.

Add join classes.

Improvements of closing.

Add Builder interface.

Add FramsServerTest?.xml

FramsServer? may be configured through xml.

Make Framsticks main class an Observer of Entities.

Make Observer a generic type.

Remove variables regarding to removed endpoint.

Simplify observer (remove endpoints).

More changes to Observer and Endpoint.

Minor improvements.

Add OutputListener? to ExternalProcess?.

Improve testing of ExternalProcess?.

Add ExternalProcess? runner.

Rename the Program class to Framsticks.

Migrate Program to use XmlLoader? configuration.

First steps with configuration using XmlLoader?.

Fix several bugs.

Move all f0 classes to apriopriate package.

XmlLoader? is able to load Schema.

XmlLoader? is loading classes and props.

Add GroupBuilder?.

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