From: gmungoc Date: Thu, 12 Feb 2015 09:33:05 +0000 (+0000) Subject: Merge remote-tracking branch 'origin/merge/JAL-845_JAL-1640' into X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=d10280f7592e21f1ed4d1030d3ece3e95f3b385b;p=jalview.git Merge remote-tracking branch 'origin/merge/JAL-845_JAL-1640' into features/JAL-845splitPaneMergeDevelop Conflicts: src/jalview/gui/Desktop.java --- d10280f7592e21f1ed4d1030d3ece3e95f3b385b diff --cc .classpath index f34aa90,6abc315..c3e70c0 --- a/.classpath +++ b/.classpath @@@ -52,8 -55,6 +55,7 @@@ - - + + diff --cc src/jalview/gui/AlignFrame.java index 9f79999,d5f34b3..d613ea7 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@@ -2721,7 -2820,7 +2778,7 @@@ public class AlignFrame extends GAlignF newap.av.getAlignment().deleteAllAnnotations(false); } -- newap.av.gatherViewsHere = false; ++ newap.av.setGatherViewsHere(false); if (viewport.viewName == null) { @@@ -2744,7 -2843,7 +2801,7 @@@ if (alignPanels.size() == 2) { -- viewport.gatherViewsHere = true; ++ viewport.setGatherViewsHere(true); } tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1); return newap; diff --cc src/jalview/gui/AlignViewport.java index deba021,feeb694..6208597 --- a/src/jalview/gui/AlignViewport.java +++ b/src/jalview/gui/AlignViewport.java @@@ -135,11 -106,11 +106,11 @@@ public class AlignViewport extends Alig boolean antiAlias = false; -- Rectangle explodedPosition; ++ private Rectangle explodedGeometry; String viewName; -- boolean gatherViewsHere = false; ++ private boolean gatherViewsHere = false; private Deque historyList = new ArrayDeque(); @@@ -1520,4 -1189,19 +1187,39 @@@ { this.annotationColumnSelectionState = currentAnnotationColumnSelectionState; } + + @Override + public void setIdWidth(int i) + { + super.setIdWidth(i); + AlignmentPanel ap = getAlignPanel(); + if (ap != null) + { + // modify GUI elements to reflect geometry change + Dimension idw = getAlignPanel().getIdPanel().getIdCanvas() + .getPreferredSize(); + idw.width = i; + getAlignPanel().getIdPanel().getIdCanvas().setPreferredSize(idw); + } + } ++ ++ public Rectangle getExplodedGeometry() ++ { ++ return explodedGeometry; ++ } ++ ++ public void setExplodedGeometry(Rectangle explodedPosition) ++ { ++ this.explodedGeometry = explodedPosition; ++ } ++ ++ public boolean isGatherViewsHere() ++ { ++ return gatherViewsHere; ++ } ++ ++ public void setGatherViewsHere(boolean gatherViewsHere) ++ { ++ this.gatherViewsHere = gatherViewsHere; ++ } } diff --cc src/jalview/gui/Desktop.java index cb6bc6e,7852253..4beacd9 --- a/src/jalview/gui/Desktop.java +++ b/src/jalview/gui/Desktop.java @@@ -20,13 -20,13 +20,15 @@@ */ package jalview.gui; + import jalview.api.AlignViewportI; +import jalview.api.AlignmentViewPanel; import jalview.bin.Cache; import jalview.io.FileLoader; import jalview.io.FormatAdapter; import jalview.io.IdentifyFile; import jalview.io.JalviewFileChooser; import jalview.io.JalviewFileView; ++import jalview.jbgui.GSplitFrame; import jalview.jbgui.GStructureViewer; import jalview.structure.StructureSelectionManager; import jalview.util.ImageMaker; @@@ -1719,14 -1719,14 +1722,6 @@@ public class Desktop extends jalview.jb aps.add(ap); } } -- // for (int a = 0; a < af.alignPanels.size(); a++) -- // { -- // if (alignmentId.equals(af.alignPanels -- // .get(a).av.getSequenceSetId())) -- // { -- // aps.add(af.alignPanels.get(a)); -- // } -- // } } if (aps.size() == 0) { @@@ -1795,13 -1792,13 +1792,19 @@@ { AlignmentPanel ap = af.alignPanels.get(i); AlignFrame newaf = new AlignFrame(ap); -- if (ap.av.explodedPosition != null -- && !ap.av.explodedPosition.equals(af.getBounds())) ++ ++ /* ++ * Restore the view's last exploded frame geometry if known. Multiple ++ * views from one exploded frame share and restore the same (frame) ++ * position and size. ++ */ ++ Rectangle geometry = ap.av.getExplodedGeometry(); ++ if (geometry != null) { -- newaf.setBounds(ap.av.explodedPosition); ++ newaf.setBounds(geometry); } -- ap.av.gatherViewsHere = false; ++ ap.av.setGatherViewsHere(false); addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); @@@ -1812,18 -1809,10 +1815,18 @@@ } + /** + * Gather expanded views (separate AlignFrame's) with the same sequence set + * identifier back in to this frame as additional views, and close the + * expanded views. Note the expanded frames may themselves have multiple + * views. We take the lot. + * + * @param source + */ public void gatherViews(AlignFrame source) { -- source.viewport.gatherViewsHere = true; -- source.viewport.explodedPosition = source.getBounds(); ++ source.viewport.setGatherViewsHere(true); ++ source.viewport.setExplodedGeometry(source.getBounds()); JInternalFrame[] frames = desktop.getAllFrames(); String viewId = source.viewport.getSequenceSetId(); @@@ -1839,8 -1828,8 +1842,8 @@@ if (viewId.equals(ap.av.getSequenceSetId())) { gatherThis = true; -- ap.av.gatherViewsHere = false; -- ap.av.explodedPosition = af.getBounds(); ++ ap.av.setGatherViewsHere(false); ++ ap.av.setExplodedGeometry(af.getBounds()); source.addAlignmentPanel(ap, false); } } @@@ -2380,14 -2358,14 +2383,14 @@@ /* * Also check for a split frame containing an AlignFrame */ -- SplitFrame sf = (SplitFrame) frames[i]; - if (sf.getTopComponent() instanceof AlignFrame) ++ GSplitFrame sf = (GSplitFrame) frames[i]; + if (sf.getTopFrame() instanceof AlignFrame) { - avp.add((AlignFrame) sf.getTopComponent()); + avp.add((AlignFrame) sf.getTopFrame()); } - if (sf.getBottomComponent() instanceof AlignFrame) + if (sf.getBottomFrame() instanceof AlignFrame) { - avp.add((AlignFrame) sf.getBottomComponent()); + avp.add((AlignFrame) sf.getBottomFrame()); } } } @@@ -2554,13 -2527,13 +2557,13 @@@ } /** - * This will return the first AlignFrame viewing AlignViewport av. It will - * break if there are more than one AlignFrames viewing a particular av. - * This will return the AlignFrame holding the given viewport instance. It ++ * This will return the first AlignFrame holding the given viewport instance. It + * will break if there are more than one AlignFrames viewing a particular av. * - * @param av - * @return alignFrame for av + * @param viewport + * @return alignFrame for viewport */ - public static AlignFrame getAlignFrameFor(AlignmentViewport av) + public static AlignFrame getAlignFrameFor(AlignViewportI viewport) { if (desktop != null) { @@@ -2936,127 -2907,9 +2940,134 @@@ im.writeImage(); } catch (Exception q) { - Cache.log.error("Couldn't write snapshot to "+of.getAbsolutePath(),q); + Cache.log.error("Couldn't write snapshot to " + of.getAbsolutePath(), + q); + return; + } + Cache.log.info("Successfully written snapshot to file " + + of.getAbsolutePath()); + } + + /** - * Explode the views in the given frame into separate AlignFrame ++ * Explode the views in the given frame into separate AlignFrame windows. + * + * @param sf + */ + public void explodeViews(SplitFrame sf) + { + AlignFrame oldTopFrame = (AlignFrame) sf.getTopFrame(); + AlignFrame oldBottomFrame = (AlignFrame) sf.getBottomFrame(); + List topPanels = oldTopFrame + .getAlignPanels(); + List bottomPanels = oldBottomFrame + .getAlignPanels(); + int viewCount = topPanels.size(); + if (viewCount < 2) + { return; } - Cache.log.info("Successfully written snapshot to file "+of.getAbsolutePath()); + + /* + * Processing in reverse order works, forwards order leaves the first panels + * not visible. I don't know why! + */ + for (int i = viewCount - 1; i >= 0; i--) + { + /* + * Make new top and bottom frames. These take over the respective + * AlignmentPanel objects, including their AlignmentViewports, so the + * cdna/protein relationships between the viewports is carried over to the + * new split frames. + */ - AlignFrame newTopFrame = new AlignFrame( - (AlignmentPanel) topPanels.get(i)); ++ AlignmentViewPanel topPanel = topPanels.get(i); ++ AlignFrame newTopFrame = new AlignFrame((AlignmentPanel) topPanel); + newTopFrame.setVisible(true); - AlignFrame newBottomFrame = new AlignFrame( - (AlignmentPanel) bottomPanels.get(i)); ++ AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i); ++ AlignFrame newBottomFrame = new AlignFrame(bottomPanel); + newBottomFrame.setVisible(true); + JInternalFrame splitFrame = new SplitFrame(newTopFrame, + newBottomFrame); ++ // either panel may hold previous exploded frame geometry ++ Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport()) ++ .getExplodedGeometry(); ++ if (geometry != null) ++ { ++ splitFrame.setBounds(geometry); ++ } + Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1); + - // if (ap.av.explodedPosition != null - // && !ap.av.explodedPosition.equals(af.getBounds())) - // { - // newaf.setBounds(ap.av.explodedPosition); - // } + // + // ap.av.gatherViewsHere = false; + } + + /* + * Clear references to the panels (now relocated in the new SplitFrames) + * before closing the old SplitFrame. + */ + topPanels.clear(); + bottomPanels.clear(); + sf.close(); + } + + /** + * Gather expanded split frames, sharing the same pairs of sequence set ids, + * back into the given SplitFrame as additional views. Note that the gathered + * frames may themselves have multiple views. + * + * @param source + */ - public void gatherViews(SplitFrame source) ++ public void gatherViews(GSplitFrame source) + { - // source.viewport.gatherViewsHere = true; - // source.viewport.explodedPosition = source.getBounds(); + AlignFrame myTopFrame = (AlignFrame) source.getTopFrame(); + AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame(); ++ myTopFrame.viewport.setExplodedGeometry(source.getBounds()); ++ myBottomFrame.viewport.setExplodedGeometry(source.getBounds()); ++ myTopFrame.viewport.setGatherViewsHere(true); ++ myBottomFrame.viewport.setGatherViewsHere(true); + String topViewId = myTopFrame.viewport.getSequenceSetId(); + String bottomViewId = myBottomFrame.viewport.getSequenceSetId(); + + JInternalFrame[] frames = desktop.getAllFrames(); + for (JInternalFrame frame : frames) + { + if (frame instanceof SplitFrame && frame != source) + { + SplitFrame sf = (SplitFrame) frame; + AlignFrame topFrame = (AlignFrame) sf.getTopFrame(); + AlignFrame bottomFrame = (AlignFrame) sf.getBottomFrame(); + boolean gatherThis = false; + for (int a = 0; a < topFrame.alignPanels.size(); a++) + { + AlignmentPanel topPanel = topFrame.alignPanels.get(a); + AlignmentPanel bottomPanel = bottomFrame.alignPanels.get(a); + if (topViewId.equals(topPanel.av.getSequenceSetId()) + && bottomViewId.equals(bottomPanel.av.getSequenceSetId())) + { + gatherThis = true; - topPanel.av.gatherViewsHere = false; - bottomPanel.av.gatherViewsHere = false; - // topPanel.av.explodedPosition = af.getBounds(); ++ topPanel.av.setGatherViewsHere(false); ++ bottomPanel.av.setGatherViewsHere(false); ++ // both panels refer to the same split frame geometry ++ Rectangle position = sf.getBounds(); ++ topPanel.av.setExplodedGeometry(position); ++ bottomPanel.av.setExplodedGeometry(position); + myTopFrame.addAlignmentPanel(topPanel, false); + myBottomFrame.addAlignmentPanel(bottomPanel, false); + } + } + + if (gatherThis) + { + topFrame.getAlignPanels().clear(); + bottomFrame.getAlignPanels().clear(); + sf.close(); + } + } + } + + /* + * The dust settles...give focus to the tab we did this from. + */ + myTopFrame.setDisplayedView(myTopFrame.alignPanel); + } } diff --cc src/jalview/gui/Jalview2XML.java index 917b6d9,6186323..e1d1925 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@@ -1043,14 -1043,14 +1043,15 @@@ public class Jalview2XM av.getSequenceSetId())); view.setId(av.getViewId()); view.setViewName(av.viewName); -- view.setGatheredViews(av.gatherViewsHere); ++ view.setGatheredViews(av.isGatherViewsHere()); -- if (ap.av.explodedPosition != null) ++ Rectangle position = ap.av.getExplodedGeometry(); ++ if (position != null) { -- view.setXpos(av.explodedPosition.x); -- view.setYpos(av.explodedPosition.y); -- view.setWidth(av.explodedPosition.width); -- view.setHeight(av.explodedPosition.height); ++ view.setXpos(position.x); ++ view.setYpos(position.y); ++ view.setWidth(position.width); ++ view.setHeight(position.height); } else { @@@ -2078,7 -2078,7 +2079,7 @@@ if (object.getJalviewModelSequence().getViewportCount() > 0) { af = _af; -- if (af.viewport.gatherViewsHere) ++ if (af.viewport.isGatherViewsHere()) { gatherToThisFrame.put(af.viewport.getSequenceSetId(), af); } @@@ -3599,7 -3599,7 +3600,7 @@@ .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour())); } -- af.viewport.gatherViewsHere = view.getGatheredViews(); ++ af.viewport.setGatherViewsHere(view.getGatheredViews()); if (view.getSequenceSetId() != null) { diff --cc src/jalview/gui/SplitFrame.java index ab4596e,f98eea7..486db47 --- a/src/jalview/gui/SplitFrame.java +++ b/src/jalview/gui/SplitFrame.java @@@ -1,14 -1,11 +1,11 @@@ package jalview.gui; +import jalview.jbgui.GAlignFrame; import jalview.jbgui.GSplitFrame; +import jalview.structure.StructureSelectionManager; import java.awt.Component; --import java.awt.MouseInfo; --import java.awt.Point; --import java.awt.Rectangle; +import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; @@@ -118,240 -108,72 +115,216 @@@ public class SplitFrame extends GSplitF } /** - * Returns the split pane component the mouse is in, or null if neither. + * Returns true if the key event is overriden and actioned (or ignored) here, + * else returns false, indicating it should be delegated to the AlignFrame's + * usual handler. + *

+ * We can't handle Cmd-Key combinations here, instead this is done by + * overriding key bindings. * + * @see addKeyOverrides + * @param e + * @param af * @return */ - protected Component getComponentAtMouse() + protected boolean overrideKey(KeyEvent e, AlignFrame af) { - Point loc = MouseInfo.getPointerInfo().getLocation(); - - if (isIn(loc, getTopComponent())) { - return getTopComponent(); - } - else if (isIn(loc, getBottomComponent())) + boolean actioned = false; + int keyCode = e.getKeyCode(); + switch (keyCode) { - return getBottomComponent(); + case KeyEvent.VK_DOWN: + if (e.isAltDown() || !af.viewport.cursorMode) + { + /* + * Key down (or Alt-key-down in cursor mode) - move selected sequences + */ + ((AlignFrame) getTopFrame()).moveSelectedSequences(false); + ((AlignFrame) getBottomFrame()).moveSelectedSequences(false); + actioned = true; + e.consume(); + } + break; + case KeyEvent.VK_UP: + if (e.isAltDown() || !af.viewport.cursorMode) + { + /* + * Key up (or Alt-key-up in cursor mode) - move selected sequences + */ + ((AlignFrame) getTopFrame()).moveSelectedSequences(true); + ((AlignFrame) getBottomFrame()).moveSelectedSequences(true); + actioned = true; + e.consume(); + } + default: } - return null; + return actioned; } - private boolean isIn(Point loc, JComponent comp) + /** - * Returns the split pane component the mouse is in, or null if neither. - * - * @return - */ - protected GAlignFrame getFrameAtMouse() - { - Point loc = MouseInfo.getPointerInfo().getLocation(); - - if (isIn(loc, getTopFrame())) - { - return getTopFrame(); - } - else if (isIn(loc, getBottomFrame())) - { - return getBottomFrame(); - } - return null; - } - - private boolean isIn(Point loc, JComponent comp) - { - Point p = comp.getLocationOnScreen(); - Rectangle r = new Rectangle(p.x, p.y, comp.getWidth(), comp.getHeight()); - return r.contains(loc); - } - - /** + * Set key bindings (recommended for Swing over key accelerators). + */ + private void addKeyBindings() { - Point p = comp.getLocationOnScreen(); - Rectangle r = new Rectangle(p.x, p.y, comp.getWidth(), comp.getHeight()); - return r.contains(loc); + overrideDelegatedKeyBindings(); + + overrideImplementedKeyBindings(); } /** - * Set key bindings (recommended for Swing over key accelerators). For now, - * delegate to the corresponding key accelerator for the AlignFrame that the - * mouse is in. Hopefully can be simplified in future if AlignFrame is changed - * to use key bindings rather than accelerators. + * Override key bindings with alternative action methods implemented in this + * class. */ - private void addKeyBindings() + protected void overrideImplementedKeyBindings() + { + overrideNewView(); + overrideCloseView(); + overrideExpandViews(); + overrideGatherViews(); + } + + /** + * Replace Cmd-W close view action with our version. + */ + protected void overrideCloseView() + { + AbstractAction action; + /* + * Ctrl-W / Cmd-W - close view or window + */ + KeyStroke key_cmdW = KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit + .getDefaultToolkit().getMenuShortcutKeyMask(), false); + action = new AbstractAction() + { + @Override + public void actionPerformed(ActionEvent e) + { + closeView_actionPerformed(); + } + }; + overrideKeyBinding(key_cmdW, action); + } + + /** + * Replace Cmd-T new view action with our version. + */ + protected void overrideNewView() + { + /* + * Ctrl-T / Cmd-T open new view + */ + KeyStroke key_cmdT = KeyStroke.getKeyStroke(KeyEvent.VK_T, Toolkit + .getDefaultToolkit().getMenuShortcutKeyMask(), false); + AbstractAction action = new AbstractAction() + { + @Override + public void actionPerformed(ActionEvent e) + { + newView_actionPerformed(); + } + }; + overrideKeyBinding(key_cmdT, action); + } + + /** + * For now, delegates key events to the corresponding key accelerator for the + * AlignFrame that the mouse is in. Hopefully can be simplified in future if + * AlignFrame is changed to use key bindings rather than accelerators. + */ + protected void overrideDelegatedKeyBindings() { - if (getTopComponent() instanceof AlignFrame) + if (getTopFrame() instanceof AlignFrame) { - for (Entry acc : ((AlignFrame) getTopComponent()) + /* + * Get all accelerator keys in the top frame (the bottom should be + * identical) and override each one. + */ + for (Entry acc : ((AlignFrame) getTopFrame()) .getAccelerators().entrySet()) { + overrideKeyBinding(acc); + } + } + } - final KeyStroke ks = acc.getKey(); - this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, ks); - this.getActionMap().put(ks, new AbstractAction() + /** + * Overrides an AlignFrame key accelerator with our version which delegates to + * the action listener in whichever frame has the mouse (and does nothing if + * neither has). + * + * @param acc + */ + private void overrideKeyBinding(Entry acc) + { + final KeyStroke ks = acc.getKey(); + InputMap inputMap = this.getInputMap(JComponent.WHEN_FOCUSED); + inputMap.put(ks, ks); + this.getActionMap().put(ks, new AbstractAction() + { + @Override + public void actionPerformed(ActionEvent e) + { + Component c = getFrameAtMouse(); + if (c != null && c instanceof AlignFrame) { - @Override - public void actionPerformed(ActionEvent e) + for (ActionListener a : ((AlignFrame) c).getAccelerators() + .get(ks).getActionListeners()) { - Component c = getComponentAtMouse(); - if (c instanceof AlignFrame) - { - for (ActionListener a : ((AlignFrame) c).getAccelerators() - .get(ks).getActionListeners()) - { - - a.actionPerformed(null); - } - } + a.actionPerformed(null); } - }); + } } - /* - * Disable unwanted here - */ - // X expand views - wrecks the split pane view - KeyStroke key_X = KeyStroke.getKeyStroke(KeyEvent.VK_X, 0, false); - disableAccelerator(key_X); + }); + } + + /** + * Replace an accelerator key's action with the specified action. + * + * @param ks + */ + protected void overrideKeyBinding(KeyStroke ks, AbstractAction action) + { + this.getActionMap().put(ks, action); + overrideMenuItem(ks, action); + } + + /** + * Create and link new views (with matching names) in both panes. + *

+ * Note this is _not_ multiple tabs, each hosting a split pane view, rather it + * is a single split pane with each split holding multiple tabs which are + * linked in pairs. ++ *

++ * TODO implement instead with a tabbed holder in the SplitView, each tab ++ * holding a single JSplitPane. Would avoid a duplicated tab, at the cost of ++ * some additional coding. + */ + protected void newView_actionPerformed() + { - System.out.println("newView " + this.hashCode()); + AlignFrame topFrame = (AlignFrame) getTopFrame(); + AlignFrame bottomFrame = (AlignFrame) getBottomFrame(); + + AlignmentPanel newTopPanel = topFrame.newView(null, true); + AlignmentPanel newBottomPanel = bottomFrame.newView(null, true); + + /* + * This currently (for the first new view only) leaves the top pane on tab 0 + * but the bottom on tab 1. This results from 'setInitialTabVisible' echoing + * from the bottom back to the first frame. Next line is a fudge to work + * around this. TODO find a better way. + */ + if (topFrame.getTabIndex() != bottomFrame.getTabIndex()) + { + topFrame.setDisplayedView(newTopPanel); } + + newBottomPanel.av.viewName = newTopPanel.av.viewName; + newTopPanel.av.setCodingComplement(newBottomPanel.av); + + final StructureSelectionManager ssm = StructureSelectionManager + .getStructureSelectionManager(Desktop.instance); + ssm.addCommandListener(newTopPanel.av); + ssm.addCommandListener(newBottomPanel.av); } /** diff --cc src/jalview/jbgui/GAlignFrame.java index 2d23e6b,df930c4..4b36729 --- a/src/jalview/jbgui/GAlignFrame.java +++ b/src/jalview/jbgui/GAlignFrame.java @@@ -3253,15 -3253,4 +3253,20 @@@ public class GAlignFrame extends JInter { return this.accelerators; } + + /** + * Returns the selected index of the tabbed pane, or -1 if none selected + * (including the case where the tabbed pane has not been made visible). + * + * @return + */ + public int getTabIndex() + { + return tabbedPane.getSelectedIndex(); + } ++ ++ public JPanel getStatusPanel() ++ { ++ return statusPanel; ++ } } diff --cc src/jalview/jbgui/GSplitFrame.java index 40cce0d,281a93e..b2ecaeb --- a/src/jalview/jbgui/GSplitFrame.java +++ b/src/jalview/jbgui/GSplitFrame.java @@@ -1,42 -1,43 +1,114 @@@ package jalview.jbgui; -import javax.swing.JComponent; ++import jalview.util.Platform; ++ ++import java.awt.Component; ++import java.awt.MouseInfo; ++import java.awt.Point; ++import java.awt.Rectangle; ++ import javax.swing.JInternalFrame; import javax.swing.JSplitPane; ++import javax.swing.plaf.basic.BasicInternalFrameUI; public class GSplitFrame extends JInternalFrame { private static final long serialVersionUID = 1L; - private JComponent topComponent; + private GAlignFrame topFrame; - private JComponent bottomComponent; + private GAlignFrame bottomFrame; + ++ private JSplitPane splitPane; + /** * Constructor * * @param top * @param bottom */ - public GSplitFrame(JComponent top, JComponent bottom) + public GSplitFrame(GAlignFrame top, GAlignFrame bottom) + { + this.topFrame = top; + this.bottomFrame = bottom; - JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, top, - bottom); ++ ++ hideTitleBars(); ++ ++ addSplitPane(); ++ } ++ ++ /** ++ * Create and add the split pane containing the top and bottom components. ++ */ ++ protected void addSplitPane() + { - this.topComponent = top; - this.bottomComponent = bottom; - JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, top, - bottom); ++ splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topFrame, ++ bottomFrame); splitPane.setVisible(true); splitPane.setDividerLocation(0.5d); splitPane.setResizeWeight(0.5d); splitPane.setDividerSize(0); ++ add(splitPane); ++ } ++ ++ /** ++ * Try to hide the title bars as a waste of precious space. ++ * ++ * @see http ++ * ://stackoverflow.com/questions/7218971/java-method-works-on-windows ++ * -but-not-macintosh -java ++ */ ++ protected void hideTitleBars() ++ { ++ if (new Platform().isAMac()) ++ { ++ // this saves some space - but doesn't hide the title bar ++ topFrame.putClientProperty("JInternalFrame.isPalette", true); ++ // topFrame.getRootPane().putClientProperty("Window.style", "small"); ++ bottomFrame.putClientProperty("JInternalFrame.isPalette", true); ++ } ++ else ++ { ++ ((BasicInternalFrameUI) topFrame.getUI()).setNorthPane(null); ++ ((BasicInternalFrameUI) bottomFrame.getUI()).setNorthPane(null); ++ } + } + + public GAlignFrame getTopFrame() + { + return topFrame; } - public JComponent getTopComponent() + public GAlignFrame getBottomFrame() { - return topComponent; + return bottomFrame; } + - public JComponent getBottomComponent() ++ /** ++ * Returns the split pane component the mouse is in, or null if neither. ++ * ++ * @return ++ */ ++ protected GAlignFrame getFrameAtMouse() + { - return bottomComponent; ++ Point loc = MouseInfo.getPointerInfo().getLocation(); ++ ++ if (isIn(loc, splitPane.getTopComponent())) ++ { ++ return getTopFrame(); ++ } ++ else if (isIn(loc, splitPane.getBottomComponent())) ++ { ++ return getBottomFrame(); ++ } ++ return null; + } ++ ++ private boolean isIn(Point loc, Component comp) ++ { ++ Point p = comp.getLocationOnScreen(); ++ Rectangle r = new Rectangle(p.x, p.y, comp.getWidth(), comp.getHeight()); ++ return r.contains(loc); ++ } ++ }