fd25116949b6eed2ab1d930fdc57dd18e490fbf6
[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   /**
53    * Constructor
54    * 
55    * @param top
56    * @param bottom
57    */
58   public GSplitFrame(GAlignFrame top, GAlignFrame bottom)
59   {
60     this.topFrame = top;
61     this.bottomFrame = bottom;
62
63     hideTitleBars();
64
65     addSplitPane();
66   }
67
68   /**
69    * Create and add the split pane containing the top and bottom components.
70    */
71   protected void addSplitPane()
72   {
73     splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topFrame,
74             bottomFrame);
75     splitPane.setVisible(true);
76
77     /*
78      * set divider split at 50:50, or restore saved split if loading from
79      * project
80      */
81     int topFrameHeight = topFrame.getHeight();
82     /**
83      * TODO SplitFrame.setDividerLocation
84      * 
85      * @j2sNative
86      */
87     {
88       splitPane.setDividerSize(DIVIDER_SIZE);
89       if (topFrameHeight == 0)
90       {
91         setRelativeDividerLocation(0.5d); // as a proportion
92       }
93       else
94       {
95         int dividerPosition = topFrameHeight + DIVIDER_SIZE / 2;
96         splitPane.setDividerLocation(dividerPosition); // absolute position
97       }
98       splitPane.setResizeWeight(0.5d);
99     }
100     add(splitPane);
101   }
102
103   /**
104    * Try to hide the title bars as a waste of precious space.
105    * 
106    * @see http
107    *      ://stackoverflow.com/questions/7218971/java-method-works-on-windows
108    *      -but-not-macintosh -java
109    */
110   protected void hideTitleBars()
111   {
112     if (Platform.isAMacAndNotJS())
113     {
114       // this saves some space - but doesn't hide the title bar
115       topFrame.putClientProperty("JInternalFrame.isPalette", true);
116       // topFrame.getRootPane().putClientProperty("Window.style", "small");
117       bottomFrame.putClientProperty("JInternalFrame.isPalette", true);
118     }
119     else
120     {
121             ((BasicInternalFrameUI) topFrame.getUI()).setNorthPane(null);
122             ((BasicInternalFrameUI) bottomFrame.getUI()).setNorthPane(null);
123     }
124   }
125
126   public GAlignFrame getTopFrame()
127   {
128     return topFrame;
129   }
130
131   public GAlignFrame getBottomFrame()
132   {
133     return bottomFrame;
134   }
135
136   /**
137    * Returns the split pane component the mouse is in, or null if neither.
138    * 
139    * @return
140    */
141   protected GAlignFrame getFrameAtMouse()
142   {
143     Point loc = MouseInfo.getPointerInfo().getLocation();
144
145     if (isIn(loc, splitPane.getTopComponent()))
146     {
147       return getTopFrame();
148     }
149     else if (isIn(loc, splitPane.getBottomComponent()))
150     {
151       return getBottomFrame();
152     }
153     return null;
154   }
155
156   private boolean isIn(Point loc, Component comp)
157   {
158     if (!comp.isVisible())
159     {
160       return false;
161     }
162     Point p = comp.getLocationOnScreen();
163     Rectangle r = new Rectangle(p.x, p.y, comp.getWidth(),
164             comp.getHeight());
165     return r.contains(loc);
166   }
167
168   /**
169    * Makes the complement of the specified split component visible or hidden,
170    * restoring or saving the position of the split divide.
171    */
172   public void setComplementVisible(Object alignFrame, boolean show)
173   {
174     /*
175      * save divider ratio on hide, restore on show
176      */
177     if (show)
178     {
179       setRelativeDividerLocation(dividerRatio);
180     }
181     else
182     {
183       this.dividerRatio = splitPane.getDividerLocation()
184               / (double) (splitPane.getHeight()
185                       - splitPane.getDividerSize());
186     }
187
188     if (alignFrame == this.topFrame)
189     {
190       this.bottomFrame.setVisible(show);
191     }
192     else if (alignFrame == this.bottomFrame)
193     {
194       this.topFrame.setVisible(show);
195     }
196
197     validate();
198   }
199
200   /**
201    * Set the divider location as a proportion (0 <= r <= 1) of the height <br>
202    * Warning: this overloads setDividerLocation(int), and getDividerLocation()
203    * returns the int (pixel count) value
204    * 
205    * @param r
206    */
207   public void setRelativeDividerLocation(double r)
208   {
209     this.dividerRatio = r;
210     /**
211      * @j2sNative
212      */
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     /**
226      * @j2sNative
227      */
228     {
229       splitPane.setDividerLocation(p);
230     }
231   }
232
233   /**
234    * Returns the divider location (in pixels from top)
235    * 
236    * @return
237    */
238   protected int getDividerLocation()
239   {
240     return splitPane.getDividerLocation();
241   }
242 }