package com.limegroup.gnutella.gui.search; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.Insets; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.UIManager; import com.limegroup.gnutella.MediaType; import com.limegroup.gnutella.gui.BoxPanel; import com.limegroup.gnutella.gui.GUIMediator; import com.limegroup.gnutella.gui.ImageManipulator; import com.limegroup.gnutella.gui.themes.ThemeFileHandler; import com.limegroup.gnutella.xml.LimeXMLSchema; /** * A group of radio buttons for each schema. */ final class SchemaBox extends JPanel { /** * String for 'Select Type' */ private static final String SELECT_TYPE = GUIMediator.getStringResource("SEARCH_SELECT_TYPE"); /** * The property that the media type is stored in. */ private static final String MEDIA = "NAMED_MEDIA_TYPE"; /** * The property to store the selected icon in. */ private static final String SELECTED = "SELECTED_ICON"; /** * The property to store the unselected icon in. */ private static final String DESELECTED = "DESELECTED_ICON"; /** * The panel containing the schemas. */ private final JPanel SCHEMAS = new JPanel(); /** * The button group that holds the buttons together. */ private final ButtonGroup GROUP = new ButtonGroup(); /** * The listener for changing the highlighting of buttons. */ private final ItemListener HIGHLIGHTER = new Highlighter(); /** * The clicker forwarder. */ private final MouseListener CLICK_FORWARDER = new Clicker(); /** * The ditherer for highlighted buttons. */ private final Ditherer DITHERER = new Ditherer(20, ThemeFileHandler.FILTER_TITLE_TOP_COLOR.getValue(), ThemeFileHandler.FILTER_TITLE_COLOR.getValue() ); /** * Constructs the SchemaBox. */ SchemaBox() { List allSchemas = NamedMediaType.getAllNamedMediaTypes(); int cols, rows; cols = 2; rows = (int)Math.ceil((double)allSchemas.size() / 2.0); SCHEMAS.setBackground(ThemeFileHandler.SEARCH_GRID_COLOR.getValue()); SCHEMAS.setLayout(new GridLayout(rows, cols, 1, 1)); SCHEMAS.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); addSchemas(allSchemas); JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); panel.add(new JLabel(SELECT_TYPE)); add(panel); setLayout( new BoxLayout(this, BoxLayout.Y_AXIS)); JPanel p = new BoxPanel(BoxPanel.X_AXIS); p.add(SCHEMAS); p.add(Box.createHorizontalStrut(1)); add(p); } /** * Adds the specified ActionListener to all possible buttons. */ public void addSelectionListener(ActionListener listener) { Enumeration elements = GROUP.getElements(); for(; elements.hasMoreElements(); ) { AbstractButton button = (AbstractButton)elements.nextElement(); button.addActionListener(listener); } } /** * Returns the selected icon, or null if the selection has no icon. */ public Icon getSelectedIcon() { NamedMediaType nmt = getSelectedMedia(); if(nmt == null) return null; return nmt.getIcon(); } /** * Returns the selected schema, or null if the selected item has no schema. */ public LimeXMLSchema getSelectedSchema() { NamedMediaType nmt = getSelectedMedia(); if(nmt == null) return null; return nmt.getSchema(); } /** * Returns the description of the selected item. */ public String getSelectedItem() { NamedMediaType nmt = getSelectedMedia(); if(nmt == null) return null; return nmt.getName(); } /** * Returns the selected item's media type. */ public MediaType getSelectedMediaType() { NamedMediaType nmt = getSelectedMedia(); if(nmt == null) return null; return nmt.getMediaType(); } /** * Adds the given schemas as radio buttons. */ private void addSchemas(List schemas) { //We first add specific ones in a certain order. //After that, leave it to random chance. NamedMediaType current; // First add 'Any Type' current = NamedMediaType.getFromDescription(MediaType.SCHEMA_ANY_TYPE); schemas.remove(current); addMediaType(current); // Then add 'Audio' current = NamedMediaType.getFromDescription(MediaType.SCHEMA_AUDIO); schemas.remove(current); addMediaType(current, GUIMediator.getStringResource("SEARCH_MEDIA_AUDIO_TOOLTIP")); // Then add 'Images' current = NamedMediaType.getFromDescription(MediaType.SCHEMA_IMAGES); schemas.remove(current); addMediaType(current, GUIMediator.getStringResource("SEARCH_MEDIA_IMAGES_TOOLTIP")); // Then add 'Video' current = NamedMediaType.getFromDescription(MediaType.SCHEMA_VIDEO); schemas.remove(current); addMediaType(current, GUIMediator.getStringResource("SEARCH_MEDIA_VIDEO_TOOLTIP")); // Then add 'Documents' current = NamedMediaType.getFromDescription(MediaType.SCHEMA_DOCUMENTS); schemas.remove(current); addMediaType(current, GUIMediator.getStringResource("SEARCH_MEDIA_DOCUMENTS_TOOLTIP")); // Then add 'Programs' current = NamedMediaType.getFromDescription(MediaType.SCHEMA_PROGRAMS); schemas.remove(current); addMediaType(current, GUIMediator.getStringResource("SEARCH_MEDIA_PROGRAMS_TOOLTIP")); // Then add anything that was left. for(Iterator i = schemas.iterator(); i.hasNext(); ) { addMediaType((NamedMediaType)i.next()); } } private void addMediaType(NamedMediaType type) { addMediaType(type, null); } /** * Adds the given NamedMediaType. * * Marks the 'Any Type' as selected. */ private void addMediaType(NamedMediaType type, String toolTip) { Icon icon = type.getIcon(); Icon disabledIcon = null; Icon rolloverIcon = null; AbstractButton button = new JRadioButton(type.getName()); button.putClientProperty(MEDIA, type); button.putClientProperty(SELECTED, icon); if(icon != null) { disabledIcon = ImageManipulator.darken(icon); rolloverIcon = ImageManipulator.brighten(icon); } button.putClientProperty(DESELECTED, disabledIcon); button.setIcon(disabledIcon); button.setRolloverIcon(rolloverIcon); button.addItemListener(HIGHLIGHTER); button.setBorderPainted(false); button.setFocusPainted(false); button.setContentAreaFilled(false); button.setMargin(new Insets(0, 0, 0, 0)); button.setOpaque(false); button.addMouseListener(CLICK_FORWARDER); button.setPreferredSize(new Dimension(100, 22)); if (toolTip != null) { button.setToolTipText(toolTip); } GROUP.add(button); DitherPanel panel = new DitherPanel(DITHERER); panel.setDithering(false); panel.setLayout(new FlowLayout(FlowLayout.LEFT, 7, 1)); panel.add(button); panel.addMouseListener(CLICK_FORWARDER); panel.setBackground(UIManager.getColor( "TabbedPane.background")); SCHEMAS.add(panel); if(type.getMediaType() == MediaType.getAnyTypeMediaType()) button.setSelected(true); else button.setSelected(false); } /** * Iterates through all the elements in the group * and returns the media type of the selected button. */ NamedMediaType getSelectedMedia() { Enumeration elements = GROUP.getElements(); for(; elements.hasMoreElements(); ) { AbstractButton button = (AbstractButton)elements.nextElement(); if(button.isSelected()) return (NamedMediaType)button.getClientProperty(MEDIA); } return null; } /** * Listener for ItemEvent, so that the buttons can be highlighted or not * when selected (or not). */ private static class Highlighter implements ItemListener { public void itemStateChanged(ItemEvent e) { AbstractButton button = (AbstractButton)e.getSource(); DitherPanel parent = (DitherPanel)button.getParent(); if(e.getStateChange() == ItemEvent.SELECTED) { button.setIcon((Icon)button.getClientProperty(SELECTED)); parent.setDithering(true); parent.setBackground(ThemeFileHandler.FILTER_TITLE_COLOR.getValue()); } else { button.setIcon((Icon)button.getClientProperty(DESELECTED)); parent.setDithering(false); parent.setBackground(UIManager.getColor("TabbedPane.background")); } } } private static void setIfNotNull(JComponent c, String col) { Color color = UIManager.getColor(col); if(color != null) c.setBackground(color); } /** * Forwards click events from a panel to the panel's component. */ private static class Clicker implements MouseListener { public void mouseEntered(MouseEvent e) { JComponent c = (JComponent)e.getSource(); AbstractButton b; if(c instanceof AbstractButton) { b = (AbstractButton)c; c = (JComponent)c.getParent(); } else { b = (AbstractButton)c.getComponent(0); } if(!b.isSelected()) setIfNotNull(c, "TabbedPane.selected"); } public void mouseExited(MouseEvent e) { JComponent c = (JComponent)e.getSource(); AbstractButton b; if(c instanceof AbstractButton) { b = (AbstractButton)c; c = (JComponent)c.getParent(); } else { b = (AbstractButton)c.getComponent(0); } if(!b.isSelected()) setIfNotNull(c, "TabbedPane.background"); } public void mouseClicked(MouseEvent e) { JComponent c = (JComponent)e.getSource(); if(!(c instanceof AbstractButton)) { AbstractButton b = (AbstractButton)c.getComponent(0); b.doClick(); } } public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} } }