/******************************************************************************* * Mission Control Technologies, Copyright (c) 2009-2012, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * * The MCT platform is licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * MCT includes source code licensed under additional open source licenses. See * the MCT Open Source Licenses file included with this distribution or the About * MCT Licenses dialog available at runtime from the MCT Help menu for additional * information. *******************************************************************************/ package gov.nasa.arc.mct.defaults.view; import gov.nasa.arc.mct.components.AbstractComponent; import gov.nasa.arc.mct.gui.View; import gov.nasa.arc.mct.gui.ViewProvider; import gov.nasa.arc.mct.services.component.ViewInfo; import gov.nasa.arc.mct.services.component.ViewType; import gov.nasa.arc.mct.util.MCTIcons; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.Set; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.ListCellRenderer; import javax.swing.UIManager; import javax.swing.plaf.basic.BasicComboBoxUI; /** * A view containing a drop-down of available view types * for the represented component. Used by Inspector views * for view switching. */ public class SwitcherView extends View { private static final long serialVersionUID = -7338842560419381410L; private ViewProvider managedView = null; // Where to send "switch" events @SuppressWarnings("rawtypes") private JComboBox comboBox; private JLabel label; private static final float FONT_SIZE = 10f; private static final Color ICON_COLOR = new Color(144,144,144); /** * The view info used to instantiate this view. */ public static final ViewInfo VIEW_INFO = new ViewInfo(SwitcherView.class, "Switcher", ViewType.VIEW_SWITCHER); @SuppressWarnings({ "rawtypes", "unchecked" }) public SwitcherView(AbstractComponent ac, ViewInfo vi) { Set<ViewInfo> viewInfoSet = ac.getViewInfos(ViewType.OBJECT); ViewInfo[] viewInfos = viewInfoSet.toArray(new ViewInfo[viewInfoSet.size()]); if (viewInfos.length > 1) { // Only show combo box if there are multiple views comboBox = new JComboBox(viewInfos); comboBox.setUI(new SwitcherComboBoxUI()); comboBox.setRenderer(viewInfoRenderer); comboBox.addItemListener(itemListener); comboBox.setVisible(false); comboBox.setEnabled(false); comboBox.setOpaque(false); add(comboBox); } else if (viewInfos.length == 1) { // Otherwise, just show the one available view as a label label = new JLabel(); label.setIcon(getIcon(vi)); label.setText(vi.getViewName()); add(label); } else { // No views to show } setBorder(BorderFactory.createEmptyBorder(1,4,1,2)); setOpaque(false); } @Override public <T> void addMonitoredGUI(T gui) { if (gui instanceof ViewProvider) { managedView = (ViewProvider) gui; } if (managedView != null) { resetSelection(); if (comboBox != null) { comboBox.setVisible(true); comboBox.setEnabled(true); } } super.addMonitoredGUI(gui); } @Override public void setForeground(Color fg) { if (label != null) { label.setForeground(fg); } super.setForeground(fg); } private void resetSelection() { if (managedView != null) { View housedView = managedView.getHousedViewManifestation(); if (housedView != null) { ViewInfo vi = housedView.getInfo(); if (comboBox != null) { comboBox.removeItemListener(itemListener); // Avoid triggering listener comboBox.setSelectedItem(vi); comboBox.addItemListener(itemListener); } if (label != null) { label.setIcon(getIcon(vi)); label.setText(vi.getViewName()); } } } } private static ImageIcon getIcon(ViewInfo vi) { return MCTIcons.processIcon(vi.getAsset(ImageIcon.class), ICON_COLOR, false); } private final ItemListener itemListener = new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { // Only respond to SELECTED events to avoid double-firing if (managedView != null && e.getStateChange() == ItemEvent.SELECTED) { Object item = e.getItem(); if (item != null && item instanceof ViewInfo) { // Try to change the view if (!managedView.setHousedViewManifestation((ViewInfo) item)) { // View says it didn't change - restore previous selection resetSelection(); } } } } }; // Used for providing components to represent ViewInfos in the drop-down @SuppressWarnings("rawtypes") private static final ListCellRenderer viewInfoRenderer = new ListCellRenderer() { private JLabel label = new JLabel(); // Reuse, since it's only used for rendering @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { label.setFont(label.getFont().deriveFont(FONT_SIZE)); if (value instanceof ViewInfo) { ViewInfo vi = (ViewInfo) value; label.setIcon(getIcon(vi)); label.setText(vi.getViewName()); } else { label.setIcon(null); label.setText("Error"); } return label; } }; private static class SwitcherComboBoxUI extends BasicComboBoxUI { @Override protected JButton createArrowButton() { JButton emptyButton = new JButton(); emptyButton.setIcon(ARROW_ICON); emptyButton.setBorder(BorderFactory.createEmptyBorder()); emptyButton.setContentAreaFilled(false); return emptyButton; } @Override public Dimension getDisplaySize() { Dimension d = super.getDisplaySize(); return new Dimension(d.width + 12, d.height); } @Override public void paint(Graphics g, JComponent c) { if (g instanceof Graphics2D) { ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } g.setColor(c.getBackground()); g.fillRoundRect(0, 1, c.getWidth()-1, c.getHeight()-2, 10, 10); super.paint(g, c); } @Override public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus) { if (hasFocus) { if (g instanceof Graphics2D) { ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } g.setColor(UIManager.getColor("Button.focus")); g.drawRect(bounds.x + 2, bounds.y + 2, bounds.width-8, bounds.height-5); } } } private static final Icon ARROW_ICON = new Icon() { @Override public void paintIcon(Component c, Graphics g, int x, int y) { int tx[] = { 3, 11, 7 }; int ty[] = { 6, 6, 10 }; if (g instanceof Graphics2D) { ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } g.setColor(Color.DARK_GRAY); g.fillPolygon(tx, ty, 3); } @Override public int getIconWidth() { return 12; } @Override public int getIconHeight() { return 12; } }; }