Gridarta Editor
BorderSplitPane.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2015 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.gui.utils.borderpanel;
21 
22 import java.awt.BorderLayout;
23 import java.awt.Component;
24 import java.awt.Container;
25 import java.awt.Dimension;
26 import java.awt.event.HierarchyEvent;
27 import java.awt.event.HierarchyListener;
28 import java.beans.PropertyChangeEvent;
29 import java.beans.PropertyChangeListener;
30 import javax.swing.JSplitPane;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
33 
39 public class BorderSplitPane extends Container {
40 
44  private static final long serialVersionUID = 1L;
45 
50  @NotNull
51  private final Component component;
52 
57  @NotNull
58  private final Location location;
59 
64  @NotNull
65  private final Component @NotNull [] optionalComponents = new Component[2];
66 
72  @NotNull
73  private final JSplitPane splitPane;
74 
80  @NotNull
81  private final JSplitPane splitPane2;
82 
87  private boolean showing;
88 
95  private int size = -1;
96 
103  private int size2;
104 
108  private boolean ignoreSizeChange;
109 
117  public BorderSplitPane(@NotNull final Component component, @NotNull final Location location, @NotNull final BorderSplitPaneListener borderSplitPaneListener, final int size2) {
118  this.component = component;
119  this.location = location;
120  this.size2 = size2;
121  splitPane = new JSplitPane(location.getSplitPaneOrientation(), true, null, null);
122  splitPane.setOneTouchExpandable(false);
123  splitPane.setResizeWeight(location.getSplitPaneResizeWeight());
124  splitPane2 = new JSplitPane(location.getSplitPaneOppositeOrientation(), true, null, null);
125  splitPane2.setOneTouchExpandable(false);
126  splitPane2.setResizeWeight(0.5);
127  setLayout(new BorderLayout());
128  setOptionalComponent(null, false, 0, true);
129 
130  splitPane.addPropertyChangeListener(new PropertyChangeListener() {
131 
132  @Override
133  public void propertyChange(final PropertyChangeEvent evt) {
134  if (ignoreSizeChange) {
135  return;
136  }
137  if (optionalComponents[0] != null || optionalComponents[1] != null) {
138  //Property names are interned strings.
139  //noinspection StringEquality
140  if (evt.getPropertyName() == JSplitPane.DIVIDER_LOCATION_PROPERTY) {
141  final Object value = evt.getNewValue();
142  if (value instanceof Integer) {
143  final int newSize = (Integer) value;
144  final int splitPaneSize = getSplitPaneSize(newSize);
145  for (final Component optionalComponent : optionalComponents) {
146  if (optionalComponent != null) {
147  borderSplitPaneListener.sizeChanged(optionalComponent, splitPaneSize);
148  }
149  }
150  }
151  }
152  }
153  }
154 
155  });
156 
157  splitPane2.addPropertyChangeListener(new PropertyChangeListener() {
158 
159  @Override
160  public void propertyChange(final PropertyChangeEvent evt) {
161  if (ignoreSizeChange) {
162  return;
163  }
164  if (optionalComponents[0] != null && optionalComponents[1] != null) {
165  //Property names are interned strings.
166  //noinspection StringEquality
167  if (evt.getPropertyName() == JSplitPane.DIVIDER_LOCATION_PROPERTY) {
168  final Object value = evt.getNewValue();
169  if (value instanceof Integer) {
170  final int newSize = (Integer) value;
171  BorderSplitPane.this.size2 = newSize;
172  borderSplitPaneListener.size2Changed(newSize);
173  }
174  }
175  }
176  }
177 
178  });
179 
180  final HierarchyListener hierarchyListener = new HierarchyListener() {
181 
182  @Override
183  public void hierarchyChanged(final HierarchyEvent e) {
184  if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0L && isShowing()) {
185  removeHierarchyListener(this);
186  assert !showing;
187  showing = true;
188  if (size != -1) {
190  size = -1;
191  }
192  setDividerSize2();
193  }
194  }
195 
196  };
197  addHierarchyListener(hierarchyListener);
198  }
199 
209  public void setOptionalComponent(@Nullable final Component optionalComponent, final boolean alternativeLocation, final int size) {
210  setOptionalComponent(optionalComponent, alternativeLocation, size, false);
211  }
212 
223  private void setOptionalComponent(@Nullable final Component optionalComponent, final boolean alternativeLocation, final int size, final boolean force) {
224  final int index = alternativeLocation ? 1 : 0;
225  if (!force && optionalComponents[index] == optionalComponent) {
226  return;
227  }
228 
229  optionalComponents[index] = optionalComponent;
230 
231  final Component centerComponent;
232  final boolean setSize2;
233  if (optionalComponents[0] == null && optionalComponents[1] == null) {
234  setSize2 = false;
235  centerComponent = component;
236  } else {
237  centerComponent = splitPane;
238 
239  final Component tmp;
240  if (optionalComponents[0] == null) {
241  setSize2 = false;
242  tmp = optionalComponents[1];
243  assert tmp != null;
244  } else if (optionalComponents[1] == null) {
245  setSize2 = false;
246  tmp = optionalComponents[0];
247  assert tmp != null;
248  } else {
249  setSize2 = true;
250  tmp = splitPane2;
251  splitPane2.setTopComponent(optionalComponents[0]);
252  splitPane2.setBottomComponent(optionalComponents[1]);
253  }
254 
255  if (location.isTopOrLeft()) {
256  splitPane.setTopComponent(tmp);
257  splitPane.setBottomComponent(component);
258  } else {
259  splitPane.setTopComponent(component);
260  splitPane.setBottomComponent(tmp);
261  }
262  }
263 
264  removeAll();
265  add(centerComponent, BorderLayout.CENTER);
266  ignoreSizeChange = true;
267  try {
268  validate();
269  } finally {
270  ignoreSizeChange = false;
271  }
272 
273  final Component otherComponent = optionalComponents[1 - index];
274  if (optionalComponent == null) {
275  if (otherComponent == null) {
276  // no resize
277  } else {
278  final Dimension preferredSizeTmp = otherComponent.getPreferredSize();
279  final int preferredSize = getSplitPaneSize(preferredSizeTmp == null ? 50 : location.isTopOrBottom() ? preferredSizeTmp.height : preferredSizeTmp.width);
280  setDividerSizeInt(preferredSize);
281  }
282  } else {
283  if (otherComponent == null) {
285  } else {
286  final Dimension preferredSizeTmp = otherComponent.getPreferredSize();
287  final int preferredSize = getSplitPaneSize(preferredSizeTmp == null ? 50 : location.isTopOrBottom() ? preferredSizeTmp.height : preferredSizeTmp.width);
288  setDividerSizeInt(Math.max(size, preferredSize));
289  }
290  }
291 
292  if (setSize2) {
293  setDividerSize2();
294  }
295 
296  validate();
297  }
298 
303  private void setDividerSizeInt(final int size) {
304  if (showing) {
306  } else {
307  this.size = size;
308  }
309  }
310 
315  private void setDividerSize(final int size) {
316  splitPane.setDividerLocation(getSplitPaneSize(size));
317  }
318 
322  private void setDividerSize2() {
323  if (size2 == -1) {
324  return;
325  }
326  splitPane2.setDividerLocation(size2);
327  }
328 
334  private int getSplitPaneSize(final int size) {
335  final Dimension preferredSize = getSplitPanePreferredSize();
336  if (location.isTopOrBottom()) {
337  preferredSize.height = size;
338  } else {
339  preferredSize.width = size;
340  }
341  setSplitPanePreferredSize(preferredSize);
342 
343  final int result;
344  if (location.isTopOrLeft()) {
345  result = size;
346  } else {
347  final int splitPaneSize = (location.isTopOrBottom() ? splitPane.getHeight() : splitPane.getWidth()) - splitPane.getDividerSize();
348  result = Math.max(0, splitPaneSize - size);
349  }
350  return result;
351  }
352 
357  @NotNull
358  private Dimension getSplitPanePreferredSize() {
359  for (final Component optionalComponent : optionalComponents) {
360  if (optionalComponent != null) {
361  final Dimension preferredSize = optionalComponent.getPreferredSize();
362  if (preferredSize != null) {
363  return preferredSize;
364  }
365  }
366  }
367 
368  for (final Component optionalComponent : optionalComponents) {
369  if (optionalComponent != null) {
370  return optionalComponent.getSize();
371  }
372  }
373 
374  return splitPane.getSize();
375  }
376 
381  private void setSplitPanePreferredSize(@NotNull final Dimension preferredSize) {
382  for (final Component optionalComponent : optionalComponents) {
383  if (optionalComponent != null) {
384  optionalComponent.setPreferredSize(preferredSize);
385  }
386  }
387  }
388 
389 }
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.serialVersionUID
static final long serialVersionUID
Definition: BorderSplitPane.java:44
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.location
final Location location
Definition: BorderSplitPane.java:58
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.setDividerSize2
void setDividerSize2()
Definition: BorderSplitPane.java:322
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.optionalComponents
final Component[] optionalComponents
Definition: BorderSplitPane.java:65
net.sf.gridarta.gui.utils.borderpanel.Location.isTopOrLeft
abstract boolean isTopOrLeft()
net.sf.gridarta.gui.utils.borderpanel.Location.getSplitPaneResizeWeight
abstract double getSplitPaneResizeWeight()
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.splitPane2
final JSplitPane splitPane2
Definition: BorderSplitPane.java:81
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.splitPane
final JSplitPane splitPane
Definition: BorderSplitPane.java:73
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPaneListener
Definition: BorderSplitPaneListener.java:30
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.component
final Component component
Definition: BorderSplitPane.java:51
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.setDividerSize
void setDividerSize(final int size)
Definition: BorderSplitPane.java:315
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane
Definition: BorderSplitPane.java:39
net.sf.gridarta.gui.utils.borderpanel.Location.getSplitPaneOrientation
abstract int getSplitPaneOrientation()
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.showing
boolean showing
Definition: BorderSplitPane.java:87
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.getSplitPaneSize
int getSplitPaneSize(final int size)
Definition: BorderSplitPane.java:334
net.sf.gridarta.gui.utils.borderpanel.Location.isTopOrBottom
abstract boolean isTopOrBottom()
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.setOptionalComponent
void setOptionalComponent(@Nullable final Component optionalComponent, final boolean alternativeLocation, final int size)
Definition: BorderSplitPane.java:209
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.BorderSplitPane
BorderSplitPane(@NotNull final Component component, @NotNull final Location location, @NotNull final BorderSplitPaneListener borderSplitPaneListener, final int size2)
Definition: BorderSplitPane.java:117
net.sf.gridarta.gui.utils.borderpanel.Location
Definition: Location.java:33
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.setDividerSizeInt
void setDividerSizeInt(final int size)
Definition: BorderSplitPane.java:303
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.setSplitPanePreferredSize
void setSplitPanePreferredSize(@NotNull final Dimension preferredSize)
Definition: BorderSplitPane.java:381
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.getSplitPanePreferredSize
Dimension getSplitPanePreferredSize()
Definition: BorderSplitPane.java:358
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.size
int size
Definition: BorderSplitPane.java:95
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.setOptionalComponent
void setOptionalComponent(@Nullable final Component optionalComponent, final boolean alternativeLocation, final int size, final boolean force)
Definition: BorderSplitPane.java:223
net.sf.gridarta.gui.utils.borderpanel.Location.getSplitPaneOppositeOrientation
abstract int getSplitPaneOppositeOrientation()
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.ignoreSizeChange
boolean ignoreSizeChange
Definition: BorderSplitPane.java:108
net.sf.gridarta.gui.utils.borderpanel.BorderSplitPane.size2
int size2
Definition: BorderSplitPane.java:103