001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2015 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 029package edu.wisc.ssec.mcidasv.ui; 030 031import java.awt.BorderLayout; 032import java.awt.Color; 033import java.awt.Component; 034import java.awt.Container; 035import java.awt.Cursor; 036import java.awt.Dimension; 037import java.awt.Font; 038import java.awt.FontMetrics; 039import java.awt.Graphics; 040import java.awt.Image; 041import java.awt.Insets; 042import java.awt.Rectangle; 043import java.awt.event.ActionEvent; 044import java.awt.event.ActionListener; 045import java.awt.event.KeyAdapter; 046import java.awt.event.KeyEvent; 047import java.awt.event.KeyListener; 048import java.awt.event.MouseAdapter; 049import java.awt.event.MouseEvent; 050import java.awt.image.ImageObserver; 051import java.util.ArrayList; 052import java.util.Hashtable; 053import java.util.List; 054 055import javax.swing.BorderFactory; 056import javax.swing.BoxLayout; 057import javax.swing.ButtonGroup; 058import javax.swing.ImageIcon; 059import javax.swing.JButton; 060import javax.swing.JComponent; 061import javax.swing.JLabel; 062import javax.swing.JMenuItem; 063import javax.swing.JPanel; 064import javax.swing.JPopupMenu; 065import javax.swing.JScrollPane; 066import javax.swing.JToggleButton; 067import javax.swing.SwingConstants; 068import javax.swing.border.Border; 069import javax.swing.border.EtchedBorder; 070 071import edu.wisc.ssec.mcidasv.Constants; 072 073import ucar.unidata.idv.DisplayControl; 074import ucar.unidata.idv.IdvConstants; 075import ucar.unidata.idv.IdvManager; 076import ucar.unidata.idv.IntegratedDataViewer; 077import ucar.unidata.idv.MapViewManager; 078import ucar.unidata.idv.TransectViewManager; 079import ucar.unidata.idv.ViewManager; 080import ucar.unidata.idv.control.DisplayControlImpl; 081import ucar.unidata.idv.control.MapDisplayControl; 082import ucar.unidata.idv.ui.IdvComponentGroup; 083import ucar.unidata.idv.ui.IdvWindow; 084import ucar.unidata.idv.ui.ViewPanel; 085import ucar.unidata.ui.ComponentHolder; 086import ucar.unidata.ui.DndImageButton; 087import ucar.unidata.util.GuiUtils; 088import ucar.unidata.util.Misc; 089import ucar.unidata.util.Msg; 090import ucar.unidata.util.StringUtil; 091 092/** 093 * 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. 097 * 098 * <p>That said, I personally recommend avoiding this class until the JTree 099 * stuff is ready to go.</p> 100 */ 101public 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 protected void initButtonState() { 443 if (fgColor != null) 444 return; 445 446 fgColor = Color.black; 447 448 showPopup = idv.getProperty(Constants.PROP_VP_SHOWPOPUP, false); 449 450 showCategories = idv.getProperty(Constants.PROP_VP_SHOWCATS, false); 451 } 452 453 public VMInfo getVMInfo(ViewManager vm) { 454 VMInfo info = findVMInfo(vm); 455 if (info == null) { 456 457 // oh no :( 458 if (vm instanceof MapViewManager) 459 if (((MapViewManager)vm).getUseGlobeDisplay()) 460 info = new VMInfo(vm, ViewManagers.GLOBE); 461 else 462 info = new VMInfo(vm, ViewManagers.MAP); 463 else if (vm instanceof TransectViewManager) 464 info = new VMInfo(vm, ViewManagers.TRANSECT); 465 else 466 info = new VMInfo(vm, ViewManagers.DEFAULT); 467 468 vmInfos.add(info); 469 } 470 return info; 471 } 472 473 public VMInfo findVMInfo(ViewManager vm) { 474 for (VMInfo info : vmInfos) 475 if (info.holds(vm)) 476 return info; 477 478 return null; 479 } 480 481 public class VMInfo implements ImageObserver { 482 private ViewManager viewManager; 483 484 private JButton popupButton; 485 486 private JComponent tabContents = new JPanel(new BorderLayout()); 487 488 private JPanel headerPanel; 489 490 private boolean ignore = false; 491 492 // private list of controlinfos? 493 private List<ControlInfo> controlInfos = new ArrayList<ControlInfo>(); 494 private List<JToggleButton> buttons = new ArrayList<JToggleButton>(); 495 496 //private JComponent buttonPanel; 497 498 private JComponent contents; 499 500 private JLabel viewLabel; 501 502 private JButton catToggle; 503 504 private boolean catOpen = true; 505 506 private KeyListener listener; 507 508 private List<String> categories = new ArrayList<String>(); 509 510 private ViewManagers myType = ViewManagers.DEFAULT; 511 512 public VMInfo(ViewManager vm, ViewManagers type) { 513 514 listener = new KeyAdapter() { 515 public void keyPressed(KeyEvent e) { 516 if (e.getKeyCode() == KeyEvent.VK_UP) 517 selectNext(true); 518 else if (e.getKeyCode() == KeyEvent.VK_DOWN) 519 selectNext(false); 520 } 521 }; 522 523 initButtonState(); 524 BUTTON_ICON.getWidth(this); 525 526 viewManager = vm; 527 528 ImageIcon icon = ICON_DEFAULT; 529 if (type == ViewManagers.GLOBE) 530 icon = ICON_GLOBE; 531 else if (type == ViewManagers.MAP) 532 icon = ICON_MAP; 533 else if (type == ViewManagers.TRANSECT) 534 icon = ICON_TRANSECT; 535 536 viewLabel = new JLabel(" " + getLabel()); 537 viewLabel.addMouseListener(new MouseAdapter() { 538 public void mousePressed(MouseEvent e) { 539 if (viewManager == null) 540 return; 541 542 getVMManager().setLastActiveViewManager(viewManager); 543 if (e.getClickCount() == 2) 544 viewManager.toFront(); 545 } 546 }); 547 548 catToggle = GuiUtils.getImageButton(getCatOpen() ? CATEGORY_OPEN_ICON : CATEGORY_CLOSED_ICON); 549 catToggle.addKeyListener(listener); 550 catToggle.addActionListener(new ActionListener() { 551 public void actionPerformed(ActionEvent e) { 552 setCatOpen(!getCatOpen()); 553 } 554 }); 555 556 popupButton = new JButton(icon); 557 popupButton.addKeyListener(listener); 558 popupButton.setContentAreaFilled(false); 559 popupButton.addActionListener(GuiUtils.makeActionListener(VMInfo.this, "showPopupMenu", null)); 560 popupButton.setToolTipText("Show View Menu"); 561 popupButton.setBorder(BorderFactory.createEmptyBorder()); 562 563 headerPanel = GuiUtils.leftCenter(GuiUtils.hbox( 564 GuiUtils.inset(catToggle, 1), 565 popupButton), viewLabel); 566 567 if (viewManager != null) 568 headerPanel = viewManager.makeDropPanel(headerPanel, true); 569 570 JComponent headerWrapper = GuiUtils.center(headerPanel); 571 headerPanel.setBorder(headerNormal); 572 contents = GuiUtils.topCenter(headerWrapper, tabContents); 573 viewContainer.add(contents); 574 popupButton.setHorizontalAlignment(SwingConstants.LEFT); 575 buttonsChanged(); 576 577 setCatOpen(getCatOpen()); 578 579 if (viewManager != null) 580 viewManagerChanged(); 581 } 582 583 public boolean getCatOpen() { 584 if (viewManager != null) { 585 Boolean b = 586 (Boolean)viewManager.getProperty(Constants.PROP_VP_CATOPEN); 587 if (b != null) 588 return b; 589 } 590 591 return catOpen; 592 } 593 594 public void setCatOpen(boolean v) { 595 if (viewManager != null) 596 viewManager.putProperty(Constants.PROP_VP_CATOPEN, v); 597 598 catOpen = v; 599 catToggle.setIcon(v ? CATEGORY_OPEN_ICON : CATEGORY_CLOSED_ICON); 600 tabContents.setVisible(v); 601 } 602 603 public void showPopupMenu() { 604 if (viewManager == null) 605 return; 606 607 List items = new ArrayList(); 608 viewManager.addContextMenuItems(items); 609 JPopupMenu popup = GuiUtils.makePopupMenu(items); 610 popup.show(popupButton, 0, popupButton.getHeight()); 611 } 612 613 /** 614 * Determine if this VMInfo contains a given ViewManager. 615 * 616 * @param vm The ViewManager you wish to test. 617 * 618 * @return {@code true} if this VMInfo contains {@code vm}, 619 * {@code false} otherwise. 620 */ 621 public boolean holds(ViewManager vm) { 622 return viewManager == vm; 623 } 624 625 public void removeControlInfo(ControlInfo info) { 626 int idx = controlInfos.indexOf(info); 627 if (idx == -1) 628 return; 629 630 int btnIdx = buttons.indexOf(info.button); 631 controlInfos.remove(info); 632 rightPanel.remove(info.outer); 633 634 if (info.button.isSelected() && (buttons.size() > 0)) { 635 while ((btnIdx >= buttons.size()) && (btnIdx >= 0)) 636 btnIdx--; 637 638 if (btnIdx >= 0) 639 buttons.get(btnIdx).doClick(); 640 } 641 642 GuiUtils.toggleHeavyWeightComponents(info.outer, true); 643 644 buttonsChanged(); 645 646 // hmm -- this must be for synchronization? 647 ignore = true; 648 buttonGroup.remove(info.button); 649 ignore = false; 650 651 // if there are still control infos left then we'll use those? 652 if (controlInfos.size() > 0) 653 return; 654 655 // otherwise we need to click the buttons of each remaining viewmanager? 656 for (VMInfo vm : vmInfos) 657 if (vm.controlInfos.size() > 0) 658 vm.controlInfos.get(0).button.doClick(); 659 } 660 661 public void changeControlInfo(ControlInfo info) { 662 if (!Misc.equals(info.lastCategory, info.control.getDisplayCategory())) 663 buttonsChanged(); 664 } 665 666 public void paintButton(Graphics g, ControlInfo info) { 667 g.setFont(BUTTON_FONT); 668 FontMetrics fm = g.getFontMetrics(g.getFont()); 669 670 JToggleButton btn = info.button; 671 Rectangle b = btn.getBounds(); 672 String text = info.getLabel(); 673 int y = (btn.getHeight() + fm.getHeight()) / 2 - 2; 674 int buttonWidth = BUTTON_ICON.getWidth(null); 675 int offset = 2 + buttonWidth + 4; 676 g.setColor(btn.getBackground()); 677 g.fillRect(0, 0, b.width, b.height); 678 679 if (btn.isSelected()) { 680 681 if (onColor == null) { 682 Color c = btn.getBackground(); 683 //Just go a little bit darker than the normal background 684 onColor = new Color((int) Math.max(0, 685 c.getRed() - 20), (int) Math.max(0, 686 c.getGreen() - 20), (int) Math.max(0, 687 c.getBlue() - 20)); 688 } 689 690 g.setColor(onColor); 691 g.fillRect(offset - 1, 0, b.width, b.height); 692 } 693 g.setColor(LINE_COLOR); 694 695 g.drawLine(offset - 1, b.height - 1, b.width, b.height - 1); 696 697 g.setColor(fgColor); 698 int rightSide = b.width; 699 if (btn.isSelected()) 700 rightSide = b.width - buttonWidth - 2; 701 702 int textPos = offset; 703 int textRight = textPos + fm.stringWidth(text); 704 if (textRight >= rightSide) { 705 while ((text.length() > 5) && (textRight >= rightSide)) { 706 text = text.substring(0, text.length() - 2); 707 textRight = textPos + fm.stringWidth(text + "."); 708 } 709 text = text + "."; 710 } 711 g.drawString(text, offset, y); 712 713 if (!btn.isSelected()) 714 return; 715 716 int height = BUTTON_ICON.getHeight(null); 717 g.drawImage(BUTTON_ICON, b.width - 2 - buttonWidth, b.height / 2 - height / 2, null); 718 } 719 720 public void addControlInfo(final ControlInfo info) { 721 // ugly :( 722 // why even have b? 723 //JToggleButton b = info.button = new JToggleButton(StringUtil.padRight("", 20), true) { 724 info.button = new JToggleButton(StringUtil.padRight("", 20), true) { 725 public void paint(Graphics g) { 726 paintButton(g, info); 727 } 728 }; 729 730 info.button.addKeyListener(listener); 731 info.button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 732 info.button.setToolTipText(info.getLabel()); 733 info.button.setFont(BUTTON_FONT); 734 info.button.setForeground(fgColor); 735 info.button.setBorder(BUTTON_BORDER); 736 737 info.button.setHorizontalAlignment(SwingConstants.LEFT); 738 info.button.addActionListener(new ActionListener() { 739 public void actionPerformed(ActionEvent e) { 740 if (ignore) 741 return; 742 743 GuiUtils.toggleHeavyWeightComponents(info.outer, true); 744 rightPanel.show(info.outer); 745 } 746 }); 747 buttons.add(info.button); 748 controlInfos.add(info); 749 rightPanel.addCard(info.outer); 750 GuiUtils.toggleHeavyWeightComponents(info.outer, false); 751 info.displayControlChanged(); 752 753 if (info.control.getExpandedInTabs()) 754 info.expand(); 755 756 buttonGroup.add(info.button); 757 buttonsChanged(); 758 setCatOpen(getCatOpen()); 759 } 760 761 /** 762 * Redo the buttons 763 */ 764 private void buttonsChanged() { 765 List<JComponent> comps = new ArrayList<JComponent>(); 766 767 Hashtable<String, List<JComponent>> catMap = 768 new Hashtable<String, List<JComponent>>(); 769 770 for (ControlInfo info : controlInfos) { 771 String cat = info.control.getDisplayCategory(); 772 if (cat == null) 773 cat = "Displays"; 774 775 info.lastCategory = cat; 776 777 if (!showCategories) { 778 comps.add(info.button); 779 continue; 780 } 781 782 List<JComponent> catList = catMap.get(cat); 783 if (catList == null) { 784 if (!categories.contains(cat)) 785 categories.add(cat); 786 787 catList = new ArrayList<JComponent>(); 788 789 catMap.put(cat, catList); 790 791 JLabel catLabel = new JLabel(" " + cat); 792 793 catLabel.setFont(CAT_FONT); 794 795 catList.add(catLabel); 796 } 797 catList.add(info.button); 798 } 799 800 if (showCategories) { 801 for (String category : categories) { 802 List<JComponent> catList = catMap.get(category); 803 if (catList != null) 804 comps.addAll(catList); 805 } 806 } 807 808 if (comps.size() == 0) { 809 if (myType == ViewManagers.TRANSECT) { 810 JLabel noLbl = new JLabel("No Displays"); 811 noLbl.setFont(BUTTON_FONT); 812 JPanel inset = GuiUtils.inset(noLbl, new Insets(0, 10, 0, 0)); 813 inset.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, 814 Color.gray)); 815 comps.add(inset); 816 } else { 817 headerPanel.setVisible(false); 818 } 819 } else { 820 headerPanel.setVisible(true); 821 } 822 823 comps.add(GuiUtils.filler(10, 2)); 824 JComponent buttonPanel = GuiUtils.vbox(comps); 825 826 tabContents.removeAll(); 827 tabContents.add(BorderLayout.NORTH, buttonPanel); 828 tabContents.repaint(); 829 } 830 831 /** 832 * Handles ViewManager removal. 833 */ 834 public void viewManagerDestroyed() { 835 viewContainer.remove(contents); 836 } 837 838 /** 839 * my viewmanager has changed. Update the gui. 840 */ 841 public void viewManagerChanged() { 842 viewLabel.setText(getLabel()); 843 844 if (viewManager.showHighlight()) { 845 846 headerHighlight = 847 BorderFactory.createCompoundBorder( 848 BorderFactory.createEmptyBorder(3, 0, 0, 0), 849 BorderFactory.createMatteBorder( 850 0, 0, 2, 0, 851 getStore().get( 852 ViewManager.PREF_BORDERCOLOR, Color.blue))); 853 854 headerPanel.setBorder(headerHighlight); 855 } else { 856 headerPanel.setBorder(headerNormal); 857 } 858 859 if (contents != null) 860 contents.repaint(); 861 } 862 863 /** 864 * Get the ViewManager label. If the ViewManager does not already have 865 * a valid name, a default name is created, based on the number of 866 * existing ViewManagers. 867 * 868 * @return label The ViewManager's name. 869 */ 870 public String getLabel() { 871 // nothing to query for a name? 872 if (viewManager == null) 873 return "No Display"; 874 875 // do we already have a valid name? 876 String name = viewManager.getName(); 877 if ((name != null) && (name.trim().length() > 0)) { 878 UIManager uiManager = (UIManager)idv.getIdvUIManager(); 879 ComponentHolder holder = uiManager.getViewManagerHolder(viewManager); 880 if (holder != null) 881 return holder.getName() + ">" + name; 882 else 883 return name; 884 } 885 886 // if our name was invalid, build a default one. 887 int idx = vmInfos.indexOf(this); 888 return "Default " + Constants.PANEL_NAME + " " + 889 ((idx == -1) ? vmInfos.size() : idx); 890 } 891 892 public boolean imageUpdate(Image img, int flags, int x, int y, int width, int height) { 893 if ((flags & ImageObserver.ALLBITS) == 0) 894 return true; 895 896 leftPanel.repaint(); 897 return false; 898 } 899 } 900 901 public class ControlInfo { 902 DisplayControl control; 903 JButton expandButton; 904 JComponent outer; 905 JComponent inner; 906 boolean expanded = false; 907 Dimension innerSize = new Dimension(); 908 VMInfo info; 909 JToggleButton button; 910 String lastCategory = ""; 911 String label = null; 912 913 /** 914 * ctor 915 * 916 * @param control control 917 * @param expandButton expand button 918 * @param outer outer comp 919 * @param inner inner comp 920 * @param vmInfo my vminfo 921 */ 922 public ControlInfo(DisplayControl control, JButton expandButton, 923 JComponent outer, JComponent inner, 924 VMInfo vmInfo) { 925 this.info = vmInfo; 926 this.control = control; 927 if (control.getExpandedInTabs()) 928 expanded = false; 929 930 this.expandButton = expandButton; 931 this.outer = outer; 932 this.inner = inner; 933 inner.getSize(innerSize); 934 info.addControlInfo(this); 935 this.expand(); 936 } 937 938 /** 939 * get the label for the display control 940 * 941 * @return display control label 942 */ 943 public String getLabel() { 944 if (label == null) 945 label = control.getMenuLabel(); 946 947 return label; 948 } 949 950 /** 951 * display control changed 952 */ 953 public void displayControlChanged() { 954 String tmp = label; 955 label = null; 956 getLabel(); 957 if (!Misc.equals(tmp, label) && (button != null)) { 958 button.setToolTipText(label); 959 button.repaint(); 960 } 961 info.changeControlInfo(this); 962 } 963 964 /** 965 * display control is removed 966 */ 967 public void removeDisplayControl() { 968 info.removeControlInfo(this); 969 } 970 971 /** 972 * Expand the contents 973 */ 974 public void expand() { 975 outer.removeAll(); 976 outer.setLayout(new BorderLayout()); 977 978 if (!expanded) { 979 outer.add(BorderLayout.CENTER, inner); 980 expandButton.setIcon( 981 GuiUtils.getImageIcon("/auxdata/ui/icons/UpUp.gif")); 982 inner.getSize(innerSize); 983// System.err.println("ControlInfo.expand: innerSize=" + innerSize); 984 } else { 985 outer.add(BorderLayout.NORTH, inner); 986 expandButton.setIcon( 987 GuiUtils.getImageIcon("/auxdata/ui/icons/DownDown.gif")); 988 inner.setSize(innerSize); 989 } 990 991 expanded = !expanded; 992 control.setExpandedInTabs(expanded); 993 994 final Container parent = outer.getParent(); 995 outer.invalidate(); 996 parent.validate(); 997 parent.doLayout(); 998 } 999 } 1000}