Index: trunk/src/org/openstreetmap/josm/data/osm/Filter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Filter.java	(revision 2125)
+++ trunk/src/org/openstreetmap/josm/data/osm/Filter.java	(revision 2125)
@@ -0,0 +1,52 @@
+package org.openstreetmap.josm.data.osm;
+
+import org.openstreetmap.josm.actions.search.SearchAction;
+import org.openstreetmap.josm.actions.search.SearchAction.SearchSetting;
+import org.openstreetmap.josm.actions.search.SearchAction.SearchMode;
+
+/**
+ *
+ * @author Petr_Dlouhý
+ */
+public class Filter extends SearchSetting {
+   private final String version = "1";
+   public String filterName = "";
+   public Boolean filtered = false;
+   public Boolean disabled = true;
+   public Boolean inverted = false;
+   public Boolean applyForChildren = true;
+   public Filter() {
+       super("", SearchMode.add, false, false);
+   }
+   public Filter(String text, SearchMode mode, boolean caseSensitive, boolean regexSearch, String filterName) {
+       super(text, mode, caseSensitive, regexSearch);
+       this.filterName = filterName;
+   }
+
+   public Filter(String prefText){
+      super("", SearchMode.add, false, false);
+      String[] prfs = prefText.split(";");
+      if(prfs.length != 10 && !prfs[0].equals(version))
+         throw new Error("Incompatible filter preferences");
+      text = prfs[1];
+      if(prfs[2].equals("replace")) mode = SearchMode.replace;
+      if(prfs[2].equals("add")) mode = SearchMode.add;
+      if(prfs[2].equals("remove")) mode = SearchMode.remove;
+      if(prfs[2].equals("in_selection")) mode = SearchMode.in_selection;
+      caseSensitive = Boolean.parseBoolean(prfs[3]);
+      regexSearch = Boolean.parseBoolean(prfs[4]);
+      filterName = prfs[5];
+      filtered = Boolean.parseBoolean(prfs[6]);
+      disabled = Boolean.parseBoolean(prfs[7]);
+      inverted = Boolean.parseBoolean(prfs[8]);
+      applyForChildren = Boolean.parseBoolean(prfs[9]);
+
+   }  
+
+   public String getPrefString(){
+      return version + ";" + 
+          text + ";" + mode + ";" + caseSensitive + ";" + regexSearch + ";" +
+          filterName + ";" + filtered + ";" + disabled + ";" + 
+          inverted + ";" + applyForChildren;
+   }
+}
Index: trunk/src/org/openstreetmap/josm/data/osm/Filters.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Filters.java	(revision 2125)
+++ trunk/src/org/openstreetmap/josm/data/osm/Filters.java	(revision 2125)
@@ -0,0 +1,193 @@
+package org.openstreetmap.josm.data.osm;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import javax.swing.table.AbstractTableModel;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Collection;
+import java.util.Map;
+
+import org.openstreetmap.josm.data.osm.Filter;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.search.SearchAction.Function;
+import org.openstreetmap.josm.actions.search.SearchAction;
+
+/**
+ *
+ * @author Petr_Dlouhý
+ */
+public class Filters extends AbstractTableModel{
+
+   public Filters(){
+      loadPrefs();
+   }
+
+   private List<Filter> filters = new LinkedList<Filter>();
+   public void filter(){
+      Collection<OsmPrimitive> seld = new LinkedList<OsmPrimitive> ();
+      Collection<OsmPrimitive> self = new LinkedList<OsmPrimitive> ();
+      Main.main.getCurrentDataSet().setFiltered();
+      Main.main.getCurrentDataSet().setDisabled();
+      for (Filter flt : filters){
+            if(flt.filtered){
+               SearchAction.getSelection(flt, self, new Function(){
+                  public Boolean isSomething(OsmPrimitive o){
+                     return o.isFiltered();
+                  }
+               });
+            } 
+            if(flt.disabled) {
+               SearchAction.getSelection(flt, seld, new Function(){
+                  public Boolean isSomething(OsmPrimitive o){
+                     return o.isDisabled();
+                  }
+               });
+            }
+      }
+      Main.main.getCurrentDataSet().setFiltered(self);
+      Main.main.getCurrentDataSet().setDisabled(seld);
+      Main.map.mapView.repaint();
+   }
+
+   private void loadPrefs(){
+      Map<String,String> prefs = Main.pref.getAllPrefix("filters.filter");
+      for (String value : prefs.values()) {
+         Filter filter = new Filter(value);
+         if(filter!=null)
+            filters.add(filter);
+      }
+   }
+
+   private void savePrefs(){
+      Map<String,String> prefs = Main.pref.getAllPrefix("filters.filter");
+      for (String key : prefs.keySet()) {
+         String[] sts = key.split("\\.");
+         if (sts.length != 3)throw new Error("Incompatible filter preferences");
+         Main.pref.put("filters.filter." + sts[2], null);
+      }
+
+      int i = 0;
+      for (Filter flt : filters){
+         Main.pref.put("filters.filter." + i++, flt.getPrefString());
+      }
+   }
+
+   private void savePref(int i){
+      if(i >= filters.size())
+         Main.pref.put("filters.filter." + i, null);
+      else
+         Main.pref.put("filters.filter." + i, filters.get(i).getPrefString());
+   }
+
+   public void addFilter(Filter f){
+      filters.add(f);
+      savePref(filters.size()-1);
+      filter();
+      fireTableRowsInserted(filters.size()-1, filters.size()-1);
+   }
+
+   public void moveDownFilter(int i){
+      if(i >= filters.size()-1) return;
+      filters.add(i+1, filters.remove(i));
+      savePref(i);
+      savePref(i+1);
+      filter();
+      fireTableRowsUpdated(i, i+1);
+   }
+
+   public void moveUpFilter(int i){
+      if(i == 0) return;
+      filters.add(i-1, filters.remove(i));
+      savePref(i);
+      savePref(i-1);
+      filter();
+      fireTableRowsUpdated(i-1, i);
+   }
+
+   public void removeFilter(int i){
+      filters.remove(i);
+      savePrefs();
+      filter();
+      fireTableRowsDeleted(i, i);
+   }
+
+   public void setFilter(int i, Filter f){
+      filters.set(i, f);
+      savePref(i);
+      filter();
+      fireTableRowsUpdated(i, i);
+   }
+
+   public Filter getFilter(int i){
+      return filters.get(i);
+   }
+
+   public int getRowCount(){
+      return filters.size();
+   }
+
+   public int getColumnCount(){
+      return 6;
+   }
+
+   public String getColumnName(int column){
+      String[] names = { tr("F"), tr("D"), tr("Name"), tr("C"), tr("I"), tr("M") };
+      return names[column];
+   }
+
+   public Class getColumnClass(int column){
+      Class[] classes = { Boolean.class, Boolean.class, String.class, Boolean.class, Boolean.class, String.class };
+      return classes[column];
+   }
+
+   public boolean isCellEditable(int row, int column){
+      if(column < 5)return true;
+      return false;
+   }
+
+   public void setValueAt(Object aValue, int row, int column){
+      Filter f = filters.get(row);
+      switch(column){
+         case 0: f.filtered = (Boolean)aValue;
+                 savePref(row);
+                 filter();
+                 return;
+         case 1: f.disabled = (Boolean)aValue;
+                 savePref(row);
+                 filter();
+                 return;
+         case 2: f.filterName = (String)aValue;
+                 savePref(row);
+                 return;
+         case 3: f.applyForChildren = (Boolean)aValue;
+                 savePref(row);
+                 filter();
+                 return;
+         case 4: f.inverted = (Boolean)aValue;
+                 savePref(row);
+                 filter();
+                 return;
+      }
+   }
+
+   public Object getValueAt(int row, int column){
+      Filter f = filters.get(row);
+      switch(column){
+         case 0: return f.filtered;
+         case 1: return f.disabled;
+         case 2: return f.filterName;
+         case 3: return f.applyForChildren;
+         case 4: return f.inverted;
+         case 5:
+                 switch(f.mode){
+                    case replace: return "∅";
+                    case add: return "∪";
+                    case remove: return "∖";
+                    case in_selection: return "∩";
+                 }
+      }
+      return null;
+   }
+}
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java	(revision 2125)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java	(revision 2125)
@@ -0,0 +1,189 @@
+// License: GPL. Copyright 2007 by Immanuel Scholz and others
+package org.openstreetmap.josm.gui.dialogs;
+
+import static org.openstreetmap.josm.tools.I18n.marktr;
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
+
+import javax.swing.JPanel;
+import javax.swing.JTable;
+import javax.swing.table.JTableHeader;
+import javax.swing.ListSelectionModel;
+import javax.swing.JPopupMenu;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.JScrollPane;
+
+import java.awt.FlowLayout;
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+import java.awt.event.KeyEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseEvent;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.SideButton;
+import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
+import org.openstreetmap.josm.gui.layer.DataChangeListener;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.data.osm.Filters;
+import org.openstreetmap.josm.data.osm.Filter;
+import org.openstreetmap.josm.tools.Shortcut;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.actions.search.SearchAction;
+
+/**
+ *
+ * @author Petr_Dlouhý
+ */
+public class FilterDialog extends ToggleDialog implements DataChangeListener, LayerChangeListener {
+    private JTable userTable;
+    private Filters filters = new Filters();
+    private SideButton addButton;
+    private SideButton editButton;
+    private SideButton deleteButton;
+    private SideButton upButton;
+    private SideButton downButton;
+    private JPopupMenu popupMenu;
+
+    public FilterDialog(){
+       super(tr("Filter"), "filter", tr("Filter objects and hide/disable them."),
+               Shortcut.registerShortcut("subwindow:filter", tr("Toggle: {0}", tr("Filter")), KeyEvent.VK_F, Shortcut.GROUP_LAYER, Shortcut.SHIFT_DEFAULT), 162);
+
+       Layer.listeners.add(this);
+       build();
+    }
+
+    protected JPanel buildButtonRow() {
+        JPanel pnl = new JPanel(new GridLayout(1, 4));
+
+        addButton = new SideButton(marktr("Add"), "add", "SelectionList", tr("Add filter."),
+              new ActionListener(){
+                 public void actionPerformed(ActionEvent evt){
+                    Filter filter = (Filter)SearchAction.showSearchDialog(new Filter());
+                    if(filter != null){
+                       filters.addFilter(filter);
+                       filters.filter();
+                    }
+                 }
+              });
+        pnl.add(addButton);
+
+        editButton = new SideButton(marktr("Edit"), "edit", "SelectionList", tr("Edit filter."),
+              new ActionListener(){
+                 public void actionPerformed(ActionEvent evt){
+                    int index = userTable.getSelectionModel().getMinSelectionIndex();
+                    if(index < 0) return;
+                    Filter f = filters.getFilter(index);
+                    Filter filter = (Filter)SearchAction.showSearchDialog(f);
+                    if(filter != null){
+                       filters.setFilter(index, filter);
+                       filters.filter();
+                    }
+                 }
+              });
+        pnl.add(editButton);
+
+        deleteButton = new SideButton(marktr("Delete"), "delete", "SelectionList", tr("Delete filter."),
+              new ActionListener(){
+                 public void actionPerformed(ActionEvent evt){
+                    int index = userTable.getSelectionModel().getMinSelectionIndex();
+                    if(index < 0) return;
+                    filters.removeFilter(index);
+                 }
+              });
+        pnl.add(deleteButton);
+
+        upButton = new SideButton(marktr("Up"), "up", "SelectionList", tr("Move filter up."),
+              new ActionListener(){
+                 public void actionPerformed(ActionEvent evt){
+                    int index = userTable.getSelectionModel().getMinSelectionIndex();
+                    if(index < 0) return;
+                    filters.moveUpFilter(index);
+                    userTable.getSelectionModel().setSelectionInterval(index-1, index-1);
+                 }
+              });
+        pnl.add(upButton);
+        
+        downButton = new SideButton(marktr("Down"), "down", "SelectionList", tr("Move filter down."),
+              new ActionListener(){
+                 public void actionPerformed(ActionEvent evt){
+                    int index = userTable.getSelectionModel().getMinSelectionIndex();
+                    if(index < 0) return;
+                    filters.moveDownFilter(index);
+                    userTable.getSelectionModel().setSelectionInterval(index+1, index+1);
+                 }
+              });
+        pnl.add(downButton);
+        return pnl;
+    }
+
+    protected String[] columnToolTips = {
+        tr("Filter elements"),
+        tr("Disable elements"),
+        tr("Apply also for children"),
+        tr("Inverse filter"),
+        null,
+        tr("Filter mode")
+    };
+
+    protected void build() {
+        JPanel pnl = new JPanel();
+        pnl.setLayout(new BorderLayout());
+        userTable = new JTable(filters){
+            protected JTableHeader createDefaultTableHeader() {
+                return new JTableHeader(columnModel) {
+                   public String getToolTipText(MouseEvent e) {
+                       String tip = null;
+                       java.awt.Point p = e.getPoint();
+                       int index = columnModel.getColumnIndexAtX(p.x);
+                       int realIndex = columnModel.getColumn(index).getModelIndex();
+                       return columnToolTips[realIndex];
+                   }
+               };
+           }
+        };   
+  
+        userTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+        userTable.getColumnModel().getColumn(0).setMaxWidth(1);
+        userTable.getColumnModel().getColumn(1).setMaxWidth(1);
+        userTable.getColumnModel().getColumn(3).setMaxWidth(1);
+        userTable.getColumnModel().getColumn(4).setMaxWidth(1);
+        userTable.getColumnModel().getColumn(5).setMaxWidth(1);
+
+        userTable.getColumnModel().getColumn(0).setResizable(false);
+        userTable.getColumnModel().getColumn(1).setResizable(false);
+        userTable.getColumnModel().getColumn(3).setResizable(false);
+        userTable.getColumnModel().getColumn(4).setResizable(false);
+        userTable.getColumnModel().getColumn(5).setResizable(false);
+
+        pnl.add(new JScrollPane(userTable), BorderLayout.CENTER);
+
+        // -- the button row
+        pnl.add(buildButtonRow(), BorderLayout.SOUTH);
+        /*userTable.addMouseListener(new DoubleClickAdapter());*/
+        add(pnl, BorderLayout.CENTER);
+    }
+
+    public void layerRemoved(Layer a) {
+        if (a instanceof OsmDataLayer) {
+            ((OsmDataLayer)a).listenerDataChanged.remove(this);
+        }
+    }
+
+    public void layerAdded(Layer a) {
+        if (a instanceof OsmDataLayer) {
+            ((OsmDataLayer)a).listenerDataChanged.add(this);
+        }
+    }
+
+   public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+      filters.filter();
+   }
+
+   public void dataChanged(OsmDataLayer l){
+      filters.filter();
+   }
+}
