/* * Copyright to the original author or authors. * * 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. */ package org.rioproject.tools.ui.servicenotification.filter; import org.rioproject.tools.ui.Constants; import org.rioproject.tools.ui.servicenotification.EventCollectorListener; import org.rioproject.tools.ui.servicenotification.EventColorManager; import org.rioproject.tools.ui.servicenotification.TreeExpansionListener; import org.rioproject.ui.Util; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * Provides filtering options for service notifications. * * @author Dennis Reedy */ @SuppressWarnings("unchecked") public class FilterPanel extends JPanel { private final JComboBox filterQuery; private final FilterParser filterParser = new FilterParser(); private final EventCollectorListener eventCollectorListener; private final EventColorManager eventColorManager = new EventColorManager(); private final JCheckBox useEventCollector; public FilterPanel(final FilterListener filterListener, final TreeExpansionListener treeExpansionListener, final EventCollectorListener eventCollectorListener, final Properties props) { super(new BorderLayout()); this.eventCollectorListener = eventCollectorListener; setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(), BorderFactory.createEmptyBorder(8, 8, 8, 8))); filterQuery = new JComboBox(); filterQuery.setEditable(true); filterQuery.addItem(""); filterQuery.setSelectedIndex(0); JPanel p = new JPanel(new BorderLayout(8, 8)); try { final JEditorPane syntaxHelp = new JEditorPane(getSyntaxHelp()); syntaxHelp.setEditable(false); syntaxHelp.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(), BorderFactory.createEmptyBorder(8, 8, 8, 8))); syntaxHelp.setVisible(false); final JLabel syntaxLink = new JLabel("<html><a href=\"\">Syntax help</a></html>"); syntaxLink.addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { syntaxLink.setCursor(new Cursor(Cursor.HAND_CURSOR)); } @Override public void mouseExited(MouseEvent e) { syntaxLink.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } @Override public void mousePressed(MouseEvent e) { /*Window parent = SwingUtilities.windowForComponent(syntaxHelp); if(parent!=null) { showSyntaxHelpDialog(parent, syntaxHelp); } else {*/ if(syntaxHelp.isVisible()) { syntaxHelp.setVisible(false); } else { syntaxHelp.setVisible(true); } //} } }); p.add(syntaxLink, BorderLayout.WEST); p.add(syntaxHelp, BorderLayout.SOUTH); } catch(IOException e) { e.printStackTrace(); } useEventCollector = new JCheckBox(); setUseEventCollectorCheckBoxText(); setCheckBox(useEventCollector, props, Constants.USE_EVENT_COLLECTOR, false); useEventCollector.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { eventCollectorListener.handleEventCollectorRegistration(useEventCollector.isSelected()); } }); p.add(useEventCollector, BorderLayout.EAST); add(p, BorderLayout.SOUTH); /*java.util.List<String> autoCompleteElements = new ArrayList<String>(); autoCompleteElements.add("type"); autoCompleteElements.add("PROVISION_FAILURE"); for(ProvisionMonitorEvent.Action action : ProvisionMonitorEvent.Action.values()) { autoCompleteElements.add(action.name()); } for(ThresholdType type : ThresholdType.values()) { autoCompleteElements.add(type.name()); } AutoCompleteDecorator.decorate(filterQuery, autoCompleteElements, true);*/ add(new JLabel("Filter Using "), BorderLayout.WEST); add(filterQuery, BorderLayout.CENTER); JToolBar toolBar = new JToolBar(JToolBar.HORIZONTAL); toolBar.setFloatable(false); toolBar.setRollover(true); toolBar.setBorderPainted(false); ImageIcon collapseIcon = Util.getImageIcon("org/rioproject/tools/ui/images/collapseall.gif"); ImageIcon expandIcon = Util.getImageIcon("org/rioproject/tools/ui/images/expandall.gif"); ImageIcon refreshIcon = Util.getScaledImageIcon("org/rioproject/tools/ui/images/view-refresh.png", expandIcon.getIconWidth(), expandIcon.getIconHeight()); ImageIcon colorOptionsIcon = Util.getScaledImageIcon("org/rioproject/tools/ui/images/color-options.png", expandIcon.getIconWidth(), expandIcon.getIconHeight()); JButton collapse = new JButton(); collapse.setIcon(collapseIcon); collapse.setPreferredSize(new Dimension(22, 22)); collapse.setMaximumSize(new Dimension(22, 22)); collapse.setToolTipText("Collapse all nodes"); collapse.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { treeExpansionListener.collapse(); } }); JButton expand = new JButton(); expand.setIcon(expandIcon); expand.setPreferredSize(new Dimension(22, 22)); expand.setMaximumSize(new Dimension(22, 22)); expand.setToolTipText("Expand all nodes"); expand.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { treeExpansionListener.expand(); } }); final JButton refresh = new JButton(refreshIcon); refresh.setPreferredSize(new Dimension(22, 22)); refresh.setMaximumSize(new Dimension(22, 22)); refresh.getAccessibleContext().setAccessibleName("refresh events"); refresh.setToolTipText("Refresh the events"); final JButton colorOptions = new JButton(colorOptionsIcon); colorOptions.setPreferredSize(new Dimension(22, 22)); colorOptions.setMaximumSize(new Dimension(22, 22)); colorOptions.getAccessibleContext().setAccessibleName("event tree color options"); colorOptions.setToolTipText("Event tree color options"); colorOptions.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { showColorOptionsDialog(SwingUtilities.windowForComponent(colorOptions)); } }); toolBar.add(collapse); toolBar.add(expand); toolBar.add(refresh); refresh.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { eventCollectorListener.refresh(); } }); toolBar.add(colorOptions); add(toolBar, BorderLayout.EAST); filterQuery.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { handleFilterQueryInput(filterListener); } }); } private void handleFilterQueryInput(final FilterListener filterListener) { String query = (String) filterQuery.getSelectedItem(); if(query!=null) { query = query.trim(); if(query.length()>0) { boolean inHistory = false; for(int i=0; i<filterQuery.getItemCount(); i++) { if(filterQuery.getItemAt(i).equals(query)) { inHistory = true; break; } } if(!inHistory) filterQuery.addItem(query); } } filterListener.notify(filterParser.parse(query)); } private void setCheckBox(JCheckBox checkBox, Properties props, String propertyName, boolean defaultValue) { String s = props.getProperty(propertyName); boolean value = defaultValue; if(s!=null) value = Boolean.parseBoolean(s); checkBox.setSelected(value); checkBox.setFont(Constants.ITEM_FONT); } private void showColorOptionsDialog(Window parent) { final JDialog dialog = new JDialog(parent, "Event Color Options"); dialog.setModal(true); JPanel panel = new JPanel(); GroupLayout layout = new GroupLayout(panel); panel.setLayout(layout); /* Turn on automatically adding gaps between components */ layout.setAutoCreateGaps(true); /* Turn on automatically creating gaps between components that touch * the edge of the container and the container. */ layout.setAutoCreateContainerGaps(true); /* Create a sequential group for the horizontal axis. */ GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup(); /* The sequential group in turn contains two parallel groups. * One parallel group contains the labels, the other the text fields. * Putting the labels in a parallel group along the horizontal axis * positions them at the same x location. */ /* Variable indentation is used to reinforce the level of grouping. */ final Map<JLabel, JComponent> eventLabelButtonMap = getEventLabelButtonMap(); GroupLayout.ParallelGroup labelGroup = layout.createParallelGroup(); GroupLayout.ParallelGroup buttonGroup = layout.createParallelGroup(); for(Map.Entry<JLabel, JComponent> eventTypes : eventLabelButtonMap.entrySet()) { labelGroup.addComponent(eventTypes.getKey()); buttonGroup.addComponent(eventTypes.getValue()); } hGroup.addGroup(labelGroup); hGroup.addGroup(buttonGroup); layout.setHorizontalGroup(hGroup); /* Create a sequential group for the vertical axis. */ GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup(); /* The sequential group contains two parallel groups that align * the contents along the baseline. The first parallel group contains * the first label and text field, and the second parallel group contains * the second label and text field. By using a sequential group * the labels and text fields are positioned vertically after one another.*/ for(Map.Entry<JLabel, JComponent> eventTypes : eventLabelButtonMap.entrySet()) { GroupLayout.ParallelGroup group = layout.createParallelGroup(GroupLayout.Alignment.BASELINE); group.addComponent(eventTypes.getKey()).addComponent(eventTypes.getValue()); vGroup.addGroup(group); } layout.setVerticalGroup(vGroup); JPanel p = new JPanel(new BorderLayout(8, 8)); //p.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); p.add(new JScrollPane(panel), BorderLayout.CENTER); JPanel buttonPane = new JPanel(); final JButton close = new JButton("Close"); close.setToolTipText("Close this dialog"); close.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { dialog.dispose(); } }); final JButton reset = new JButton("Reset"); reset.setToolTipText("Reset event colors"); reset.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { for(Map.Entry<JLabel, JComponent> eventTypes : eventLabelButtonMap.entrySet()) { eventTypes.getValue().setBackground(eventColorManager.getEventColor(eventTypes.getKey().getText())); } } }); buttonPane.add(close); buttonPane.add(reset); p.add(buttonPane, BorderLayout.SOUTH); dialog.getContentPane().add(p); dialog.pack(); dialog.setSize(400, 600); dialog.setLocationRelativeTo(parent); dialog.setVisible(true); } @SuppressWarnings("unused") private void showSyntaxHelpDialog(Window parent, JEditorPane syntaxHelp) { syntaxHelp.setVisible(true); final JDialog dialog = new JDialog(parent, "Filter Syntax Help"); JPanel panel = new JPanel(new BorderLayout(8, 8)); panel.add(new JScrollPane(syntaxHelp), BorderLayout.CENTER); final JButton close = new JButton("Close"); close.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { dialog.dispose(); } }); JPanel buttonPane = new JPanel(); buttonPane.add(close); panel.add(buttonPane, BorderLayout.SOUTH); dialog.getContentPane().add(panel); dialog.pack(); dialog.setSize(850, 405); dialog.setLocationRelativeTo(parent); dialog.setVisible(true); } public boolean getUseEventCollector() { return useEventCollector.isSelected(); } public void setUseEventCollectorCheckBoxText() { useEventCollector.setText(String.format("Use EventCollector (discovered %d EventCollectors)", eventCollectorListener.getEventControllerCount())); } private URL getSyntaxHelp() { return Thread.currentThread().getContextClassLoader().getResource("filter-syntax-help.html"); } private Map<JLabel, JComponent> getEventLabelButtonMap() { Map<JLabel, JComponent> eventTypeMap = new HashMap<JLabel, JComponent>(); for(Map.Entry<String, Color> entry : eventColorManager.getEventColorMap().entrySet()) { JComponent comp = makeColorComponent(entry.getValue(), "Color for "+entry.getKey()); eventTypeMap.put(new JLabel(entry.getKey()), comp); } return eventTypeMap; } private JComponent makeColorComponent(final Color color, final String desc) { /*Vector<JLabel> labels = new Vector<JLabel>(); int index = 0; for(Map.Entry<String, Color> entry : eventColorManager.getColorMap().entrySet()) { StringBuilder labelBuilder = new StringBuilder(); labelBuilder.append("<html>"); labelBuilder.append("<small>").append(entry.getKey()).append("</small>"); labelBuilder.append("</html>"); final JLabel comp = new JLabel(labelBuilder.toString()); comp.setOpaque(true); comp.setBackground(entry.getValue()); comp.setForeground(Color.GRAY); labels.add(comp); if(color.equals(entry.getValue())) { index = labels.indexOf(comp); } } JComboBox<JLabel> labelJComboBox = new JComboBox<JLabel>(labels); labelJComboBox.setSelectedIndex(index); labelJComboBox.setRenderer(new ColorCellRenderer()); return labelJComboBox;*/ StringBuilder labelBuilder = new StringBuilder(); labelBuilder.append("<html>"); labelBuilder.append("<small>").append(eventColorManager.getColorName(color)).append("</small>"); labelBuilder.append("</html>"); final JLabel comp = new JLabel(labelBuilder.toString()); comp.setOpaque(true); comp.setBackground(color); comp.setForeground(Color.GRAY); comp.setToolTipText(desc); comp.setBorder(BorderFactory.createRaisedBevelBorder()); comp.addMouseListener(new MouseAdapter() { public void mousePressed(final MouseEvent event) { JLabel c = (JLabel)event.getComponent(); comp.setBorder(BorderFactory.createLoweredBevelBorder()); Color color = c.getBackground(); color = JColorChooser.showDialog(comp, desc, color); comp.setBorder(BorderFactory.createRaisedBevelBorder()); if(color!=null) { c.setBackground(color); } } }); return comp; } /*class ColorCellRenderer extends BasicComboBoxRenderer { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { setText(((JLabel)value).getText()); //if(isSelected) // setBackground(list.getSelectionBackground()); //else setBackground(((JLabel)value).getBackground()); return this; } }*/ }