1. /*
  2. * @(#)SynthSplitPaneUI.java 1.12 03/09/04
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.java.swing.plaf.gtk;
  8. import javax.swing.*;
  9. import javax.swing.border.Border;
  10. import javax.swing.event.*;
  11. import java.awt.*;
  12. import java.awt.event.*;
  13. import java.awt.peer.ComponentPeer;
  14. import java.awt.peer.LightweightPeer;
  15. import java.beans.*;
  16. import java.util.*;
  17. import javax.swing.plaf.ActionMapUIResource;
  18. import javax.swing.plaf.SplitPaneUI;
  19. import javax.swing.plaf.ComponentUI;
  20. import javax.swing.plaf.UIResource;
  21. /**
  22. * A Basic L&F implementation of the SplitPaneUI.
  23. *
  24. * @version 1.12, 09/04/03 (based on BasicSplitPaneUI v 1.72)
  25. * @author Scott Violet
  26. * @author Steve Wilson
  27. * @author Ralph Kar
  28. */
  29. class SynthSplitPaneUI extends SplitPaneUI implements SynthUI {
  30. /**
  31. * The divider used for non-continuous layout is added to the split pane
  32. * with this object.
  33. */
  34. private static final String NON_CONTINUOUS_DIVIDER =
  35. "nonContinuousDivider";
  36. /**
  37. * How far (relativ) the divider does move when it is moved around by
  38. * the cursor keys on the keyboard.
  39. */
  40. protected static int KEYBOARD_DIVIDER_MOVE_OFFSET = 3;
  41. /**
  42. * JSplitPane instance this instance is providing
  43. * the look and feel for.
  44. */
  45. protected JSplitPane splitPane;
  46. /**
  47. * Instance of the divider for this JSplitPane.
  48. */
  49. protected Divider divider;
  50. /**
  51. * Instance of the PropertyChangeListener for this JSplitPane.
  52. */
  53. protected PropertyChangeListener propertyChangeListener;
  54. /**
  55. * Instance of the FocusListener for this JSplitPane.
  56. */
  57. protected FocusListener focusListener;
  58. /**
  59. * Keys to use for forward focus traversal when the JComponent is
  60. * managing focus.
  61. */
  62. private static Set managingFocusForwardTraversalKeys;
  63. /**
  64. * Keys to use for backward focus traversal when the JComponent is
  65. * managing focus.
  66. */
  67. private static Set managingFocusBackwardTraversalKeys;
  68. /**
  69. * The size of the divider while the dragging session is valid.
  70. */
  71. protected int dividerSize;
  72. /**
  73. * Instance for the shadow of the divider when non continuous layout
  74. * is being used.
  75. */
  76. protected Component nonContinuousLayoutDivider;
  77. /**
  78. * Set to true in startDragging if any of the children
  79. * (not including the nonContinuousLayoutDivider) are heavy weights.
  80. */
  81. protected boolean draggingHW;
  82. /**
  83. * Location of the divider when the dragging session began.
  84. */
  85. protected int beginDragDividerLocation;
  86. // Private data of the instance
  87. private int orientation;
  88. private int lastDragLocation;
  89. private boolean continuousLayout;
  90. private boolean dividerKeyboardResize;
  91. private boolean dividerLocationIsSet; // needed for tracking
  92. // the first occurrence of
  93. // setDividerLocation()
  94. private boolean rememberPaneSizes;
  95. /** Indicates that we have painted once. */
  96. // This is used by the LayoutManager to determine when it should use
  97. // the divider location provided by the JSplitPane. This is used as there
  98. // is no way to determine when the layout process has completed.
  99. boolean painted;
  100. /** If true, setDividerLocation does nothing. */
  101. boolean ignoreDividerLocationChange;
  102. /**
  103. * Style for the JSplitPane.
  104. */
  105. private SynthStyle style;
  106. /**
  107. * Style for the divider.
  108. */
  109. private SynthStyle dividerStyle;
  110. /**
  111. * Size of the one touch buttons.
  112. */
  113. private int oneTouchSize;
  114. /**
  115. * Amount to offset one touch buttons.
  116. */
  117. private int oneTouchOffset;
  118. /**
  119. * Creates a new SynthSplitPaneUI instance
  120. */
  121. public static ComponentUI createUI(JComponent x) {
  122. return new SynthSplitPaneUI();
  123. }
  124. public static void loadActionMap(ActionMap map) {
  125. // NOTE: this needs to remain static. If you have a need to
  126. // have Actions that reference the UI in the ActionMap,
  127. // then you'll also need to change the registeration of the
  128. // ActionMap.
  129. map.put("negativeIncrement", new KeyboardUpLeftAction());
  130. map.put("positiveIncrement", new KeyboardDownRightAction());
  131. map.put("selectMin", new KeyboardHomeAction());
  132. map.put("selectMax", new KeyboardEndAction());
  133. map.put("startResize", new KeyboardResizeToggleAction());
  134. map.put("toggleFocus", new ToggleSideFocusAction());
  135. map.put("focusOutForward", new MoveFocusOutAction(1));
  136. map.put("focusOutBackward", new MoveFocusOutAction(-1));
  137. }
  138. /**
  139. * Installs the UI.
  140. */
  141. public void installUI(JComponent c) {
  142. splitPane = (JSplitPane) c;
  143. dividerLocationIsSet = false;
  144. dividerKeyboardResize = false;
  145. installComponents();
  146. installDefaults();
  147. installListeners();
  148. installKeyboardActions();
  149. setLastDragLocation(-1);
  150. }
  151. protected void installComponents() {
  152. divider = new Divider(splitPane);
  153. splitPane.add(divider, JSplitPane.DIVIDER);
  154. }
  155. /**
  156. * Installs the UI defaults.
  157. */
  158. protected void installDefaults() {
  159. setOrientation(splitPane.getOrientation());
  160. setContinuousLayout(splitPane.isContinuousLayout());
  161. fetchStyle(splitPane);
  162. resetLayoutManager();
  163. /* Install the nonContinuousLayoutDivider here to avoid having to
  164. add/remove everything later. */
  165. if(nonContinuousLayoutDivider == null) {
  166. setNonContinuousLayoutDivider(
  167. createDefaultNonContinuousLayoutDivider(),
  168. true);
  169. } else {
  170. setNonContinuousLayoutDivider(nonContinuousLayoutDivider, true);
  171. }
  172. // focus forward traversal key
  173. if (managingFocusForwardTraversalKeys==null) {
  174. managingFocusForwardTraversalKeys = new TreeSet();
  175. managingFocusForwardTraversalKeys.add(
  176. KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0));
  177. }
  178. splitPane.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
  179. managingFocusForwardTraversalKeys);
  180. // focus backward traversal key
  181. if (managingFocusBackwardTraversalKeys==null) {
  182. managingFocusBackwardTraversalKeys = new TreeSet();
  183. managingFocusBackwardTraversalKeys.add(
  184. KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK));
  185. }
  186. splitPane.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
  187. managingFocusBackwardTraversalKeys);
  188. }
  189. private void fetchStyle(JSplitPane splitPane) {
  190. SynthContext context = getContext(splitPane, ENABLED);
  191. SynthStyle oldStyle = style;
  192. style = SynthLookAndFeel.updateStyle(context, this);
  193. if (style != oldStyle) {
  194. splitPane.setDividerSize(((Number)style.get(
  195. context,"SplitPaneDivider.size")).intValue());
  196. divider.setDividerSize(splitPane.getDividerSize());
  197. }
  198. context.dispose();
  199. context = getContext(splitPane, Region.SPLIT_PANE_DIVIDER, ENABLED);
  200. dividerStyle = SynthLookAndFeel.updateStyle(context, this);
  201. divider.setOpaque(dividerStyle.isOpaque(context));
  202. oneTouchSize = dividerStyle.getInt(context,
  203. "SplitPaneDivider.oneTouchButtonSize", 6);
  204. oneTouchOffset = dividerStyle.getInt(context,
  205. "SplitPaneDivider.oneTouchOffset", 6);
  206. context.dispose();
  207. }
  208. /**
  209. * Installs the event listeners for the UI.
  210. */
  211. protected void installListeners() {
  212. if ((propertyChangeListener = createPropertyChangeListener()) !=
  213. null) {
  214. splitPane.addPropertyChangeListener(propertyChangeListener);
  215. }
  216. if ((focusListener = createFocusListener()) != null) {
  217. splitPane.addFocusListener(focusListener);
  218. }
  219. }
  220. /**
  221. * Installs the keyboard actions for the UI.
  222. */
  223. protected void installKeyboardActions() {
  224. InputMap km = getInputMap(JComponent.
  225. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  226. SwingUtilities.replaceUIInputMap(splitPane, JComponent.
  227. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
  228. km);
  229. LazyActionMap.installLazyActionMap(splitPane, SynthSplitPaneUI.class,
  230. "SplitPane.actionMap");
  231. }
  232. InputMap getInputMap(int condition) {
  233. if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
  234. SynthContext context = getContext(splitPane, ENABLED);
  235. InputMap map = (InputMap)context.getStyle().get(context,
  236. "SplitPane.ancestorInputMap");
  237. context.dispose();
  238. return map;
  239. }
  240. return null;
  241. }
  242. /**
  243. * Uninstalls the UI.
  244. */
  245. public void uninstallUI(JComponent c) {
  246. uninstallKeyboardActions();
  247. uninstallListeners();
  248. uninstallDefaults();
  249. uninstallComponents();
  250. dividerLocationIsSet = false;
  251. dividerKeyboardResize = false;
  252. splitPane = null;
  253. }
  254. private void uninstallComponents() {
  255. if(nonContinuousLayoutDivider != null) {
  256. splitPane.remove(nonContinuousLayoutDivider);
  257. }
  258. splitPane.remove(divider);
  259. divider = null;
  260. }
  261. /**
  262. * Uninstalls the UI defaults.
  263. */
  264. protected void uninstallDefaults() {
  265. if (splitPane.getLayout() instanceof UIResource) {
  266. splitPane.setLayout(null);
  267. }
  268. SynthContext context = getContext(splitPane, ENABLED);
  269. style.uninstallDefaults(context);
  270. context.dispose();
  271. style = null;
  272. context = getContext(splitPane, Region.SPLIT_PANE_DIVIDER, ENABLED);
  273. dividerStyle.uninstallDefaults(context);
  274. context.dispose();
  275. dividerStyle = null;
  276. nonContinuousLayoutDivider = null;
  277. setNonContinuousLayoutDivider(null);
  278. // sets the focus forward and backward traversal keys to null
  279. // to restore the defaults
  280. splitPane.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null);
  281. splitPane.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null);
  282. }
  283. /**
  284. * Uninstalls the event listeners for the UI.
  285. */
  286. protected void uninstallListeners() {
  287. if (propertyChangeListener != null) {
  288. splitPane.removePropertyChangeListener(propertyChangeListener);
  289. propertyChangeListener = null;
  290. }
  291. if (focusListener != null) {
  292. splitPane.removeFocusListener(focusListener);
  293. focusListener = null;
  294. }
  295. }
  296. /**
  297. * Uninstalls the keyboard actions for the UI.
  298. */
  299. protected void uninstallKeyboardActions() {
  300. SwingUtilities.replaceUIActionMap(splitPane, null);
  301. SwingUtilities.replaceUIInputMap(splitPane, JComponent.
  302. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
  303. null);
  304. }
  305. public SynthContext getContext(JComponent c) {
  306. return getContext(c, getComponentState(c));
  307. }
  308. private SynthContext getContext(JComponent c, int state) {
  309. return SynthContext.getContext(SynthContext.class, c,
  310. SynthLookAndFeel.getRegion(c), style, state);
  311. }
  312. private Region getRegion(JComponent c) {
  313. return SynthLookAndFeel.getRegion(c);
  314. }
  315. private int getComponentState(JComponent c) {
  316. return SynthLookAndFeel.getComponentState(c);
  317. }
  318. private SynthContext getContext(JComponent c, Region region) {
  319. return getContext(c, region, getComponentState(c, region));
  320. }
  321. private SynthContext getContext(JComponent c, Region region, int state) {
  322. return SynthContext.getContext(SynthContext.class, c, region,
  323. style, state);
  324. }
  325. private int getComponentState(JComponent c, Region subregion) {
  326. int state = SynthLookAndFeel.getComponentState(c);
  327. if (divider.isMouseOver()) {
  328. state |= MOUSE_OVER;
  329. }
  330. return state;
  331. }
  332. /**
  333. * Creates a PropertyChangeListener for the JSplitPane UI.
  334. */
  335. protected PropertyChangeListener createPropertyChangeListener() {
  336. return new PropertyHandler();
  337. }
  338. /**
  339. * Creates a FocusListener for the JSplitPane UI.
  340. */
  341. protected FocusListener createFocusListener() {
  342. return new FocusHandler();
  343. }
  344. /**
  345. * Returns the orientation for the JSplitPane.
  346. */
  347. public int getOrientation() {
  348. return orientation;
  349. }
  350. /**
  351. * Set the orientation for the JSplitPane.
  352. */
  353. public void setOrientation(int orientation) {
  354. this.orientation = orientation;
  355. }
  356. /**
  357. * Determines wether the JSplitPane is set to use a continuous layout.
  358. */
  359. public boolean isContinuousLayout() {
  360. return continuousLayout;
  361. }
  362. /**
  363. * Turn continuous layout on/off.
  364. */
  365. public void setContinuousLayout(boolean b) {
  366. continuousLayout = b;
  367. }
  368. /**
  369. * Returns the last drag location of the JSplitPane.
  370. */
  371. public int getLastDragLocation() {
  372. return lastDragLocation;
  373. }
  374. /**
  375. * Set the last drag location of the JSplitPane.
  376. */
  377. public void setLastDragLocation(int l) {
  378. lastDragLocation = l;
  379. }
  380. /**
  381. * @return increment via keyboard methods.
  382. */
  383. int getKeyboardMoveIncrement() {
  384. return KEYBOARD_DIVIDER_MOVE_OFFSET;
  385. }
  386. /**
  387. * Implementation of the PropertyChangeListener
  388. * that the JSplitPane UI uses.
  389. */
  390. class PropertyHandler implements PropertyChangeListener
  391. {
  392. /**
  393. * Messaged from the <code>JSplitPane</code> the receiver is
  394. * contained in. May potentially reset the layout manager and cause a
  395. * <code>validate</code> to be sent.
  396. */
  397. public void propertyChange(PropertyChangeEvent e) {
  398. if(e.getSource() == splitPane) {
  399. String changeName = e.getPropertyName();
  400. if (SynthLookAndFeel.shouldUpdateStyle(e)) {
  401. fetchStyle((JSplitPane)e.getSource());
  402. }
  403. if(changeName.equals(JSplitPane.ORIENTATION_PROPERTY)) {
  404. orientation = splitPane.getOrientation();
  405. resetLayoutManager();
  406. } else if(changeName.equals(
  407. JSplitPane.CONTINUOUS_LAYOUT_PROPERTY)) {
  408. setContinuousLayout(splitPane.isContinuousLayout());
  409. if(!isContinuousLayout()) {
  410. if(nonContinuousLayoutDivider == null) {
  411. setNonContinuousLayoutDivider(
  412. createDefaultNonContinuousLayoutDivider(),
  413. true);
  414. } else if(nonContinuousLayoutDivider.getParent() ==
  415. null) {
  416. setNonContinuousLayoutDivider(
  417. nonContinuousLayoutDivider,
  418. true);
  419. }
  420. }
  421. } else if(changeName.equals(JSplitPane.DIVIDER_SIZE_PROPERTY)){
  422. divider.setDividerSize(splitPane.getDividerSize());
  423. dividerSize = divider.getDividerSize();
  424. splitPane.revalidate();
  425. splitPane.repaint();
  426. }
  427. }
  428. }
  429. }
  430. /**
  431. * Implementation of the FocusListener that the JSplitPane UI uses.
  432. */
  433. class FocusHandler extends FocusAdapter
  434. {
  435. public void focusGained(FocusEvent ev) {
  436. dividerKeyboardResize = true;
  437. splitPane.repaint();
  438. }
  439. public void focusLost(FocusEvent ev) {
  440. dividerKeyboardResize = false;
  441. splitPane.repaint();
  442. }
  443. }
  444. static class KeyboardUpLeftAction extends AbstractAction {
  445. public void actionPerformed(ActionEvent ev) {
  446. JSplitPane splitPane = (JSplitPane)ev.getSource();
  447. SynthSplitPaneUI ui = (SynthSplitPaneUI)splitPane.getUI();
  448. if (ui.dividerKeyboardResize) {
  449. splitPane.setDividerLocation(Math.max(0,ui.getDividerLocation
  450. (splitPane) - ui.getKeyboardMoveIncrement()));
  451. }
  452. }
  453. }
  454. static class KeyboardDownRightAction extends AbstractAction {
  455. public void actionPerformed(ActionEvent ev) {
  456. JSplitPane splitPane = (JSplitPane)ev.getSource();
  457. SynthSplitPaneUI ui = (SynthSplitPaneUI)splitPane.getUI();
  458. if (ui.dividerKeyboardResize) {
  459. splitPane.setDividerLocation(ui.getDividerLocation(splitPane) +
  460. ui.getKeyboardMoveIncrement());
  461. }
  462. }
  463. }
  464. static class KeyboardHomeAction extends AbstractAction {
  465. public void actionPerformed(ActionEvent ev) {
  466. JSplitPane splitPane = (JSplitPane)ev.getSource();
  467. SynthSplitPaneUI ui = (SynthSplitPaneUI)splitPane.getUI();
  468. if (ui.dividerKeyboardResize) {
  469. splitPane.setDividerLocation(0);
  470. }
  471. }
  472. }
  473. static class KeyboardEndAction extends AbstractAction {
  474. public void actionPerformed(ActionEvent ev) {
  475. JSplitPane splitPane = (JSplitPane)ev.getSource();
  476. SynthSplitPaneUI ui = (SynthSplitPaneUI)splitPane.getUI();
  477. if (ui.dividerKeyboardResize) {
  478. Insets insets = splitPane.getInsets();
  479. int bottomI = (insets != null) ? insets.bottom : 0;
  480. int rightI = (insets != null) ? insets.right : 0;
  481. if (ui.orientation == JSplitPane.VERTICAL_SPLIT) {
  482. splitPane.setDividerLocation(splitPane.getHeight() -
  483. bottomI);
  484. }
  485. else {
  486. splitPane.setDividerLocation(splitPane.getWidth() -
  487. rightI);
  488. }
  489. }
  490. }
  491. }
  492. static class KeyboardResizeToggleAction extends AbstractAction {
  493. public void actionPerformed(ActionEvent ev) {
  494. JSplitPane splitPane = (JSplitPane)ev.getSource();
  495. SynthSplitPaneUI ui = (SynthSplitPaneUI)splitPane.getUI();
  496. if (!ui.dividerKeyboardResize) {
  497. splitPane.requestFocus();
  498. } else {
  499. JSplitPane parentSplitPane =
  500. (JSplitPane)SwingUtilities.getAncestorOfClass(JSplitPane.class, splitPane);
  501. if (parentSplitPane!=null) {
  502. parentSplitPane.requestFocus();
  503. }
  504. }
  505. }
  506. }
  507. /**
  508. * ActionListener that will focus on the opposite component that
  509. * has focus. EG if the left side has focus, this will transfer focus
  510. * to the right component.
  511. */
  512. static class ToggleSideFocusAction extends AbstractAction {
  513. public void actionPerformed(ActionEvent ae) {
  514. JSplitPane splitPane = (JSplitPane)ae.getSource();
  515. Component left = splitPane.getLeftComponent();
  516. Component right = splitPane.getRightComponent();
  517. KeyboardFocusManager manager =
  518. KeyboardFocusManager.getCurrentKeyboardFocusManager();
  519. Component focus = manager.getFocusOwner();
  520. Component focusOn = getNextSide(splitPane, focus);
  521. if (focusOn != null) {
  522. // don't change the focus if the new focused component belongs
  523. // to the same splitpane and the same side
  524. if ( focus!=null &&
  525. ( (SwingUtilities.isDescendingFrom(focus, left) &&
  526. SwingUtilities.isDescendingFrom(focusOn, left)) ||
  527. (SwingUtilities.isDescendingFrom(focus, right) &&
  528. SwingUtilities.isDescendingFrom(focusOn, right)) ) ) {
  529. return;
  530. }
  531. SynthLookAndFeel.compositeRequestFocus(focusOn);
  532. }
  533. }
  534. private Component getNextSide(JSplitPane splitPane, Component focus) {
  535. Component left = splitPane.getLeftComponent();
  536. Component right = splitPane.getRightComponent();
  537. Component next = null;
  538. if (focus!=null && SwingUtilities.isDescendingFrom(focus, left) &&
  539. right!=null) {
  540. next = getFirstAvailableComponent(right);
  541. if (next != null) {
  542. return next;
  543. }
  544. }
  545. JSplitPane parentSplitPane = (JSplitPane)SwingUtilities.getAncestorOfClass(JSplitPane.class, splitPane);
  546. if (parentSplitPane!=null) {
  547. // focus next side of the parent split pane
  548. next = getNextSide(parentSplitPane, focus);
  549. } else {
  550. next = getFirstAvailableComponent(left);
  551. if (next == null) {
  552. next = getFirstAvailableComponent(right);
  553. }
  554. }
  555. return next;
  556. }
  557. private Component getFirstAvailableComponent(Component c) {
  558. if (c!=null && c instanceof JSplitPane) {
  559. JSplitPane sp = (JSplitPane)c;
  560. Component left = getFirstAvailableComponent(sp.getLeftComponent());
  561. if (left != null) {
  562. c = left;
  563. } else {
  564. c = getFirstAvailableComponent(sp.getRightComponent());
  565. }
  566. }
  567. return c;
  568. }
  569. }
  570. /**
  571. * Action that will move focus out of the splitpane to the next
  572. * component (if present) if direction > 0 or to the previous
  573. * component (if present) if direction < 0
  574. */
  575. static class MoveFocusOutAction extends AbstractAction {
  576. private int direction;
  577. public MoveFocusOutAction(int newDirection) {
  578. direction = newDirection;
  579. }
  580. public void actionPerformed(ActionEvent ae) {
  581. JSplitPane splitPane = (JSplitPane)ae.getSource();
  582. Container rootAncestor = splitPane.getFocusCycleRootAncestor();
  583. FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy();
  584. Component focusOn = (direction > 0) ?
  585. policy.getComponentAfter(rootAncestor, splitPane) :
  586. policy.getComponentBefore(rootAncestor, splitPane);
  587. HashSet focusFrom = new HashSet();
  588. if (splitPane.isAncestorOf(focusOn)) {
  589. do {
  590. focusFrom.add(focusOn);
  591. rootAncestor = focusOn.getFocusCycleRootAncestor();
  592. policy = rootAncestor.getFocusTraversalPolicy();
  593. focusOn = (direction > 0) ?
  594. policy.getComponentAfter(rootAncestor, focusOn) :
  595. policy.getComponentBefore(rootAncestor, focusOn);
  596. } while (splitPane.isAncestorOf(focusOn) &&
  597. !focusFrom.contains(focusOn));
  598. }
  599. if ( focusOn!=null && !splitPane.isAncestorOf(focusOn) ) {
  600. focusOn.requestFocus();
  601. }
  602. }
  603. }
  604. /**
  605. * Returns the default non continuous layout divider, which is an
  606. * instanceof Canvas that fills the background in dark gray.
  607. */
  608. protected Component createDefaultNonContinuousLayoutDivider() {
  609. // PENDING: make this lightweight.
  610. return new Canvas() {
  611. public void paint(Graphics g) {
  612. paintDragDivider(g, 0, 0, getWidth(), getHeight());
  613. /*
  614. if(!isContinuousLayout() && getLastDragLocation() != -1) {
  615. Dimension size = splitPane.getSize();
  616. g.setColor(Color.darkGray);
  617. if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  618. g.fillRect(0, 0, dividerSize - 1, size.height - 1);
  619. } else {
  620. g.fillRect(0, 0, size.width - 1, dividerSize - 1);
  621. }
  622. }
  623. */
  624. }
  625. };
  626. }
  627. /**
  628. * Sets the divider to use when the splitPane is configured to
  629. * not continuously layout. This divider will only be used during a
  630. * dragging session. It is recommended that the passed in component
  631. * be a heavy weight.
  632. */
  633. protected void setNonContinuousLayoutDivider(Component newDivider) {
  634. setNonContinuousLayoutDivider(newDivider, true);
  635. }
  636. /**
  637. * Sets the divider to use.
  638. */
  639. protected void setNonContinuousLayoutDivider(Component newDivider,
  640. boolean rememberSizes) {
  641. rememberPaneSizes = rememberSizes;
  642. if(nonContinuousLayoutDivider != null && splitPane != null) {
  643. splitPane.remove(nonContinuousLayoutDivider);
  644. }
  645. nonContinuousLayoutDivider = newDivider;
  646. }
  647. private void addHeavyweightDivider() {
  648. // PENDING: nuke this.
  649. if(nonContinuousLayoutDivider != null && splitPane != null) {
  650. /* Needs to remove all the components and re-add them! YECK! */
  651. // This is all done so that the nonContinuousLayoutDivider will
  652. // be drawn on top of the other components, without this, one
  653. // of the heavyweights will draw over the divider!
  654. Component leftC = splitPane.getLeftComponent();
  655. Component rightC = splitPane.getRightComponent();
  656. int lastLocation = splitPane.
  657. getDividerLocation();
  658. if(leftC != null)
  659. splitPane.setLeftComponent(null);
  660. if(rightC != null)
  661. splitPane.setRightComponent(null);
  662. splitPane.remove(divider);
  663. splitPane.add(nonContinuousLayoutDivider, SynthSplitPaneUI.
  664. NON_CONTINUOUS_DIVIDER,
  665. splitPane.getComponentCount());
  666. splitPane.setLeftComponent(leftC);
  667. splitPane.setRightComponent(rightC);
  668. splitPane.add(divider, JSplitPane.DIVIDER);
  669. if(rememberPaneSizes) {
  670. splitPane.setDividerLocation(lastLocation);
  671. }
  672. }
  673. }
  674. /**
  675. * Returns the divider to use when the splitPane is configured to
  676. * not continuously layout. This divider will only be used during a
  677. * dragging session.
  678. */
  679. public Component getNonContinuousLayoutDivider() {
  680. return nonContinuousLayoutDivider;
  681. }
  682. /**
  683. * Returns the splitpane this instance is currently contained
  684. * in.
  685. */
  686. public JSplitPane getSplitPane() {
  687. return splitPane;
  688. }
  689. /**
  690. * Messaged to reset the preferred sizes.
  691. */
  692. public void resetToPreferredSizes(JSplitPane jc) {
  693. if(splitPane != null) {
  694. LayoutManager layout = jc.getLayout();
  695. if (layout instanceof SplitPaneLayoutManager) {
  696. ((SplitPaneLayoutManager)layout).resetToPreferredSizes();
  697. }
  698. splitPane.revalidate();
  699. splitPane.repaint();
  700. }
  701. }
  702. /**
  703. * Sets the location of the divider to location.
  704. */
  705. public void setDividerLocation(JSplitPane jc, int location) {
  706. if (!ignoreDividerLocationChange) {
  707. dividerLocationIsSet = true;
  708. splitPane.revalidate();
  709. splitPane.repaint();
  710. }
  711. else {
  712. ignoreDividerLocationChange = false;
  713. }
  714. }
  715. /**
  716. * Returns the location of the divider, which may differ from what
  717. * the splitpane thinks the location of the divider is.
  718. */
  719. public int getDividerLocation(JSplitPane jc) {
  720. if(orientation == JSplitPane.HORIZONTAL_SPLIT)
  721. return divider.getX();
  722. return divider.getY();
  723. }
  724. /**
  725. * Gets the minimum location of the divider.
  726. */
  727. public int getMinimumDividerLocation(JSplitPane jc) {
  728. int minLoc = 0;
  729. Component leftC = splitPane.getLeftComponent();
  730. if ((leftC != null) && (leftC.isVisible())) {
  731. Insets insets = splitPane.getInsets();
  732. Dimension minSize = leftC.getMinimumSize();
  733. if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  734. minLoc = minSize.width;
  735. } else {
  736. minLoc = minSize.height;
  737. }
  738. if(insets != null) {
  739. if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  740. minLoc += insets.left;
  741. } else {
  742. minLoc += insets.top;
  743. }
  744. }
  745. }
  746. return minLoc;
  747. }
  748. /**
  749. * Gets the maximum location of the divider.
  750. */
  751. public int getMaximumDividerLocation(JSplitPane jc) {
  752. Dimension splitPaneSize = splitPane.getSize();
  753. int maxLoc = 0;
  754. Component rightC = splitPane.getRightComponent();
  755. if (rightC != null) {
  756. Insets insets = splitPane.getInsets();
  757. Dimension minSize = new Dimension(0, 0);
  758. if (rightC.isVisible()) {
  759. minSize = rightC.getMinimumSize();
  760. }
  761. if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  762. maxLoc = splitPaneSize.width - minSize.width;
  763. } else {
  764. maxLoc = splitPaneSize.height - minSize.height;
  765. }
  766. maxLoc -= dividerSize;
  767. if(insets != null) {
  768. if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  769. maxLoc -= insets.right;
  770. } else {
  771. maxLoc -= insets.top;
  772. }
  773. }
  774. }
  775. return Math.max(getMinimumDividerLocation(splitPane), maxLoc);
  776. }
  777. public void update(Graphics g, JComponent c) {
  778. SynthContext context = getContext(c);
  779. SynthLookAndFeel.update(context, g);
  780. paint(context, g);
  781. context.dispose();
  782. }
  783. public void paint(Graphics g, JComponent c) {
  784. SynthContext context = getContext(c);
  785. paint(context, g);
  786. context.dispose();
  787. }
  788. protected void paint(SynthContext context, Graphics g) {
  789. if (!painted && splitPane.getDividerLocation()<0) {
  790. ignoreDividerLocationChange = true;
  791. splitPane.setDividerLocation(getDividerLocation(splitPane));
  792. }
  793. painted = true;
  794. }
  795. private void paintDragDivider(Graphics g, int x, int y, int w, int h) {
  796. SynthContext context = getContext(splitPane,Region.SPLIT_PANE_DIVIDER);
  797. context.setComponentState(((context.getComponentState() | MOUSE_OVER) ^
  798. MOUSE_OVER) | PRESSED);
  799. SynthPainter painter = (SynthPainter)context.getStyle().
  800. get(context, "SplitPane.dragPainter");
  801. if (painter != null) {
  802. painter.paint(context, "foreground", g, x, y, w, h);
  803. }
  804. context.dispose();
  805. }
  806. /**
  807. * Messaged after the JSplitPane the receiver is providing the look
  808. * and feel for paints its children.
  809. */
  810. public void finishedPaintingChildren(JSplitPane jc, Graphics g) {
  811. if(jc == splitPane && getLastDragLocation() != -1 &&
  812. !isContinuousLayout() && !draggingHW) {
  813. if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  814. paintDragDivider(g, getLastDragLocation(), 0, dividerSize - 1,
  815. splitPane.getHeight() - 1);
  816. } else {
  817. paintDragDivider(g, 0, lastDragLocation,
  818. splitPane.getWidth() - 1, dividerSize - 1);
  819. }
  820. }
  821. }
  822. /**
  823. * Resets the layout manager based on orientation and messages it
  824. * with invalidateLayout to pull in appropriate Components.
  825. */
  826. protected void resetLayoutManager() {
  827. SplitPaneLayoutManager layoutManager;
  828. if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  829. layoutManager = new SplitPaneLayoutManager(0);
  830. } else {
  831. layoutManager = new SplitPaneLayoutManager(1);
  832. }
  833. splitPane.setLayout(layoutManager);
  834. layoutManager.updateComponents();
  835. splitPane.revalidate();
  836. splitPane.repaint();
  837. }
  838. /**
  839. * Should be messaged before the dragging session starts, resets
  840. * lastDragLocation and dividerSize.
  841. */
  842. protected void startDragging() {
  843. Component leftC = splitPane.getLeftComponent();
  844. Component rightC = splitPane.getRightComponent();
  845. ComponentPeer cPeer;
  846. beginDragDividerLocation = getDividerLocation(splitPane);
  847. draggingHW = false;
  848. if(leftC != null && (cPeer = leftC.getPeer()) != null &&
  849. !(cPeer instanceof LightweightPeer)) {
  850. draggingHW = true;
  851. } else if(rightC != null && (cPeer = rightC.getPeer()) != null
  852. && !(cPeer instanceof LightweightPeer)) {
  853. draggingHW = true;
  854. }
  855. if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  856. setLastDragLocation(divider.getBounds().x);
  857. dividerSize = divider.getSize().width;
  858. if(!isContinuousLayout() && draggingHW) {
  859. nonContinuousLayoutDivider.setBounds
  860. (getLastDragLocation(), 0, dividerSize,
  861. splitPane.getHeight());
  862. addHeavyweightDivider();
  863. }
  864. } else {
  865. setLastDragLocation(divider.getBounds().y);
  866. dividerSize = divider.getSize().height;
  867. if(!isContinuousLayout() && draggingHW) {
  868. nonContinuousLayoutDivider.setBounds
  869. (0, getLastDragLocation(), splitPane.getWidth(),
  870. dividerSize);
  871. addHeavyweightDivider();
  872. }
  873. }
  874. }
  875. /**
  876. * Messaged during a dragging session to move the divider to the
  877. * passed in location. If continuousLayout is true the location is
  878. * reset and the splitPane validated.
  879. */
  880. protected void dragDividerTo(int location) {
  881. if(getLastDragLocation() != location) {
  882. if(isContinuousLayout()) {
  883. splitPane.setDividerLocation(location);
  884. setLastDragLocation(location);
  885. } else {
  886. int lastLoc = getLastDragLocation();
  887. setLastDragLocation(location);
  888. if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  889. if(draggingHW) {
  890. nonContinuousLayoutDivider.setLocation(
  891. getLastDragLocation(), 0);
  892. } else {
  893. int splitHeight = splitPane.getHeight();
  894. splitPane.repaint(lastLoc, 0, dividerSize,
  895. splitHeight);
  896. splitPane.repaint(location, 0, dividerSize,
  897. splitHeight);
  898. }
  899. } else {
  900. if(draggingHW) {
  901. nonContinuousLayoutDivider.setLocation(0,
  902. getLastDragLocation());
  903. } else {
  904. int splitWidth = splitPane.getWidth();
  905. splitPane.repaint(0, lastLoc, splitWidth,
  906. dividerSize);
  907. splitPane.repaint(0, location, splitWidth,
  908. dividerSize);
  909. }
  910. }
  911. }
  912. }
  913. }
  914. /**
  915. * Messaged to finish the dragging session. If not continuous display
  916. * the dividers location will be reset.
  917. */
  918. protected void finishDraggingTo(int location) {
  919. dragDividerTo(location);
  920. setLastDragLocation(-1);
  921. if(!isContinuousLayout()) {
  922. Component leftC = splitPane.getLeftComponent();
  923. Rectangle leftBounds = leftC.getBounds();
  924. if (draggingHW) {
  925. if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  926. nonContinuousLayoutDivider.setLocation(-dividerSize, 0);
  927. }
  928. else {
  929. nonContinuousLayoutDivider.setLocation(0, -dividerSize);
  930. }
  931. splitPane.remove(nonContinuousLayoutDivider);
  932. }
  933. splitPane.setDividerLocation(location);
  934. }
  935. }
  936. /**
  937. * LayoutManager for JSplitPanes that have an orientation of
  938. * HORIZONTAL_SPLIT.
  939. */
  940. private class SplitPaneLayoutManager implements LayoutManager2,UIResource {
  941. /* left, right, divider. (in this exact order) */
  942. protected int[] sizes;
  943. protected Component[] components;
  944. /** Size of the splitpane the last time laid out. */
  945. private int lastSplitPaneSize;
  946. /** True if resetToPreferredSizes has been invoked. */
  947. private boolean doReset;
  948. /** Axis, 0 for horizontal, or 1 for veritcal. */
  949. private int axis;
  950. SplitPaneLayoutManager(int axis) {
  951. this.axis = axis;
  952. components = new Component[3];
  953. components[0] = components[1] = components[2] = null;
  954. sizes = new int[3];
  955. }
  956. //
  957. // LayoutManager
  958. //
  959. /**
  960. * Does the actual layout.
  961. */
  962. public void layoutContainer(Container container) {
  963. Dimension containerSize = container.getSize();
  964. // If the splitpane has a zero size then no op out of here.
  965. // If we execute this function now, we're going to cause ourselves
  966. // much grief.
  967. if (containerSize.height <= 0 || containerSize.width <= 0 ) {
  968. lastSplitPaneSize = 0;
  969. return;
  970. }
  971. int spDividerLocation = splitPane.getDividerLocation();
  972. Insets insets = splitPane.getInsets();
  973. int availableSize = getAvailableSize(containerSize,
  974. insets);
  975. int newSize = getSizeForPrimaryAxis(containerSize);
  976. int beginLocation = getDividerLocation(splitPane);
  977. int dOffset = getSizeForPrimaryAxis(insets, true);
  978. Dimension dSize = (components[2] == null) ? null :
  979. components[2].getPreferredSize();
  980. if ((doReset && !dividerLocationIsSet) || spDividerLocation < 0) {
  981. resetToPreferredSizes(availableSize);
  982. }
  983. else if (lastSplitPaneSize <= 0 ||
  984. availableSize == lastSplitPaneSize || !painted ||
  985. (dSize != null &&
  986. getSizeForPrimaryAxis(dSize) != sizes[2])) {
  987. if (dSize != null) {
  988. sizes[2] = getSizeForPrimaryAxis(dSize);
  989. }
  990. else {
  991. sizes[2] = 0;
  992. }
  993. setDividerLocation(spDividerLocation - dOffset, availableSize);
  994. dividerLocationIsSet = false;
  995. }
  996. else if (availableSize != lastSplitPaneSize) {
  997. distributeSpace(availableSize - lastSplitPaneSize, true);
  998. }
  999. doReset = false;
  1000. dividerLocationIsSet = false;
  1001. lastSplitPaneSize = availableSize;
  1002. // Reset the bounds of each component
  1003. int nextLocation = getInitialLocation(insets);
  1004. int counter = 0;
  1005. while (counter < 3) {
  1006. if (components[counter] != null &&
  1007. components[counter].isVisible()) {
  1008. setComponentToSize(components[counter], sizes[counter],
  1009. nextLocation, insets, containerSize);
  1010. nextLocation += sizes[counter];
  1011. }
  1012. switch (counter) {
  1013. case 0:
  1014. counter = 2;
  1015. break;
  1016. case 2:
  1017. counter = 1;
  1018. break;
  1019. case 1:
  1020. counter = 3;
  1021. break;
  1022. }
  1023. }
  1024. if (painted) {
  1025. // This is tricky, there is never a good time for us
  1026. // to push the value to the splitpane, painted appears to
  1027. // the best time to do it. What is really needed is
  1028. // notification that layout has completed.
  1029. int newLocation = getDividerLocation(splitPane);
  1030. if (newLocation != (spDividerLocation - dOffset)) {
  1031. int lastLocation = splitPane.getLastDividerLocation();
  1032. ignoreDividerLocationChange = true;
  1033. try {
  1034. splitPane.setDividerLocation(newLocation);
  1035. // This is not always needed, but is rather tricky
  1036. // to determine when... The case this is needed for
  1037. // is if the user sets the divider location to some
  1038. // bogus value, say 0, and the actual value is 1, the
  1039. // call to setDividerLocation(1) will preserve the
  1040. // old value of 0, when we really want the divider
  1041. // location value before the call. This is needed for
  1042. // the one touch buttons.
  1043. splitPane.setLastDividerLocation(lastLocation);
  1044. } finally {
  1045. ignoreDividerLocationChange = false;
  1046. }
  1047. }
  1048. }
  1049. }
  1050. /**
  1051. * Adds the component at place. Place must be one of
  1052. * JSplitPane.LEFT, RIGHT, TOP, BOTTOM, or null (for the
  1053. * divider).
  1054. */
  1055. public void addLayoutComponent(String place, Component component) {
  1056. boolean isValid = true;
  1057. if(place != null) {
  1058. if(place.equals(JSplitPane.DIVIDER)) {
  1059. /* Divider. */
  1060. components[2] = component;
  1061. sizes[2] = getSizeForPrimaryAxis(component.
  1062. getPreferredSize());
  1063. } else if(place.equals(JSplitPane.LEFT) ||
  1064. place.equals(JSplitPane.TOP)) {
  1065. components[0] = component;
  1066. sizes[0] = 0;
  1067. } else if(place.equals(JSplitPane.RIGHT) ||
  1068. place.equals(JSplitPane.BOTTOM)) {
  1069. components[1] = component;
  1070. sizes[1] = 0;
  1071. } else if(!place.equals(
  1072. SynthSplitPaneUI.NON_CONTINUOUS_DIVIDER))
  1073. isValid = false;
  1074. } else {
  1075. isValid = false;
  1076. }
  1077. if(!isValid)
  1078. throw new IllegalArgumentException("cannot add to layout: " +
  1079. "unknown constraint: " +
  1080. place);
  1081. doReset = true;
  1082. }
  1083. /**
  1084. * Returns the minimum size needed to contain the children.
  1085. * The width is the sum of all the childrens min widths and
  1086. * the height is the largest of the childrens minimum heights.
  1087. */
  1088. public Dimension minimumLayoutSize(Container container) {
  1089. int minPrimary = 0;
  1090. int minSecondary = 0;
  1091. Insets insets = splitPane.getInsets();
  1092. for (int counter=0; counter<3; counter++) {
  1093. if(components[counter] != null) {
  1094. Dimension minSize = components[counter].getMinimumSize();
  1095. int secSize = getSizeForSecondaryAxis(minSize);
  1096. minPrimary += getSizeForPrimaryAxis(minSize);
  1097. if(secSize > minSecondary)
  1098. minSecondary = secSize;
  1099. }
  1100. }
  1101. if(insets != null) {
  1102. minPrimary += getSizeForPrimaryAxis(insets, true) +
  1103. getSizeForPrimaryAxis(insets, false);
  1104. minSecondary += getSizeForSecondaryAxis(insets, true) +
  1105. getSizeForSecondaryAxis(insets, false);
  1106. }
  1107. if (axis == 0) {
  1108. return new Dimension(minPrimary, minSecondary);
  1109. }
  1110. return new Dimension(minSecondary, minPrimary);
  1111. }
  1112. /**
  1113. * Returns the preferred size needed to contain the children.
  1114. * The width is the sum of all the childrens preferred widths and
  1115. * the height is the largest of the childrens preferred heights.
  1116. */
  1117. public Dimension preferredLayoutSize(Container container) {
  1118. int prePrimary = 0;
  1119. int preSecondary = 0;
  1120. Insets insets = splitPane.getInsets();
  1121. for(int counter = 0; counter < 3; counter++) {
  1122. if(components[counter] != null) {
  1123. Dimension preSize = components[counter].
  1124. getPreferredSize();
  1125. int secSize = getSizeForSecondaryAxis(preSize);
  1126. prePrimary += getSizeForPrimaryAxis(preSize);
  1127. if(secSize > preSecondary)
  1128. preSecondary = secSize;
  1129. }
  1130. }
  1131. if(insets != null) {
  1132. prePrimary += getSizeForPrimaryAxis(insets, true) +
  1133. getSizeForPrimaryAxis(insets, false);
  1134. preSecondary += getSizeForSecondaryAxis(insets, true) +
  1135. getSizeForSecondaryAxis(insets, false);
  1136. }
  1137. if (axis == 0) {
  1138. return new Dimension(prePrimary, preSecondary);
  1139. }
  1140. return new Dimension(preSecondary, prePrimary);
  1141. }
  1142. /**
  1143. * Removes the specified component from our knowledge.
  1144. */
  1145. public void removeLayoutComponent(Component component) {
  1146. for(int counter = 0; counter < 3; counter++) {
  1147. if(components[counter] == component) {
  1148. components[counter] = null;
  1149. sizes[counter] = 0;
  1150. doReset = true;
  1151. }
  1152. }
  1153. }
  1154. //
  1155. // LayoutManager2
  1156. //
  1157. /**
  1158. * Adds the specified component to the layout, using the specified
  1159. * constraint object.
  1160. * @param comp the component to be added
  1161. * @param constraints where/how the component is added to the layout.
  1162. */
  1163. public void addLayoutComponent(Component comp, Object constraints) {
  1164. if ((constraints == null) || (constraints instanceof String)) {
  1165. addLayoutComponent((String)constraints, comp);
  1166. } else {
  1167. throw new IllegalArgumentException("cannot add to layout: " +
  1168. "constraint must be a " +
  1169. "string (or null)");
  1170. }
  1171. }
  1172. /**
  1173. * Returns the alignment along the x axis. This specifies how
  1174. * the component would like to be aligned relative to other
  1175. * components. The value should be a number between 0 and 1
  1176. * where 0 represents alignment along the origin, 1 is aligned
  1177. * the furthest away from the origin, 0.5 is centered, etc.
  1178. */
  1179. public float getLayoutAlignmentX(Container target) {
  1180. return 0.0f;
  1181. }
  1182. /**
  1183. * Returns the alignment along the y axis. This specifies how
  1184. * the component would like to be aligned relative to other
  1185. * components. The value should be a number between 0 and 1
  1186. * where 0 represents alignment along the origin, 1 is aligned
  1187. * the furthest away from the origin, 0.5 is centered, etc.
  1188. */
  1189. public float getLayoutAlignmentY(Container target) {
  1190. return 0.0f;
  1191. }
  1192. /**
  1193. * Does nothing. If the developer really wants to change the
  1194. * size of one of the views JSplitPane.resetToPreferredSizes should
  1195. * be messaged.
  1196. */
  1197. public void invalidateLayout(Container c) {
  1198. }
  1199. /**
  1200. * Returns the maximum layout size, which is Integer.MAX_VALUE
  1201. * in both directions.
  1202. */
  1203. public Dimension maximumLayoutSize(Container target) {
  1204. return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
  1205. }
  1206. //
  1207. // New methods.
  1208. //
  1209. /**
  1210. * Marks the receiver so that the next time this instance is
  1211. * laid out it'll ask for the preferred sizes.
  1212. */
  1213. public void resetToPreferredSizes() {
  1214. doReset = true;
  1215. }
  1216. /**
  1217. * Resets the size of the Component at the passed in location.
  1218. */
  1219. protected void resetSizeAt(int index) {
  1220. sizes[index] = 0;
  1221. doReset = true;
  1222. }
  1223. /**
  1224. * Sets the sizes to <code>newSizes</code>.
  1225. */
  1226. protected void setSizes(int[] newSizes) {
  1227. System.arraycopy(newSizes, 0, sizes, 0, 3);
  1228. }
  1229. /**
  1230. * Returns the sizes of the components.
  1231. */
  1232. protected int[] getSizes() {
  1233. int[] retSizes = new int[3];
  1234. System.arraycopy(sizes, 0, retSizes, 0, 3);
  1235. return retSizes;
  1236. }
  1237. /**
  1238. * Returns the width of the passed in Components preferred size.
  1239. */
  1240. protected int getPreferredSizeOfComponent(Component c) {
  1241. return getSizeForPrimaryAxis(c.getPreferredSize());
  1242. }
  1243. /**
  1244. * Returns the width of the passed in Components minimum size.
  1245. */
  1246. int getMinimumSizeOfComponent(Component c) {
  1247. return getSizeForPrimaryAxis(c.getMinimumSize());
  1248. }
  1249. /**
  1250. * Returns the width of the passed in component.
  1251. */
  1252. protected int getSizeOfComponent(Component c) {
  1253. return getSizeForPrimaryAxis(c.getSize());
  1254. }
  1255. /**
  1256. * Returns the available width based on the container size and
  1257. * Insets.
  1258. */
  1259. protected int getAvailableSize(Dimension containerSize,
  1260. Insets insets) {
  1261. if(insets == null)
  1262. return getSizeForPrimaryAxis(containerSize);
  1263. return (getSizeForPrimaryAxis(containerSize) -
  1264. (getSizeForPrimaryAxis(insets, true) +
  1265. getSizeForPrimaryAxis(insets, false)));
  1266. }
  1267. /**
  1268. * Returns the left inset, unless the Insets are null in which case
  1269. * 0 is returned.
  1270. */
  1271. protected int getInitialLocation(Insets insets) {
  1272. if(insets != null)
  1273. return getSizeForPrimaryAxis(insets, true);
  1274. return 0;
  1275. }
  1276. /**
  1277. * Sets the width of the component c to be size, placing its
  1278. * x location at location, y to the insets.top and height
  1279. * to the containersize.height less the top and bottom insets.
  1280. */
  1281. protected void setComponentToSize(Component c, int size,
  1282. int location, Insets insets,
  1283. Dimension containerSize) {
  1284. if(insets != null) {
  1285. if (axis == 0) {
  1286. c.setBounds(location, insets.top, size,
  1287. containerSize.height -
  1288. (insets.top + insets.bottom));
  1289. }
  1290. else {
  1291. c.setBounds(insets.left, location, containerSize.width -
  1292. (insets.left + insets.right), size);
  1293. }
  1294. }
  1295. else {
  1296. if (axis == 0) {
  1297. c.setBounds(location, 0, size, containerSize.height);
  1298. }
  1299. else {
  1300. c.setBounds(0, location, containerSize.width, size);
  1301. }
  1302. }
  1303. }
  1304. /**
  1305. * If the axis == 0, the width is returned, otherwise the height.
  1306. */
  1307. int getSizeForPrimaryAxis(Dimension size) {
  1308. if (axis == 0) {
  1309. return size.width;
  1310. }
  1311. return size.height;
  1312. }
  1313. /**
  1314. * If the axis == 0, the width is returned, otherwise the height.
  1315. */
  1316. int getSizeForSecondaryAxis(Dimension size) {
  1317. if (axis == 0) {
  1318. return size.height;
  1319. }
  1320. return size.width;
  1321. }
  1322. /**
  1323. * Returns a particular value of the inset identified by the
  1324. * axis and <code>isTop</code><p>
  1325. * axis isTop
  1326. * 0 true - left
  1327. * 0 false - right
  1328. * 1 true - top
  1329. * 1 false - bottom
  1330. */
  1331. int getSizeForPrimaryAxis(Insets insets, boolean isTop) {
  1332. if (axis == 0) {
  1333. if (isTop) {
  1334. return insets.left;
  1335. }
  1336. return insets.right;
  1337. }
  1338. if (isTop) {
  1339. return insets.top;
  1340. }
  1341. return insets.bottom;
  1342. }
  1343. /**
  1344. * Returns a particular value of the inset identified by the
  1345. * axis and <code>isTop</code><p>
  1346. * axis isTop
  1347. * 0 true - left
  1348. * 0 false - right
  1349. * 1 true - top
  1350. * 1 false - bottom
  1351. */
  1352. int getSizeForSecondaryAxis(Insets insets, boolean isTop) {
  1353. if (axis == 0) {
  1354. if (isTop) {
  1355. return insets.top;
  1356. }
  1357. return insets.bottom;
  1358. }
  1359. if (isTop) {
  1360. return insets.left;
  1361. }
  1362. return insets.right;
  1363. }
  1364. /**
  1365. * Determines the components. This should be called whenever
  1366. * a new instance of this is installed into an existing
  1367. * SplitPane.
  1368. */
  1369. protected void updateComponents() {