001: /*
002: * Javu WingS - Lightweight Java Component Set
003: * Copyright (c) 2005-2007 Krzysztof A. Sadlocha
004: * e-mail: ksadlocha@programics.com
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020:
021: package com.javujavu.javux.wings;
022:
023: import java.awt.AWTEvent;
024: import java.awt.Component;
025: import java.awt.Cursor;
026: import java.awt.Dimension;
027: import java.awt.Point;
028: import java.awt.event.MouseEvent;
029:
030: /**
031: * This SplitterWnd class provides the functionality of a splitter
032: * pane, which contains two components that can then be
033: * interactively resized by the user.<br>
034: * <br>
035: * <b>This class is thread safe.</b>
036: **/
037: public class WingSplitPane extends WingComponent {
038: protected int divWidth;
039:
040: private/*final*/int orientation;
041: private Component left, right;
042: private/*final*/Divider div;
043: private int divLocation;
044: private boolean divLocationSet;
045: private Dimension prevSize;
046: private double weight;
047: private boolean drag;
048: private boolean laying;
049: private boolean continuousLayout;
050:
051: public WingSplitPane(int orientation) {
052: this .orientation = orientation;
053: div = new Divider();
054: add(div);
055: weight = 0.0;
056: divLocation = -1;
057: continuousLayout = true;
058: }
059:
060: public void loadSkin() {
061: stNormal = WingSkin.getStyle(styleId, "split.pane", NORMAL,
062: null);
063: stDisabled = WingSkin.getStyle(styleId, "split.pane", DISABLED,
064: stNormal);
065: divWidth = WingSkin.getInteger(styleId, "split.width", 4);
066: }
067:
068: public void setContinuousLayout(boolean continuousLayout) {
069: this .continuousLayout = continuousLayout;
070: }
071:
072: public void setStyleId(String styleId) {
073: div.setStyleId(styleId);
074: super .setStyleId(styleId);
075: }
076:
077: /**
078: * <br><br><strong>This method acquire TreeLock</strong>
079: */
080: public void setLeftComponent(Component c) {
081: setTopComponent(c);
082: }
083:
084: /**
085: * <br><br><strong>This method acquire TreeLock</strong>
086: */
087: public void setTopComponent(Component c) {
088: synchronized (getTreeLock()) {
089: if (left != null)
090: remove(left);
091: left = c;
092: if (c != null)
093: add(c);
094: divLocation = -1;
095: }
096: revalidateAndRepaint();
097: }
098:
099: /**
100: * <br><br><strong>This method acquire TreeLock</strong>
101: */
102: public void setRightComponent(Component c) {
103: setBottomComponent(c);
104: }
105:
106: /**
107: * <br><br><strong>This method acquire TreeLock</strong>
108: */
109: public void setBottomComponent(Component c) {
110: synchronized (getTreeLock()) {
111: if (right != null)
112: remove(right);
113: right = c;
114: if (c != null)
115: add(c);
116: divLocation = -1;
117: }
118: revalidateAndRepaint();
119: }
120:
121: public void setDividerLocation(int newLocation) {
122: if (divLocation != newLocation) {
123: divLocation = newLocation;
124: divLocationSet = true;
125: div.revalidateAndRepaint();
126: // revalidate();
127: }
128: }
129:
130: /**
131: * <br><br><strong>This method acquire TreeLock</strong>
132: */
133: protected void dragDivider(int newLocation) {
134: divLocationSet = true;
135: int oldLocation = divLocation;
136: newLocation += oldLocation;
137: if (newLocation < 0)
138: newLocation = 0;
139: Dimension d = getSize();
140: int maximum = ((orientation == HORIZONTAL) ? d.width : d.height)
141: - divWidth;
142: if (newLocation >= maximum)
143: newLocation = maximum;
144: if (oldLocation != newLocation) {
145: divLocation = newLocation;
146: laying = true;
147: if (orientation == HORIZONTAL)
148: div.setLocation(newLocation, 0);
149: else
150: div.setLocation(0, newLocation);
151: laying = false;
152: if (continuousLayout)
153: revalidateAndRepaint();
154: }
155: }
156:
157: public int getDividerLocation() {
158: return divLocation;
159: }
160:
161: public void resetToPreferredSizes() {
162: divLocationSet = false;
163: if (divLocation == -1)
164: return;
165: divLocation = -1;
166: div.revalidateAndRepaint();
167: }
168:
169: public int getDividerSize() {
170: return divWidth;
171: }
172:
173: public void setResizeWeight(double weight) {
174: if (weight >= 0 && weight <= 1)
175: this .weight = weight;
176: }
177:
178: /**
179: * <br><br><strong>This method acquire TreeLock</strong>
180: */
181: public Dimension getPreferredSize() {
182: Dimension prefSize = wingPrefSize, d2;
183: if (prefSize == null) {
184: synchronized (getTreeLock()) {
185: prefSize = new Dimension();
186: if (left != null)
187: prefSize = left.getPreferredSize();
188: if (right != null) {
189: d2 = right.getPreferredSize();
190: if (left == null)
191: return d2;
192: prefSize = new Dimension(prefSize);
193: if (orientation == HORIZONTAL) {
194: if (d2.height > prefSize.height)
195: prefSize.height = d2.height;
196: prefSize.width += divWidth + d2.width;
197: } else {
198: if (d2.width > prefSize.width)
199: prefSize.width = d2.width;
200: prefSize.height += divWidth + d2.height;
201: }
202: }
203: wingPrefSize = prefSize;
204: }
205: }
206: return prefSize;
207: }
208:
209: public void invalidate() {
210: if (!laying)
211: super .invalidate();
212: }
213:
214: /**
215: * <br><br><strong>This method acquire TreeLock</strong>
216: */
217: public void doLayout() {
218: synchronized (getTreeLock()) {
219: if ((left == null && right == null))
220: return;
221: Dimension size = getSize();
222: if (size.width <= 0 || size.height <= 0)
223: return;
224: if (left == null || right == null) {
225: div.setVisible(false);
226: Component c = left != null ? left : right;
227: c.setBounds(0, 0, size.width, size.height);
228: } else {
229: for (int f = 0; f < 10; f++) {
230: int divLocation = this .divLocation;
231: Dimension d1 = null;
232: Dimension d2 = null;
233: int m = ((orientation == HORIZONTAL) ? size.width
234: : size.height)
235: - divWidth;
236: if (divLocation < 0 || !divLocationSet) {
237: d1 = left.getPreferredSize();
238: d2 = right.getPreferredSize();
239: int a = (orientation == HORIZONTAL) ? d1.width
240: : d1.height;
241: int b = (orientation == HORIZONTAL) ? d2.width
242: : d2.height;
243: divLocation = a + (int) ((m - a - b) * weight);
244: } else if (!size.equals(prevSize)) {
245: if (prevSize != null) {
246: int ex = (orientation == HORIZONTAL) ? (size.width - prevSize.width)
247: : (size.height - prevSize.height);
248: divLocation += ex * weight;
249: }
250:
251: prevSize = size;
252: }
253:
254: if (divLocation < 0)
255: divLocation = 0;
256: if (divLocation >= m)
257: divLocation = m;
258: this .divLocation = divLocation;
259:
260: div.setVisible(true);
261: if (orientation == HORIZONTAL) {
262: left.setBounds(0, 0, divLocation, size.height);
263: div.setBounds(divLocation, 0, divWidth,
264: size.height);
265: right.setBounds(divLocation + divWidth, 0,
266: size.width - divLocation - divWidth,
267: size.height);
268: } else {
269: left.setBounds(0, 0, size.width, divLocation);
270: div.setBounds(0, divLocation, size.width,
271: divWidth);
272: right.setBounds(0, divLocation + divWidth,
273: size.width, size.height - divLocation
274: - divWidth);
275: }
276: if (d1 == null
277: || (d1.equals(left.getPreferredSize()) && d2
278: .equals(right.getPreferredSize())))
279: break;
280: }
281: }
282: }
283: }
284:
285: class Divider extends WingComponent {
286: private Style stDrag;
287: private Style stHover;
288:
289: private boolean hover;
290: private int divHandle;
291:
292: Divider() {
293: setCursor(Cursor
294: .getPredefinedCursor(orientation == HORIZONTAL ? Cursor.E_RESIZE_CURSOR
295: : Cursor.N_RESIZE_CURSOR));
296: enableEvents(AWTEvent.MOUSE_EVENT_MASK
297: | AWTEvent.MOUSE_MOTION_EVENT_MASK);
298: }
299:
300: public void loadSkin() {
301: String idt = WingSkin
302: .catKeys(styleId,
303: (orientation == HORIZONTAL) ? "h.split"
304: : "v.split");
305:
306: stNormal = WingSkin.getStyle(idt, null, NORMAL, null);
307: stDrag = WingSkin.getStyle(idt, null, PRESSED, stNormal);
308: stHover = WingSkin.getStyle(idt, null, HOVER, stNormal);
309: }
310:
311: public Style getStyle() {
312: return (drag) ? stDrag : (hover) ? stHover : stNormal;
313: }
314:
315: /**
316: * <br><br><strong>This method acquire TreeLock</strong>
317: */
318: protected void wingProcessMouseEvent(MouseEvent e) {
319: int id = e.getID();
320: if (id == MouseEvent.MOUSE_PRESSED) {
321: Point p = e.getPoint();
322: if (orientation == HORIZONTAL)
323: divHandle = p.x;
324: else
325: divHandle = p.y;
326: drag = true;
327: repaint();
328: } else if (id == MouseEvent.MOUSE_RELEASED) {
329: drag = false;
330: if (!continuousLayout)
331: revalidateAndRepaint();
332: else
333: repaint();
334: } else if (id == MouseEvent.MOUSE_ENTERED) {
335: if (drag
336: || (e.getModifiers() & (MouseEvent.BUTTON1_MASK
337: | MouseEvent.BUTTON2_MASK | MouseEvent.BUTTON3_MASK)) == 0) {
338: hover = true;
339: repaint();
340: }
341: } else if (id == MouseEvent.MOUSE_EXITED) {
342: if (hover) {
343: hover = false;
344: repaint();
345: }
346: } else if (id == MouseEvent.MOUSE_DRAGGED) {
347: Point p = e.getPoint();
348: if (orientation == HORIZONTAL)
349: dragDivider(p.x - divHandle);
350: else
351: dragDivider(p.y - divHandle);
352: }
353: }
354: }
355:
356: }
|