1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.cosylab.gui.components.util;
21
22 import java.awt.BasicStroke;
23 import java.awt.Color;
24 import java.awt.Component;
25 import java.awt.Container;
26 import java.awt.Dimension;
27 import java.awt.Graphics;
28 import java.awt.Graphics2D;
29 import java.awt.GridLayout;
30 import java.awt.Insets;
31 import java.awt.LayoutManager;
32 import java.awt.LayoutManager2;
33 import java.awt.Rectangle;
34
35 import javax.swing.JButton;
36 import javax.swing.border.Border;
37 import javax.swing.plaf.metal.MetalBorders;
38 import javax.swing.plaf.metal.MetalTabbedPaneUI;
39
40 import com.cosylab.gui.components.SimpleButton;
41
42
43
44
45
46
47
48
49
50 public class CosyUIElements {
51 public static final int BOTTOM = 1;
52 public static final int LEFT = 2;
53 public static final int RIGHT = 3;
54 public static final int TOP = 0;
55 private static Border panelBorder = null;
56 private static Border containerBorder = null;
57 private static Border flushBorder = null;
58
59
60 public static Border getPlainBorder(boolean raised) {
61 if (raised) {
62 if (panelBorder == null) {
63 panelBorder = new PanelFlushBorder(true, true);
64 }
65
66 return panelBorder;
67 } else {
68 if (containerBorder == null) {
69 containerBorder = new PanelFlushBorder(false, true);
70 }
71
72 return containerBorder;
73 }
74 }
75
76 public static Border getSingleLineBorder(int location, Color color) {
77 return new SingleLineBorder(location, color);
78 }
79
80 public static Border getFlushBorder() {
81 if (flushBorder == null) {
82 flushBorder = new MetalBorders.Flush3DBorder();
83 }
84
85 return flushBorder;
86 }
87
88 public static class ButtonOnRightLayout implements LayoutManager2 {
89 private static String BUTTON = "Button";
90
91 private Dimension minSize = new Dimension(60, 20);
92 private Dimension prefSize = new Dimension(2, 20);
93 private Component button = null;
94 private Component other = null;
95
96
97
98
99 public void addLayoutComponent(String name, Component comp) {
100 if (comp instanceof SimpleButton || comp instanceof JButton) {
101 button = comp;
102 } else {
103 other = comp;
104 }
105
106 prefSize.width = prefSize.width + comp.getPreferredSize().width;
107 }
108
109
110
111
112 public void layoutContainer(Container parent) {
113 int x = parent.getInsets().left;
114 int y = parent.getInsets().top;
115 int w = parent.getWidth() - x - parent.getInsets().right;
116 int h = parent.getHeight() - y - parent.getInsets().bottom;
117
118 if (button != null) {
119 button.setBounds((x + w) - h, y, h, h);
120 w = w - h;
121 }
122
123 if (other != null) {
124 other.setBounds(x, y, w, h);
125 }
126 }
127
128
129
130
131 public Dimension minimumLayoutSize(Container parent) {
132 minSize.width = 2;
133 minSize.height = 20;
134
135 if (button != null) {
136 minSize.width = minSize.width + button.getMinimumSize().width;
137 }
138
139 if (other != null) {
140 minSize.width = minSize.width + other.getMinimumSize().width;
141 minSize.height = other.getMinimumSize().height;
142 }
143
144 return minSize;
145 }
146
147
148
149
150 public Dimension preferredLayoutSize(Container parent) {
151 prefSize.width = 0;
152 prefSize.height = 20;
153
154 if (button != null) {
155 prefSize.width = prefSize.width +
156 button.getPreferredSize().width;
157 }
158
159 if (other != null) {
160 prefSize.width = prefSize.width +
161 other.getPreferredSize().width;
162 prefSize.height = other.getPreferredSize().height;
163 }
164
165 return prefSize;
166 }
167
168
169
170
171 public void removeLayoutComponent(Component comp) {
172 if (comp.equals(button)) {
173 button = null;
174 } else if (comp.equals(other)) {
175 other = null;
176 }
177 }
178
179
180
181
182 public void addLayoutComponent(Component comp, Object constraints) {
183 if (constraints == BUTTON) {
184 button = comp;
185 } else {
186 other = comp;
187 }
188
189 prefSize.width = prefSize.width + comp.getPreferredSize().width;
190 }
191
192
193
194
195 public float getLayoutAlignmentX(Container target) {
196 return 0;
197 }
198
199
200
201
202 public float getLayoutAlignmentY(Container target) {
203 return 0;
204 }
205
206
207
208
209 public void invalidateLayout(Container target) {
210 }
211
212
213
214
215 public Dimension maximumLayoutSize(Container target) {
216 return prefSize;
217 }
218 }
219
220
221
222
223
224
225
226 public static class TwinOptimalLayout implements LayoutManager {
227 private int horBorder;
228 private int vertBorder;
229 private int spaceBetween;
230 private Component[] comps;
231
232 public TwinOptimalLayout(int horBorder, int vertBorder, int spaceBetween) {
233 this.horBorder = horBorder;
234 this.vertBorder = vertBorder;
235 this.spaceBetween = spaceBetween;
236 comps = new Component[2];
237 }
238
239
240
241
242 public void addLayoutComponent(String name, Component comp) {
243 if (comps[0] == null) {
244 comps[0] = comp;
245 } else {
246 comps[1] = comp;
247 }
248 }
249
250
251
252
253 public void layoutContainer(Container parent) {
254 int w = parent.getWidth();
255 int h = parent.getHeight();
256 double ratio = (double) w / (double) h;
257
258 if (ratio > 1) {
259 int cw = (w - (2 * horBorder) - spaceBetween) / 2;
260
261 if (comps[0] != null) {
262 comps[0].setBounds(horBorder, vertBorder, cw,
263 h - (2 * vertBorder));
264 }
265
266 if (comps[1] != null) {
267 comps[1].setBounds(w - cw - horBorder, vertBorder, cw,
268 h - (2 * vertBorder));
269 }
270 } else {
271 int ch = (h - (2 * vertBorder) - spaceBetween) / 2;
272
273 if (comps[0] != null) {
274 comps[0].setBounds(horBorder, vertBorder,
275 w - (2 * horBorder), ch);
276 }
277
278 if (comps[1] != null) {
279 comps[1].setBounds(horBorder, h - ch - vertBorder,
280 w - (2 * horBorder), ch);
281 }
282 }
283 }
284
285
286
287
288 public Dimension minimumLayoutSize(Container parent) {
289 return new Dimension(10, 12);
290 }
291
292
293
294
295 public Dimension preferredLayoutSize(Container parent) {
296 return new Dimension(30, 20);
297 }
298
299
300
301
302 public void removeLayoutComponent(Component comp) {
303 if (comps[0] == comp) {
304 comps[0] = null;
305 }
306
307 if (comps[1] == comp) {
308 comps[1] = null;
309 }
310 }
311 }
312
313
314
315
316
317
318
319 public static class FlushTabbedPaneUI extends MetalTabbedPaneUI {
320 private static final Insets ZERO_INSETS = new Insets(0, 0, 0, 0);
321
322
323
324
325 protected Insets getContentBorderInsets(int tabPlacement) {
326 return ZERO_INSETS;
327 }
328
329
330
331
332 protected Insets getTabAreaInsets(int tabPlacement) {
333 return ZERO_INSETS;
334 }
335
336
337
338
339 protected void paintFocusIndicator(Graphics g, int tabPlacement,
340 Rectangle[] rects, int tabIndex, Rectangle iconRect,
341 Rectangle textRect, boolean isSelected) {
342 if (tabPane.hasFocus() && isSelected) {
343 Rectangle tabRect = rects[tabIndex];
344 boolean lastInRun = (tabIndex == (tabPane.getTabCount() - 1));
345 g.setColor(focus);
346 g.translate(tabRect.x, tabRect.y);
347
348 int right = tabRect.width - 2;
349
350 if (lastInRun) {
351 right = right - 1;
352 }
353
354 int bottom = tabRect.height - 1;
355 boolean leftToRight = true;
356
357 switch (tabPlacement) {
358 case RIGHT:
359 g.drawLine(right - 6, 2, right - 2, 6);
360 g.drawLine(1, 2, right - 6, 2);
361 g.drawLine(right - 2, 6, right - 2, bottom);
362 g.drawLine(1, 2, 1, bottom);
363 g.drawLine(1, bottom, right - 2, bottom);
364
365 break;
366
367 case BOTTOM:
368
369 if (leftToRight) {
370 g.drawLine(2, bottom - 6, 6, bottom - 2);
371 g.drawLine(6, bottom - 2, right, bottom - 2);
372 g.drawLine(2, 0, 2, bottom - 6);
373 g.drawLine(2, 0, right, 0);
374 g.drawLine(right, 0, right, bottom - 2);
375 } else {
376 g.drawLine(right - 2, bottom - 6, right - 6, bottom -
377 2);
378 g.drawLine(right - 2, 0, right - 2, bottom - 6);
379
380 if (lastInRun) {
381
382 g.drawLine(2, bottom - 2, right - 6, bottom - 2);
383 g.drawLine(2, 0, right - 2, 0);
384 g.drawLine(2, 0, 2, bottom - 2);
385 } else {
386 g.drawLine(1, bottom - 2, right - 6, bottom - 2);
387 g.drawLine(1, 0, right - 2, 0);
388 g.drawLine(1, 0, 1, bottom - 2);
389 }
390 }
391
392 break;
393
394 case LEFT:
395 g.drawLine(2, 2, 2, bottom - 1);
396 g.drawLine(2, 2, right, 2);
397 g.drawLine(right, 2, right, bottom - 1);
398 g.drawLine(2, bottom - 1, right, bottom - 1);
399
400 break;
401
402 case TOP:default:
403
404 if (leftToRight) {
405 g.drawLine(2, 5, 5, 2);
406 g.drawLine(2, 5, 2, bottom - 2);
407 g.drawLine(5, 2, right - 4, 2);
408 g.drawLine(right - 4, 2, right - 1, 5);
409 g.drawLine(right - 1, 5, right - 1, bottom - 2);
410 g.drawLine(2, bottom - 2, right - 1, bottom - 2);
411 } else {
412 g.drawLine(right - 2, 6, right - 6, 2);
413 g.drawLine(right - 2, 6, right - 2, bottom - 1);
414
415 if (lastInRun) {
416
417 g.drawLine(right - 6, 2, 2, 2);
418 g.drawLine(2, 2, 2, bottom - 1);
419 g.drawLine(right - 2, bottom - 1, 2, bottom - 1);
420 } else {
421 g.drawLine(right - 6, 2, 1, 2);
422 g.drawLine(1, 2, 1, bottom - 1);
423 g.drawLine(right - 2, bottom - 1, 1, bottom - 1);
424 }
425 }
426 }
427
428 g.translate(-tabRect.x, -tabRect.y);
429 }
430 }
431
432
433
434
435 protected void paintTopTabBorder(int tabIndex, Graphics g, int x,
436 int y, int w, int h, int btm, int rght, boolean isSelected) {
437 int currentRun = getRunForTab(tabPane.getTabCount(), tabIndex);
438
439 int firstIndex = tabRuns[currentRun];
440 boolean leftToRight = true;
441 int bottom = h - 1;
442 int right = w - 1;
443
444 g.translate(x, y);
445
446
447
448
449 g.setColor(shadow);
450
451 if (leftToRight) {
452
453 g.drawLine(right - 4, 0, right, 4);
454 }
455
456 g.setColor(darkShadow);
457
458 if (leftToRight) {
459
460
461
462
463
464
465 g.drawLine(right, 4, right, bottom);
466
467
468 g.drawLine(1, bottom, right - 1, bottom);
469
470
471
472
473 }
474
475
476
477
478 g.setColor(isSelected ? selectHighlight : highlight);
479
480 if (leftToRight) {
481
482 g.drawLine(0, 4, 4, 0);
483
484
485 g.drawLine(4, 0, right - 4, 0);
486
487
488 g.drawLine(0, 5, 0, bottom);
489
490
491
492 if ((tabIndex == firstIndex) &&
493 (tabIndex != tabRuns[runCount - 1])) {
494
495 if (tabPane.getSelectedIndex() == tabRuns[currentRun + 1]) {
496
497 g.setColor(selectHighlight);
498 } else {
499
500 g.setColor(highlight);
501 }
502
503 g.drawLine(1, 0, 1, 4);
504 }
505 }
506
507 g.translate(-x, -y);
508 }
509
510
511
512
513 protected void paintTabBackground(Graphics g, int tabPlacement,
514 int tabIndex, int x, int y, int w, int h, boolean isSelected) {
515
516
517 if (isSelected) {
518 g.setColor(selectColor);
519 } else {
520 g.setColor(tabPane.getBackgroundAt(tabIndex));
521 }
522
523 switch (tabPlacement) {
524 case LEFT:
525 g.fillRect(x + 2, y + 1, w - 2, h - 1);
526
527 break;
528
529 case BOTTOM:
530 g.fillRect(x + 2, y, w - 2, h - 4);
531 g.fillRect(x + 5, (y + (h - 1)) - 3, w - 5, 3);
532
533 break;
534
535 case RIGHT:
536 g.fillRect(x + 1, y + 1, w - 5, h - 1);
537 g.fillRect((x + (w - 1)) - 3, y + 5, 3, h - 5);
538
539 break;
540
541 case TOP:default:
542 g.fillRect(x + 1, y + 3, 2, h - 3);
543 g.fillRect(x + 3, y + 1, w - 6, h - 1);
544 g.fillRect(x + (w - 3), y + 3, 2, h - 3);
545 }
546 }
547 }
548
549 public static final class FillingGridLayout extends GridLayout {
550
551 private static final long serialVersionUID = 1L;
552
553
554
555
556
557
558
559 public FillingGridLayout() {
560 this(1, 0, 0, 0);
561 }
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576 public FillingGridLayout(int rows, int cols) {
577 this(rows, cols, 0, 0);
578 }
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605 public FillingGridLayout(int rows, int cols, int hgap, int vgap) {
606 super(rows, cols, hgap, vgap);
607 }
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627 public void layoutContainer(Container parent) {
628 synchronized (parent.getTreeLock()) {
629 Insets insets = parent.getInsets();
630 int ncomponents = parent.getComponentCount();
631 int nrows = getRows();
632 int ncols = getColumns();
633 boolean ltr = parent.getComponentOrientation().isLeftToRight();
634
635 if (ncomponents == 0) {
636 return;
637 }
638
639 if (nrows > 0) {
640 ncols = ((ncomponents + nrows) - 1) / nrows;
641 } else {
642 nrows = ((ncomponents + ncols) - 1) / ncols;
643 }
644
645 double w = parent.getWidth() - (insets.left + insets.right);
646 double h = parent.getHeight() - (insets.top + insets.bottom);
647 w = (w - (((double) ncols - 1) * getHgap())) / ncols;
648 h = (h - (((double) nrows - 1) * getVgap())) / nrows;
649
650 if (ltr) {
651 int oldx = insets.left;
652 double x = oldx;
653 int oldy;
654 double y;
655
656 for (int c = 0; c < ncols; c++) {
657 x = x + w + getVgap();
658 oldy = insets.top;
659 y = oldy;
660
661 for (int r = 0; r < nrows; r++) {
662 int i = (r * ncols) + c;
663 y = y + h + getVgap();
664
665 if (i < ncomponents) {
666 parent.getComponent(i).setBounds(oldx,
667 oldy, (int) (x - oldx),
668 (int) (y - oldy));
669 }
670
671 oldy = oldy + (int) (y - oldy);
672 }
673
674 oldx = oldx + (int) (x - oldx);
675 }
676 } else {
677 double x = parent.getWidth() - insets.right - w;
678 double y;
679
680 for (int c = 0; c < ncols; c++, x -= (w + getHgap())) {
681 y = insets.top;
682
683 for (int r = 0; r < nrows; r++, y += (h + getVgap())) {
684 int i = (r * ncols) + c;
685
686 if (i < ncomponents) {
687 parent.getComponent(i).setBounds((int) x,
688 (int) y, (int) w, (int) h);
689 }
690 }
691 }
692 }
693 }
694 }
695 }
696
697
698
699
700
701
702
703 public static final class PlainTabbedPaneUI extends FlushTabbedPaneUI {
704 private static final Insets CONTENT_INSETS = new Insets(1, 1, 1, 1);
705
706
707
708
709 protected Insets getContentBorderInsets(int tabPlacement) {
710 return CONTENT_INSETS;
711 }
712
713
714
715
716 protected void paintTopTabBorder(int tabIndex, Graphics g, int x,
717 int y, int w, int h, int btm, int rght, boolean isSelected) {
718 super.paintTopTabBorder(tabIndex, g, x, y, w, h, btm, rght,
719 isSelected);
720
721 int bottom = h - 1;
722 int right = w - 1;
723
724 g.translate(x, y);
725
726 if (isSelected) {
727 g.setColor(selectColor);
728 } else {
729 g.setColor(tabPane.getBackgroundAt(tabIndex));
730 }
731
732
733 g.drawLine(1, bottom, right - 1, bottom);
734 g.translate(-x, -y);
735 }
736
737
738
739
740 protected void paintContentBorder(Graphics g, int tabPlacement,
741 int selectedIndex) {
742 super.paintContentBorder(g, tabPlacement, selectedIndex);
743
744 Rectangle tab = new Rectangle();
745 getTabBounds(selectedIndex, tab);
746 PanelFlushBorder.paintBorder(g, 0, tab.y + tab.height,
747 g.getClipBounds().width,
748 g.getClipBounds().height - tab.height - tab.y);
749 g.setColor(selectColor);
750 g.drawLine(tab.x + 1, tab.y + tab.height, (tab.x + tab.width) - 2,
751 tab.y + tab.height);
752 g.setColor(shadow);
753 g.drawLine((tab.x + tab.width) - 1, tab.y + tab.height,
754 (tab.x + tab.width) - 1, tab.y + tab.height);
755 }
756 }
757
758
759
760
761
762
763
764
765 public static class PanelFlushBorder implements Border {
766 private final Insets insets = new Insets(1, 1, 1, 1);
767 private final Insets cloneInsets = new Insets(1, 1, 1, 1);
768 private boolean lockInsets = false;
769 private boolean raised = true;
770
771 public PanelFlushBorder() {
772 this(true);
773 }
774
775 public PanelFlushBorder(boolean isRaised) {
776 this(isRaised, false);
777 }
778
779 private PanelFlushBorder(boolean isRaised, boolean lockInsets) {
780 this.lockInsets = lockInsets;
781 raised = isRaised;
782 }
783
784
785
786
787 public void paintBorder(Component c, Graphics g, int x, int y,
788 int width, int height) {
789 if (raised) {
790 paintBorder(g, x, y, width, height);
791 } else {
792 paintBorder(g, (x + width) - 1, (y + height) - 1, 2 - width,
793 2 - height);
794 }
795 }
796
797 public static void paintBorder(Graphics g, int x, int y, int width,
798 int height) {
799 ((Graphics2D)g).setStroke(new BasicStroke());
800 g.setColor(ColorHelper.getControlShadow());
801 g.drawLine((x + width) - 1, y, (x + width) - 1, (y + height) - 1);
802 g.drawLine(x, (y + height) - 1, (x + width) - 1, (y + height) - 1);
803
804 g.setColor(ColorHelper.getControlLightHighlight());
805 g.drawLine(x, y, x, (y + height) - 1);
806 g.drawLine(x, y, (x + width) - 1, y);
807
808 g.setColor(ColorHelper.getControl());
809 g.drawLine((x + width) - 1, y, (x + width) - 1, y);
810 g.drawLine(x, (y + height) - 1, x, (y + height) - 1);
811 }
812
813
814
815
816 public Insets getBorderInsets(Component c) {
817 if (!lockInsets) {
818 return insets;
819 } else {
820 cloneInsets.top = insets.top;
821 cloneInsets.bottom = insets.bottom;
822 cloneInsets.left = insets.left;
823 cloneInsets.right = insets.right;
824
825 return cloneInsets;
826 }
827 }
828
829
830
831
832 public boolean isBorderOpaque() {
833 return true;
834 }
835 }
836
837
838
839
840 private static final class SingleLineBorder implements Border {
841 private final Insets insets = new Insets(0, 0, 0, 0);
842 private Color color;
843 private int orientation;
844
845 public SingleLineBorder(int orientation, Color color) {
846 this.orientation = orientation;
847 this.color = color;
848
849 switch (orientation) {
850 case TOP:
851 insets.top = 1;
852
853 break;
854
855 case BOTTOM:
856 insets.bottom = 1;
857
858 break;
859
860 case LEFT:
861 insets.left = 1;
862
863 break;
864
865 case RIGHT:
866 insets.right = 1;
867
868 break;
869 }
870 }
871
872
873
874
875 public void paintBorder(Component c, Graphics g, int x, int y,
876 int width, int height) {
877 g.setColor(color);
878
879 switch (orientation) {
880 case TOP:
881 g.drawLine(x, y, (x + width) - 1, y);
882
883 break;
884
885 case BOTTOM:
886 g.drawLine(x, (y + height) - 1, (x + width) - 1,
887 (y + height) - 1);
888
889 break;
890
891 case LEFT:
892 g.drawLine(x, y, x, (y + height) - 1);
893
894 break;
895
896 case RIGHT:
897 g.drawLine((x + width) - 1, y, (x + width) - 1, (y + height) -
898 1);
899
900 break;
901 }
902 }
903
904
905
906
907 public Insets getBorderInsets(Component c) {
908 return insets;
909 }
910
911
912
913
914 public boolean isBorderOpaque() {
915 return true;
916 }
917 }
918 }