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 }