001/* 002 * $Id: McIDASVViewPanel.java,v 1.14 2011/03/24 18:13:11 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2011 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 031package edu.wisc.ssec.mcidasv.ui; 032 033import java.awt.BorderLayout; 034import java.awt.Color; 035import java.awt.Component; 036import java.awt.Container; 037import java.awt.Cursor; 038import java.awt.Dimension; 039import java.awt.Font; 040import java.awt.FontMetrics; 041import java.awt.Graphics; 042import java.awt.Image; 043import java.awt.Insets; 044import java.awt.Rectangle; 045import java.awt.event.ActionEvent; 046import java.awt.event.ActionListener; 047import java.awt.event.KeyAdapter; 048import java.awt.event.KeyEvent; 049import java.awt.event.KeyListener; 050import java.awt.event.MouseAdapter; 051import java.awt.event.MouseEvent; 052import java.awt.image.ImageObserver; 053import java.util.ArrayList; 054import java.util.Hashtable; 055import java.util.List; 056 057import javax.swing.BorderFactory; 058import javax.swing.BoxLayout; 059import javax.swing.ButtonGroup; 060import javax.swing.ImageIcon; 061import javax.swing.JButton; 062import javax.swing.JComponent; 063import javax.swing.JLabel; 064import javax.swing.JMenuItem; 065import javax.swing.JPanel; 066import javax.swing.JPopupMenu; 067import javax.swing.JScrollPane; 068import javax.swing.JToggleButton; 069import javax.swing.SwingConstants; 070import javax.swing.border.Border; 071import javax.swing.border.EtchedBorder; 072 073import edu.wisc.ssec.mcidasv.Constants; 074 075import ucar.unidata.idv.DisplayControl; 076import ucar.unidata.idv.IdvConstants; 077import ucar.unidata.idv.IdvManager; 078import ucar.unidata.idv.IntegratedDataViewer; 079import ucar.unidata.idv.MapViewManager; 080import ucar.unidata.idv.TransectViewManager; 081import ucar.unidata.idv.ViewManager; 082import ucar.unidata.idv.control.DisplayControlImpl; 083import ucar.unidata.idv.control.MapDisplayControl; 084import ucar.unidata.idv.ui.IdvComponentGroup; 085import ucar.unidata.idv.ui.IdvWindow; 086import ucar.unidata.idv.ui.ViewPanel; 087import ucar.unidata.ui.ComponentHolder; 088import ucar.unidata.ui.DndImageButton; 089import ucar.unidata.util.GuiUtils; 090import ucar.unidata.util.Misc; 091import ucar.unidata.util.Msg; 092import 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 */ 103public 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}