blob: 09cf4c18ee089e7e0a08de60ab0dec39f85a72de [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.netbeans.modules.tasklist.filter;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.UIManager;
import org.openide.util.NbBundle;
/**
* Panel which is used to create a filter for the tasklist
* The GUI is based on the one in Mozilla's mail tool.
* Please read comment at the beginning of initA11y before editing
* this file using the form builder.
*
* @author Tor Norbye
*/
final class KeywordsPanel extends JPanel implements ActionListener, PropertyChangeListener {
private static final long serialVersionUID = 1;
// private FilteredTopComponent view;
private KeywordsFilter filter;
// head of subpanels chain
private FilterSubpanel subpanel;
/**
* Creates new form KeywordsPanel.
*
* @param view view with the given filter
* @param filter filter to be edited. Can be null and in that case
* all fields are disabled.
*/
public KeywordsPanel( KeywordsFilter filter ) {
this.filter = filter;
initComponents();
initA11y();
if( "Metal".equals( UIManager.getLookAndFeel().getID() ) ) //NOI18N
setOpaque( true );
else
setOpaque( false );
// it's not generated by form editor
JPanel topAlign = new JPanel();
topAlign.setLayout(new BorderLayout());
topAlign.add(conditionsPanel, BorderLayout.NORTH);
conditionsScrollPane.setViewportView(topAlign);
// compute 80x10 chars space in scroll pane
FontMetrics fm = getFontMetrics(getFont());
int width = fm.charWidth('n') * 80; // NOI18N
int height = fm.getHeight() * 10;
conditionsScrollPane.setPreferredSize(new java.awt.Dimension(width, height));
Color background = (Color)UIManager.get("Table.background"); //NOI18N
conditionsPanel.setBackground(background);
topAlign.setBackground(background);
moreButton.addActionListener(this);
fewerButton.addActionListener(this);
matchAllRadio.addActionListener(this);
matchAnyRadio.addActionListener(this);
showFilter(filter);
updateSensitivity();
}
/**
* Links to next filter customizer (or null).
*/
public void initSubpanel(FilterSubpanel next) {
assert subpanel == null;
subpanel = next;
}
/**
* Show the given filter in the GUI
*/
private void showFilter(KeywordsFilter filter) {
if (filter != null) {
if (filter.matchAll()) {
matchAllRadio.setSelected(true);
} else {
matchAnyRadio.setSelected(true);
}
conditionsPanel.removeAll();
List conditions = filter.getConditions();
if (conditions.size() > 0) {
Iterator it = conditions.iterator();
while (it.hasNext()) {
AppliedFilterCondition cond = (AppliedFilterCondition) it.next();
addCondition(false, cond);
}
} else {
addCondition(false, null);
}
} else {
this.setEnabled(false);
matchAnyRadio.setEnabled(false);
matchAllRadio.setEnabled(false);
conditionsPanel.setEnabled(false);
moreButton.setEnabled(false);
fewerButton.setEnabled(false);
}
}
/**
* This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
matchGroup.add(matchAllRadio);
org.openide.awt.Mnemonics.setLocalizedText(matchAllRadio, NbBundle.getMessage(KeywordsPanel.class, "MatchAll")); // NOI18N(); // NOI18N
matchAllRadio.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordsPanel.class, "HINT_MatchAll")); // NOI18N
matchAllRadio.setOpaque(false);
matchGroup.add(matchAnyRadio);
matchAnyRadio.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(matchAnyRadio, NbBundle.getMessage(KeywordsPanel.class, "MatchAny")); // NOI18N(); // NOI18N
matchAnyRadio.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordsPanel.class, "HINT_MatchAny")); // NOI18N
matchAnyRadio.setOpaque(false);
conditionsScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
conditionsScrollPane.setAlignmentX(0.0F);
conditionsScrollPane.setAlignmentY(0.0F);
conditionsScrollPane.setPreferredSize(new java.awt.Dimension(32767, 32767));
conditionsPanel.setLayout(new java.awt.GridBagLayout());
conditionsScrollPane.setViewportView(conditionsPanel);
org.openide.awt.Mnemonics.setLocalizedText(fewerButton, NbBundle.getMessage(KeywordsPanel.class, "Fewer")); // NOI18N(); // NOI18N
fewerButton.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordsPanel.class, "HINT_Fewer")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(moreButton, NbBundle.getMessage(KeywordsPanel.class, "More")); // NOI18N(); // NOI18N
moreButton.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordsPanel.class, "HINT_More")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(moreButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fewerButton))
.addGroup(layout.createSequentialGroup()
.addComponent(matchAllRadio)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(matchAnyRadio)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))
.addComponent(conditionsScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 596, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(matchAllRadio)
.addComponent(matchAnyRadio))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(conditionsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 321, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(fewerButton)
.addComponent(moreButton))
.addContainerGap())
);
conditionsScrollPane.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getBundle(KeywordsPanel.class).getString("LBL_Conditions")); // NOI18N
conditionsScrollPane.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(KeywordsPanel.class).getString("HNT_Conditions")); // NOI18N
}// </editor-fold>//GEN-END:initComponents
private void initA11y() {
// accessible
this.getAccessibleContext().setAccessibleDescription(
NbBundle.getMessage(KeywordsPanel.class,
"ACSD_Filter")); // NOI18N
conditionsPanel.getAccessibleContext().setAccessibleName(
NbBundle.getMessage(KeywordsPanel.class,
"ACSN_Conditions")); // NOI18N
conditionsPanel.getAccessibleContext().setAccessibleDescription(
NbBundle.getMessage(KeywordsPanel.class,
"ACSD_Conditions")); // NOI18N
}
/**
* Adds a condition to the filter.
*
* @param revalidate true = invalidate() will be called
* @param condition a condition or null
*/
private ConditionPanel addCondition(boolean revalidate, AppliedFilterCondition condition) {
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = GridBagConstraints.NORTH;
gridBagConstraints.insets = new Insets(6, 0, 0, 0);
gridBagConstraints.weightx = 1.0;
ConditionPanel panel = new ConditionPanel(filter, condition);
panel.addPropertyChangeListener(FilterCondition.PROP_VALUE_VALID, this);
panel.setBackground((Color)UIManager.get("Table.background")); //NOI18N
conditionsPanel.add(panel, gridBagConstraints);
if (revalidate) {
invalidate();
getParent().validate();
repaint();
}
putClientProperty(FilterCondition.PROP_VALUE_VALID, Boolean.valueOf(isValueValid()));
return panel;
}
/** @return aggregated PROP_VALUE_VALID value */
public final boolean isValueValid() {
Component[] cps = conditionsPanel.getComponents();
for (int i = 0; i < cps.length; i++) {
ConditionPanel condition = (ConditionPanel) cps[i];
if (condition != null) {
if (condition.isValueValid() == false) {
return false;
}
}
}
return true;
}
// forward aggregated PROP_VALUE_VALID value
public void propertyChange(PropertyChangeEvent evt) {
putClientProperty(FilterCondition.PROP_VALUE_VALID, Boolean.valueOf(isValueValid()));
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (source == moreButton) {
ConditionPanel comp = addCondition(true, null);
JScrollBar vsb = conditionsScrollPane.getVerticalScrollBar();
vsb.setValue(vsb.getMaximum());
comp.focusPropertyCombo();
} else if (source == fewerButton) {
conditionsPanel.remove(conditionsPanel.getComponentCount() - 1);
invalidate();
getParent().validate();
repaint();
}
updateSensitivity();
putClientProperty(FilterCondition.PROP_VALUE_VALID, Boolean.valueOf(isValueValid()));
}
/**
* Updates enabled/disabled state of the "fewer" button
*/
private void updateSensitivity() {
int n = conditionsPanel.getComponentCount();
fewerButton.setEnabled(n > 0);
}
/**
* Return a filter corresponding to what is in the GUI
*
* @return filter or null
*/
public KeywordsFilter getFilter() {
if (filter != null) {
// Get conditions
Component[] cps = conditionsPanel.getComponents();
ArrayList<AppliedFilterCondition> conditions = new ArrayList<AppliedFilterCondition>(cps.length);
for (int i = 0; i < cps.length; i++) {
AppliedFilterCondition condition = ((ConditionPanel)cps[i]).getCondition();
if (condition != null) {
conditions.add(condition);
}
}
filter.setConditions(conditions);
filter.setMatchAll(matchAllRadio.isSelected());
if (subpanel != null) {
subpanel.updateFilter(filter);
}
}
return filter;
}
// Variables declaration - do not modify//GEN-BEGIN:variables
final javax.swing.JPanel conditionsPanel = new javax.swing.JPanel();
final javax.swing.JScrollPane conditionsScrollPane = new javax.swing.JScrollPane();
final javax.swing.JButton fewerButton = new javax.swing.JButton();
final javax.swing.JRadioButton matchAllRadio = new javax.swing.JRadioButton();
final javax.swing.JRadioButton matchAnyRadio = new javax.swing.JRadioButton();
final javax.swing.ButtonGroup matchGroup = new javax.swing.ButtonGroup();
final javax.swing.JButton moreButton = new javax.swing.JButton();
final javax.swing.ButtonGroup subtaskGroup = new javax.swing.ButtonGroup();
// End of variables declaration//GEN-END:variables
}