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
RevLine 
[77]1package com.framsticks.gui;
2
[88]3import com.framsticks.core.Entity;
[84]4import com.framsticks.core.Instance;
[77]5import com.framsticks.core.Path;
6import com.framsticks.gui.view.*;
7import com.framsticks.gui.view.TreeCellRenderer;
[84]8import com.framsticks.util.dispatching.Dispatcher;
[88]9import com.framsticks.util.dispatching.JoinableCollection;
[85]10import com.framsticks.util.lang.ScopeEnd;
[84]11import com.framsticks.util.swing.KeyboardModifier;
[88]12import com.framsticks.util.swing.MenuConstructor;
13
[77]14import org.apache.log4j.Logger;
15
16import javax.swing.*;
[84]17import javax.swing.event.TreeModelEvent;
18import javax.swing.event.TreeModelListener;
[77]19import javax.swing.event.TreeSelectionEvent;
20import javax.swing.event.TreeSelectionListener;
21import javax.swing.tree.*;
[84]22
[77]23import java.awt.*;
[78]24import java.awt.datatransfer.StringSelection;
[84]25import java.awt.event.*;
[77]26import java.util.HashMap;
27import java.util.Map;
[85]28import com.framsticks.util.dispatching.RunAt;
[77]29
30/**
31 * @author Piotr Sniegowski
32 */
[84]33@SuppressWarnings("serial")
[88]34public class Frame extends JoinableCollection<Instance> implements Entity, Dispatcher<Frame> {
[77]35
[84]36        private static final Logger log = Logger.getLogger(Frame.class.getName());
[77]37
[84]38        protected final Browser browser;
[77]39
[88]40        protected final Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
[77]41
[88]42        protected CardLayout cardPanelLayout;
43        protected JPanel cardPanel;
[77]44
[88]45        protected final String title;
46        protected JFrame swing;
[84]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;
[77]55
[84]56        TreeNode currentlyPoppedTreeNode;
57        protected JLabel statusBar;
58        protected JPanel mainPanel;
59        protected JPanel leftPanel;
60        protected JPanel normalWorkPanel;
61        protected CardLayout mainPanelLayout;
[77]62
[84]63        protected JMenuBar menuBar;
64        protected JMenu fileMenu;
65        protected JMenu editMenu;
66        protected JMenu viewMenu;
67        protected JMenu windowMenu;
68        protected JMenu helpMenu;
[77]69
[88]70        protected final Map<Instance, InstanceAtFrame> instancesAtFrames = new HashMap<Instance, InstanceAtFrame>();
[77]71
[84]72        public Frame(String title, Browser browser) {
[88]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                });
[84]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);
[77]92
[88]93                statusBar = new JLabel("not connected");
[77]94
[88]95                Container contentPane = swing.getContentPane();
[84]96                contentPane.setLayout(new BorderLayout());
[77]97
[84]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
[77]109
[84]110                treePopupMenu.add(new JMenuItem("Refresh"));
111                treePopupMenu.add(new JMenuItem("Open in new frame as root"));
[88]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                });
[84]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
[78]129                        @Override
[84]130                        public void treeNodesChanged(TreeModelEvent arg0) {
131                                log.trace("treeNodesChanged: " + arg0);
[78]132                        }
[77]133
[84]134                        @Override
135                        public void treeNodesInserted(TreeModelEvent arg0) {
136                                // log.trace("treeNodesInserted: " + arg0);
137                        }
[77]138
[84]139                        @Override
140                        public void treeNodesRemoved(TreeModelEvent arg0) {
141                                log.trace("treeNodesRemoved: " + arg0);
142                        }
[77]143
[84]144                        @Override
145                        public void treeStructureChanged(TreeModelEvent arg0) {
146                                log.trace("treeStructureChanged: " + arg0);
147                        }
148                });
[77]149
[84]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);
[77]156
[84]157                tree.addTreeSelectionListener(new TreeSelectionListener() {
158                        @Override
159                        public void valueChanged(TreeSelectionEvent e) {
160                                chooseTreeNode(e.getNewLeadSelectionPath());
161                        }
162                });
[77]163
[84]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                        }
[77]177
[84]178                        @Override
179                        public void mouseReleased(MouseEvent e) {
180                                assert isActive();
181                                showPopup(e);
182                        }
183                });
[77]184
[88]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));
[77]186
[84]187                tree.setCellRenderer(new TreeCellRenderer());
[77]188
[84]189                treeScrollPane = new JScrollPane(tree);
190                treeScrollPane.setBorder(BorderFactory.createEmptyBorder());
[77]191
[84]192                treePanel.add(treeScrollPane);
[77]193
[84]194                rootNode = new DefaultMutableTreeNode();
195                rootNode.setUserObject("root");
196                treeModel.setRoot(rootNode);
[77]197
[84]198                normalWorkPanel = new JPanel();
199                normalWorkPanel.setLayout(new BorderLayout());
200                normalWorkPanel.setName("browser");
[77]201
[84]202                mainPanel = new JPanel();
203                mainPanel.setName("main");
204                mainPanelLayout = new CardLayout();
205                mainPanel.setLayout(mainPanelLayout);
206                mainPanel.add(normalWorkPanel, "browser");
[77]207
[84]208                menuBar = new JMenuBar();
[77]209
[84]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"));
[77]215
[84]216                contentPane.add(menuBar, BorderLayout.NORTH);
217                contentPane.add(mainPanel, BorderLayout.CENTER);
218                contentPane.add(statusBar, BorderLayout.SOUTH);
[77]219
[84]220                leftPanel = new JPanel();
221                leftPanel.setLayout(new BorderLayout());
222                //leftPanel.add(new ViewerTest(), BorderLayout.PAGE_START);
[88]223                //        JPanel leftTopPanel = createLeftTopPanel();
224                //        if (leftTopPanel != null) {
225                //            leftPanel.add(leftTopPanel, BorderLayout.PAGE_START);
226                //        }
[84]227                leftPanel.add(treePanel, BorderLayout.CENTER);
228                leftPanel.setBackground(Color.WHITE);
229                leftPanel.setForeground(Color.WHITE);
[77]230
[88]231                cardPanel = new JPanel();
[84]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");
[77]240
[84]241                normalWorkPanel.add(split);
[77]242
[84]243                //this.setVisible(true);
244                mainPanelLayout.show(mainPanel, "browser");
[77]245
[88]246                cardPanelLayout = new CardLayout();
[84]247                cardPanel.setLayout(cardPanelLayout);
[77]248
[88]249                swing.pack();
[84]250                tree.requestFocusInWindow();
[77]251
[88]252                log.debug("frame configured: " + this);
[77]253
[88]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
[84]261        }
[77]262
[84]263        protected JPanel createLeftTopPanel() {
264                return null;
265        }
[77]266
[88]267        public void addRootPath(Path path) {
[84]268                assert isActive();
[88]269                Instance instance = path.getInstance();
270                assert browser.getInstances().containsValue(instance);
[77]271
[88]272                InstanceAtFrame e = new InstanceAtFrame(instance, this);
273                instance.addListener(e);
274                instancesAtFrames.put(instance, e);
[84]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        }
[77]280
[84]281        @Override
282        public boolean isActive() {
283                return SwingDispatcher.instance.isActive();
284        }
[77]285
[84]286        @Override
[85]287        public void invokeLater(RunAt<? extends Frame> runnable) {
288                SwingDispatcher.getInstance().invokeLater(runnable);
[84]289        }
[77]290
[84]291        public Action addActionToTreePopupMenu(Action action) {
292                assert isActive();
293                treePopupMenu.add(action);
294                return action;
295        }
[77]296
[84]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        }
[77]310
[84]311        public void showPanel(Panel panel) {
312                assert isActive();
313                assert panel != null;
314                cardPanelLayout.show(cardPanel, panel.getUniqueName());
315        }
[77]316
[84]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        }
[77]330
[88]331        /**
332         * @return the swing
333         */
334        public JFrame getSwing() {
335                return swing;
336        }
337
[84]338        public TreeNode getCurrentlyPoppedTreeNode() {
339                assert isActive();
340                return currentlyPoppedTreeNode;
341        }
[77]342
[84]343        public void clear() {
344                treeModel.setRoot(null);
345                cardPanel.removeAll();
346                cardPanel.updateUI();
347                tree.setEnabled(false);
348        }
[77]349
[85]350        public ScopeEnd startChange(final DefaultMutableTreeNode node) {
[84]351                assert isActive();
352                final TreePath selection = tree.getSelectionPath();
[85]353                return new ScopeEnd() {
[84]354                        @Override
[85]355                        public void close() {
[84]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();
[88]365                /*              final Panel panel = treeNode.getOrCreatePanel();
366                 if (panel == null) {
367                 return;
368                 }
369                 panel.setCurrentTreeNode(treeNode);
370                 treeNode.updateData();
371                 showPanel(panel);*/
[84]372        }
[77]373
[84]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                }
[88]382                return (TreeNode) treePath.getLastPathComponent();
[84]383        }
[77]384
[84]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        }
[77]393
[84]394        public void goTo(Path path) {
395                assert isActive();
[88]396                final TreePath treePath = instancesAtFrames.get(path.getInstance()).getTreePath(path, false);
[84]397                log.info("go to path: " + path + "(" + treePath + ")");
[85]398
399                new RunAt<Frame>(this) {
[84]400                        @Override
401                        public void run() {
[85]402                                log.info("executed");
[84]403                                tree.setSelectionPath(treePath);
404                                tree.makeVisible(treePath);
405                                assert tree.isVisible(treePath);
406                        }
[85]407                };
[77]408
[84]409        }
[77]410
[84]411        public void addNode(TreeNode child, DefaultMutableTreeNode parent) {
412                assert isActive();
[85]413
414                try (ScopeEnd e = startChange(parent)) {
415                        treeModel.insertNodeInto(child, parent, parent.getChildCount());
416                }
[84]417        }
418
419        @Override
420        public String toString() {
[88]421                return title + "@" + browser.getName();
[84]422        }
423
[88]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
[77]456}
Note: See TracBrowser for help on using the repository browser.