Libraryless. Click here for Pure Java version (219L/2K).
1 | // FlowLayout subclass that fully supports wrapping of components |
2 | // (showing in multiple lines) |
3 | |
4 | // from https://tips4java.wordpress.com/2008/11/06/wrap-layout/ |
5 | |
6 | sclass WrapLayout extends FlowLayout { |
7 | private Dimension preferredLayoutSize; |
8 | |
9 | bool preferredAsMinimum = false; |
10 | |
11 | /** |
12 | * Constructs a new <code>WrapLayout</code> with a left |
13 | * alignment and a default 5-unit horizontal and vertical gap. |
14 | */ |
15 | *() {} |
16 | |
17 | /** |
18 | * Constructs a new <code>FlowLayout</code> with the specified |
19 | * alignment and a default 5-unit horizontal and vertical gap. |
20 | * The value of the alignment argument must be one of |
21 | * <code>WrapLayout</code>, <code>WrapLayout</code>, |
22 | * or <code>WrapLayout</code>. |
23 | * @param align the alignment value |
24 | */ |
25 | public WrapLayout(int align) |
26 | { |
27 | super(align); |
28 | } |
29 | |
30 | /** |
31 | * Creates a new flow layout manager with the indicated alignment |
32 | * and the indicated horizontal and vertical gaps. |
33 | * <p> |
34 | * The value of the alignment argument must be one of |
35 | * <code>WrapLayout</code>, <code>WrapLayout</code>, |
36 | * or <code>WrapLayout</code>. |
37 | * @param align the alignment value |
38 | * @param hgap the horizontal gap between components |
39 | * @param vgap the vertical gap between components |
40 | */ |
41 | public WrapLayout(int align, int hgap, int vgap) |
42 | { |
43 | super(align, hgap, vgap); |
44 | } |
45 | |
46 | /** |
47 | * Returns the preferred dimensions for this layout given the |
48 | * <i>visible</i> components in the specified target container. |
49 | * @param target the component which needs to be laid out |
50 | * @return the preferred dimensions to lay out the |
51 | * subcomponents of the specified container |
52 | */ |
53 | @Override |
54 | public Dimension preferredLayoutSize(Container target) |
55 | { |
56 | return layoutSize(target, true); |
57 | } |
58 | |
59 | /** |
60 | * Returns the minimum dimensions needed to layout the <i>visible</i> |
61 | * components contained in the specified target container. |
62 | * @param target the component which needs to be laid out |
63 | * @return the minimum dimensions to lay out the |
64 | * subcomponents of the specified container |
65 | */ |
66 | @Override |
67 | public Dimension minimumLayoutSize(Container target) |
68 | { |
69 | Dimension minimum = layoutSize(target, preferredAsMinimum); |
70 | minimum.width -= (getHgap() + 1); |
71 | return minimum; |
72 | } |
73 | |
74 | /** |
75 | * Returns the minimum or preferred dimension needed to layout the target |
76 | * container. |
77 | * |
78 | * @param target target to get layout size for |
79 | * @param preferred should preferred size be calculated |
80 | * @return the dimension to layout the target container |
81 | */ |
82 | private Dimension layoutSize(Container target, boolean preferred) |
83 | { |
84 | synchronized (target.getTreeLock()) |
85 | { |
86 | // Each row must fit with the width allocated to the containter. |
87 | // When the container width = 0, the preferred width of the container |
88 | // has not yet been calculated so lets ask for the maximum. |
89 | |
90 | int targetWidth = target.getSize().width; |
91 | print ifdef WrapLayout_debug(+targetWidth); |
92 | Container container = target; |
93 | |
94 | while (container.getSize().width == 0 && container.getParent() != null) |
95 | { |
96 | container = container.getParent(); |
97 | } |
98 | |
99 | targetWidth = container.getSize().width; |
100 | |
101 | if (targetWidth == 0) |
102 | targetWidth = Integer.MAX_VALUE; |
103 | |
104 | int hgap = getHgap(); |
105 | int vgap = getVgap(); |
106 | Insets insets = target.getInsets(); |
107 | int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2); |
108 | int maxWidth = targetWidth - horizontalInsetsAndGap; |
109 | |
110 | // Fit components into the allowed width |
111 | |
112 | Dimension dim = new Dimension(0, 0); |
113 | int rowWidth = 0; |
114 | int rowHeight = 0; |
115 | |
116 | int nmembers = target.getComponentCount(); |
117 | |
118 | for (int i = 0; i < nmembers; i++) |
119 | { |
120 | Component m = target.getComponent(i); |
121 | |
122 | if (m.isVisible()) |
123 | { |
124 | Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize(); |
125 | |
126 | // Can't add the component to current row. Start a new row. |
127 | |
128 | if (rowWidth + d.width > maxWidth) |
129 | { |
130 | addRow(dim, rowWidth, rowHeight); |
131 | rowWidth = 0; |
132 | rowHeight = 0; |
133 | } |
134 | |
135 | // Add a horizontal gap for all components after the first |
136 | |
137 | if (rowWidth != 0) |
138 | { |
139 | rowWidth += hgap; |
140 | } |
141 | |
142 | rowWidth += d.width; |
143 | rowHeight = Math.max(rowHeight, d.height); |
144 | } |
145 | } |
146 | |
147 | addRow(dim, rowWidth, rowHeight); |
148 | |
149 | dim.width += horizontalInsetsAndGap; |
150 | dim.height += insets.top + insets.bottom + vgap * 2; |
151 | |
152 | // When using a scroll pane or the DecoratedLookAndFeel we need to |
153 | // make sure the preferred size is less than the size of the |
154 | // target containter so shrinking the container size works |
155 | // correctly. Removing the horizontal gap is an easy way to do this. |
156 | |
157 | Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target); |
158 | |
159 | if (scrollPane != null && target.isValid()) |
160 | { |
161 | dim.width -= (hgap + 1); |
162 | } |
163 | |
164 | ifdef WrapLayout_debug |
165 | print(renderVars("WrapLayout layoutSize", +preferred, +targetWidth, +dim)); |
166 | endifdef |
167 | |
168 | return dim; |
169 | } |
170 | } |
171 | |
172 | /* |
173 | * A new row has been completed. Use the dimensions of this row |
174 | * to update the preferred size for the container. |
175 | * |
176 | * @param dim update the width and height when appropriate |
177 | * @param rowWidth the width of the row to add |
178 | * @param rowHeight the height of the row to add |
179 | */ |
180 | private void addRow(Dimension dim, int rowWidth, int rowHeight) |
181 | { |
182 | dim.width = Math.max(dim.width, rowWidth); |
183 | |
184 | if (dim.height > 0) |
185 | { |
186 | dim.height += getVgap(); |
187 | } |
188 | |
189 | dim.height += rowHeight; |
190 | } |
191 | } |
download show line numbers debug dex old transpilations
Travelled to 3 computer(s): bhatertpkbcr, ekrmjmnbrukm, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1033556 |
Snippet name: | WrapLayout |
Eternal ID of this version: | #1033556/10 |
Text MD5: | aa364120020ee5926a035aa355ad2d17 |
Transpilation MD5: | eda2f1c104a9da5bdc04c93166f1f813 |
Author: | stefan |
Category: | javax / gui |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-08-17 16:29:47 |
Source code size: | 5710 bytes / 191 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 182 / 298 |
Version history: | 9 change(s) |
Referenced in: | [show references] |