001 /*
002 * $Id: McIDASVViewPanel.java,v 1.15 2012/02/19 17:35:51 davep Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2012
007 * Space Science and Engineering Center (SSEC)
008 * University of Wisconsin - Madison
009 * 1225 W. Dayton Street, Madison, WI 53706, USA
010 * https://www.ssec.wisc.edu/mcidas
011 *
012 * All Rights Reserved
013 *
014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015 * some McIDAS-V source code is based on IDV and VisAD source code.
016 *
017 * McIDAS-V is free software; you can redistribute it and/or modify
018 * it under the terms of the GNU Lesser Public License as published by
019 * the Free Software Foundation; either version 3 of the License, or
020 * (at your option) any later version.
021 *
022 * McIDAS-V is distributed in the hope that it will be useful,
023 * but WITHOUT ANY WARRANTY; without even the implied warranty of
024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
025 * GNU Lesser Public License for more details.
026 *
027 * You should have received a copy of the GNU Lesser Public License
028 * along with this program. If not, see http://www.gnu.org/licenses.
029 */
030
031 package edu.wisc.ssec.mcidasv.ui;
032
033 import java.awt.BorderLayout;
034 import java.awt.Color;
035 import java.awt.Component;
036 import java.awt.Container;
037 import java.awt.Cursor;
038 import java.awt.Dimension;
039 import java.awt.Font;
040 import java.awt.FontMetrics;
041 import java.awt.Graphics;
042 import java.awt.Image;
043 import java.awt.Insets;
044 import java.awt.Rectangle;
045 import java.awt.event.ActionEvent;
046 import java.awt.event.ActionListener;
047 import java.awt.event.KeyAdapter;
048 import java.awt.event.KeyEvent;
049 import java.awt.event.KeyListener;
050 import java.awt.event.MouseAdapter;
051 import java.awt.event.MouseEvent;
052 import java.awt.image.ImageObserver;
053 import java.util.ArrayList;
054 import java.util.Hashtable;
055 import java.util.List;
056
057 import javax.swing.BorderFactory;
058 import javax.swing.BoxLayout;
059 import javax.swing.ButtonGroup;
060 import javax.swing.ImageIcon;
061 import javax.swing.JButton;
062 import javax.swing.JComponent;
063 import javax.swing.JLabel;
064 import javax.swing.JMenuItem;
065 import javax.swing.JPanel;
066 import javax.swing.JPopupMenu;
067 import javax.swing.JScrollPane;
068 import javax.swing.JToggleButton;
069 import javax.swing.SwingConstants;
070 import javax.swing.border.Border;
071 import javax.swing.border.EtchedBorder;
072
073 import edu.wisc.ssec.mcidasv.Constants;
074
075 import ucar.unidata.idv.DisplayControl;
076 import ucar.unidata.idv.IdvConstants;
077 import ucar.unidata.idv.IdvManager;
078 import ucar.unidata.idv.IntegratedDataViewer;
079 import ucar.unidata.idv.MapViewManager;
080 import ucar.unidata.idv.TransectViewManager;
081 import ucar.unidata.idv.ViewManager;
082 import ucar.unidata.idv.control.DisplayControlImpl;
083 import ucar.unidata.idv.control.MapDisplayControl;
084 import ucar.unidata.idv.ui.IdvComponentGroup;
085 import ucar.unidata.idv.ui.IdvWindow;
086 import ucar.unidata.idv.ui.ViewPanel;
087 import ucar.unidata.ui.ComponentHolder;
088 import ucar.unidata.ui.DndImageButton;
089 import ucar.unidata.util.GuiUtils;
090 import ucar.unidata.util.Misc;
091 import ucar.unidata.util.Msg;
092 import ucar.unidata.util.StringUtil;
093
094 /**
095 * <p>This class has largely been copied over wholesale from the IDV code.
096 * Merely extending was proving to be as much as a hassle as just copying it,
097 * though now we still maintain complete control over the ViewPanel, and we have
098 * an obvious point of departure for whenever the JTree is started.</p>
099 *
100 * <p>That said, I personally recommend avoiding this class until the JTree
101 * stuff is ready to go.</p>
102 */
103 public class McIDASVViewPanel extends IdvManager implements ViewPanel {
104
105 private static final Image BUTTON_ICON =
106 GuiUtils.getImage("/auxdata/ui/icons/Selected.gif");
107
108 private static final ImageIcon CATEGORY_OPEN_ICON =
109 GuiUtils.getImageIcon("/auxdata/ui/icons/CategoryOpen.gif");
110
111 private static final ImageIcon CATEGORY_CLOSED_ICON =
112 GuiUtils.getImageIcon("/auxdata/ui/icons/CategoryClosed.gif");
113
114 private static final Border BUTTON_BORDER =
115 BorderFactory.createEmptyBorder(2, 6, 2, 0);
116
117 private static final Font BUTTON_FONT = new Font("Dialog", Font.PLAIN, 11);
118 private static final Color LINE_COLOR = Color.gray;
119 private static final Font CAT_FONT = new Font("Dialog", Font.BOLD, 11);
120
121 /** The border for the header panel */
122 public static Border headerNormal =
123 BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(3,
124 0, 0, 0), BorderFactory.createMatteBorder(0, 0, 2, 0,
125 Color.black));
126
127 /** highlight border for view infos */
128 public static Border headerHighlight =
129 BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(3,
130 0, 0, 0), BorderFactory.createMatteBorder(0, 0, 2, 0,
131 ViewManager.borderHighlightColor));
132
133 private static Color fgColor = Color.black;
134 private static Color onColor = null;
135 private static boolean showPopup = true;
136 private static boolean showCategories = false;
137
138 private JComponent contents;
139
140 private JPanel leftPanel;
141
142 private JPanel viewContainer;
143
144 private ButtonGroup buttonGroup = new ButtonGroup();
145
146 private GuiUtils.CardLayoutPanel rightPanel;
147
148 private IntegratedDataViewer idv;
149
150 private enum ViewManagers { DEFAULT, GLOBE, MAP, TRANSECT };
151
152 private Hashtable<DisplayControl, ControlInfo> controlToInfo =
153 new Hashtable<DisplayControl, ControlInfo>();
154
155
156 private List<VMInfo> vmInfos = new ArrayList<VMInfo>();
157
158 public McIDASVViewPanel(IntegratedDataViewer idv) {
159 super(idv);
160
161 this.idv = idv;
162
163 }
164
165 public void createUI() {
166
167 leftPanel = new JPanel(new BorderLayout());
168 leftPanel.setBorder(
169 BorderFactory.createCompoundBorder(
170 BorderFactory.createEtchedBorder(EtchedBorder.LOWERED),
171 BorderFactory.createEmptyBorder(0, 0, 0, 0)));
172
173 leftPanel.add(BorderLayout.NORTH, GuiUtils.filler(150, 1));
174
175 viewContainer = new JPanel();
176 viewContainer.setLayout(new BoxLayout(viewContainer, BoxLayout.Y_AXIS));
177
178 JScrollPane viewScroll = new JScrollPane(GuiUtils.top(viewContainer));
179 viewScroll.setBorder(null);
180
181 leftPanel.add(BorderLayout.CENTER, viewScroll);
182
183 rightPanel = new GuiUtils.CardLayoutPanel() {
184 public void show(Component comp) {
185 super.show(comp);
186 for (VMInfo vinfo : vmInfos) {
187 for (ControlInfo cinfo : vinfo.controlInfos) {
188 if (cinfo.outer == comp) {
189 cinfo.button.setSelected(true);
190 break;
191 }
192 }
193 }
194 }
195 };
196
197 contents = GuiUtils.leftCenter(leftPanel, rightPanel);
198 Msg.translateTree(contents);
199 }
200
201 public void selectNext(boolean up) {
202 boolean gotit = false;
203 VMInfo select = null;
204 int index = 0;
205 for (int vmIdx = 0; !gotit && (vmIdx < vmInfos.size()); vmIdx++) {
206
207 VMInfo vmInfo = vmInfos.get(vmIdx);
208
209 List<ControlInfo> ctrlInfos = vmInfo.controlInfos;
210
211 for (int i = 0; i < ctrlInfos.size(); i++) {
212 ControlInfo ci = ctrlInfos.get(i);
213
214 if ( !ci.button.isSelected())
215 continue;
216
217 if (up) {
218 if (vmInfo.getCatOpen() && (i > 0)) {
219 select = vmInfo;
220 index = i - 1;
221 } else {
222 vmIdx--;
223 while (vmIdx >= 0) {
224 VMInfo prev = vmInfos.get(vmIdx--);
225 if (prev.getCatOpen() && (prev.controlInfos.size() > 0)) {
226 select = prev;
227 index = select.controlInfos.size() - 1;
228 break;
229 }
230 }
231 }
232 } else {
233 if (vmInfo.getCatOpen() && (i < ctrlInfos.size() - 1)) {
234 select = vmInfo;
235 index = i + 1;
236 } else {
237 vmIdx++;
238 while (vmIdx < vmInfos.size()) {
239 VMInfo next = vmInfos.get(vmIdx++);
240 if (next.getCatOpen() && (next.controlInfos.size() > 0)) {
241 select = next;
242 index = 0;
243 break;
244 }
245 }
246 }
247 }
248 gotit = true;
249 break;
250 }
251 }
252
253 if ((select != null) && (index >= 0) && (index < select.controlInfos.size()))
254 select.controlInfos.get(index).button.doClick();
255 }
256
257 public void addControlTab(DisplayControl control, boolean forceShow) {
258 if (!control.canBeDocked() || !control.shouldBeDocked())
259 return;
260
261 //Check if there are any groups that have autoimport set
262 ViewManager viewManager = control.getViewManager();
263 if (viewManager != null) {
264 IdvWindow window = viewManager.getDisplayWindow();
265 if (window != null) {
266 List groups = window.getComponentGroups();
267 for (int i = 0; i < groups.size(); i++) {
268 Object obj = groups.get(i);
269 if (obj instanceof IdvComponentGroup) {
270 if (((IdvComponentGroup) obj)
271 .tryToImportDisplayControl(
272 (DisplayControlImpl)control)) {
273 return;
274 }
275 }
276 }
277 }
278 }
279
280 ControlInfo info = controlToInfo.get(control);
281 if (info != null)
282 return;
283
284 //For now cheat a little with the cast
285 ((DisplayControlImpl)control).setMakeWindow(false);
286
287 JButton removeBtn =
288 GuiUtils.makeImageButton("/auxdata/ui/icons/Remove16.gif",
289 control, "doRemove");
290 removeBtn.setToolTipText("Remove Display Control");
291
292 JButton expandBtn =
293 GuiUtils.makeImageButton("/auxdata/ui/icons/DownDown.gif", this,
294 "expandControl", control);
295 expandBtn.setToolTipText("Expand in the tabs");
296
297 JButton exportBtn =
298 GuiUtils.makeImageButton("/auxdata/ui/icons/Export16.gif", this,
299 "undockControl", control);
300 exportBtn.setToolTipText("Undock control window");
301
302 JButton propBtn =
303 GuiUtils.makeImageButton("/auxdata/ui/icons/Information16.gif",
304 control, "showProperties");
305 propBtn.setToolTipText("Show Display Control Properties");
306
307 DndImageButton dnd = new DndImageButton(control, "idv/display");
308 dnd.setToolTipText("Drag and drop to a window component");
309 // JPanel buttonPanel =
310 // GuiUtils.left(GuiUtils.hbox(Misc.newList(expandBtn, exportBtn,
311 // propBtn, removeBtn, dnd), 4));
312 JPanel buttonPanel =
313 GuiUtils.left(GuiUtils.hbox(Misc.newList(exportBtn,
314 propBtn, removeBtn, dnd), 4));
315
316 buttonPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0,
317 Color.lightGray.darker()));
318
319 JComponent inner =
320 (JComponent) ((DisplayControlImpl)control).getOuterContents();
321 inner = GuiUtils.centerBottom(inner, buttonPanel);
322 JComponent outer = GuiUtils.top(inner);
323 outer.setBorder(BorderFactory.createEmptyBorder(2, 1, 0, 0));
324
325 info = new ControlInfo(control, expandBtn, outer, inner,
326 getVMInfo(control.getDefaultViewManager()));
327
328 controlToInfo.put(control, info);
329
330 GuiUtils.toggleHeavyWeightComponents(outer, false);
331 if (!getStateManager().getProperty(IdvConstants.PROP_LOADINGXML, false)) {
332
333 //A hack for now
334 if (!(control instanceof MapDisplayControl)) {
335 GuiUtils.toggleHeavyWeightComponents(outer, true);
336 GuiUtils.showComponentInTabs(outer);
337 }
338
339 }
340 }
341
342 public void expandControl(DisplayControl control) {
343 ControlInfo info = controlToInfo.get(control);
344 if (info != null)
345 info.expand();
346 }
347
348 public void dockControl(DisplayControl control) {
349 control.setShowInTabs(true);
350 ((DisplayControlImpl)control).guiImported();
351 addControlTab(control, true);
352 }
353
354 public void undockControl(DisplayControl control) {
355 removeControlTab(control);
356 control.setShowInTabs(false);
357 ((DisplayControlImpl)control).setMakeWindow(true);
358 ((DisplayControlImpl)control).popup(null);
359 }
360
361 public void controlMoved(DisplayControl control) {
362 removeControlTab(control);
363 addControlTab(control, true);
364 }
365
366 public void removeControlTab(DisplayControl control) {
367 ControlInfo info = controlToInfo.remove(control);
368 if (info != null)
369 info.removeDisplayControl();
370 }
371
372 public JComponent getContents() {
373 if (contents == null)
374 createUI();
375
376 return contents;
377 }
378
379 public void addDisplayControl(DisplayControl control) {
380 addControlTab(control, false);
381 }
382
383 public void displayControlChanged(DisplayControl control) {
384 ControlInfo info = controlToInfo.get(control);
385 if (info != null)
386 info.displayControlChanged();
387 }
388
389 public void removeDisplayControl(DisplayControl control) {
390 removeControlTab(control);
391 }
392
393 public void addViewMenuItems(DisplayControl control, List items) {
394 if (!control.canBeDocked())
395 return;
396
397 items.add(GuiUtils.MENU_SEPARATOR);
398
399 if (!control.shouldBeDocked())
400 items.add(GuiUtils.makeMenuItem("Dock in Data Explorer", this, "dockControl", control));
401 else
402 items.add(GuiUtils.makeMenuItem("Undock from Data Explorer", this, "undockControl", control));
403
404 List groups = getIdvUIManager().getComponentGroups();
405 List<JMenuItem> subItems = new ArrayList<JMenuItem>();
406 for (int i = 0; i < groups.size(); i++) {
407 IdvComponentGroup group = (IdvComponentGroup)groups.get(i);
408 subItems.add(GuiUtils.makeMenuItem(group.getHierachicalName(), group, "importDisplayControl", control));
409 }
410
411 if (subItems.size() > 0)
412 items.add(GuiUtils.makeMenu("Export to component", subItems));
413 }
414
415 public void viewManagerAdded(ViewManager vm) {
416 // this forces the addition of the ViewManager
417 getVMInfo(vm);
418 }
419
420 public void viewManagerDestroyed(ViewManager vm) {
421 VMInfo info = findVMInfo(vm);
422 if (info != null) {
423 vmInfos.remove(info);
424 info.viewManagerDestroyed();
425 // System.err.println("destroying "+info+" for "+vm);
426 }
427 }
428
429 /**
430 * Triggered upon a change in the given ViewManager. Just used so that our
431 * ControlInfo object can update its internal state.
432 *
433 * @param vm The ViewManager that's changed.
434 */
435 public void viewManagerChanged(ViewManager vm) {
436 VMInfo info = findVMInfo(vm);
437 if (info != null)
438 info.viewManagerChanged();
439 }
440
441 /**
442 * Initialize the button state
443 *
444 * @param idv the idv
445 */
446 protected void initButtonState() {
447 if (fgColor != null)
448 return;
449
450 fgColor = Color.black;
451
452 showPopup = idv.getProperty(Constants.PROP_VP_SHOWPOPUP, false);
453
454 showCategories = idv.getProperty(Constants.PROP_VP_SHOWCATS, false);
455 }
456
457 public VMInfo getVMInfo(ViewManager vm) {
458 VMInfo info = findVMInfo(vm);
459 if (info == null) {
460
461 // oh no :(
462 if (vm instanceof MapViewManager)
463 if (((MapViewManager)vm).getUseGlobeDisplay())
464 info = new VMInfo(vm, ViewManagers.GLOBE);
465 else
466 info = new VMInfo(vm, ViewManagers.MAP);
467 else if (vm instanceof TransectViewManager)
468 info = new VMInfo(vm, ViewManagers.TRANSECT);
469 else
470 info = new VMInfo(vm, ViewManagers.DEFAULT);
471
472 vmInfos.add(info);
473 }
474 return info;
475 }
476
477 public VMInfo findVMInfo(ViewManager vm) {
478 for (VMInfo info : vmInfos)
479 if (info.holds(vm))
480 return info;
481
482 return null;
483 }
484
485 public class VMInfo implements ImageObserver {
486 private ViewManager viewManager;
487
488 private JButton popupButton;
489
490 private JComponent tabContents = new JPanel(new BorderLayout());
491
492 private JPanel headerPanel;
493
494 private boolean ignore = false;
495
496 // private list of controlinfos?
497 private List<ControlInfo> controlInfos = new ArrayList<ControlInfo>();
498 private List<JToggleButton> buttons = new ArrayList<JToggleButton>();
499
500 //private JComponent buttonPanel;
501
502 private JComponent contents;
503
504 private JLabel viewLabel;
505
506 private JButton catToggle;
507
508 private boolean catOpen = true;
509
510 private KeyListener listener;
511
512 private List<String> categories = new ArrayList<String>();
513
514 private ViewManagers myType = ViewManagers.DEFAULT;
515
516 public VMInfo(ViewManager vm, ViewManagers type) {
517
518 listener = new KeyAdapter() {
519 public void keyPressed(KeyEvent e) {
520 if (e.getKeyCode() == KeyEvent.VK_UP)
521 selectNext(true);
522 else if (e.getKeyCode() == KeyEvent.VK_DOWN)
523 selectNext(false);
524 }
525 };
526
527 initButtonState();
528 BUTTON_ICON.getWidth(this);
529
530 viewManager = vm;
531
532 ImageIcon icon = ICON_DEFAULT;
533 if (type == ViewManagers.GLOBE)
534 icon = ICON_GLOBE;
535 else if (type == ViewManagers.MAP)
536 icon = ICON_MAP;
537 else if (type == ViewManagers.TRANSECT)
538 icon = ICON_TRANSECT;
539
540 viewLabel = new JLabel(" " + getLabel());
541 viewLabel.addMouseListener(new MouseAdapter() {
542 public void mousePressed(MouseEvent e) {
543 if (viewManager == null)
544 return;
545
546 getVMManager().setLastActiveViewManager(viewManager);
547 if (e.getClickCount() == 2)
548 viewManager.toFront();
549 }
550 });
551
552 catToggle = GuiUtils.getImageButton(getCatOpen() ? CATEGORY_OPEN_ICON : CATEGORY_CLOSED_ICON);
553 catToggle.addKeyListener(listener);
554 catToggle.addActionListener(new ActionListener() {
555 public void actionPerformed(ActionEvent e) {
556 setCatOpen(!getCatOpen());
557 }
558 });
559
560 popupButton = new JButton(icon);
561 popupButton.addKeyListener(listener);
562 popupButton.setContentAreaFilled(false);
563 popupButton.addActionListener(GuiUtils.makeActionListener(VMInfo.this, "showPopupMenu", null));
564 popupButton.setToolTipText("Show View Menu");
565 popupButton.setBorder(BorderFactory.createEmptyBorder());
566
567 headerPanel = GuiUtils.leftCenter(GuiUtils.hbox(
568 GuiUtils.inset(catToggle, 1),
569 popupButton), viewLabel);
570
571 if (viewManager != null)
572 headerPanel = viewManager.makeDropPanel(headerPanel, true);
573
574 JComponent headerWrapper = GuiUtils.center(headerPanel);
575 headerPanel.setBorder(headerNormal);
576 contents = GuiUtils.topCenter(headerWrapper, tabContents);
577 viewContainer.add(contents);
578 popupButton.setHorizontalAlignment(SwingConstants.LEFT);
579 buttonsChanged();
580
581 setCatOpen(getCatOpen());
582
583 if (viewManager != null)
584 viewManagerChanged();
585 }
586
587 public boolean getCatOpen() {
588 if (viewManager != null) {
589 Boolean b =
590 (Boolean)viewManager.getProperty(Constants.PROP_VP_CATOPEN);
591 if (b != null)
592 return b;
593 }
594
595 return catOpen;
596 }
597
598 public void setCatOpen(boolean v) {
599 if (viewManager != null)
600 viewManager.putProperty(Constants.PROP_VP_CATOPEN, v);
601
602 catOpen = v;
603 catToggle.setIcon(v ? CATEGORY_OPEN_ICON : CATEGORY_CLOSED_ICON);
604 tabContents.setVisible(v);
605 }
606
607 public void showPopupMenu() {
608 if (viewManager == null)
609 return;
610
611 List items = new ArrayList();
612 viewManager.addContextMenuItems(items);
613 JPopupMenu popup = GuiUtils.makePopupMenu(items);
614 popup.show(popupButton, 0, popupButton.getHeight());
615 }
616
617 /**
618 * Determine if this VMInfo contains a given ViewManager.
619 *
620 * @param vm The ViewManager you wish to test.
621 *
622 * @return True if this VMInfo contains <tt>vm</tt>, false otherwise.
623 */
624 public boolean holds(ViewManager vm) {
625 return viewManager == vm;
626 }
627
628 public void removeControlInfo(ControlInfo info) {
629 int idx = controlInfos.indexOf(info);
630 if (idx == -1)
631 return;
632
633 int btnIdx = buttons.indexOf(info.button);
634 controlInfos.remove(info);
635 rightPanel.remove(info.outer);
636
637 if (info.button.isSelected() && (buttons.size() > 0)) {
638 while ((btnIdx >= buttons.size()) && (btnIdx >= 0))
639 btnIdx--;
640
641 if (btnIdx >= 0)
642 buttons.get(btnIdx).doClick();
643 }
644
645 GuiUtils.toggleHeavyWeightComponents(info.outer, true);
646
647 buttonsChanged();
648
649 // hmm -- this must be for synchronization?
650 ignore = true;
651 buttonGroup.remove(info.button);
652 ignore = false;
653
654 // if there are still control infos left then we'll use those?
655 if (controlInfos.size() > 0)
656 return;
657
658 // otherwise we need to click the buttons of each remaining viewmanager?
659 for (VMInfo vm : vmInfos)
660 if (vm.controlInfos.size() > 0)
661 vm.controlInfos.get(0).button.doClick();
662 }
663
664 public void changeControlInfo(ControlInfo info) {
665 if (!Misc.equals(info.lastCategory, info.control.getDisplayCategory()))
666 buttonsChanged();
667 }
668
669 public void paintButton(Graphics g, ControlInfo info) {
670 g.setFont(BUTTON_FONT);
671 FontMetrics fm = g.getFontMetrics(g.getFont());
672
673 JToggleButton btn = info.button;
674 Rectangle b = btn.getBounds();
675 String text = info.getLabel();
676 int y = (btn.getHeight() + fm.getHeight()) / 2 - 2;
677 int buttonWidth = BUTTON_ICON.getWidth(null);
678 int offset = 2 + buttonWidth + 4;
679 g.setColor(btn.getBackground());
680 g.fillRect(0, 0, b.width, b.height);
681
682 if (btn.isSelected()) {
683
684 if (onColor == null) {
685 Color c = btn.getBackground();
686 //Just go a little bit darker than the normal background
687 onColor = new Color((int) Math.max(0,
688 c.getRed() - 20), (int) Math.max(0,
689 c.getGreen() - 20), (int) Math.max(0,
690 c.getBlue() - 20));
691 }
692
693 g.setColor(onColor);
694 g.fillRect(offset - 1, 0, b.width, b.height);
695 }
696 g.setColor(LINE_COLOR);
697
698 g.drawLine(offset - 1, b.height - 1, b.width, b.height - 1);
699
700 g.setColor(fgColor);
701 int rightSide = b.width;
702 if (btn.isSelected())
703 rightSide = b.width - buttonWidth - 2;
704
705 int textPos = offset;
706 int textRight = textPos + fm.stringWidth(text);
707 if (textRight >= rightSide) {
708 while ((text.length() > 5) && (textRight >= rightSide)) {
709 text = text.substring(0, text.length() - 2);
710 textRight = textPos + fm.stringWidth(text + ".");
711 }
712 text = text + ".";
713 }
714 g.drawString(text, offset, y);
715
716 if (!btn.isSelected())
717 return;
718
719 int height = BUTTON_ICON.getHeight(null);
720 g.drawImage(BUTTON_ICON, b.width - 2 - buttonWidth, b.height / 2 - height / 2, null);
721 }
722
723 public void addControlInfo(final ControlInfo info) {
724 // ugly :(
725 // why even have b?
726 //JToggleButton b = info.button = new JToggleButton(StringUtil.padRight("", 20), true) {
727 info.button = new JToggleButton(StringUtil.padRight("", 20), true) {
728 public void paint(Graphics g) {
729 paintButton(g, info);
730 }
731 };
732
733 info.button.addKeyListener(listener);
734 info.button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
735 info.button.setToolTipText(info.getLabel());
736 info.button.setFont(BUTTON_FONT);
737 info.button.setForeground(fgColor);
738 info.button.setBorder(BUTTON_BORDER);
739
740 info.button.setHorizontalAlignment(SwingConstants.LEFT);
741 info.button.addActionListener(new ActionListener() {
742 public void actionPerformed(ActionEvent e) {
743 if (ignore)
744 return;
745
746 GuiUtils.toggleHeavyWeightComponents(info.outer, true);
747 rightPanel.show(info.outer);
748 }
749 });
750 buttons.add(info.button);
751 controlInfos.add(info);
752 rightPanel.addCard(info.outer);
753 GuiUtils.toggleHeavyWeightComponents(info.outer, false);
754 info.displayControlChanged();
755
756 if (info.control.getExpandedInTabs())
757 info.expand();
758
759 buttonGroup.add(info.button);
760 buttonsChanged();
761 setCatOpen(getCatOpen());
762 }
763
764 /**
765 * Redo the buttons
766 */
767 private void buttonsChanged() {
768 List<JComponent> comps = new ArrayList<JComponent>();
769
770 Hashtable<String, List<JComponent>> catMap =
771 new Hashtable<String, List<JComponent>>();
772
773 for (ControlInfo info : controlInfos) {
774 String cat = info.control.getDisplayCategory();
775 if (cat == null)
776 cat = "Displays";
777
778 info.lastCategory = cat;
779
780 if (!showCategories) {
781 comps.add(info.button);
782 continue;
783 }
784
785 List<JComponent> catList = catMap.get(cat);
786 if (catList == null) {
787 if (!categories.contains(cat))
788 categories.add(cat);
789
790 catList = new ArrayList<JComponent>();
791
792 catMap.put(cat, catList);
793
794 JLabel catLabel = new JLabel(" " + cat);
795
796 catLabel.setFont(CAT_FONT);
797
798 catList.add(catLabel);
799 }
800 catList.add(info.button);
801 }
802
803 if (showCategories) {
804 for (String category : categories) {
805 List<JComponent> catList = catMap.get(category);
806 if (catList != null)
807 comps.addAll(catList);
808 }
809 }
810
811 if (comps.size() == 0) {
812 if (myType == ViewManagers.TRANSECT) {
813 JLabel noLbl = new JLabel("No Displays");
814 noLbl.setFont(BUTTON_FONT);
815 JPanel inset = GuiUtils.inset(noLbl, new Insets(0, 10, 0, 0));
816 inset.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0,
817 Color.gray));
818 comps.add(inset);
819 } else {
820 headerPanel.setVisible(false);
821 }
822 } else {
823 headerPanel.setVisible(true);
824 }
825
826 comps.add(GuiUtils.filler(10, 2));
827 JComponent buttonPanel = GuiUtils.vbox(comps);
828
829 tabContents.removeAll();
830 tabContents.add(BorderLayout.NORTH, buttonPanel);
831 tabContents.repaint();
832 }
833
834 /**
835 * Handles ViewManager removal.
836 */
837 public void viewManagerDestroyed() {
838 viewContainer.remove(contents);
839 }
840
841 /**
842 * my viewmanager has changed. Update the gui.
843 */
844 public void viewManagerChanged() {
845 viewLabel.setText(getLabel());
846
847 if (viewManager.showHighlight()) {
848
849 headerHighlight =
850 BorderFactory.createCompoundBorder(
851 BorderFactory.createEmptyBorder(3, 0, 0, 0),
852 BorderFactory.createMatteBorder(
853 0, 0, 2, 0,
854 getStore().get(
855 ViewManager.PREF_BORDERCOLOR, Color.blue)));
856
857 headerPanel.setBorder(headerHighlight);
858 } else {
859 headerPanel.setBorder(headerNormal);
860 }
861
862 if (contents != null)
863 contents.repaint();
864 }
865
866 /**
867 * Get the ViewManager label. If the ViewManager does not already have
868 * a valid name, a default name is created, based on the number of
869 * existing ViewManagers.
870 *
871 * @return label The ViewManager's name.
872 */
873 public String getLabel() {
874 // nothing to query for a name?
875 if (viewManager == null)
876 return "No Display";
877
878 // do we already have a valid name?
879 String name = viewManager.getName();
880 if ((name != null) && (name.trim().length() > 0)) {
881 UIManager uiManager = (UIManager)idv.getIdvUIManager();
882 ComponentHolder holder = uiManager.getViewManagerHolder(viewManager);
883 if (holder != null)
884 return holder.getName() + ">" + name;
885 else
886 return name;
887 }
888
889 // if our name was invalid, build a default one.
890 int idx = vmInfos.indexOf(this);
891 return "Default " + Constants.PANEL_NAME + " " +
892 ((idx == -1) ? vmInfos.size() : idx);
893 }
894
895 public boolean imageUpdate(Image img, int flags, int x, int y, int width, int height) {
896 if ((flags & ImageObserver.ALLBITS) == 0)
897 return true;
898
899 leftPanel.repaint();
900 return false;
901 }
902 }
903
904 public class ControlInfo {
905 DisplayControl control;
906 JButton expandButton;
907 JComponent outer;
908 JComponent inner;
909 boolean expanded = false;
910 Dimension innerSize = new Dimension();
911 VMInfo info;
912 JToggleButton button;
913 String lastCategory = "";
914 String label = null;
915
916 /**
917 * ctor
918 *
919 * @param control control
920 * @param expandButton expand button
921 * @param outer outer comp
922 * @param inner inner comp
923 * @param vmInfo my vminfo
924 */
925 public ControlInfo(DisplayControl control, JButton expandButton,
926 JComponent outer, JComponent inner,
927 VMInfo vmInfo) {
928 this.info = vmInfo;
929 this.control = control;
930 if (control.getExpandedInTabs())
931 expanded = false;
932
933 this.expandButton = expandButton;
934 this.outer = outer;
935 this.inner = inner;
936 inner.getSize(innerSize);
937 info.addControlInfo(this);
938 this.expand();
939 }
940
941 /**
942 * get the label for the display control
943 *
944 * @return display control label
945 */
946 public String getLabel() {
947 if (label == null)
948 label = control.getMenuLabel();
949
950 return label;
951 }
952
953 /**
954 * display control changed
955 */
956 public void displayControlChanged() {
957 String tmp = label;
958 label = null;
959 getLabel();
960 if (!Misc.equals(tmp, label) && (button != null)) {
961 button.setToolTipText(label);
962 button.repaint();
963 }
964 info.changeControlInfo(this);
965 }
966
967 /**
968 * display control is removed
969 */
970 public void removeDisplayControl() {
971 info.removeControlInfo(this);
972 }
973
974 /**
975 * Expand the contents
976 */
977 public void expand() {
978 outer.removeAll();
979 outer.setLayout(new BorderLayout());
980
981 if (!expanded) {
982 outer.add(BorderLayout.CENTER, inner);
983 expandButton.setIcon(
984 GuiUtils.getImageIcon("/auxdata/ui/icons/UpUp.gif"));
985 inner.getSize(innerSize);
986 // System.err.println("ControlInfo.expand: innerSize=" + innerSize);
987 } else {
988 outer.add(BorderLayout.NORTH, inner);
989 expandButton.setIcon(
990 GuiUtils.getImageIcon("/auxdata/ui/icons/DownDown.gif"));
991 inner.setSize(innerSize);
992 }
993
994 expanded = !expanded;
995 control.setExpandedInTabs(expanded);
996
997 final Container parent = outer.getParent();
998 outer.invalidate();
999 parent.validate();
1000 parent.doLayout();
1001 }
1002 }
1003 }