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