History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/awt/FlowLayout.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/awt/FlowLayout.java+696−0
@@ -0,0 +1,696 @@
1+/*
2+ * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+package java.awt;
26+
27+import java.io.ObjectInputStream;
28+import java.io.IOException;
29+
30+/**
31+ * A flow layout arranges components in a directional flow, much
32+ * like lines of text in a paragraph. The flow direction is
33+ * determined by the container's <code>componentOrientation</code>
34+ * property and may be one of two values:
35+ * <ul>
36+ * <li><code>ComponentOrientation.LEFT_TO_RIGHT</code>
37+ * <li><code>ComponentOrientation.RIGHT_TO_LEFT</code>
38+ * </ul>
39+ * Flow layouts are typically used
40+ * to arrange buttons in a panel. It arranges buttons
41+ * horizontally until no more buttons fit on the same line.
42+ * The line alignment is determined by the <code>align</code>
43+ * property. The possible values are:
44+ * <ul>
45+ * <li>{@link #LEFT LEFT}
46+ * <li>{@link #RIGHT RIGHT}
47+ * <li>{@link #CENTER CENTER}
48+ * <li>{@link #LEADING LEADING}
49+ * <li>{@link #TRAILING TRAILING}
50+ * </ul>
51+ * <p>
52+ * For example, the following picture shows an applet using the flow
53+ * layout manager (its default layout manager) to position three buttons:
54+ * <p>
55+ * <img src="doc-files/FlowLayout-1.gif"
56+ * ALT="Graphic of Layout for Three Buttons"
57+ * ALIGN=center HSPACE=10 VSPACE=7>
58+ * <p>
59+ * Here is the code for this applet:
60+ * <p>
61+ * <hr><blockquote><pre>
62+ * import java.awt.*;
63+ * import java.applet.Applet;
64+ *
65+ * public class myButtons extends Applet {
66+ * Button button1, button2, button3;
67+ * public void init() {
68+ * button1 = new Button("Ok");
69+ * button2 = new Button("Open");
70+ * button3 = new Button("Close");
71+ * add(button1);
72+ * add(button2);
73+ * add(button3);
74+ * }
75+ * }
76+ * </pre></blockquote><hr>
77+ * <p>
78+ * A flow layout lets each component assume its natural (preferred) size.
79+ *
80+ * @author Arthur van Hoff
81+ * @author Sami Shaio
82+ * @since JDK1.0
83+ * @see ComponentOrientation
84+ */
85+public class FlowLayout implements LayoutManager, java.io.Serializable {
86+
87+ /**
88+ * This value indicates that each row of components
89+ * should be left-justified.
90+ */
91+ public static final int LEFT = 0;
92+
93+ /**
94+ * This value indicates that each row of components
95+ * should be centered.
96+ */
97+ public static final int CENTER = 1;
98+
99+ /**
100+ * This value indicates that each row of components
101+ * should be right-justified.
102+ */
103+ public static final int RIGHT = 2;
104+
105+ /**
106+ * This value indicates that each row of components
107+ * should be justified to the leading edge of the container's
108+ * orientation, for example, to the left in left-to-right orientations.
109+ *
110+ * @see java.awt.Component#getComponentOrientation
111+ * @see java.awt.ComponentOrientation
112+ * @since 1.2
113+ */
114+ public static final int LEADING = 3;
115+
116+ /**
117+ * This value indicates that each row of components
118+ * should be justified to the trailing edge of the container's
119+ * orientation, for example, to the right in left-to-right orientations.
120+ *
121+ * @see java.awt.Component#getComponentOrientation
122+ * @see java.awt.ComponentOrientation
123+ * @since 1.2
124+ */
125+ public static final int TRAILING = 4;
126+
127+ /**
128+ * <code>align</code> is the property that determines
129+ * how each row distributes empty space.
130+ * It can be one of the following values:
131+ * <ul>
132+ * <code>LEFT</code>
133+ * <code>RIGHT</code>
134+ * <code>CENTER</code>
135+ * </ul>
136+ *
137+ * @serial
138+ * @see #getAlignment
139+ * @see #setAlignment
140+ */
141+ int align; // This is for 1.1 serialization compatibility
142+
143+ /**
144+ * <code>newAlign</code> is the property that determines
145+ * how each row distributes empty space for the Java 2 platform,
146+ * v1.2 and greater.
147+ * It can be one of the following three values:
148+ * <ul>
149+ * <code>LEFT</code>
150+ * <code>RIGHT</code>
151+ * <code>CENTER</code>
152+ * <code>LEADING</code>
153+ * <code>TRAILING</code>
154+ * </ul>
155+ *
156+ * @serial
157+ * @since 1.2
158+ * @see #getAlignment
159+ * @see #setAlignment
160+ */
161+ int newAlign; // This is the one we actually use
162+
163+ /**
164+ * The flow layout manager allows a seperation of
165+ * components with gaps. The horizontal gap will
166+ * specify the space between components and between
167+ * the components and the borders of the
168+ * <code>Container</code>.
169+ *
170+ * @serial
171+ * @see #getHgap()
172+ * @see #setHgap(int)
173+ */
174+ int hgap;
175+
176+ /**
177+ * The flow layout manager allows a seperation of
178+ * components with gaps. The vertical gap will
179+ * specify the space between rows and between the
180+ * the rows and the borders of the <code>Container</code>.
181+ *
182+ * @serial
183+ * @see #getHgap()
184+ * @see #setHgap(int)
185+ */
186+ int vgap;
187+
188+ /**
189+ * If true, components will be aligned on their baseline.
190+ */
191+ private boolean alignOnBaseline;
192+
193+ /*
194+ * JDK 1.1 serialVersionUID
195+ */
196+ private static final long serialVersionUID = -7262534875583282631L;
197+
198+ /**
199+ * Constructs a new <code>FlowLayout</code> with a centered alignment and a
200+ * default 5-unit horizontal and vertical gap.
201+ */
202+ public FlowLayout() {
203+ this(CENTER, 5, 5);
204+ }
205+
206+ /**
207+ * Constructs a new <code>FlowLayout</code> with the specified
208+ * alignment and a default 5-unit horizontal and vertical gap.
209+ * The value of the alignment argument must be one of
210+ * <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,
211+ * <code>FlowLayout.CENTER</code>, <code>FlowLayout.LEADING</code>,
212+ * or <code>FlowLayout.TRAILING</code>.
213+ * @param align the alignment value
214+ */
215+ public FlowLayout(int align) {
216+ this(align, 5, 5);
217+ }
218+
219+ /**
220+ * Creates a new flow layout manager with the indicated alignment
221+ * and the indicated horizontal and vertical gaps.
222+ * <p>
223+ * The value of the alignment argument must be one of
224+ * <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,
225+ * <code>FlowLayout.CENTER</code>, <code>FlowLayout.LEADING</code>,
226+ * or <code>FlowLayout.TRAILING</code>.
227+ * @param align the alignment value
228+ * @param hgap the horizontal gap between components
229+ * and between the components and the
230+ * borders of the <code>Container</code>
231+ * @param vgap the vertical gap between components
232+ * and between the components and the
233+ * borders of the <code>Container</code>
234+ */
235+ public FlowLayout(int align, int hgap, int vgap) {
236+ this.hgap = hgap;
237+ this.vgap = vgap;
238+ setAlignment(align);
239+ }
240+
241+ /**
242+ * Gets the alignment for this layout.
243+ * Possible values are <code>FlowLayout.LEFT</code>,
244+ * <code>FlowLayout.RIGHT</code>, <code>FlowLayout.CENTER</code>,
245+ * <code>FlowLayout.LEADING</code>,
246+ * or <code>FlowLayout.TRAILING</code>.
247+ * @return the alignment value for this layout
248+ * @see java.awt.FlowLayout#setAlignment
249+ * @since JDK1.1
250+ */
251+ public int getAlignment() {
252+ return newAlign;
253+ }
254+
255+ /**
256+ * Sets the alignment for this layout.
257+ * Possible values are
258+ * <ul>
259+ * <li><code>FlowLayout.LEFT</code>
260+ * <li><code>FlowLayout.RIGHT</code>
261+ * <li><code>FlowLayout.CENTER</code>
262+ * <li><code>FlowLayout.LEADING</code>
263+ * <li><code>FlowLayout.TRAILING</code>
264+ * </ul>
265+ * @param align one of the alignment values shown above
266+ * @see #getAlignment()
267+ * @since JDK1.1
268+ */
269+ public void setAlignment(int align) {
270+ this.newAlign = align;
271+
272+ // this.align is used only for serialization compatibility,
273+ // so set it to a value compatible with the 1.1 version
274+ // of the class
275+
276+ switch (align) {
277+ case LEADING:
278+ this.align = LEFT;
279+ break;
280+ case TRAILING:
281+ this.align = RIGHT;
282+ break;
283+ default:
284+ this.align = align;
285+ break;
286+ }
287+ }
288+
289+ /**
290+ * Gets the horizontal gap between components
291+ * and between the components and the borders
292+ * of the <code>Container</code>
293+ *
294+ * @return the horizontal gap between components
295+ * and between the components and the borders
296+ * of the <code>Container</code>
297+ * @see java.awt.FlowLayout#setHgap
298+ * @since JDK1.1
299+ */
300+ public int getHgap() {
301+ return hgap;
302+ }
303+
304+ /**
305+ * Sets the horizontal gap between components and
306+ * between the components and the borders of the
307+ * <code>Container</code>.
308+ *
309+ * @param hgap the horizontal gap between components
310+ * and between the components and the borders
311+ * of the <code>Container</code>
312+ * @see java.awt.FlowLayout#getHgap
313+ * @since JDK1.1
314+ */
315+ public void setHgap(int hgap) {
316+ this.hgap = hgap;
317+ }
318+
319+ /**
320+ * Gets the vertical gap between components and
321+ * between the components and the borders of the
322+ * <code>Container</code>.
323+ *
324+ * @return the vertical gap between components
325+ * and between the components and the borders
326+ * of the <code>Container</code>
327+ * @see java.awt.FlowLayout#setVgap
328+ * @since JDK1.1
329+ */
330+ public int getVgap() {
331+ return vgap;
332+ }
333+
334+ /**
335+ * Sets the vertical gap between components and between
336+ * the components and the borders of the <code>Container</code>.
337+ *
338+ * @param vgap the vertical gap between components
339+ * and between the components and the borders
340+ * of the <code>Container</code>
341+ * @see java.awt.FlowLayout#getVgap
342+ * @since JDK1.1
343+ */
344+ public void setVgap(int vgap) {
345+ this.vgap = vgap;
346+ }
347+
348+ /**
349+ * Sets whether or not components should be vertically aligned along their
350+ * baseline. Components that do not have a baseline will be centered.
351+ * The default is false.
352+ *
353+ * @param alignOnBaseline whether or not components should be
354+ * vertically aligned on their baseline
355+ * @since 1.6
356+ */
357+ public void setAlignOnBaseline(boolean alignOnBaseline) {
358+ this.alignOnBaseline = alignOnBaseline;
359+ }
360+
361+ /**
362+ * Returns true if components are to be vertically aligned along
363+ * their baseline. The default is false.
364+ *
365+ * @return true if components are to be vertically aligned along
366+ * their baseline
367+ * @since 1.6
368+ */
369+ public boolean getAlignOnBaseline() {
370+ return alignOnBaseline;
371+ }
372+
373+ /**
374+ * Adds the specified component to the layout.
375+ * Not used by this class.
376+ * @param name the name of the component
377+ * @param comp the component to be added
378+ */
379+ public void addLayoutComponent(String name, Component comp) {
380+ }
381+
382+ /**
383+ * Removes the specified component from the layout.
384+ * Not used by this class.
385+ * @param comp the component to remove
386+ * @see java.awt.Container#removeAll
387+ */
388+ public void removeLayoutComponent(Component comp) {
389+ }
390+
391+ /**
392+ * Returns the preferred dimensions for this layout given the
393+ * <i>visible</i> components in the specified target container.
394+ *
395+ * @param target the container that needs to be laid out
396+ * @return the preferred dimensions to lay out the
397+ * subcomponents of the specified container
398+ * @see Container
399+ * @see #minimumLayoutSize
400+ * @see java.awt.Container#getPreferredSize
401+ */
402+ public Dimension preferredLayoutSize(Container target) {
403+ synchronized (target.getTreeLock()) {
404+ Dimension dim = new Dimension(0, 0);
405+ int nmembers = target.getComponentCount();
406+ boolean firstVisibleComponent = true;
407+ boolean useBaseline = getAlignOnBaseline();
408+ int maxAscent = 0;
409+ int maxDescent = 0;
410+
411+ for (int i = 0 ; i < nmembers ; i++) {
412+ Component m = target.getComponent(i);
413+ if (m.isVisible()) {
414+ Dimension d = m.getPreferredSize();
415+ dim.height = Math.max(dim.height, d.height);
416+ if (firstVisibleComponent) {
417+ firstVisibleComponent = false;
418+ } else {
419+ dim.width += hgap;
420+ }
421+ dim.width += d.width;
422+ if (useBaseline) {
423+ int baseline = m.getBaseline(d.width, d.height);
424+ if (baseline >= 0) {
425+ maxAscent = Math.max(maxAscent, baseline);
426+ maxDescent = Math.max(maxDescent, d.height - baseline);
427+ }
428+ }
429+ }
430+ }
431+ if (useBaseline) {
432+ dim.height = Math.max(maxAscent + maxDescent, dim.height);
433+ }
434+ Insets insets = target.getInsets();
435+ dim.width += insets.left + insets.right + hgap*2;
436+ dim.height += insets.top + insets.bottom + vgap*2;
437+ return dim;
438+ }
439+ }
440+
441+ /**
442+ * Returns the minimum dimensions needed to layout the <i>visible</i>
443+ * components contained in the specified target container.
444+ * @param target the container that needs to be laid out
445+ * @return the minimum dimensions to lay out the
446+ * subcomponents of the specified container
447+ * @see #preferredLayoutSize
448+ * @see java.awt.Container
449+ * @see java.awt.Container#doLayout
450+ */
451+ public Dimension minimumLayoutSize(Container target) {
452+ synchronized (target.getTreeLock()) {
453+ boolean useBaseline = getAlignOnBaseline();
454+ Dimension dim = new Dimension(0, 0);
455+ int nmembers = target.getComponentCount();
456+ int maxAscent = 0;
457+ int maxDescent = 0;
458+ boolean firstVisibleComponent = true;
459+
460+ for (int i = 0 ; i < nmembers ; i++) {
461+ Component m = target.getComponent(i);
462+ if (m.visible) {
463+ Dimension d = m.getMinimumSize();
464+ dim.height = Math.max(dim.height, d.height);
465+ if (firstVisibleComponent) {
466+ firstVisibleComponent = false;
467+ } else {
468+ dim.width += hgap;
469+ }
470+ dim.width += d.width;
471+ if (useBaseline) {
472+ int baseline = m.getBaseline(d.width, d.height);
473+ if (baseline >= 0) {
474+ maxAscent = Math.max(maxAscent, baseline);
475+ maxDescent = Math.max(maxDescent,
476+ dim.height - baseline);
477+ }
478+ }
479+}
480+}
481+
482+ if (useBaseline) {
483+ dim.height = Math.max(maxAscent + maxDescent, dim.height);
484+ }
485+
486+ Insets insets = target.getInsets();
487+ dim.width += insets.left + insets.right + hgap*2;
488+ dim.height += insets.top + insets.bottom + vgap*2;
489+ return dim;
490+
491+
492+
493+
494+
495+ }
496+ }
497+
498+ /**
499+ * Centers the elements in the specified row, if there is any slack.
500+ * @param target the component which needs to be moved
501+ * @param x the x coordinate
502+ * @param y the y coordinate
503+ * @param width the width dimensions
504+ * @param height the height dimensions
505+ * @param rowStart the beginning of the row
506+ * @param rowEnd the the ending of the row
507+ * @param useBaseline Whether or not to align on baseline.
508+ * @param ascent Ascent for the components. This is only valid if
509+ * useBaseline is true.
510+ * @param descent Ascent for the components. This is only valid if
511+ * useBaseline is true.
512+ * @return actual row height
513+ */
514+ private int moveComponents(Container target, int x, int y, int width, int height,
515+ int rowStart, int rowEnd, boolean ltr,
516+ boolean useBaseline, int[] ascent,
517+ int[] descent) {
518+ switch (newAlign) {
519+ case LEFT:
520+ x += ltr ? 0 : width;
521+ break;
522+ case CENTER:
523+ x += width / 2;
524+ break;
525+ case RIGHT:
526+ x += ltr ? width : 0;
527+ break;
528+ case LEADING:
529+ break;
530+ case TRAILING:
531+ x += width;
532+ break;
533+ }
534+ int maxAscent = 0;
535+ int nonbaselineHeight = 0;
536+ int baselineOffset = 0;
537+ if (useBaseline) {
538+ int maxDescent = 0;
539+ for (int i = rowStart ; i < rowEnd ; i++) {
540+ Component m = target.getComponent(i);
541+ if (m.visible) {
542+ if (ascent[i] >= 0) {
543+ maxAscent = Math.max(maxAscent, ascent[i]);
544+ maxDescent = Math.max(maxDescent, descent[i]);
545+ }
546+ else {
547+ nonbaselineHeight = Math.max(m.getHeight(),
548+ nonbaselineHeight);
549+ }
550+ }
551+ }
552+ height = Math.max(maxAscent + maxDescent, nonbaselineHeight);
553+ baselineOffset = (height - maxAscent - maxDescent) / 2;
554+ }
555+ for (int i = rowStart ; i < rowEnd ; i++) {
556+ Component m = target.getComponent(i);
557+ if (m.isVisible()) {
558+ int cy;
559+ if (useBaseline && ascent[i] >= 0) {
560+ cy = y + baselineOffset + maxAscent - ascent[i];
561+ }
562+ else {
563+ cy = y + (height - m.height) / 2;
564+ }
565+ if (ltr) {
566+ m.setLocation(x, cy);
567+ } else {
568+ m.setLocation(target.width - x - m.width, cy);
569+ }
570+ x += m.width + hgap;
571+ }
572+ }
573+ return height;
574+ }
575+
576+ /**
577+ * Lays out the container. This method lets each
578+ * <i>visible</i> component take
579+ * its preferred size by reshaping the components in the
580+ * target container in order to satisfy the alignment of
581+ * this <code>FlowLayout</code> object.
582+ *
583+ * @param target the specified component being laid out
584+ * @see Container
585+ * @see java.awt.Container#doLayout
586+ */
587+ public void layoutContainer(Container target) {
588+ synchronized (target.getTreeLock()) {
589+ Insets insets = target.getInsets();
590+ int maxwidth = target.width - (insets.left + insets.right + hgap*2);
591+ int nmembers = target.getComponentCount();
592+ int x = 0, y = insets.top + vgap;
593+ int rowh = 0, start = 0;
594+
595+ boolean ltr = target.getComponentOrientation().isLeftToRight();
596+
597+ boolean useBaseline = getAlignOnBaseline();
598+ int[] ascent = null;
599+ int[] descent = null;
600+
601+ if (useBaseline) {
602+ ascent = new int[nmembers];
603+ descent = new int[nmembers];
604+ }
605+
606+ for (int i = 0 ; i < nmembers ; i++) {
607+ Component m = target.getComponent(i);
608+ if (m.isVisible()) {
609+ Dimension d = m.getPreferredSize();
610+ m.setSize(d.width, d.height);
611+
612+ if (useBaseline) {
613+ int baseline = m.getBaseline(d.width, d.height);
614+ if (baseline >= 0) {
615+ ascent[i] = baseline;
616+ descent[i] = d.height - baseline;
617+ }
618+ else {
619+ ascent[i] = -1;
620+ }
621+ }
622+ if ((x == 0) || ((x + d.width) <= maxwidth)) {
623+ if (x > 0) {
624+ x += hgap;
625+ }
626+ x += d.width;
627+ rowh = Math.max(rowh, d.height);
628+ } else {
629+ rowh = moveComponents(target, insets.left + hgap, y,
630+ maxwidth - x, rowh, start, i, ltr,
631+ useBaseline, ascent, descent);
632+ x = d.width;
633+ y += vgap + rowh;
634+ rowh = d.height;
635+ start = i;
636+ }
637+ }
638+ }
639+ moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh,
640+ start, nmembers, ltr, useBaseline, ascent, descent);
641+ }
642+ }
643+
644+ //
645+ // the internal serial version which says which version was written
646+ // - 0 (default) for versions before the Java 2 platform, v1.2
647+ // - 1 for version >= Java 2 platform v1.2, which includes "newAlign" field
648+ //
649+ private static final int currentSerialVersion = 1;
650+ /**
651+ * This represent the <code>currentSerialVersion</code>
652+ * which is bein used. It will be one of two values :
653+ * <code>0</code> versions before Java 2 platform v1.2..
654+ * <code>1</code> versions after Java 2 platform v1.2..
655+ *
656+ * @serial
657+ * @since 1.2
658+ */
659+ private int serialVersionOnStream = currentSerialVersion;
660+
661+ /**
662+ * Reads this object out of a serialization stream, handling
663+ * objects written by older versions of the class that didn't contain all
664+ * of the fields we use now..
665+ */
666+ private void readObject(ObjectInputStream stream)
667+ throws IOException, ClassNotFoundException
668+ {
669+ stream.defaultReadObject();
670+
671+ if (serialVersionOnStream < 1) {
672+ // "newAlign" field wasn't present, so use the old "align" field.
673+ setAlignment(this.align);
674+ }
675+ serialVersionOnStream = currentSerialVersion;
676+ }
677+
678+ /**
679+ * Returns a string representation of this <code>FlowLayout</code>
680+ * object and its values.
681+ * @return a string representation of this layout
682+ */
683+ public String toString() {
684+ String str = "";
685+ switch (align) {
686+ case LEFT: str = ",align=left"; break;
687+ case CENTER: str = ",align=center"; break;
688+ case RIGHT: str = ",align=right"; break;
689+ case LEADING: str = ",align=leading"; break;
690+ case TRAILING: str = ",align=trailing"; break;
691+ }
692+ return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + str + "]";
693+ }
694+
695+
696+}