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;
21
22 import com.cosylab.gui.components.util.Actions;
23 import com.cosylab.gui.components.util.ColorHelper;
24 import com.cosylab.gui.components.util.CosyUIElements;
25
26 import java.awt.Color;
27 import java.awt.Component;
28 import java.awt.Container;
29 import java.awt.Dimension;
30 import java.awt.Font;
31 import java.awt.Graphics;
32 import java.awt.Insets;
33 import java.awt.LayoutManager;
34 import java.awt.event.ComponentAdapter;
35 import java.awt.event.ComponentEvent;
36 import java.awt.event.FocusAdapter;
37 import java.awt.event.FocusEvent;
38 import java.awt.event.KeyAdapter;
39 import java.awt.event.KeyEvent;
40 import java.awt.event.MouseAdapter;
41 import java.awt.event.MouseEvent;
42
43 import java.beans.PropertyChangeEvent;
44 import java.beans.PropertyChangeListener;
45
46 import java.util.ArrayList;
47 import java.util.Iterator;
48
49 import javax.swing.AbstractButton;
50 import javax.swing.Action;
51 import javax.swing.Icon;
52 import javax.swing.JButton;
53 import javax.swing.JPanel;
54 import javax.swing.JToggleButton;
55 import javax.swing.border.Border;
56 import javax.swing.event.ChangeEvent;
57 import javax.swing.event.ChangeListener;
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 public class PanelTitleBar extends JPanel
82 {
83 private static final long serialVersionUID = 1L;
84
85
86 public static final String ACTION_STICKY = "sticky";
87
88
89 public static final String ACTION_VISIBLE = "visible";
90 private Border pressedBorder = CosyUIElements.getPlainBorder(false);
91 private Border overBorder = CosyUIElements.getPlainBorder(true);
92 private static final String BUTTON_KEY = "com.cosylab.gui.components.PanelTitleBar Key For Buttons 2431";
93 private GradientLabel title = null;
94 private ArrayList<AbstractButton> buttons = null;
95 private int selectedIndex = -1;
96 private boolean mouseIn = false;
97 private PanelTitleBarLayout titleBarLayout;
98
99 private class PanelTitleBarLayout implements LayoutManager
100 {
101 private int height = 38;
102 private PanelTitleBar panel = null;
103 private int panelWidth = 0;
104 private int minWidth = 0;
105 private int minHeight = 0;
106
107
108
109
110
111
112 public PanelTitleBarLayout(int height)
113 {
114 setHeight(height);
115 }
116
117
118
119
120 public void addLayoutComponent(String name, Component comp)
121 {
122 reposition(true);
123 }
124
125
126
127
128 public void removeLayoutComponent(Component comp)
129 {
130 if ((panel != null) && (panel.getButtonsList() != null)) {
131 if (panel.getButtonsList().contains(comp)) {
132 panel.getButtonsList().remove(comp);
133 }
134
135 reposition(true);
136 }
137 }
138
139
140
141
142 public Dimension preferredLayoutSize(Container parent)
143 {
144 reposition(true);
145
146 if (panel == null) {
147 return new Dimension(height, height);
148 }
149
150 return new Dimension(panel.getTitleLabel().getPreferredSize().width
151 + panel.getButtonsList().size() * height
152 + panel.getInsets().left + panel.getInsets().right, minHeight);
153 }
154
155
156
157
158 public Dimension minimumLayoutSize(Container parent)
159 {
160 reposition(true);
161
162 return new Dimension(minWidth, minHeight);
163 }
164
165
166
167
168 public void layoutContainer(Container parent)
169 {
170 if (panel == null) {
171 panel = (PanelTitleBar)parent;
172 panel.addComponentListener(new ComponentAdapter() {
173 public void componentResized(ComponentEvent event)
174 {
175 int h = minHeight;
176 reposition(false);
177
178 if (h != minHeight) {
179 panelWidth = -1;
180 panel.revalidate();
181 }
182 }
183 });
184 reposition(true);
185 }
186 }
187
188 private void reposition(boolean force)
189 {
190 if ((panel == null) || (panel.getTitleLabel() == null)) {
191 return;
192 }
193
194 if ((force) || (panel.getWidth() != panelWidth)) {
195 panelWidth = panel.getWidth();
196
197 int titleWidth = panel.getTitleLabel().getPreferredSize().width;
198 int numButtons = 0;
199
200 for (Iterator iterator = panel.getButtonsList().iterator();
201 iterator.hasNext();) {
202 AbstractButton b = (AbstractButton)iterator.next();
203
204 if (!isVisible(b)) {
205 continue;
206 }
207
208 if (!isSticky(b)) {
209 numButtons++;
210 }
211 }
212
213 int[] currX = new int[]{ 0, 0 };
214 int[] currY = new int[]{ 1, 1 };
215 int botIdx = 0;
216
217 if (((panelWidth - titleWidth - numButtons * height) < 0)
218 && (numButtons != 0)) {
219 currY[1] = height - 1;
220 botIdx = 1;
221 }
222
223 currX[0] = panelWidth - height + 1;
224 currX[1] = currX[0];
225
226 for (Iterator iterator = panel.getButtonsList().iterator();
227 iterator.hasNext();) {
228 AbstractButton b = (AbstractButton)iterator.next();
229
230 if (!isVisible(b)) {
231 b.setVisible(false);
232 } else {
233 b.setVisible(true);
234
235 if (isSticky(b)) {
236 b.setBounds(currX[0], currY[0], height - 2,
237 height - 2);
238 currX[0] = currX[0] - height + 2;
239 } else {
240 b.setBounds(currX[botIdx], currY[botIdx],
241 height - 2, height - 2);
242 currX[botIdx] = currX[botIdx] - height + 2;
243 }
244 }
245 }
246
247 titleWidth = currX[0] + height - 3;
248 panel.getTitleLabel().setBounds(1, 1, titleWidth, height - 2);
249 minHeight = currY[botIdx] + height - 1;
250 panel.setMinimumSize(new Dimension(height, minHeight));
251 }
252 }
253
254 private boolean isSticky(AbstractButton b)
255 {
256 if (b.getAction() == null) {
257 return false;
258 }
259
260 Action act = b.getAction();
261
262 return act.getValue(ACTION_STICKY) == Boolean.TRUE;
263 }
264
265 private boolean isVisible(AbstractButton b)
266 {
267 if (b.getAction() == null) {
268 return b.isVisible();
269 }
270
271 Action act = b.getAction();
272
273 return act.getValue(ACTION_VISIBLE) != Boolean.FALSE;
274 }
275
276 int getHeight()
277 {
278 return height;
279 }
280
281 void setHeight(int height)
282 {
283 this.height = height;
284 reposition(true);
285 }
286 }
287
288
289
290
291
292
293
294
295
296 public PanelTitleBar(String title, Icon icon, int height)
297 {
298 super();
299 this.title = new GradientLabel(title);
300
301 if (icon != null) {
302 this.title.setIcon(icon);
303 }
304
305 buttons = new ArrayList<AbstractButton>(10);
306 initialize(height);
307 }
308
309
310
311
312
313
314
315 public PanelTitleBar(String title)
316 {
317 this(title, null, 24);
318 }
319
320
321
322
323
324 public PanelTitleBar()
325 {
326 this("");
327 }
328
329
330
331
332
333
334 public String getTitle()
335 {
336 return title.getText();
337 }
338
339
340
341
342
343
344
345 public void setTitle(String title)
346 {
347 this.title.setText(title);
348 }
349
350 private void setSelectedButton(AbstractButton button)
351 {
352 if ((selectedIndex > -1) && (selectedIndex < buttons.size())) {
353 AbstractButton old = buttons.get(selectedIndex);
354 old.setBorderPainted(old.isSelected());
355 old.setOpaque(false);
356 }
357
358 if (button != null) {
359 button.setBorderPainted(true);
360 button.setOpaque(true);
361 selectedIndex = buttons.indexOf(button);
362 } else {
363 selectedIndex = -1;
364 }
365 }
366
367
368
369
370
371
372
373 public Icon getIcon()
374 {
375 return title.getIcon();
376 }
377
378
379
380
381
382
383
384
385
386
387 public void setIcon(Icon icon)
388 {
389 title.setIcon(icon);
390 }
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407 public void addButton(int index, AbstractButton button)
408 {
409 final AbstractButton butt = button;
410 buttons.add(index, butt);
411
412 if (butt.isSelected()) {
413 butt.setBorder(pressedBorder);
414 } else {
415 butt.setBorder(overBorder);
416 }
417
418 butt.setFocusable(false);
419 butt.setBorderPainted(butt.isSelected());
420 butt.setOpaque(false);
421 butt.setBackground(getBackground());
422 butt.addMouseListener(new MouseAdapter() {
423 public void mouseEntered(MouseEvent event)
424 {
425 if (butt.isEnabled()) {
426 setSelectedButton(butt);
427 }
428
429 mouseIn = true;
430 }
431
432 public void mouseExited(MouseEvent event)
433 {
434 setSelectedButton(null);
435 mouseIn = false;
436 }
437
438
439
440
441 public void mousePressed(MouseEvent e)
442 {
443 if (butt.isEnabled()) {
444 butt.setBorder(pressedBorder);
445
446 if (pressedBorder != null) {
447 butt.setBorderPainted(true);
448 } else {
449 butt.setBorderPainted(false);
450 }
451 }
452 }
453
454
455
456
457 public void mouseReleased(MouseEvent e)
458 {
459 if (butt.isSelected()) {
460 butt.setBorder(pressedBorder);
461
462 if (pressedBorder != null) {
463 butt.setBorderPainted(true);
464 } else {
465 butt.setBorderPainted(false);
466 }
467 } else {
468 butt.setBorder(overBorder);
469
470 if (overBorder != null) {
471 if (butt.isEnabled()) {
472 butt.setBorderPainted(true);
473 }
474 } else {
475 butt.setBorderPainted(false);
476 }
477 }
478 }
479 });
480
481 if (butt instanceof JToggleButton) {
482 butt.addChangeListener(new ChangeListener() {
483
484
485
486 public void stateChanged(ChangeEvent evt)
487 {
488 if (butt.isSelected()) {
489 butt.setBorder(pressedBorder);
490
491 if (pressedBorder != null) {
492 butt.setBorderPainted(true);
493 } else {
494 butt.setBorderPainted(false);
495 }
496 } else {
497 butt.setBorder(overBorder);
498
499 if (overBorder != null) {
500 butt.setBorderPainted(true);
501 } else {
502 butt.setBorderPainted(false);
503 }
504 }
505 }
506 });
507 }
508
509 add(butt, "Button");
510 }
511
512
513
514
515
516
517
518
519 public void addButton(AbstractButton button)
520 {
521 addButton(buttons.size(), button);
522 }
523
524
525
526
527
528
529
530
531
532
533 public void addActionButton(int index, Action action)
534 {
535 if (buttons.contains(action.getValue(BUTTON_KEY))) {
536 buttons.add(index, (AbstractButton) action.getValue(BUTTON_KEY));
537 buttons.remove(action.getValue(BUTTON_KEY));
538
539 return;
540 }
541
542 AbstractButton tempButt = Actions.createButton(action);
543 tempButt.setText("");
544 tempButt.setToolTipText((String)action.getValue(Action.NAME));
545
546 if (action.getValue(Action.SMALL_ICON) != null) {
547 tempButt.setIcon((Icon)action.getValue(Action.SMALL_ICON));
548 }
549
550 action.addPropertyChangeListener(new PropertyChangeListener() {
551 public void propertyChange(PropertyChangeEvent evt)
552 {
553 if (evt.getPropertyName().equals(ACTION_VISIBLE)) {
554 revalidate();
555 repaint();
556 }
557 }
558 });
559
560 addButton(index, tempButt);
561 action.putValue(BUTTON_KEY, tempButt);
562 }
563
564
565
566
567
568
569
570
571 public void addActionButton(Action action)
572 {
573 addActionButton(buttons.size(), action);
574 }
575
576
577
578
579
580
581 public void removeButton(AbstractButton button)
582 {
583 if (button != null) {
584 remove(button);
585 buttons.remove(button);
586 }
587 }
588
589
590
591
592
593
594
595
596
597 public boolean containsButton(AbstractButton button)
598 {
599 return buttons.contains(button);
600 }
601
602
603
604
605
606
607
608 public void removeActionButton(Action action)
609 {
610 removeButton((JButton)action.getValue(BUTTON_KEY));
611 revalidate();
612 repaint();
613 }
614
615
616
617
618
619
620
621
622
623 public boolean containsAction(Action action)
624 {
625 return containsButton((JButton)action.getValue(BUTTON_KEY));
626 }
627
628 private void initialize(int heigth)
629 {
630 setOpaque(true);
631 setBorder(CosyUIElements.getPlainBorder(true));
632 setLayout(titleBarLayout = new PanelTitleBarLayout(heigth));
633 setFocusable(true);
634 addFocusListener(new FocusAdapter() {
635 public void focusGained(FocusEvent event)
636 {
637 if (buttons.size() < 1) {
638 setSelectedButton(null);
639
640 if (event.getOppositeComponent() == getFocusCycleRootAncestor()
641 .getFocusTraversalPolicy().getComponentAfter(getFocusCycleRootAncestor(),
642 PanelTitleBar.this)) {
643 PanelTitleBar.this.transferFocusBackward();
644 } else {
645 PanelTitleBar.this.transferFocus();
646 }
647 } else {
648 setSelectedButton(buttons.get(buttons.size() - 1));
649 }
650 }
651
652 public void focusLost(FocusEvent event)
653 {
654 if (!mouseIn) {
655 setSelectedButton(null);
656 }
657 }
658 });
659 addKeyListener(new KeyAdapter() {
660 public void keyPressed(KeyEvent event)
661 {
662 if (event.getKeyCode() == KeyEvent.VK_LEFT) {
663 moveSelectedLeft();
664 } else if (event.getKeyCode() == KeyEvent.VK_RIGHT) {
665 moveSelectedRight();
666 } else if (event.getKeyCode() == KeyEvent.VK_SPACE) {
667 actionSelected();
668 }
669 }
670 });
671 getInsets().bottom = 0;
672 getInsets().right = 0;
673 getInsets().top = 0;
674 getInsets().left = 0;
675
676 setBackground(ColorHelper.getTextHighlight());
677 setBackgroundStart(ColorHelper.getFocus());
678 title.setFont(title.getFont().deriveFont(Font.PLAIN));
679 title.setBorder(new Border() {
680
681
682
683 public boolean isBorderOpaque()
684 {
685 return false;
686 }
687
688
689
690
691 public Insets getBorderInsets(Component c)
692 {
693 return new Insets(0, 4, 0, 0);
694 }
695
696
697
698
699
700 public void paintBorder(Component c, Graphics g, int x, int y,
701 int width, int height)
702 {
703
704 }
705 });
706 title.setOpaque(true);
707 add(title, "Title");
708 revalidate();
709 repaint();
710 }
711
712 private void moveSelectedRight()
713 {
714 if (buttons.size() > 0) {
715 int newIdx = selectedIndex;
716 AbstractButton newButton;
717
718 do {
719 newIdx--;
720
721 if (newIdx < 0) {
722 newIdx = buttons.size() - 1;
723 }
724 } while (!((newButton = buttons.get(newIdx))
725 .isEnabled() || newIdx == selectedIndex));
726
727 setSelectedButton(newButton);
728 }
729 }
730
731 private void moveSelectedLeft()
732 {
733 if (buttons.size() > 0) {
734 int newIdx = selectedIndex;
735 AbstractButton newButton;
736
737 do {
738 newIdx++;
739
740 if (newIdx >= buttons.size()) {
741 newIdx = 0;
742 }
743 } while (!((newButton = buttons.get(newIdx))
744 .isEnabled() || newIdx == selectedIndex));
745
746 setSelectedButton(newButton);
747 }
748 }
749
750 private void actionSelected()
751 {
752 if ((selectedIndex > -1) && (selectedIndex < buttons.size())) {
753 ((JButton)buttons.get(selectedIndex)).doClick(100);
754 }
755 }
756
757
758
759
760
761
762
763
764 public void setActive(boolean active)
765 {
766 if (active) {
767 title.setOpaque(true);
768 } else {
769 title.setOpaque(false);
770 }
771 }
772
773
774
775
776
777
778 public GradientLabel getTitleLabel()
779 {
780 return title;
781 }
782
783 protected ArrayList getButtonsList()
784 {
785 return buttons;
786 }
787
788
789
790
791
792
793 public Color getBackgroundStart()
794 {
795 return title.getBackgroundStart();
796 }
797
798
799
800
801
802
803
804 public void setBackgroundStart(Color c)
805 {
806 title.setBackgroundStart(c);
807 }
808
809
810
811
812
813
814
815
816
817 public void setBackground(Color backgroundStart, Color background)
818 {
819 setBackground(background);
820 title.setBackgroundStart(backgroundStart);
821 }
822
823
824
825
826
827
828
829 public void setBackground(Color c)
830 {
831 super.setBackground(c);
832
833 if (title != null) {
834 title.setBackground(c);
835 }
836
837 if (buttons != null) {
838 for (Iterator iter = buttons.iterator(); iter.hasNext();) {
839 AbstractButton element = (AbstractButton)iter.next();
840 element.setBackground(c);
841 }
842 }
843 }
844
845
846
847
848
849
850 public Border getOverBorder()
851 {
852 return overBorder;
853 }
854
855
856
857
858
859
860 public Border getPressedBorder()
861 {
862 return pressedBorder;
863 }
864
865
866
867
868
869
870 public void setOverBorder(Border overBorder)
871 {
872 this.overBorder = overBorder;
873
874 if (buttons != null) {
875 for (Iterator iter = buttons.iterator(); iter.hasNext();) {
876 AbstractButton element = (AbstractButton)iter.next();
877
878 if (!element.isSelected()) {
879 element.setBorder(overBorder);
880 }
881 }
882 }
883 }
884
885
886
887
888
889
890 public void setPressedBorder(Border pressedBorder)
891 {
892 this.pressedBorder = pressedBorder;
893
894 if (buttons != null) {
895 for (Iterator iter = buttons.iterator(); iter.hasNext();) {
896 AbstractButton element = (AbstractButton)iter.next();
897
898 if (element.isSelected()) {
899 element.setBorder(pressedBorder);
900 }
901 }
902 }
903 }
904
905
906
907
908
909
910
911
912 public boolean hasAction(Action act)
913 {
914 AbstractButton[] buts = new AbstractButton[buttons.size()];
915 buttons.toArray(buts);
916
917 for (int i = 0; i < buts.length; i++) {
918 if (act.equals(buts[i].getAction())) {
919 return true;
920 }
921 }
922
923 return false;
924 }
925
926
927
928
929
930
931 public int getTitleBarHeight()
932 {
933 return titleBarLayout.getHeight();
934 }
935
936
937
938
939
940
941 void setTitleBarHeight(int titleBarHeight)
942 {
943 titleBarLayout.setHeight(titleBarHeight);
944 }
945 }
946
947