Index: trunk/src/org/openstreetmap/josm/data/osm/FilterWorker.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/FilterWorker.java	(revision 3370)
+++ trunk/src/org/openstreetmap/josm/data/osm/FilterWorker.java	(revision 3371)
@@ -61,4 +61,17 @@
     }
 
+    public static boolean executeFilters(OsmPrimitive primitive, FilterMatcher filterMatcher) {
+        boolean hidden = primitive.isDisabledAndHidden();
+        boolean disabled = primitive.isDisabled();
+        if (filterMatcher.isHidden(primitive)) {
+            primitive.setDisabledState(true);
+        } else if (filterMatcher.isDisabled(primitive)) {
+            primitive.setDisabledState(false);
+        } else {
+            primitive.unsetDisabledState();
+        }
+        return hidden != primitive.isDisabledAndHidden() || disabled != primitive.isDisabled();
+    }
+
     public static void clearFilterFlags(Collection<OsmPrimitive> prims) {
         for (OsmPrimitive osm : prims) {
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java	(revision 3370)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java	(revision 3371)
@@ -12,4 +12,8 @@
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseEvent;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Stack;
 
 import javax.swing.JCheckBox;
@@ -26,9 +30,18 @@
 import org.openstreetmap.josm.actions.search.SearchAction;
 import org.openstreetmap.josm.data.osm.Filter;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.RelationMember;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
+import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
 import org.openstreetmap.josm.data.osm.event.DataSetListener;
-import org.openstreetmap.josm.data.osm.event.DataSetListenerAdapter;
 import org.openstreetmap.josm.data.osm.event.DatasetEventManager;
-import org.openstreetmap.josm.data.osm.event.DataSetListenerAdapter.Listener;
+import org.openstreetmap.josm.data.osm.event.NodeMovedEvent;
+import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent;
+import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
+import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
+import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
+import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
 import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
 import org.openstreetmap.josm.gui.SideButton;
@@ -39,5 +52,5 @@
  * @author Petr_Dlouhý
  */
-public class FilterDialog extends ToggleDialog implements Listener {
+public class FilterDialog extends ToggleDialog implements DataSetListener {
 
     private JTable userTable;
@@ -49,5 +62,4 @@
     private SideButton downButton;
 
-    private final DataSetListener listenerAdapter = new DataSetListenerAdapter(this);
 
     public FilterDialog(){
@@ -59,5 +71,5 @@
     @Override
     public void showNotify() {
-        DatasetEventManager.getInstance().addDatasetListener(listenerAdapter, FireMode.IN_EDT_CONSOLIDATED);
+        DatasetEventManager.getInstance().addDatasetListener(this, FireMode.IN_EDT_CONSOLIDATED);
         filterModel.executeFilters();
     }
@@ -65,5 +77,5 @@
     @Override
     public void hideNotify() {
-        DatasetEventManager.getInstance().removeDatasetListener(listenerAdapter);
+        DatasetEventManager.getInstance().removeDatasetListener(this);
         filterModel.clearFilterFlags();
         Main.map.mapView.repaint();
@@ -181,8 +193,4 @@
     }
 
-    public void processDatasetEvent(AbstractDatasetChangedEvent event) {
-        filterModel.executeFilters();
-    }
-
     static class StringRenderer extends DefaultTableCellRenderer {
         @Override
@@ -216,3 +224,82 @@
         filterModel.drawOSDText(g);
     }
+
+    /**
+     *
+     * @param primitive
+     * @return List of primitives whose filtering can be affected by change in primitive
+     */
+    private Collection<OsmPrimitive> getAffectedPrimitives(Collection<? extends OsmPrimitive> primitives) {
+        // Filters can use nested parent/child expression so complete tree is necessary
+        Set<OsmPrimitive> result = new HashSet<OsmPrimitive>();
+        Stack<OsmPrimitive> stack = new Stack<OsmPrimitive>();
+        stack.addAll(primitives);
+
+        while (!stack.isEmpty()) {
+            OsmPrimitive p = stack.pop();
+
+            if (result.contains(p)) {
+                continue;
+            }
+
+            result.add(p);
+
+            if (p instanceof Way) {
+                for (OsmPrimitive n: ((Way)p).getNodes()) {
+                    stack.push(n);
+                }
+            } else if (p instanceof Relation) {
+                for (RelationMember rm: ((Relation)p).getMembers()) {
+                    stack.push(rm.getMember());
+                }
+            }
+
+            for (OsmPrimitive ref: p.getReferrers()) {
+                stack.push(ref);
+            }
+        }
+
+        return result;
+    }
+
+
+    @Override
+    public void dataChanged(DataChangedEvent event) {
+        filterModel.executeFilters();
+    }
+
+    @Override
+    public void nodeMoved(NodeMovedEvent event) {
+        // Do nothing
+    }
+
+    @Override
+    public void otherDatasetChange(AbstractDatasetChangedEvent event) {
+        filterModel.executeFilters();
+    }
+
+    @Override
+    public void primtivesAdded(PrimitivesAddedEvent event) {
+        filterModel.executeFilters(event.getPrimitives());
+    }
+
+    @Override
+    public void primtivesRemoved(PrimitivesRemovedEvent event) {
+        filterModel.executeFilters();
+    }
+
+    @Override
+    public void relationMembersChanged(RelationMembersChangedEvent event) {
+        filterModel.executeFilters(getAffectedPrimitives(event.getPrimitives()));
+    }
+
+    @Override
+    public void tagsChanged(TagsChangedEvent event) {
+        filterModel.executeFilters(getAffectedPrimitives(event.getPrimitives()));
+    }
+
+    @Override
+    public void wayNodesChanged(WayNodesChangedEvent event) {
+        filterModel.executeFilters(getAffectedPrimitives(event.getPrimitives()));
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/FilterTableModel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/FilterTableModel.java	(revision 3370)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/FilterTableModel.java	(revision 3371)
@@ -8,4 +8,5 @@
 import java.awt.Graphics;
 import java.awt.Graphics2D;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
@@ -25,4 +26,5 @@
 import org.openstreetmap.josm.data.osm.FilterMatcher;
 import org.openstreetmap.josm.data.osm.FilterWorker;
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
@@ -59,5 +61,5 @@
 
 
-    
+
     public void executeFilters() {
         DataSet ds = Main.main.getCurrentDataSet();
@@ -65,24 +67,32 @@
             return;
 
-        final Collection<OsmPrimitive> all = ds.allNonDeletedCompletePrimitives();
-
-        FilterWorker.executeFilters(all, filterMatcher);
-
-        disabledCount = 0;
-        disabledAndHiddenCount = 0;
-        // collect disabled and selected the primitives
         final Collection<OsmPrimitive> deselect = new HashSet<OsmPrimitive>();
-        for (OsmPrimitive osm : all) {
-            if (osm.isDisabled()) {
-                disabledCount++;
-                if (osm.isSelected()) {
-                    deselect.add(osm);
-                }
-                if (osm.isDisabledAndHidden()) {
-                    disabledAndHiddenCount++;
+
+        ds.beginUpdate();
+        try {
+
+            final Collection<OsmPrimitive> all = ds.allNonDeletedCompletePrimitives();
+
+            FilterWorker.executeFilters(all, filterMatcher);
+
+            disabledCount = 0;
+            disabledAndHiddenCount = 0;
+            // collect disabled and selected the primitives
+            for (OsmPrimitive osm : all) {
+                if (osm.isDisabled()) {
+                    disabledCount++;
+                    if (osm.isSelected()) {
+                        deselect.add(osm);
+                    }
+                    if (osm.isDisabledAndHidden()) {
+                        disabledAndHiddenCount++;
+                    }
                 }
             }
-        }
-        disabledCount -= disabledAndHiddenCount;
+            disabledCount -= disabledAndHiddenCount;
+        } finally {
+            ds.endUpdate();
+        }
+
         if (!deselect.isEmpty()) {
             ds.clearSelection(deselect);
@@ -91,4 +101,58 @@
         Main.map.mapView.repaint();
         Main.map.filterDialog.updateDialogHeader();
+    }
+
+
+    public void executeFilters(Collection<? extends OsmPrimitive> primitives) {
+        DataSet ds = Main.main.getCurrentDataSet();
+        if (ds == null)
+            return;
+
+        boolean changed = false;
+        List<OsmPrimitive> deselect = new ArrayList<OsmPrimitive>();
+
+        ds.beginUpdate();
+        try {
+            for (int i=0; i<2; i++) {
+                for (OsmPrimitive primitive: primitives) {
+
+                    if (i == 0 && primitive instanceof Node) {
+                        continue;
+                    }
+
+                    if (i == 1 && !(primitive instanceof Node)) {
+                        continue;
+                    }
+
+                    if (primitive.isDisabled()) {
+                        disabledCount--;
+                    }
+                    if (primitive.isDisabledAndHidden()) {
+                        disabledAndHiddenCount--;
+                    }
+                    changed = changed | FilterWorker.executeFilters(primitive, filterMatcher);
+                    if (primitive.isDisabled()) {
+                        disabledCount++;
+                    }
+                    if (primitive.isDisabledAndHidden()) {
+                        disabledAndHiddenCount++;
+                    }
+
+                    if (primitive.isSelected() && primitive.isDisabled()) {
+                        deselect.add(primitive);
+                    }
+
+                }
+            }
+        } finally {
+            ds.endUpdate();
+        }
+
+        if (changed) {
+            Main.map.mapView.repaint();
+            Main.map.filterDialog.updateDialogHeader();
+            ds.clearSelection(deselect);
+        }
+
     }
 
