1 | class VariableGridLayout implements LayoutManager2, java.io.Serializable↵ | | 1 | class VariableGridLayout implements LayoutManager2, java.io.Serializable↵
|
2 | {↵ | | 2 | {↵
|
|
3 | public static final int FIXED_NUM_ROWS = 1;↵ | | 3 | public static final int FIXED_NUM_ROWS = 1;↵
|
4 | public static final int FIXED_NUM_COLUMNS = 2;↵ | | 4 | public static final int FIXED_NUM_COLUMNS = 2;↵
|
|
|
5 | public VariableGridLayout(int mode, int size, int hgap, int vgap) {↵ | | 5 | public VariableGridLayout(int mode, int size, int hgap, int vgap) {↵
|
6 | if (mode != FIXED_NUM_ROWS && mode != FIXED_NUM_COLUMNS) {↵ | | 6 | if (mode != FIXED_NUM_ROWS && mode != FIXED_NUM_COLUMNS) {↵
|
7 | throw new IllegalArgumentException("illegal mode; value is " + mode);↵ | | 7 | throw new IllegalArgumentException("illegal mode; value is " + mode);↵
|
8 | }↵ | | 8 | }↵
|
9 | if (size <= 0) {↵ | | 9 | if (size <= 0) {↵
|
10 | throw new IllegalArgumentException("size cannot be zero or less; value is " + size);↵ | | 10 | throw new IllegalArgumentException("size cannot be zero or less; value is " + size);↵
|
11 | }↵ | | 11 | }↵
|
12 | if (hgap < 0) {↵ | | 12 | if (hgap < 0) {↵
|
13 | throw new IllegalArgumentException("hgap cannot be negative; value is " + hgap);↵ | | 13 | throw new IllegalArgumentException("hgap cannot be negative; value is " + hgap);↵
|
14 | }↵ | | 14 | }↵
|
15 | if (vgap < 0) {↵ | | 15 | if (vgap < 0) {↵
|
16 | throw new IllegalArgumentException("vgap cannot be negative; value is " + vgap);↵ | | 16 | throw new IllegalArgumentException("vgap cannot be negative; value is " + vgap);↵
|
17 | }↵ | | 17 | }↵
|
18 | this.mode = mode;↵ | | 18 | this.mode = mode;↵
|
19 | this.size = size;↵ | | 19 | this.size = size;↵
|
20 | this.hgap = hgap;↵ | | 20 | this.hgap = hgap;↵
|
21 | this.vgap = vgap;↵ | | 21 | this.vgap = vgap;↵
|
22 | }↵ | | 22 | }↵
|
|
|
23 | /**↵ | | 23 | /**↵
|
24 | * Creates a variable grid layout manager with the specified mode↵ | | 24 | * Creates a variable grid layout manager with the specified mode↵
|
25 | * and zero horizontal and vertical gap.↵ | | 25 | * and zero horizontal and vertical gap.↵
|
26 | */↵ | | 26 | */↵
|
27 | public VariableGridLayout(int mode, int size) {↵ | | 27 | public VariableGridLayout(int mode, int size) {↵
|
28 | this(mode, size, 0, 0);↵ | | 28 | this(mode, size, 0, 0);↵
|
29 | }↵ | | 29 | }↵
|
|
|
30 | /**↵ | | 30 | /**↵
|
31 | * Creates a variable grid layout manager with mode FIXED_NUM_ROWS,↵ | | 31 | * Creates a variable grid layout manager with mode FIXED_NUM_ROWS,↵
|
32 | * number of rows == 1 and zero horizontal and vertical gap.↵ | | 32 | * number of rows == 1 and zero horizontal and vertical gap.↵
|
33 | */↵ | | 33 | */↵
|
34 | public VariableGridLayout() {↵ | | 34 | public VariableGridLayout() {↵
|
35 | this(FIXED_NUM_ROWS, 1, 0, 0);↵ | | 35 | this(FIXED_NUM_ROWS, 1, 0, 0);↵
|
36 | }↵ | | 36 | }↵
|
|
|
37 | /**↵ | | 37 | /**↵
|
38 | * Not used in this class.↵ | | 38 | * Not used in this class.↵
|
39 | */↵ | | 39 | */↵
|
40 | public void addLayoutComponent(String name, Component component) { }↵ | | 40 | public void addLayoutComponent(String name, Component component) { }↵
|
|
|
41 | /**↵ | | 41 | /**↵
|
42 | * Not used in this class.↵ | | 42 | * Not used in this class.↵
|
43 | */↵ | | 43 | */↵
|
44 | public void addLayoutComponent(Component component, Object constraints) { }↵ | | 44 | public void addLayoutComponent(Component component, Object constraints) { }↵
|
|
|
45 | /**↵ | | 45 | /**↵
|
46 | * Not used in this class.↵ | | 46 | * Not used in this class.↵
|
47 | */↵ | | 47 | */↵
|
48 | public void removeLayoutComponent(Component component) { }↵ | | 48 | public void removeLayoutComponent(Component component) { }↵
|
|
|
49 | /**↵ | | 49 | /**↵
|
50 | * Always returns 0.5.↵ | | 50 | * Always returns 0.5.↵
|
51 | */↵ | | 51 | */↵
|
52 | public float getLayoutAlignmentX(Container container) {↵ | | 52 | public float getLayoutAlignmentX(Container container) {↵
|
53 | return 0.5f;↵ | | 53 | return 0.5f;↵
|
54 | }↵ | | 54 | }↵
|
|
|
55 | /**↵ | | 55 | /**↵
|
56 | * Always returns 0.5.↵ | | 56 | * Always returns 0.5.↵
|
57 | */↵ | | 57 | */↵
|
58 | public float getLayoutAlignmentY(Container container) {↵ | | 58 | public float getLayoutAlignmentY(Container container) {↵
|
59 | return 0.5f;↵ | | 59 | return 0.5f;↵
|
60 | }↵ | | 60 | }↵
|
|
|
61 | public Dimension preferredLayoutSize(Container parent) {↵ | | 61 | public Dimension preferredLayoutSize(Container parent) {↵
|
62 | return getLayoutSize(parent, 2);↵ | | 62 | return getLayoutSize(parent, 2);↵
|
63 | }↵ | | 63 | }↵
|
|
|
64 | public Dimension minimumLayoutSize(Container parent) {↵ | | 64 | public Dimension minimumLayoutSize(Container parent) {↵
|
65 | return getLayoutSize(parent, 0);↵ | | 65 | return getLayoutSize(parent, 0);↵
|
66 | }↵ | | 66 | }↵
|
|
|
67 | public Dimension maximumLayoutSize(Container parent) {↵ | | 67 | public Dimension maximumLayoutSize(Container parent) {↵
|
68 | return getLayoutSize(parent, 1);↵ | | 68 | return getLayoutSize(parent, 1);↵
|
69 | }↵ | | 69 | }↵
|
|
|
70 | public void layoutContainer(Container parent) {↵ | | 70 | public void layoutContainer(Container parent) {↵
|
71 | synchronized (parent.getTreeLock()) {↵ | | 71 | synchronized (parent.getTreeLock()) {↵
|
72 | update(parent);↵ | | 72 | update(parent);↵
|
|
73 | int ncomponents = parent.getComponentCount();↵ | | 73 | int ncomponents = parent.getComponentCount();↵
|
|
74 | if (ncomponents == 0) {↵ | | 74 | if (ncomponents == 0) {↵
|
75 | return;↵ | | 75 | return;↵
|
76 | }↵ | | 76 | }↵
|
|
77 | // Pass 1: compute preferred row heights / column widths↵ | | 77 | // Pass 1: compute preferred row heights / column widths↵
|
78 | int total_height = 0;↵ | | 78 | int total_height = 0;↵
|
79 | for (int r = 0, i = 0; r < nrows; r++) {↵ | | 79 | for (int r = 0, i = 0; r < nrows; r++) {↵
|
80 | for (int c = 0; c < ncols; c++, i++) {↵ | | 80 | for (int c = 0; c < ncols; c++, i++) {↵
|
81 | if (i < ncomponents) {↵ | | 81 | if (i < ncomponents) {↵
|
82 | Dimension d = parent.getComponent(i).getPreferredSize();↵ | | 82 | Dimension d = parent.getComponent(i).getPreferredSize();↵
|
83 | row_heights[r] = Math.max(row_heights[r], d.height);↵ | | 83 | row_heights[r] = Math.max(row_heights[r], d.height);↵
|
84 | col_widths[c] = Math.max(col_widths[c], d.width);↵ | | 84 | col_widths[c] = Math.max(col_widths[c], d.width);↵
|
85 | } else {↵ | | 85 | } else {↵
|
86 | break;↵ | | 86 | break;↵
|
87 | }↵ | | 87 | }↵
|
88 | }↵ | | 88 | }↵
|
89 | total_height += row_heights[r];↵ | | 89 | total_height += row_heights[r];↵
|
90 | }↵ | | 90 | }↵
|
|
91 | int total_width = 0;↵ | | 91 | int total_width = 0;↵
|
92 | for (int c = 0; c < ncols; c++) {↵ | | 92 | for (int c = 0; c < ncols; c++) {↵
|
93 | total_width += col_widths[c];↵ | | 93 | total_width += col_widths[c];↵
|
94 | }↵ | | 94 | }↵
|
|
95 | // Pass 2: redistribute free space↵ | | 95 | // Pass 2: redistribute free space↵
|
96 | Dimension parent_size = parent.getSize();↵ | | 96 | Dimension parent_size = parent.getSize();↵
|
97 | Insets insets = parent.getInsets();↵ | | 97 | Insets insets = parent.getInsets();↵
|
98 | int free_height = parent_size.height - insets.top - insets.bottom - (nrows - 1) * vgap;↵ | | 98 | int free_height = parent_size.height - insets.top - insets.bottom - (nrows - 1) * vgap;↵
|
99 | int free_width = parent_size.width - insets.left - insets.right - (ncols - 1) * hgap;↵ | | 99 | int free_width = parent_size.width - insets.left - insets.right - (ncols - 1) * hgap;↵
|
|
100 | if (total_height != free_height) {↵ | | 100 | if (total_height != free_height) {↵
|
101 | double dy = (double)free_height / (double)total_height;↵ | | 101 | double dy = (double)free_height / (double)total_height;↵
|
102 | for (int r = 0; r < nrows; r++) {↵ | | 102 | for (int r = 0; r < nrows; r++) {↵
|
103 | row_heights[r] = (int) ((double)row_heights[r] * dy);↵ | | 103 | row_heights[r] = (int) ((double)row_heights[r] * dy);↵
|
104 | }↵ | | 104 | }↵
|
105 | }↵ | | 105 | }↵
|
|
106 | if (total_width != free_width) {↵ | | 106 | if (total_width != free_width) {↵
|
107 | double dx = ((double)free_width) / ((double)total_width);↵ | | 107 | double dx = ((double)free_width) / ((double)total_width);↵
|
108 | for (int c = 0; c < ncols; c++) {↵ | | 108 | for (int c = 0; c < ncols; c++) {↵
|
109 | col_widths[c] = (int) ((double)col_widths[c] * dx);↵ | | 109 | col_widths[c] = (int) ((double)col_widths[c] * dx);↵
|
110 | }↵ | | 110 | }↵
|
111 | }↵ | | 111 | }↵
|
|
112 | // Pass 3: layout components↵ | | 112 | // Pass 3: layout components↵
|
113 | for (int r = 0, y = insets.top, i = 0; r < nrows; y += row_heights[r] + vgap, r++) {↵ | | 113 | for (int r = 0, y = insets.top, i = 0; r < nrows; y += row_heights[r] + vgap, r++) {↵
|
114 | for (int c = 0, x = insets.left; c < ncols; x += col_widths[c] + hgap, c++, i++) {↵ | | 114 | for (int c = 0, x = insets.left; c < ncols; x += col_widths[c] + hgap, c++, i++) {↵
|
115 | if (i < ncomponents) {↵ | | 115 | if (i < ncomponents) {↵
|
116 | parent.getComponent(i).setBounds(x, y, col_widths[c], row_heights[r]);↵ | | 116 | parent.getComponent(i).setBounds(x, y, col_widths[c], row_heights[r]);↵
|
117 | }↵ | | 117 | }↵
|
118 | }↵ | | 118 | }↵
|
119 | }↵ | | 119 | }↵
|
|
120 | } // synchronized↵ | | 120 | } // synchronized↵
|
121 | }↵ | | 121 | }↵
|
|
|
122 | public void invalidateLayout(Container container) {}↵ | | 122 | public void invalidateLayout(Container container) {}↵
|
|
|
123 | /**↵ | | 123 | /**↵
|
124 | * Returns the string representation of this variable grid layout's values.↵ | | 124 | * Returns the string representation of this variable grid layout's values.↵
|
125 | * @return a string representation of this variable grid layout.↵ | | 125 | * @return a string representation of this variable grid layout.↵
|
126 | */↵ | | 126 | */↵
|
127 | public String toString() {↵ | | 127 | public String toString() {↵
|
128 | return getClass().getName() + "[mode=" + mode + ",size=" + size↵ | | 128 | return getClass().getName() + "[mode=" + mode + ",size=" + size↵
|
129 | + ",hgap=" + hgap + ",vgap=" + vgap + "]";↵ | | 129 | + ",hgap=" + hgap + ",vgap=" + vgap + "]";↵
|
130 | }↵ | | 130 | }↵
|
|
|
131 | /**↵ | | 131 | /**↵
|
132 | * @param which if 0 compute minimum layout size,↵ | | 132 | * @param which if 0 compute minimum layout size,↵
|
133 | * if 1 compute maximum layout size,↵ | | 133 | * if 1 compute maximum layout size,↵
|
134 | * otherwise compute preferred layout size.↵ | | 134 | * otherwise compute preferred layout size.↵
|
135 | */↵ | | 135 | */↵
|
136 | private Dimension getLayoutSize(Container parent, int which) {↵ | | 136 | private Dimension getLayoutSize(Container parent, int which) {↵
|
137 | synchronized (parent.getTreeLock()){↵ | | 137 | synchronized (parent.getTreeLock()){↵
|
138 | update(parent);↵ | | 138 | update(parent);↵
|
|
139 | int ncomponents = parent.getComponentCount();↵ | | 139 | int ncomponents = parent.getComponentCount();↵
|
140 | int h = 0;↵ | | 140 | int h = 0;↵
|
141 | int w = 0;↵ | | 141 | int w = 0;↵
|
|
142 | for (int r = 0, i = 0; r < nrows; r++) {↵ | | 142 | for (int r = 0, i = 0; r < nrows; r++) {↵
|
143 | int row_height = 0;↵ | | 143 | int row_height = 0;↵
|
144 | for (int c = 0; c < ncols; c++, i++) {↵ | | 144 | for (int c = 0; c < ncols; c++, i++) {↵
|
145 | if (i < ncomponents) {↵ | | 145 | if (i < ncomponents) {↵
|
146 | switch (which) {↵ | | 146 | switch (which) {↵
|
147 | case 0:↵ | | 147 | case 0:↵
|
148 | row_height = Math.max(row_height, parent.getComponent(i).getMinimumSize().height);↵ | | 148 | row_height = Math.max(row_height, parent.getComponent(i).getMinimumSize().height);↵
|
149 | break;↵ | | 149 | break;↵
|
150 | case 1:↵ | | 150 | case 1:↵
|
151 | row_height = Math.max(row_height, parent.getComponent(i).getMaximumSize().height);↵ | | 151 | row_height = Math.max(row_height, parent.getComponent(i).getMaximumSize().height);↵
|
152 | break;↵ | | 152 | break;↵
|
153 | default:↵ | | 153 | default:↵
|
154 | row_height = Math.max(row_height, parent.getComponent(i).getPreferredSize().height);↵ | | 154 | row_height = Math.max(row_height, parent.getComponent(i).getPreferredSize().height);↵
|
155 | break;↵ | | 155 | break;↵
|
156 | }↵ | | 156 | }↵
|
157 | } else {↵ | | 157 | } else {↵
|
158 | break;↵ | | 158 | break;↵
|
159 | }↵ | | 159 | }↵
|
160 | }↵ | | 160 | }↵
|
161 | h += row_height;↵ | | 161 | h += row_height;↵
|
162 | }↵ | | 162 | }↵
|
|
163 | for (int c = 0; c < ncols; c++) {↵ | | 163 | for (int c = 0; c < ncols; c++) {↵
|
164 | int col_width = 0;↵ | | 164 | int col_width = 0;↵
|
165 | for (int r = 0; r < nrows; r++) {↵ | | 165 | for (int r = 0; r < nrows; r++) {↵
|
166 | int i = r * ncols + c;↵ | | 166 | int i = r * ncols + c;↵
|
167 | if (i < ncomponents) {↵ | | 167 | if (i < ncomponents) {↵
|
168 | switch (which) {↵ | | 168 | switch (which) {↵
|
169 | case 0:↵ | | 169 | case 0:↵
|
170 | col_width = Math.max(col_width, parent.getComponent(i).getMinimumSize().width);↵ | | 170 | col_width = Math.max(col_width, parent.getComponent(i).getMinimumSize().width);↵
|
171 | break;↵ | | 171 | break;↵
|
172 | case 1:↵ | | 172 | case 1:↵
|
173 | col_width = Math.max(col_width, parent.getComponent(i).getMaximumSize().width);↵ | | 173 | col_width = Math.max(col_width, parent.getComponent(i).getMaximumSize().width);↵
|
174 | break;↵ | | 174 | break;↵
|
175 | default:↵ | | 175 | default:↵
|
176 | col_width = Math.max(col_width, parent.getComponent(i).getPreferredSize().width);↵ | | 176 | col_width = Math.max(col_width, parent.getComponent(i).getPreferredSize().width);↵
|
177 | break;↵ | | 177 | break;↵
|
178 | }↵ | | 178 | }↵
|
179 | } else {↵ | | 179 | } else {↵
|
180 | break;↵ | | 180 | break;↵
|
181 | }↵ | | 181 | }↵
|
182 | }↵ | | 182 | }↵
|
183 | w += col_width;↵ | | 183 | w += col_width;↵
|
184 | }↵ | | 184 | }↵
|
|
185 | Insets insets = parent.getInsets();↵ | | 185 | Insets insets = parent.getInsets();↵
|
186 | return new Dimension(w + insets.left + insets.right + ((ncols - 1) * hgap),↵ | | 186 | return new Dimension(w + insets.left + insets.right + ((ncols - 1) * hgap),↵
|
187 | h + insets.top + insets.bottom + ((nrows - 1) * vgap));↵ | | 187 | h + insets.top + insets.bottom + ((nrows - 1) * vgap));↵
|
188 | }↵ | | 188 | }↵
|
189 | }↵ | | 189 | }↵
|
|
|
190 | private void update(Container container) {↵ | | 190 | private void update(Container container) {↵
|
191 | int ncomponents = container.getComponentCount();↵ | | 191 | int ncomponents = container.getComponentCount();↵
|
192 | int old_nrows = nrows;↵ | | 192 | int old_nrows = nrows;↵
|
193 | int old_ncols = ncols;↵ | | 193 | int old_ncols = ncols;↵
|
194 | if (this.mode == FIXED_NUM_ROWS) {↵ | | 194 | if (this.mode == FIXED_NUM_ROWS) {↵
|
195 | nrows = this.size;↵ | | 195 | nrows = this.size;↵
|
196 | ncols = (ncomponents + nrows - 1) / nrows;↵ | | 196 | ncols = (ncomponents + nrows - 1) / nrows;↵
|
197 | } else {↵ | | 197 | } else {↵
|
198 | ncols = this.size;↵ | | 198 | ncols = this.size;↵
|
199 | nrows = (ncomponents + ncols - 1) / ncols;↵ | | 199 | nrows = (ncomponents + ncols - 1) / ncols;↵
|
200 | }↵ | | 200 | }↵
|
201 | if (old_nrows != nrows) {↵ | | 201 | if (old_nrows != nrows) {↵
|
202 | row_heights = new int[nrows];↵ | | 202 | row_heights = new int[nrows];↵
|
203 | }↵ | | 203 | }↵
|
204 | if (old_ncols != ncols) {↵ | | 204 | if (old_ncols != ncols) {↵
|
205 | col_widths = new int[ncols];↵ | | 205 | col_widths = new int[ncols];↵
|
206 | }↵ | | 206 | }↵
|
207 | }↵ | | 207 | }↵
|
|
|
208 | private int mode;↵ | | 208 | private int mode;↵
|
209 | private int size;↵ | | 209 | private int size;↵
|
210 | private int hgap;↵ | | 210 | private int hgap;↵
|
211 | private int vgap;↵ | | 211 | private int vgap;↵
|
212 | private transient int nrows = -1;↵ | | 212 | private transient int nrows = -1;↵
|
213 | private transient int ncols = -1;↵ | | 213 | private transient int ncols = -1;↵
|
214 | private transient int[] row_heights = null;↵ | | 214 | private transient int[] row_heights = null;↵
|
215 | private transient int[] col_widths = null;↵ | | 215 | private transient int[] col_widths = null;↵
|
216 | } | | 216 | }
|