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