blob: 911a2d6e13ae80b899673e7fef6650b05a34a5c2 [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.Dialog;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import javax.swing.AbstractListModel;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.BadLocationException;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
/**
*
* @author sa154850
*/
public class FilterEditor extends JPanel implements PropertyChangeListener {
private HashMap<KeywordsFilter, KeywordsPanel> filter2keywords = new HashMap<KeywordsFilter, KeywordsPanel>(10);
private HashMap<TypesFilter, TypesPanel> filter2types = new HashMap<TypesFilter, TypesPanel>(10);
/** Reference to orginal filterRepository this dialog act upon.
* It is not changed until ok or apply is pressed */
private FilterRepository filterRepository;
/**
* Contains temporary data (cloned filters) for the list and also selection
* model for the list.
*/
private FilterModel filterModel;
private JButton btnOk;
private JButton btnCancel;
/** Creates new form FilterEditor */
public FilterEditor( FilterRepository filters ) {
initComponents();
this.filterRepository = filters;
if( filterRepository.size() == 0 )
filterRepository.add( filterRepository.createNewFilter() );
this.filterModel = new FilterModel( filterRepository );
init();
}
public boolean showWindow() {
DialogDescriptor dd = new DialogDescriptor( this, NbBundle.getMessage( FilterEditor.class, "LBL_FilterEditor" ), true, //NOI18N
new Object[] { btnOk, btnCancel }, btnOk, DialogDescriptor.DEFAULT_ALIGN, HelpCtx.DEFAULT_HELP, null );
Dialog dlg = DialogDisplayer.getDefault().createDialog( dd );
dlg.setVisible(true);
if( btnOk.equals( dd.getValue() ) ) {
updateFilters();
return true;
}
return false;
}
private void init() {
initComponents();
// init filters-listbox model
lstFilters.setModel(filterModel);
lstFilters.setSelectionModel(filterModel.selection);
lstFilters.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// try to select just applied filter
TaskFilter selected = filterRepository.getActive();
if( null != selected ) {
int selIndex = filterModel.getIndexOf( selected );
lstFilters.setSelectedIndex( selIndex );
}
if (filterModel.getSelectedIndex() == -1) {
if (filterModel.getSize() > 0) {
lstFilters.setSelectedIndex(0);
}
}
txtFilterName.getDocument().addDocumentListener( new DocumentListener() {
public void changedUpdate(DocumentEvent e) { update(e);}
public void insertUpdate(DocumentEvent e) { update(e);}
public void removeUpdate(DocumentEvent e) { update(e);}
private void update(DocumentEvent e) {
try {
filterModel.setCurrentFilterName(e.getDocument().getText(0, e.getDocument().getLength()));
propertyChange(null);
} catch (BadLocationException ex) {
//ignore
}
}
});
// hook list selection
lstFilters.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
showFilter(filterModel.getSelectedFilter());
btnRemoveFilter.setEnabled( filterModel.getSelectedIndex() != -1 );
txtFilterName.setEnabled( filterModel.getSelectedIndex() != -1 );
}
}
});
showFilter(filterModel.getSelectedFilter());
btnRemoveFilter.setEnabled(filterModel.getSelectedIndex() != -1);
btnOk= new JButton( NbBundle.getMessage(FilterEditor.class, "btnOk") ); //NOI18N
btnCancel = new JButton( NbBundle.getMessage(FilterEditor.class, "btnCancel") ); //NOI18N
}
/**
* Initializes the editor to the state when <filter> is selected in the list
* and it is shown on the right side. It can be used to propagate values in
* both directions - from list to pane and opposite and also to both at once.
*/
private void showFilter(final TaskFilter filter) {
if( null == filter ) {
txtFilterName.setText( null );
panelKeywords.removeAll();
panelTypes.removeAll();
panelKeywords.add( new KeywordsPanel(null), BorderLayout.CENTER );
panelTypes.add( new TypesPanel(null), BorderLayout.CENTER );
} else {
KeywordsPanel kPanel = filter2keywords.get( filter.getKeywordsFilter() );
if( kPanel == null ) {
kPanel = new KeywordsPanel( filter.getKeywordsFilter() == null ? new KeywordsFilter() : filter.getKeywordsFilter() );
filter2keywords.put( filter.getKeywordsFilter(), kPanel );
kPanel.addPropertyChangeListener( FilterCondition.PROP_VALUE_VALID, this );
}
panelKeywords.removeAll();
panelKeywords.add( kPanel, BorderLayout.CENTER );
kPanel.setVisible( true );
TypesPanel tPanel = filter2types.get( filter.getTypesFilter() );
if( tPanel == null ) {
tPanel = new TypesPanel( filter.getTypesFilter() == null ? new TypesFilter() : filter.getTypesFilter() );
filter2types.put( filter.getTypesFilter(), tPanel );
tPanel.addPropertyChangeListener( FilterCondition.PROP_VALUE_VALID, this );
}
panelTypes.removeAll();
panelTypes.add( tPanel,BorderLayout.CENTER );
tPanel.setVisible( true );
tabs.requestFocus();
// select the active filter
if (filterModel.getSelectedFilter() != filter) { // check to prevent cycle in notifications
lstFilters.setSelectedIndex(filterModel.getIndexOf(filter));
}
txtFilterName.setText( filter.getName() );
}
panelKeywords.validate();
panelKeywords.repaint();
panelTypes.validate();
panelTypes.repaint();
}
/**
* Lift of isValueValid to FiltersPanel
*/
public boolean isValueValid() {
for( KeywordsPanel fp : filter2keywords.values() ) {
if( !fp.isValueValid() )
return false;
}
for( TypesPanel tp : filter2types.values() ) {
if( !tp.isValueValid() )
return false;
}
if( txtFilterName.getText().length() == 0 )
return false;
return true;
}
public void propertyChange(PropertyChangeEvent arg0) {
if( null != btnOk )
btnOk.setEnabled( isValueValid() );
}
/**
* Reads data from the form into the filter repository
* that was passed-in in the constructor (returned by {@link #getFilterRepository})
*/
void updateFilters() {
filterRepository.clear(); // throw away all original filters
Iterator filterIt = filterModel.iterator();
while (filterIt.hasNext()) {
TaskFilter f = (TaskFilter)filterIt.next();
if( filter2keywords.get( f.getKeywordsFilter() ) != null )
f.setKeywordsFilter( filter2keywords.get( f.getKeywordsFilter() ).getFilter() ); // has panel, was touched
if( filter2types.get( f.getTypesFilter() ) != null )
f.setTypesFilter( filter2types.get( f.getTypesFilter() ).getFilter() ); // has panel, was touched
filterRepository.add( f );
}
if( filterModel.getSelectedFilter()!= null ) {
filterRepository.setActive(filterModel.getSelectedFilter());
}
}
/** 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() {
lblFilters = new javax.swing.JLabel();
scrollFilters = new javax.swing.JScrollPane();
lstFilters = new javax.swing.JList();
btnNewFilter = new javax.swing.JButton();
btnRemoveFilter = new javax.swing.JButton();
tabs = new javax.swing.JTabbedPane();
panelTypes = new javax.swing.JPanel();
panelKeywords = new javax.swing.JPanel();
lblFilterName = new javax.swing.JLabel();
txtFilterName = new javax.swing.JTextField();
lblFilters.setLabelFor(lstFilters);
org.openide.awt.Mnemonics.setLocalizedText(lblFilters, org.openide.util.NbBundle.getMessage(FilterEditor.class, "FilterEditor.lblFilters.text")); // NOI18N
lstFilters.setModel(new javax.swing.AbstractListModel() {
String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
public int getSize() { return strings.length; }
public Object getElementAt(int i) { return strings[i]; }
});
lstFilters.setToolTipText(org.openide.util.NbBundle.getMessage(FilterEditor.class, "FilterEditor.lstFilters.toolTipText")); // NOI18N
scrollFilters.setViewportView(lstFilters);
org.openide.awt.Mnemonics.setLocalizedText(btnNewFilter, org.openide.util.NbBundle.getMessage(FilterEditor.class, "FilterEditor.btnNewFilter.text")); // NOI18N
btnNewFilter.setToolTipText(org.openide.util.NbBundle.getMessage(FilterEditor.class, "FilterEditor.btnNewFilter.toolTipText")); // NOI18N
btnNewFilter.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
onNewFilter(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(btnRemoveFilter, org.openide.util.NbBundle.getMessage(FilterEditor.class, "FilterEditor.btnRemoveFilter.text")); // NOI18N
btnRemoveFilter.setToolTipText(org.openide.util.NbBundle.getMessage(FilterEditor.class, "FilterEditor.btnRemoveFilter.toolTipText")); // NOI18N
btnRemoveFilter.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
onRemoveFilter(evt);
}
});
panelTypes.setOpaque(false);
panelTypes.setLayout(new java.awt.BorderLayout());
tabs.addTab(org.openide.util.NbBundle.getMessage(FilterEditor.class, "FilterEditor.panelTypes.TabConstraints.tabTitle"), panelTypes); // NOI18N
panelKeywords.setOpaque(false);
panelKeywords.setLayout(new java.awt.BorderLayout());
tabs.addTab(org.openide.util.NbBundle.getMessage(FilterEditor.class, "FilterEditor.panelKeywords.TabConstraints.tabTitle"), panelKeywords); // NOI18N
lblFilterName.setLabelFor(txtFilterName);
org.openide.awt.Mnemonics.setLocalizedText(lblFilterName, org.openide.util.NbBundle.getMessage(FilterEditor.class, "FilterEditor.lblFilterName.text")); // NOI18N
txtFilterName.setToolTipText(org.openide.util.NbBundle.getMessage(FilterEditor.class, "FilterEditor.txtFilterName.toolTipText")); // 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, false)
.addComponent(lblFilters)
.addGroup(layout.createSequentialGroup()
.addComponent(btnNewFilter)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnRemoveFilter))
.addComponent(scrollFilters))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(lblFilterName)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtFilterName, javax.swing.GroupLayout.DEFAULT_SIZE, 459, Short.MAX_VALUE))
.addComponent(tabs, javax.swing.GroupLayout.DEFAULT_SIZE, 516, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(lblFilters)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(scrollFilters, javax.swing.GroupLayout.DEFAULT_SIZE, 229, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnNewFilter)
.addComponent(btnRemoveFilter)))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblFilterName)
.addComponent(txtFilterName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tabs, javax.swing.GroupLayout.DEFAULT_SIZE, 235, Short.MAX_VALUE)))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void onRemoveFilter(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onRemoveFilter
int i = filterModel.getSelectedIndex();
if (i != -1) {
TaskFilter f = filterModel.get(i);
filterModel.remove(i);
filter2keywords.remove( f.getKeywordsFilter() );
filter2types.remove( f.getTypesFilter() );
}
}//GEN-LAST:event_onRemoveFilter
private void onNewFilter(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onNewFilter
TaskFilter f = filterRepository.createNewFilter();
filterModel.add( f );
showFilter( f );
}//GEN-LAST:event_onNewFilter
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnNewFilter;
private javax.swing.JButton btnRemoveFilter;
private javax.swing.JLabel lblFilterName;
private javax.swing.JLabel lblFilters;
private javax.swing.JList lstFilters;
private javax.swing.JPanel panelKeywords;
private javax.swing.JPanel panelTypes;
private javax.swing.JScrollPane scrollFilters;
private javax.swing.JTabbedPane tabs;
private javax.swing.JTextField txtFilterName;
// End of variables declaration//GEN-END:variables
private static class FilterModel extends AbstractListModel {
public DefaultListSelectionModel selection = new DefaultListSelectionModel();
public ArrayList<TaskFilter> filters;
public FilterModel( FilterRepository rep ) {
filters = new ArrayList<TaskFilter>( rep.size() * 2 );
int selectedi = 0;
for( TaskFilter f : rep.getFilters() ) {
if( f == rep.getActive() )
selection.setSelectionInterval(selectedi, selectedi);
filters.add( (TaskFilter)f.clone() );
selectedi++;
}
}
public Iterator iterator() {
return filters.iterator();
}
public Object getElementAt(int index) {
return filters.get(index).getName();
}
public int getSize() {
return filters.size();
}
public TaskFilter getSelectedFilter() {
if (getSelectedIndex() > -1) {
return filters.get( getSelectedIndex() );
} else
return null;
}
public int getSelectedIndex() {
int i1 = selection.getMinSelectionIndex(), i2 = selection.getMaxSelectionIndex();
if (i1 == i2 && i1 >= 0 && i1 < filters.size()) {
return i1;
} else {
return -1;
}
}
public void remove(int i) {
int s = getSelectedIndex();
if (s != -1) {
filters.remove(i);
fireIntervalRemoved(this, i, i);
if (i < s) {
selection.setSelectionInterval(s-1, s-1);
} if (i == s) {
selection.setSelectionInterval(100,0);
}
}
}
public TaskFilter get(int i ) {
return (TaskFilter)filters.get(i);
}
public boolean add(TaskFilter f) {
if (filters.add(f)) {
fireIntervalAdded(this, filters.size()-1, filters.size()-1);
return true;
} else
return false;
}
public int getIndexOf(TaskFilter f) {
return filters.indexOf(f);
}
public void setCurrentFilterName(String name) {
int selIndex = getSelectedIndex();
if( selIndex >= 0 ) {
get(selIndex).setName(name);
fireContentsChanged(this, selIndex, selIndex);
}
}
}
}