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