001: /*
002: * @(#)ButtonPaneLayout.java
003: *
004: * Copyright 2002 - 2003 JIDE Software. All rights reserved.
005: */
006:
007: package com.jidesoft.dialog;
008:
009: import javax.swing.*;
010: import java.awt.*;
011: import java.io.Serializable;
012: import java.util.List;
013: import java.util.Vector;
014:
015: class ButtonPanelLayout implements LayoutManager2, Serializable {
016: /**
017: * Specifies that components should be laid out left to right.
018: */
019: public static final int X_AXIS = 0;
020:
021: /**
022: * Specifies that components should be laid out top to bottom.
023: */
024: public static final int Y_AXIS = 1;
025:
026: /**
027: * Specifies that components should be laid out in the direction of
028: * a line of text as determined by the target container's
029: * <code>ComponentOrientation</code> property.
030: */
031: public static final int LINE_AXIS = 2;
032:
033: /**
034: * Specifies that components should be laid out in the direction that
035: * lines flow across a page as determined by the target container's
036: * <code>ComponentOrientation</code> property.
037: */
038: public static final int PAGE_AXIS = 3;
039:
040: private Container _target;
041:
042: private transient SizeRequirements[] _xChildren;
043: private transient SizeRequirements[] _yChildren;
044: private transient SizeRequirements _xTotal;
045: private transient SizeRequirements _yTotal;
046:
047: private List<Component> _affirmativeButtons = new Vector<Component>(
048: 13);
049: private List<Component> _cancelButtons = new Vector<Component>(13);
050: private List<Component> _helpButtons = new Vector<Component>(13);
051: private List<Component> _otherButtons = new Vector<Component>(13);
052:
053: int _minWidth; // calculated value by checkRequests
054:
055: int _maxWidth; // calculated value by checkRequests
056:
057: int _groupGap = 10; // get from L&F or user can set it
058:
059: int _buttonGap = 6; // get from L&F or user can set it
060:
061: private int _sizeConstraint = ButtonPanel.NO_LESS_THAN; // get from L&F or user can set it
062:
063: private String _buttonOrder = "ACO"; // get from L&F or user can set it
064:
065: private String _oppositeButtonOrder = "H"; // get from L&F or user can set it
066:
067: private int _minButtonWidth = 75;
068:
069: private int _axis = X_AXIS; // get from L&F or user can set it
070:
071: private int _alignment = SwingConstants.RIGHT; // get from L&F or user can set it
072:
073: /**
074: * Creates a layout manager that will lay out components along the
075: * given axis.
076: *
077: * @param target the container that needs to be laid out
078: * @param axis the axis to lay out components along. Can be one of:
079: * <code>BoxLayout.X_AXIS</code>,
080: * <code>BoxLayout.Y_AXIS</code>,
081: * <code>BoxLayout.LINE_AXIS</code> or
082: * <code>BoxLayout.PAGE_AXIS</code>
083: * @param alignment the alignment
084: * @param sizeConstraint the size constraint
085: * @param buttonOrder the button order represented as string
086: * @param oppositeButtonOrder the button order on the opposite side represented as string
087: * @param buttonGap the gap btween buttons
088: * @param groupGap the gap btween button groups
089: * @throws java.awt.AWTError if the value of <code>axis</code> is invalid
090: */
091: public ButtonPanelLayout(Container target, int axis, int alignment,
092: int sizeConstraint, String buttonOrder,
093: String oppositeButtonOrder, int buttonGap, int groupGap) {
094: if (axis != X_AXIS && axis != Y_AXIS && axis != LINE_AXIS
095: && axis != PAGE_AXIS) {
096: throw new AWTError("Invalid axis");
097: }
098: _axis = axis;
099: _target = target;
100: _alignment = alignment;
101: _sizeConstraint = sizeConstraint;
102: _buttonOrder = buttonOrder;
103: _oppositeButtonOrder = oppositeButtonOrder;
104: _buttonGap = buttonGap;
105: _groupGap = groupGap;
106: }
107:
108: /**
109: * Indicates that a child has changed its layout related information,
110: * and thus any cached calculations should be flushed.
111: * <p/>
112: * This method is called by AWT when the invalidate method is called
113: * on the Container. Since the invalidate method may be called
114: * asynchronously to the event thread, this method may be called
115: * asynchronously.
116: *
117: * @param target the affected container
118: * @throws java.awt.AWTError if the target isn't the container specified to the
119: * BoxLayout constructor
120: */
121: public synchronized void invalidateLayout(Container target) {
122: checkContainer(target);
123: _xChildren = null;
124: _yChildren = null;
125: _xTotal = null;
126: _yTotal = null;
127: }
128:
129: /**
130: * Not used by this class.
131: *
132: * @param name the name of the component
133: * @param comp the component
134: */
135: public void addLayoutComponent(String name, Component comp) {
136: addLayoutComponent(comp, name);
137: }
138:
139: /**
140: * Not used by this class.
141: *
142: * @param comp the component
143: */
144: public void removeLayoutComponent(Component comp) {
145: if (_affirmativeButtons.contains(comp)) {
146: _affirmativeButtons.remove(comp);
147: }
148: if (_cancelButtons.contains(comp)) {
149: _cancelButtons.remove(comp);
150: }
151: if (_helpButtons.contains(comp)) {
152: _helpButtons.remove(comp);
153: }
154: if (_otherButtons.contains(comp)) {
155: _otherButtons.remove(comp);
156: }
157: }
158:
159: /**
160: * Not used by this class.
161: *
162: * @param comp the component
163: * @param constraints constraints
164: */
165: public void addLayoutComponent(Component comp, Object constraints) {
166: if (ButtonPanel.AFFIRMATIVE_BUTTON.equals(constraints)) {
167: if (!_affirmativeButtons.contains(comp)) {
168: _affirmativeButtons.add(comp);
169: }
170: }
171:
172: if (ButtonPanel.CANCEL_BUTTON.equals(constraints)) {
173: if (!_cancelButtons.contains(comp)) {
174: _cancelButtons.add(comp);
175: }
176: }
177:
178: if (ButtonPanel.HELP_BUTTON.equals(constraints)) {
179: if (!_helpButtons.contains(comp)) {
180: _helpButtons.add(comp);
181: }
182: }
183:
184: if (ButtonPanel.OTHER_BUTTON.equals(constraints)) {
185: if (!_otherButtons.contains(comp)) {
186: _otherButtons.add(comp);
187: }
188: }
189: }
190:
191: /**
192: * Returns the preferred dimensions for this layout, given the components
193: * in the specified target container.
194: *
195: * @param target the container that needs to be laid out
196: * @return the dimensions >= 0 && <= Integer.MAX_VALUE
197: * @throws java.awt.AWTError if the target isn't the container specified to the
198: * BoxLayout constructor
199: * @see java.awt.Container
200: * @see #minimumLayoutSize
201: * @see #maximumLayoutSize
202: */
203: public Dimension preferredLayoutSize(Container target) {
204: Dimension size;
205: synchronized (this ) {
206: checkContainer(target);
207: checkRequests();
208: size = new Dimension(_xTotal.preferred, _yTotal.preferred);
209: }
210:
211: Insets insets = target.getInsets();
212: size.width = (int) Math.min((long) size.width
213: + (long) insets.left + (long) insets.right,
214: Integer.MAX_VALUE);
215: size.height = (int) Math.min((long) size.height
216: + (long) insets.top + (long) insets.bottom,
217: Integer.MAX_VALUE);
218: return size;
219: }
220:
221: /**
222: * Returns the minimum dimensions needed to lay out the components
223: * contained in the specified target container.
224: *
225: * @param target the container that needs to be laid out
226: * @return the dimensions >= 0 && <= Integer.MAX_VALUE
227: * @throws java.awt.AWTError if the target isn't the container specified to the
228: * BoxLayout constructor
229: * @see #preferredLayoutSize
230: * @see #maximumLayoutSize
231: */
232: public Dimension minimumLayoutSize(Container target) {
233: Dimension size;
234: synchronized (this ) {
235: checkContainer(target);
236: checkRequests();
237: size = new Dimension(_xTotal.minimum, _yTotal.minimum);
238: }
239:
240: Insets insets = target.getInsets();
241: size.width = (int) Math.min((long) size.width
242: + (long) insets.left + (long) insets.right,
243: Integer.MAX_VALUE);
244: size.height = (int) Math.min((long) size.height
245: + (long) insets.top + (long) insets.bottom,
246: Integer.MAX_VALUE);
247: return size;
248: }
249:
250: /**
251: * Returns the maximum dimensions the target container can use
252: * to lay out the components it contains.
253: *
254: * @param target the container that needs to be laid out
255: * @return the dimenions >= 0 && <= Integer.MAX_VALUE
256: * @throws java.awt.AWTError if the target isn't the container specified to the
257: * BoxLayout constructor
258: * @see #preferredLayoutSize
259: * @see #minimumLayoutSize
260: */
261: public Dimension maximumLayoutSize(Container target) {
262: Dimension size;
263: synchronized (this ) {
264: checkContainer(target);
265: checkRequests();
266: size = new Dimension(_xTotal.maximum, _yTotal.maximum);
267: }
268:
269: Insets insets = target.getInsets();
270: size.width = (int) Math.min((long) size.width
271: + (long) insets.left + (long) insets.right,
272: Integer.MAX_VALUE);
273: size.height = (int) Math.min((long) size.height
274: + (long) insets.top + (long) insets.bottom,
275: Integer.MAX_VALUE);
276: return size;
277: }
278:
279: /**
280: * Returns the alignment along the X axis for the container.
281: * If the box is horizontal, the default
282: * alignment will be returned. Otherwise, the alignment needed
283: * to place the children along the X axis will be returned.
284: *
285: * @param target the container
286: * @return the alignment >= 0.0f && <= 1.0f
287: * @throws java.awt.AWTError if the target isn't the container specified to the
288: * BoxLayout constructor
289: */
290: public synchronized float getLayoutAlignmentX(Container target) {
291: checkContainer(target);
292: checkRequests();
293: return _xTotal.alignment;
294: }
295:
296: /**
297: * Returns the alignment along the Y axis for the container.
298: * If the box is vertical, the default
299: * alignment will be returned. Otherwise, the alignment needed
300: * to place the children along the Y axis will be returned.
301: *
302: * @param target the container
303: * @return the alignment >= 0.0f && <= 1.0f
304: * @throws java.awt.AWTError if the target isn't the container specified to the
305: * BoxLayout constructor
306: */
307: public synchronized float getLayoutAlignmentY(Container target) {
308: checkContainer(target);
309: checkRequests();
310: return _yTotal.alignment;
311: }
312:
313: /**
314: * Called by the AWT <!-- XXX CHECK! --> when the specified container
315: * needs to be laid out.
316: *
317: * @param target the container to lay out
318: * @throws java.awt.AWTError if the target isn't the container specified to the
319: * BoxLayout constructor
320: */
321: public void layoutContainer(Container target) {
322: checkContainer(target);
323:
324: Dimension alloc = target.getSize();
325: Insets in = target.getInsets();
326: alloc.width -= in.left + in.right;
327: alloc.height -= in.top + in.bottom;
328:
329: // Resolve axis to an absolute value (either X_AXIS or Y_AXIS)
330: ComponentOrientation o = target.getComponentOrientation();
331: int absoluteAxis = resolveAxis(_axis, o);
332:
333: // determine the child placements
334: synchronized (this ) {
335: checkRequests();
336: resetBounds();
337: if (absoluteAxis == X_AXIS) {
338: int y = in.top;
339: if (_alignment == SwingConstants.CENTER) {
340: Dimension size = preferredLayoutSize(target);
341: // layout left aligned button first
342: int x = in.left + (alloc.width + size.width) / 2;
343: for (int i = 0; i < getButtonOrder().length(); i++) {
344: char c = getButtonOrder().charAt(
345: getButtonOrder().length() - i - 1);
346: if (c == 'A' || c == 'a') {
347: x = layoutButtonsRightAlign(
348: _affirmativeButtons, x, y, alloc);
349: } else if (c == 'C' || c == 'c') {
350: x = layoutButtonsRightAlign(_cancelButtons,
351: x, y, alloc);
352: } else if (c == 'H' || c == 'h') {
353: x = layoutButtonsRightAlign(_helpButtons,
354: x, y, alloc);
355: } else if (c == 'O' || c == 'o') {
356: x = layoutButtonsRightAlign(_otherButtons,
357: x, y, alloc);
358: }
359: }
360:
361: // layout right aligned button
362: // layout left aligned button first
363: x = in.left + (alloc.width - size.width) / 2;
364: for (int i = 0; i < getOppositeButtonOrder()
365: .length(); i++) {
366: char c = getOppositeButtonOrder().charAt(i);
367: if (c == 'A' || c == 'a') {
368: x = layoutButtonsLeftAlign(
369: _affirmativeButtons, x, y, alloc);
370: } else if (c == 'C' || c == 'c') {
371: x = layoutButtonsLeftAlign(_cancelButtons,
372: x, y, alloc);
373: } else if (c == 'H' || c == 'h') {
374: x = layoutButtonsLeftAlign(_helpButtons, x,
375: y, alloc);
376: } else if (c == 'O' || c == 'o') {
377: x = layoutButtonsLeftAlign(_otherButtons,
378: x, y, alloc);
379: }
380: }
381: } else if (_alignment == SwingConstants.RIGHT) {
382: // layout left aligned button first
383: int x = in.left + alloc.width;
384: for (int i = 0; i < getButtonOrder().length(); i++) {
385: char c = getButtonOrder().charAt(
386: getButtonOrder().length() - i - 1);
387: if (c == 'A' || c == 'a') {
388: x = layoutButtonsRightAlign(
389: _affirmativeButtons, x, y, alloc);
390: } else if (c == 'C' || c == 'c') {
391: x = layoutButtonsRightAlign(_cancelButtons,
392: x, y, alloc);
393: } else if (c == 'H' || c == 'h') {
394: x = layoutButtonsRightAlign(_helpButtons,
395: x, y, alloc);
396: } else if (c == 'O' || c == 'o') {
397: x = layoutButtonsRightAlign(_otherButtons,
398: x, y, alloc);
399: }
400: }
401:
402: // layout right aligned button
403: // layout left aligned button first
404: x = in.left;
405: for (int i = 0; i < getOppositeButtonOrder()
406: .length(); i++) {
407: char c = getOppositeButtonOrder().charAt(i);
408: if (c == 'A' || c == 'a') {
409: x = layoutButtonsLeftAlign(
410: _affirmativeButtons, x, y, alloc);
411: } else if (c == 'C' || c == 'c') {
412: x = layoutButtonsLeftAlign(_cancelButtons,
413: x, y, alloc);
414: } else if (c == 'H' || c == 'h') {
415: x = layoutButtonsLeftAlign(_helpButtons, x,
416: y, alloc);
417: } else if (c == 'O' || c == 'o') {
418: x = layoutButtonsLeftAlign(_otherButtons,
419: x, y, alloc);
420: }
421: }
422: } else if (_alignment == SwingConstants.LEFT) {
423: // layout left aligned button first
424: int x = in.left;
425: for (int i = 0; i < getButtonOrder().length(); i++) {
426: char c = getButtonOrder().charAt(i);
427: if (c == 'A' || c == 'a') {
428: x = layoutButtonsLeftAlign(
429: _affirmativeButtons, x, y, alloc);
430: } else if (c == 'C' || c == 'c') {
431: x = layoutButtonsLeftAlign(_cancelButtons,
432: x, y, alloc);
433: } else if (c == 'H' || c == 'h') {
434: x = layoutButtonsLeftAlign(_helpButtons, x,
435: y, alloc);
436: } else if (c == 'O' || c == 'o') {
437: x = layoutButtonsLeftAlign(_otherButtons,
438: x, y, alloc);
439: }
440: }
441:
442: // layout right aligned button
443: x = in.left + alloc.width;
444: for (int i = 0; i < getOppositeButtonOrder()
445: .length(); i++) {
446: char c = getOppositeButtonOrder().charAt(
447: getOppositeButtonOrder().length() - i
448: - 1);
449: if (c == 'A' || c == 'a') {
450: x = layoutButtonsRightAlign(
451: _affirmativeButtons, x, y, alloc);
452: } else if (c == 'C' || c == 'c') {
453: x = layoutButtonsRightAlign(_cancelButtons,
454: x, y, alloc);
455: } else if (c == 'H' || c == 'h') {
456: x = layoutButtonsRightAlign(_helpButtons,
457: x, y, alloc);
458: } else if (c == 'O' || c == 'o') {
459: x = layoutButtonsRightAlign(_otherButtons,
460: x, y, alloc);
461: }
462: }
463: }
464: } else {
465: int x = in.left;
466: if (_alignment == SwingConstants.TOP) {
467: // layout top aligned button first
468: int y = in.top;
469: for (int i = 0; i < getButtonOrder().length(); i++) {
470: char c = getButtonOrder().charAt(i);
471: if (c == 'A' || c == 'a') {
472: y = layoutButtonsTopAlign(
473: _affirmativeButtons, x, y, alloc);
474: } else if (c == 'C' || c == 'c') {
475: y = layoutButtonsTopAlign(_cancelButtons,
476: x, y, alloc);
477: } else if (c == 'H' || c == 'h') {
478: y = layoutButtonsTopAlign(_helpButtons, x,
479: y, alloc);
480: } else if (c == 'O' || c == 'o') {
481: y = layoutButtonsTopAlign(_otherButtons, x,
482: y, alloc);
483: }
484: }
485:
486: // layout bottom aligned button
487: y = in.top + alloc.height;
488: for (int i = 0; i < getOppositeButtonOrder()
489: .length(); i++) {
490: char c = getOppositeButtonOrder().charAt(
491: getOppositeButtonOrder().length() - i
492: - 1);
493: if (c == 'A' || c == 'a') {
494: y = layoutButtonsBottomAlign(
495: _affirmativeButtons, x, y, alloc);
496: } else if (c == 'C' || c == 'c') {
497: y = layoutButtonsBottomAlign(
498: _cancelButtons, x, y, alloc);
499: } else if (c == 'H' || c == 'h') {
500: y = layoutButtonsBottomAlign(_helpButtons,
501: x, y, alloc);
502: } else if (c == 'O' || c == 'o') {
503: y = layoutButtonsBottomAlign(_otherButtons,
504: x, y, alloc);
505: }
506: }
507: } else if (_alignment == SwingConstants.BOTTOM) {
508: // layout top aligned button first
509: int y = in.top + alloc.height;
510: for (int i = 0; i < getButtonOrder().length(); i++) {
511: char c = getButtonOrder().charAt(
512: getButtonOrder().length() - i - 1);
513: if (c == 'A' || c == 'a') {
514: y = layoutButtonsBottomAlign(
515: _affirmativeButtons, x, y, alloc);
516: } else if (c == 'C' || c == 'c') {
517: y = layoutButtonsBottomAlign(
518: _cancelButtons, x, y, alloc);
519: } else if (c == 'H' || c == 'h') {
520: y = layoutButtonsBottomAlign(_helpButtons,
521: x, y, alloc);
522: } else if (c == 'O' || c == 'o') {
523: y = layoutButtonsBottomAlign(_otherButtons,
524: x, y, alloc);
525: }
526: }
527:
528: // layout bottom aligned button
529: y = in.top;
530: for (int i = 0; i < getOppositeButtonOrder()
531: .length(); i++) {
532: char c = getOppositeButtonOrder().charAt(i);
533: if (c == 'A' || c == 'a') {
534: y = layoutButtonsTopAlign(
535: _affirmativeButtons, x, y, alloc);
536: } else if (c == 'C' || c == 'c') {
537: y = layoutButtonsTopAlign(_cancelButtons,
538: x, y, alloc);
539: } else if (c == 'H' || c == 'h') {
540: y = layoutButtonsTopAlign(_helpButtons, x,
541: y, alloc);
542: } else if (c == 'O' || c == 'o') {
543: y = layoutButtonsTopAlign(_otherButtons, x,
544: y, alloc);
545: }
546: }
547: }
548: }
549: }
550: }
551:
552: private int layoutButtonsRightAlign(List buttons, int x, int y,
553: Dimension alloc) {
554: boolean containsVisibleButton = false;
555: for (int i = _target.getComponentCount() - 1; i >= 0; i--) {
556: Component component = _target.getComponent(i);
557: if (!component.isVisible() || !buttons.contains(component)) {
558: continue;
559: }
560:
561: // TRACE FIX - only decrement the x if there are other buttons visible
562: if (containsVisibleButton) {
563: x -= _buttonGap;
564: }
565:
566: containsVisibleButton = true;
567: int prefWidth = component.getPreferredSize().width;
568: int width = prefWidth > _minWidth
569: || shouldKeepPreferredWidth(component) ? prefWidth
570: : _minWidth;
571: component.setBounds(x - width, y, width, alloc.height);
572: x -= width;
573: // TRACE FIX - see above, this was the original code
574: // if (i != 0) {
575: // x -= _buttonGap;
576: // }
577: }
578: if (buttons.size() != 0 && containsVisibleButton) {
579: x -= _groupGap;
580: }
581: return x;
582: }
583:
584: private int layoutButtonsLeftAlign(List<Component> buttons, int x,
585: int y, Dimension alloc) {
586: boolean containsVisibleButton;
587: for (int i = 0; i < _target.getComponentCount(); i++) {
588: Component component = _target.getComponent(i);
589: if (!component.isVisible() || !buttons.contains(component)) {
590: continue;
591: }
592: containsVisibleButton = true;
593: int prefWidth = component.getPreferredSize().width;
594: int width = prefWidth > _minWidth
595: || shouldKeepPreferredWidth(component) ? prefWidth
596: : _minWidth;
597: component.setBounds(x, y, width, alloc.height);
598: x += width;
599: if (i != buttons.size() - 1 && containsVisibleButton) {
600: x += _buttonGap;
601: }
602: }
603: if (buttons.size() != 0) {
604: x += _groupGap;
605: }
606: return x;
607: }
608:
609: private int layoutButtonsBottomAlign(List<Component> buttons,
610: int x, int y, Dimension alloc) {
611: boolean containsVisibleButton = false;
612: for (int i = _target.getComponentCount() - 1; i >= 0; i--) {
613: Component component = _target.getComponent(i);
614: if (!component.isVisible() || !buttons.contains(component)) {
615: continue;
616: }
617: containsVisibleButton = true;
618: Dimension preferredSize = component.getPreferredSize();
619: int height = preferredSize.height;
620: int prefWidth = preferredSize.width;
621: component.setBounds(
622: shouldKeepPreferredWidth(component) ? alloc.width
623: - prefWidth + x : x, y - height,
624: shouldKeepPreferredWidth(component) ? prefWidth
625: : alloc.width, height);
626: y -= height;
627: if (i != 0) {
628: y -= _buttonGap;
629: }
630: }
631: if (buttons.size() != 0 && containsVisibleButton) {
632: y -= _groupGap;
633: }
634: return y;
635: }
636:
637: private int layoutButtonsTopAlign(List<Component> buttons, int x,
638: int y, Dimension alloc) {
639: boolean containsVisibleButton = false;
640: for (int i = 0; i < _target.getComponentCount(); i++) {
641: Component component = _target.getComponent(i);
642: if (!component.isVisible() || !buttons.contains(component)) {
643: continue;
644: }
645: containsVisibleButton = true;
646: Dimension preferredSize = component.getPreferredSize();
647: int height = preferredSize.height;
648: int prefWidth = preferredSize.width;
649: component.setBounds(
650: shouldKeepPreferredWidth(component) ? alloc.width
651: - prefWidth + x : x, y,
652: shouldKeepPreferredWidth(component) ? prefWidth
653: : alloc.width, height);
654: y += height;
655: if (i != buttons.size() - 1) {
656: y += _buttonGap;
657: }
658: }
659: if (buttons.size() != 0 && containsVisibleButton) {
660: y += _groupGap;
661: }
662: return y;
663: }
664:
665: private boolean shouldKeepPreferredWidth(Component component) {
666: return component instanceof JComponent
667: && Boolean.TRUE
668: .equals(((JComponent) component)
669: .getClientProperty(ButtonPanel.KEEP_PREFERRED_WIDTH));
670: }
671:
672: void checkContainer(Container target) {
673: if (this ._target != target) {
674: throw new AWTError("BorderPaneLayout can't be shared");
675: }
676: if (!(target instanceof ButtonPanel)) {
677: throw new AWTError("Target is not a ButtonPanel");
678: }
679: }
680:
681: int getButtonCountof(List<Component> buttons) {
682: int count = 0;
683: for (Component button : buttons) {
684: if (button.isVisible()) {
685: count++;
686: }
687: }
688: return count;
689: }
690:
691: void checkRequests() {
692: int totalGroup = (getButtonCountof(_affirmativeButtons) == 0 ? 0
693: : 1)
694: + (getButtonCountof(_otherButtons) == 0 ? 0 : 1)
695: + (getButtonCountof(_cancelButtons) == 0 ? 0 : 1)
696: + (getButtonCountof(_helpButtons) == 0 ? 0 : 1);
697:
698: int totalButtonCount = getButtonCountof(_affirmativeButtons)
699: + getButtonCountof(_otherButtons)
700: + getButtonCountof(_cancelButtons)
701: + getButtonCountof(_helpButtons);
702:
703: if (_xChildren == null || _yChildren == null) {
704: // The requests have been invalidated... recalculate
705: // the request information.
706: int componentCount = _target.getComponentCount();
707: int visibleComponentCount = componentCount;
708: for (int i = 0; i < componentCount; i++) {
709: if (!_target.getComponent(i).isVisible()) {
710: visibleComponentCount--;
711: }
712: }
713:
714: _xChildren = new SizeRequirements[visibleComponentCount];
715: _yChildren = new SizeRequirements[visibleComponentCount];
716: int index = 0;
717: for (int i = 0; i < componentCount; i++) {
718: Component c = _target.getComponent(i);
719: if (!c.isVisible()) {
720: continue;
721: }
722: Dimension min = c.getMinimumSize();
723: Dimension typ = c.getPreferredSize();
724: Dimension max = c.getMaximumSize();
725: _xChildren[index] = new SizeRequirements(min.width,
726: typ.width, max.width, c.getAlignmentX());
727: _yChildren[index] = new SizeRequirements(min.height,
728: typ.height, max.height, c.getAlignmentY());
729: if (shouldKeepPreferredWidth(_target.getComponent(i))) {
730: _xChildren[index].maximum = 0;
731: }
732: index++;
733: }
734:
735: // Resolve axis to an absolute value (either X_AXIS or Y_AXIS)
736: int absoluteAxis = resolveAxis(_axis, _target
737: .getComponentOrientation());
738:
739: if (absoluteAxis == X_AXIS) {
740: _xTotal = SizeRequirements
741: .getTiledSizeRequirements(_xChildren);
742: _yTotal = SizeRequirements
743: .getAlignedSizeRequirements(_yChildren);
744:
745: _maxWidth = SizeRequirements
746: .getAlignedSizeRequirements(_xChildren).maximum;
747:
748: if (_sizeConstraint == ButtonPanel.SAME_SIZE) {
749: int width = getMinButtonWidth();
750: if (_maxWidth < width) {
751: _maxWidth = width;
752: }
753: _minWidth = _maxWidth;
754: } else {
755: int width = getMinButtonWidth();
756: if (width == 0) {
757: _minWidth = 75;
758: } else {
759: _minWidth = width;
760: }
761: }
762:
763: for (SizeRequirements sizeRequirements : _xChildren) {
764: if (sizeRequirements.preferred < _minWidth) {
765: sizeRequirements.preferred = _minWidth;
766: }
767: }
768: _xTotal = SizeRequirements
769: .getTiledSizeRequirements(_xChildren);
770:
771: // add gap
772: _xTotal.preferred += (totalGroup - 1) * _groupGap
773: + (totalButtonCount - totalGroup) * _buttonGap;
774: _xTotal.minimum += (totalGroup - 1) * _groupGap
775: + (totalButtonCount - totalGroup) * _buttonGap;
776:
777: } else {
778: _xTotal = SizeRequirements
779: .getAlignedSizeRequirements(_xChildren);
780: _yTotal = SizeRequirements
781: .getTiledSizeRequirements(_yChildren);
782:
783: int width = getMinButtonWidth();
784: if (width == 0) {
785: _maxWidth = 75;
786: } else {
787: _maxWidth = width;
788: }
789: _minWidth = _maxWidth;
790: _xTotal.preferred = (_maxWidth > _xTotal.maximum) ? _maxWidth
791: : _xTotal.preferred;
792:
793: // add gap
794: _yTotal.preferred += (totalGroup - 1) * _groupGap
795: + (totalButtonCount - totalGroup) * _buttonGap;
796: _yTotal.minimum += (totalGroup - 1) * _groupGap
797: + (totalButtonCount - totalGroup) * _buttonGap;
798: }
799: }
800: }
801:
802: /**
803: * Given one of the 4 axis values, resolve it to an absolute axis.
804: * The relative axis values, PAGE_AXIS and LINE_AXIS are converted
805: * to their absolute couterpart given the target's ComponentOrientation
806: * value. The absolute axes, X_AXIS and Y_AXIS are returned unmodified.
807: *
808: * @param axis the axis to resolve
809: * @param o the ComponentOrientation to resolve against
810: * @return the resolved axis
811: */
812: private int resolveAxis(int axis, ComponentOrientation o) {
813: int absoluteAxis;
814: if (axis == LINE_AXIS) {
815: absoluteAxis = o.isHorizontal() ? X_AXIS : Y_AXIS;
816: } else if (axis == PAGE_AXIS) {
817: absoluteAxis = o.isHorizontal() ? Y_AXIS : X_AXIS;
818: } else {
819: absoluteAxis = axis;
820: }
821: return absoluteAxis;
822: }
823:
824: public int getGroupGap() {
825: return _groupGap;
826: }
827:
828: public void setGroupGap(int groupGap) {
829: _groupGap = groupGap;
830: invalidateLayout(_target);
831: }
832:
833: public int getButtonGap() {
834: return _buttonGap;
835: }
836:
837: public void setButtonGap(int buttonGap) {
838: _buttonGap = buttonGap;
839: invalidateLayout(_target);
840: }
841:
842: public int getSizeConstraint() {
843: return _sizeConstraint;
844: }
845:
846: public void setSizeConstraint(int sizeConstraint) {
847: _sizeConstraint = sizeConstraint;
848: invalidateLayout(_target);
849: }
850:
851: public int getMinButtonWidth() {
852: return _minButtonWidth;
853: }
854:
855: public void setMinButtonWidth(int minButtonWidth) {
856: _minButtonWidth = minButtonWidth;
857: invalidateLayout(_target);
858: }
859:
860: public String getButtonOrder() {
861: if (_buttonOrder == null) {
862: return "";
863: } else {
864: return _buttonOrder;
865: }
866: }
867:
868: public void setButtonOrder(String buttonOrder) {
869: _buttonOrder = buttonOrder;
870: invalidateLayout(_target);
871: }
872:
873: public String getOppositeButtonOrder() {
874: if (_oppositeButtonOrder == null) {
875: return "";
876: } else {
877: return _oppositeButtonOrder;
878: }
879: }
880:
881: public void setOppositeButtonOrder(String oppositeButtonOrder) {
882: _oppositeButtonOrder = oppositeButtonOrder;
883: invalidateLayout(_target);
884: }
885:
886: public int getAxis() {
887: return _axis;
888: }
889:
890: public void setAxis(int axis) {
891: _axis = axis;
892: invalidateLayout(_target);
893: }
894:
895: public int getAlignment() {
896: return _alignment;
897: }
898:
899: public void setAlignment(int alignment) {
900: _alignment = alignment;
901: invalidateLayout(_target);
902: }
903:
904: void resetBounds() {
905: for (Component component : _affirmativeButtons) {
906: component.setBounds(0, 0, 0, 0);
907: }
908: for (Component component : _cancelButtons) {
909: component.setBounds(0, 0, 0, 0);
910: }
911: for (Component component : _otherButtons) {
912: component.setBounds(0, 0, 0, 0);
913: }
914: for (Component component : _helpButtons) {
915: component.setBounds(0, 0, 0, 0);
916: }
917: }
918: }
|