1 | import java.net.*; |
2 | import java.io.*; |
3 | import javax.swing.*; |
4 | import java.util.regex.*; |
5 | import java.util.*; |
6 | |
7 | import java.awt.*; |
8 | import java.util.List; |
9 | |
10 | public class main { |
11 | public static void main(String[] args) { |
12 | JFrame frame = new JFrame("A JavaX Frame"); |
13 | |
14 | |
15 | JPanel panel = new JPanel(new GridLayout(2, 1)); |
16 | |
17 | final JTextArea textArea = new JTextArea(); |
18 | panel.add(new JScrollPane(textArea)); |
19 | |
20 | JButton btnBla = new JButton("Bla"); |
21 | panel.add(new CenteredLine(btnBla)); |
22 | |
23 | |
24 | frame.add(panel); |
25 | frame.setBounds(100, 100, 500, 400); |
26 | frame.setVisible(true); |
27 | exitOnFrameClose(frame); |
28 | } |
29 | |
30 | static void exitOnFrameClose(JFrame frame) { |
31 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
32 | } |
33 | |
34 | } |
35 | class CenteredLine extends JPanel { |
36 | public CenteredLine(Component... components) { |
37 | setLayout(LetterLayout.centeredRow()); |
38 | for (Component component : components) |
39 | add(component); |
40 | } |
41 | |
42 | public void add(String text) { |
43 | add(new JLabel(text)); |
44 | } |
45 | } |
46 | class LetterLayout implements LayoutManager { |
47 | private String[] lines; |
48 | private Map<String, Component> map = new TreeMap<String, Component>(); |
49 | private RC[] rows; |
50 | private RC[] cols; |
51 | private Cell[][] cells; |
52 | private int spacingX = 10, spacingY = 10; |
53 | private int insetTop, insetBottom, insetLeft, insetRight; |
54 | private int template; |
55 | private boolean formWideLeftSide, formWideRightSide; |
56 | |
57 | private static final int STALACTITE = 1, LEFT_ALIGNED_ROW = 2, CENTERED_ROW = 3, FORM = 4, RIGHT_ALIGNED_ROW = 5; |
58 | private boolean debug; |
59 | |
60 | public void setLeftBorder(int border) { |
61 | insetLeft = border; |
62 | } |
63 | |
64 | public void setRightBorder(int border) { |
65 | insetRight = border; |
66 | } |
67 | |
68 | public static JComponent withBorder(JComponent component, int border) { |
69 | JPanel panel = new JPanel(new LetterLayout("C").setBorder(border)); |
70 | panel.add("C", component); |
71 | return panel; |
72 | } |
73 | |
74 | public static JPanel panel(String... lines) { |
75 | return new JPanel(new LetterLayout(lines)); |
76 | } |
77 | |
78 | public static JPanel stalactitePanel() { |
79 | return new JPanel(stalactite()); |
80 | } |
81 | |
82 | static class DummyComponent extends JComponent { |
83 | } |
84 | |
85 | /** |
86 | * info about one matrix cell |
87 | */ |
88 | static class Cell { |
89 | boolean aux; // part of a larger cell, but not top-left corner |
90 | int minWidth, minHeight; |
91 | Component component; |
92 | int colspan, rowspan; |
93 | double weightX, weightY; |
94 | } |
95 | |
96 | /** |
97 | * info about one matrix row / column |
98 | */ |
99 | static class RC { |
100 | int min; |
101 | double weightSum; |
102 | int start; |
103 | int minEnd; |
104 | } |
105 | |
106 | private LetterLayout(int template) { |
107 | this.template = template; |
108 | } |
109 | |
110 | public LetterLayout(String... lines) { |
111 | this.lines = lines; |
112 | } |
113 | |
114 | public void removeLayoutComponent(Component component) { |
115 | map.values().remove(component); |
116 | } |
117 | |
118 | public void layoutContainer(Container container) { |
119 | prepareLayout(container); |
120 | |
121 | // do layout |
122 | |
123 | if (debug) |
124 | System.out.println("Container size: " + container.getSize()); |
125 | |
126 | Insets insets = getInsets(container); |
127 | for (int r = 0; r < rows.length; r++) { |
128 | for (int i = 0; i < cols.length;) { |
129 | Cell cell = cells[i][r]; |
130 | if (cell.aux) |
131 | ++i; |
132 | else { |
133 | if (cell.component != null) { |
134 | int x1 = cols[i].start; |
135 | int y1 = rows[r].start; |
136 | int x2 = i + cell.colspan < cols.length ? cols[i + cell.colspan].start - spacingX : container.getWidth() - insets.right; |
137 | int y2 = r + cell.rowspan < rows.length ? rows[r + cell.rowspan].start - spacingY : container.getHeight() - insets.bottom; |
138 | |
139 | if (debug) |
140 | System.out.println("Layouting ("+i+", "+r+", " + cell.component.getClass().getName() + "): "+x1+" "+y1+" "+x2+" "+y2); |
141 | |
142 | cell.component.setBounds(x1, y1, x2 - x1, y2 - y1); |
143 | } |
144 | i += cells[i][r].colspan; |
145 | } |
146 | } |
147 | } |
148 | } |
149 | |
150 | private void prepareLayout(Container container) { |
151 | applyTemplate(container); |
152 | |
153 | int numRows = lines.length, numCols = lines[0].length(); |
154 | for (int i = 1; i < numRows; i++) if (lines[i].length() != numCols) |
155 | throw new IllegalArgumentException("Lines have varying length"); |
156 | cells = new Cell[numCols][numRows]; |
157 | rows = new RC[numRows]; |
158 | cols = new RC[numCols]; |
159 | |
160 | for (int r = 0; r < numRows; r++) rows[r] = new RC(); |
161 | for (int i = 0; i < numCols; i++) cols[i] = new RC(); |
162 | for (int r = 0; r < numRows; r++) for (int i = 0; i < numCols; i++) cells[i][r] = new Cell(); |
163 | |
164 | // define cells |
165 | |
166 | for (int r = 0; r < numRows; r++) { |
167 | String line = lines[r]; |
168 | for (int i = 0; i < numCols;) { |
169 | Cell cell = cells[i][r]; |
170 | if (cell.aux) { |
171 | ++i; |
172 | continue; |
173 | } |
174 | char ch = line.charAt(i); |
175 | int iNext = i; |
176 | do ++iNext; while (iNext < numCols && ch == line.charAt(iNext)); |
177 | int rNext = r; |
178 | do ++rNext; while (rNext < numRows && ch == lines[rNext].charAt(i)); |
179 | |
180 | cell.weightX = numCols == 1 || iNext > i + 1 ? 1.0 : 0.0; |
181 | cell.weightY = numRows == 1 || rNext > r + 1 ? 1.0 : 0.0; |
182 | |
183 | Component c = map.get(String.valueOf(ch)); |
184 | cell.component = c; |
185 | if (c != null) { |
186 | cell.minWidth = c.getMinimumSize().width + spacingX; |
187 | cell.minHeight = getMinimumHeight(c) + spacingY; |
188 | } |
189 | cell.colspan = iNext - i; |
190 | cell.rowspan = rNext - r; |
191 | |
192 | if (cell.colspan == 1) |
193 | cols[i].min = Math.max(cols[i].min, cell.minWidth); |
194 | if (cell.rowspan == 1) |
195 | rows[r].min = Math.max(rows[r].min, cell.minHeight); |
196 | |
197 | for (int r2 = r; r2 < rNext; r2++) |
198 | for (int i2 = i; i2 < iNext; i2++) |
199 | if (r2 != r || i2 != i) |
200 | cells[i2][r2].aux = true; |
201 | |
202 | i = iNext; |
203 | } |
204 | } |
205 | |
206 | // determine minStarts, weightSums |
207 | |
208 | while (true) { |
209 | for (int i = 0; i < numCols; i++) { |
210 | int minStart = i == 0 ? 0 : cols[i - 1].minEnd; |
211 | double weightStart = i == 0 ? 0.0 : cols[i - 1].weightSum; |
212 | for (int r = 0; r < numRows; r++) { |
213 | Cell cell = cells[i][r]; |
214 | if (!cell.aux) { |
215 | RC rc = cols[i + cell.colspan - 1]; |
216 | rc.minEnd = Math.max(rc.minEnd, minStart + cell.minWidth); |
217 | rc.weightSum = Math.max(rc.weightSum, weightStart + cell.weightX); |
218 | } |
219 | } |
220 | } |
221 | |
222 | for (int r = 0; r < numRows; r++) { |
223 | int minStart = r == 0 ? 0 : rows[r - 1].minEnd; |
224 | double weightStart = r == 0 ? 0.0 : rows[r - 1].weightSum; |
225 | for (int i = 0; i < numCols; i++) { |
226 | Cell cell = cells[i][r]; |
227 | if (!cell.aux) { |
228 | RC rc = rows[r + cell.rowspan - 1]; |
229 | rc.minEnd = Math.max(rc.minEnd, minStart + cell.minHeight); |
230 | rc.weightSum = Math.max(rc.weightSum, weightStart + cell.weightY); |
231 | } |
232 | } |
233 | } |
234 | |
235 | if (allWeightsZero(cols)) { |
236 | for (int r = 0; r < numRows; r++) |
237 | for (int i = 0; i < numCols; i++) |
238 | cells[i][r].weightX = 1.0; |
239 | continue; |
240 | } |
241 | |
242 | if (allWeightsZero(rows)) { |
243 | for (int r = 0; r < numRows; r++) |
244 | for (int i = 0; i < numCols; i++) |
245 | cells[i][r].weightY = 1.0; |
246 | continue; |
247 | } |
248 | |
249 | break; |
250 | } |
251 | |
252 | // determine row, col starts |
253 | |
254 | Insets insets = getInsets(container); |
255 | determineStarts(cols, insets.left, container.getWidth() - insets.left - insets.right + spacingX, spacingX); |
256 | determineStarts(rows, insets.top, container.getHeight() - insets.top - insets.bottom + spacingY, spacingY); |
257 | } |
258 | |
259 | private boolean allWeightsZero(RC[] rcs) { |
260 | for (int i = 0; i < rcs.length; i++) |
261 | if (rcs[i].weightSum != 0.0) |
262 | return false; |
263 | return true; |
264 | } |
265 | |
266 | private static int getMinimumHeight(Component c) { |
267 | /*if (c instanceof JTextArea) { |
268 | return (int) ((JTextArea) c).getUI().getRootView((JTextArea) c).getPreferredSpan(javax.swing.text.View.Y_AXIS); |
269 | }*/ |
270 | return c.getMinimumSize().height; |
271 | } |
272 | |
273 | private void applyTemplate(Container container) { |
274 | if (template == STALACTITE) { |
275 | Component[] components = container.getComponents(); |
276 | |
277 | lines = new String[components.length + 2]; |
278 | map.clear(); |
279 | for (int i = 0; i < components.length; i++) { |
280 | String s = String.valueOf(makeIndexChar(i)); |
281 | map.put(s, components[i]); |
282 | lines[i] = s; |
283 | } |
284 | lines[components.length] = lines[components.length + 1] = " "; |
285 | } else if (template == FORM) { |
286 | /* old method of calculating numRows: |
287 | int numRows = 0; |
288 | for (String key : map.keySet()) { |
289 | if (key.length() == 1) |
290 | numRows = Math.max(numRows, Character.toLowerCase(key.charAt(0))-'a'); |
291 | }*/ |
292 | Component[] components = container.getComponents(); |
293 | int numRows = components.length/2; |
294 | |
295 | lines = new String[numRows+2]; |
296 | map.clear(); |
297 | for (int row = 0; row < numRows; row++) { |
298 | String lower = String.valueOf(makeIndexChar(row)); |
299 | String upper = String.valueOf(makeAlternateIndexChar(row)); |
300 | Component rightComponent = components[row * 2 + 1]; |
301 | if (rightComponent instanceof DummyComponent) |
302 | upper = lower; |
303 | lines[row] = (formWideLeftSide ? lower + lower : lower) + (formWideRightSide ? upper + upper : upper); |
304 | map.put(lower, components[row*2]); |
305 | if (!(rightComponent instanceof DummyComponent)) |
306 | map.put(upper, rightComponent); |
307 | } |
308 | lines[numRows] = lines[numRows+1] = (formWideLeftSide ? " " : " ") + (formWideRightSide ? " " : " "); |
309 | } else if (template == LEFT_ALIGNED_ROW) { |
310 | lines = new String[] { makeSingleRow(container) + RIGHT_CHAR + RIGHT_CHAR }; |
311 | } else if (template == CENTERED_ROW) { |
312 | lines = new String[] { "" + LEFT_CHAR + LEFT_CHAR + makeSingleRow(container) + RIGHT_CHAR + RIGHT_CHAR }; |
313 | } else if (template == RIGHT_ALIGNED_ROW) { |
314 | lines = new String[] { "" + LEFT_CHAR + LEFT_CHAR + makeSingleRow(container) }; |
315 | } |
316 | } |
317 | |
318 | private String makeSingleRow(Container container) { |
319 | Component[] components = container.getComponents(); |
320 | StringBuffer buf = new StringBuffer(); |
321 | map.clear(); |
322 | for (int i = 0; i < components.length; i++) { |
323 | String s = String.valueOf(makeAlternateIndexChar(i)); |
324 | map.put(s, components[i]); |
325 | buf.append(s); |
326 | } |
327 | return buf.toString(); |
328 | } |
329 | |
330 | private static void determineStarts(RC[] rcs, int start, int totalSize, int spacing) { |
331 | int minTotal = rcs[rcs.length - 1].minEnd; |
332 | double weightSum = rcs[rcs.length - 1].weightSum; |
333 | //System.out.println("totalSize="+totalSize+",minTotal="+minTotal+",weightSum="+weightSum); |
334 | int spare = (int) ((totalSize - minTotal) / (weightSum == 0.0 ? 1.0 : weightSum)); |
335 | int x = start, minSum = 0; |
336 | double prevWeightSum = 0.0; |
337 | for (int i = 0; i < rcs.length; i++) { |
338 | int width = rcs[i].minEnd - minSum + (int) ((rcs[i].weightSum - prevWeightSum) * spare) - spacing; |
339 | //System.out.println("i="+i+",prevws="+prevWeightSum+",ws="+rcs[i].weightSum+",min="+rcs[i].min+",width="+width); |
340 | rcs[i].start = x; |
341 | x += width + spacing; |
342 | prevWeightSum = rcs[i].weightSum; |
343 | minSum = rcs[i].minEnd; |
344 | } |
345 | } |
346 | |
347 | public void addLayoutComponent(String s, Component component) { |
348 | map.put(s, component); |
349 | } |
350 | |
351 | public Dimension minimumLayoutSize(Container container) { |
352 | prepareLayout(container); |
353 | Insets insets = getInsets(container); |
354 | Dimension result = new Dimension( |
355 | insets.left + cols[cols.length - 1].minEnd + insets.right - spacingX, |
356 | insets.top + rows[rows.length - 1].minEnd + insets.bottom - spacingY); |
357 | return result; |
358 | } |
359 | |
360 | private Insets getInsets(Container container) { |
361 | Insets insets = container.getInsets(); |
362 | return new Insets(insets.top + insetTop, |
363 | insets.left + insetLeft, |
364 | insets.bottom + insetBottom, |
365 | insets.right + insetRight); |
366 | } |
367 | |
368 | public Dimension preferredLayoutSize(Container container) { |
369 | return minimumLayoutSize(container); |
370 | } |
371 | |
372 | public LetterLayout setSpacing(int x, int y) { |
373 | spacingX = x; |
374 | spacingY = y; |
375 | return this; |
376 | } |
377 | |
378 | public LetterLayout setSpacing(int spacing) { |
379 | return setSpacing(spacing, spacing); |
380 | } |
381 | |
382 | public LetterLayout setBorder(int top, int left, int bottom, int right) { |
383 | insetTop = top; |
384 | insetLeft = left; |
385 | insetBottom = bottom; |
386 | insetRight = right; |
387 | return this; |
388 | } |
389 | |
390 | public LetterLayout setBorder(int inset) { |
391 | return setBorder(inset, inset, inset, inset); |
392 | } |
393 | |
394 | public LetterLayout setTopBorder(int inset) { |
395 | insetTop = inset; |
396 | return this; |
397 | } |
398 | |
399 | /** |
400 | * layout components from top to bottom; add components without letters! |
401 | */ |
402 | public static LetterLayout stalactite() { |
403 | return new LetterLayout(STALACTITE); |
404 | } |
405 | |
406 | /** |
407 | * layout components from left to right; add components without letters! |
408 | */ |
409 | public static LetterLayout leftAlignedRow() { |
410 | return new LetterLayout(LEFT_ALIGNED_ROW); |
411 | } |
412 | |
413 | public static LetterLayout leftAlignedRow(int spacing) { |
414 | return leftAlignedRow().setSpacing(spacing); |
415 | } |
416 | |
417 | /** |
418 | * layout components from left to right, center in container; add components without letters! |
419 | */ |
420 | public static LetterLayout centeredRow() { |
421 | return new LetterLayout(CENTERED_ROW); |
422 | } |
423 | |
424 | public static LetterLayout rightAlignedRow() { |
425 | return new LetterLayout(RIGHT_ALIGNED_ROW); |
426 | } |
427 | |
428 | public static JPanel rightAlignedRowPanel(JComponent... components) { |
429 | return makePanel(new LetterLayout(RIGHT_ALIGNED_ROW), components); |
430 | } |
431 | |
432 | private static JPanel makePanel(LetterLayout letterLayout, JComponent[] components) { |
433 | JPanel panel = new JPanel(letterLayout); |
434 | for (JComponent component : components) { |
435 | panel.add(component); |
436 | } |
437 | return panel; |
438 | } |
439 | |
440 | /** |
441 | * layout components from top to bottom; two components per row |
442 | */ |
443 | public static LetterLayout form() { |
444 | LetterLayout letterLayout = new LetterLayout(FORM); |
445 | letterLayout.formWideLeftSide = true; |
446 | letterLayout.formWideRightSide = true; |
447 | return letterLayout; |
448 | } |
449 | |
450 | /** |
451 | * layout components from top to bottom; two components per row |
452 | * left column is small, right column is wide |
453 | */ |
454 | public static LetterLayout formWideRightSide() { |
455 | LetterLayout letterLayout = new LetterLayout(FORM); |
456 | letterLayout.formWideRightSide = true; |
457 | return letterLayout; |
458 | } |
459 | |
460 | public static Component getDummyComponent() { |
461 | return new DummyComponent(); |
462 | } |
463 | |
464 | public static JPanel newPanel(String... lines) { |
465 | return new JPanel(new LetterLayout(lines)); |
466 | } |
467 | |
468 | public boolean isDebug() { |
469 | return debug; |
470 | } |
471 | |
472 | public void setDebug(boolean debug) { |
473 | this.debug = debug; |
474 | } |
475 | |
476 | public static char makeIndexChar(int idx) { |
477 | return (char) ('a' + idx*2); |
478 | } |
479 | |
480 | public static char makeAlternateIndexChar(int idx) { |
481 | return (char) ('b' + idx*2); |
482 | } |
483 | |
484 | public static char LEFT_CHAR = ',', RIGHT_CHAR = '.'; |
485 | |
486 | public static void main(String[] args) { |
487 | System.out.println((int) makeIndexChar(0)); |
488 | System.out.println((int) makeAlternateIndexChar(0)); |
489 | System.out.println((int) makeIndexChar(32000)); |
490 | System.out.println((int) makeAlternateIndexChar(32000)); |
491 | System.out.println((int) LEFT_CHAR); |
492 | System.out.println((int) RIGHT_CHAR); |
493 | } |
494 | } |
Snippet is not live.
Travelled to 12 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #2000433 |
Snippet name: | |
Eternal ID of this version: | #2000433/1 |
Text MD5: | 427ec6d06dcb45058b6e56e9be1689d2 |
Author: | someone |
Category: | |
Type: | New Tinybrain snippet |
Gummipassword: | expansion-of-635 |
Uploaded from IP: | 176.0.4.89 |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2015-07-05 13:23:12 |
Source code size: | 15141 bytes / 494 lines |
Pitched / IR pitched: | No / Yes |
Views / Downloads: | 712 / 169 |
Referenced in: | [show references] |