j2sNative references moved to Platform
[jalview.git] / src / jalview / jbgui / GSplitFrame.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.jbgui;
22
23 import jalview.util.Platform;
24
25 import java.awt.Component;
26 import java.awt.MouseInfo;
27 import java.awt.Point;
28 import java.awt.Rectangle;
29
30 import javax.swing.JInternalFrame;
31 import javax.swing.JSplitPane;
32 import javax.swing.plaf.basic.BasicInternalFrameUI;
33
34 public class GSplitFrame extends JInternalFrame
35 {
36   protected static final int DIVIDER_SIZE = 5;
37
38   private static final long serialVersionUID = 1L;
39
40   private GAlignFrame topFrame;
41
42   private GAlignFrame bottomFrame;
43
44   private JSplitPane splitPane;
45
46   /*
47    * proportional position of split divider; saving this allows it to be
48    * restored after hiding one half and resizing
49    */
50   private double dividerRatio;
51
52   private static boolean doSetDivider = !Platform.isJS(); // BH why? Old?
53
54   /**
55    * Constructor
56    * 
57    * @param top
58    * @param bottom
59    */
60   public GSplitFrame(GAlignFrame top, GAlignFrame bottom)
61   {
62     this.topFrame = top;
63     this.bottomFrame = bottom;
64
65     hideTitleBars();
66
67     addSplitPane();
68   }
69
70   /**
71    * Create and add the split pane containing the top and bottom components.
72    */
73   protected void addSplitPane()
74   {
75     splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topFrame,
76             bottomFrame);
77     splitPane.setVisible(true);
78
79     /*
80      * set divider split at 50:50, or restore saved split if loading from
81      * project
82      */
83     int topFrameHeight = topFrame.getHeight();
84     if (doSetDivider)
85     {
86       splitPane.setDividerSize(DIVIDER_SIZE);
87       if (topFrameHeight == 0)
88       {
89         setRelativeDividerLocation(0.5d); // as a proportion
90       }
91       else
92       {
93         int dividerPosition = topFrameHeight + DIVIDER_SIZE / 2;
94         splitPane.setDividerLocation(dividerPosition); // absolute position
95       }
96       splitPane.setResizeWeight(0.5d);
97     }
98     add(splitPane);
99   }
100
101   /**
102    * Try to hide the title bars as a waste of precious space.
103    * 
104    * @see http
105    *      ://stackoverflow.com/questions/7218971/java-method-works-on-windows
106    *      -but-not-macintosh -java
107    */
108   protected void hideTitleBars()
109   {
110     if (Platform.isAMacAndNotJS())
111     {
112       // this saves some space - but doesn't hide the title bar
113       topFrame.putClientProperty("JInternalFrame.isPalette", true);
114       // topFrame.getRootPane().putClientProperty("Window.style", "small");
115       bottomFrame.putClientProperty("JInternalFrame.isPalette", true);
116     }
117     else
118     {
119         if (doSetDivider)
120       {
121         ((BasicInternalFrameUI) topFrame.getUI()).setNorthPane(null);
122         ((BasicInternalFrameUI) bottomFrame.getUI()).setNorthPane(null);
123       }
124     }
125   }
126
127   public GAlignFrame getTopFrame()
128   {
129     return topFrame;
130   }
131
132   public GAlignFrame getBottomFrame()
133   {
134     return bottomFrame;
135   }
136
137   /**
138    * Returns the split pane component the mouse is in, or null if neither.
139    * 
140    * @return
141    */
142   protected GAlignFrame getFrameAtMouse()
143   {
144     Point loc = MouseInfo.getPointerInfo().getLocation();
145
146     if (isIn(loc, splitPane.getTopComponent()))
147     {
148       return getTopFrame();
149     }
150     else if (isIn(loc, splitPane.getBottomComponent()))
151     {
152       return getBottomFrame();
153     }
154     return null;
155   }
156
157   private boolean isIn(Point loc, Component comp)
158   {
159     if (!comp.isVisible())
160     {
161       return false;
162     }
163     Point p = comp.getLocationOnScreen();
164     Rectangle r = new Rectangle(p.x, p.y, comp.getWidth(),
165             comp.getHeight());
166     return r.contains(loc);
167   }
168
169   /**
170    * Makes the complement of the specified split component visible or hidden,
171    * restoring or saving the position of the split divide.
172    */
173   public void setComplementVisible(Object alignFrame, boolean show)
174   {
175     /*
176      * save divider ratio on hide, restore on show
177      */
178     if (show)
179     {
180       setRelativeDividerLocation(dividerRatio);
181     }
182     else
183     {
184       this.dividerRatio = splitPane.getDividerLocation()
185               / (double) (splitPane.getHeight()
186                       - splitPane.getDividerSize());
187     }
188
189     if (alignFrame == this.topFrame)
190     {
191       this.bottomFrame.setVisible(show);
192     }
193     else if (alignFrame == this.bottomFrame)
194     {
195       this.topFrame.setVisible(show);
196     }
197
198     validate();
199   }
200
201   /**
202    * Set the divider location as a proportion (0 <= r <= 1) of the height <br>
203    * Warning: this overloads setDividerLocation(int), and getDividerLocation()
204    * returns the int (pixel count) value
205    * 
206    * @param r
207    */
208   public void setRelativeDividerLocation(double r)
209   {
210     this.dividerRatio = r;
211     // BH why?
212     if (!Platform.isJS())
213     {
214       splitPane.setDividerLocation(r);
215     }
216   }
217
218   /**
219    * Sets the divider location (in pixels from top)
220    * 
221    * @return
222    */
223   protected void setDividerLocation(int p)
224   {
225         if (doSetDivider )
226     {
227       splitPane.setDividerLocation(p);
228     }
229   }
230
231   /**
232    * Returns the divider location (in pixels from top)
233    * 
234    * @return
235    */
236   protected int getDividerLocation()
237   {
238     return splitPane.getDividerLocation();
239   }
240 }