Index: src/org/openstreetmap/josm/actions/SplitWayAction.java =================================================================== --- src/org/openstreetmap/josm/actions/SplitWayAction.java (revision 2114) +++ src/org/openstreetmap/josm/actions/SplitWayAction.java (working copy) @@ -101,7 +101,7 @@ HashMap wayOccurenceCounter = new HashMap(); for (Node n : selectedNodes) { for (Way w : getCurrentDataSet().ways) { - if (w.isDeleted() || w.incomplete) { + if (w.isDeleted() || w.isDisabled() || w.incomplete) { continue; } int last = w.getNodesCount()-1; @@ -292,7 +292,7 @@ // now copy all relations to new way also for (Relation r : getCurrentDataSet().relations) { - if (r.isDeleted() || r.incomplete) { + if (r.isDeleted() || r.isDisabled() || r.incomplete) { continue; } Relation c = null; Index: src/org/openstreetmap/josm/actions/search/SearchAction.java =================================================================== --- src/org/openstreetmap/josm/actions/search/SearchAction.java (revision 2114) +++ src/org/openstreetmap/josm/actions/search/SearchAction.java (working copy) @@ -24,13 +24,14 @@ import org.openstreetmap.josm.gui.ExtendedDialog; import org.openstreetmap.josm.tools.GBC; import org.openstreetmap.josm.tools.Shortcut; +import org.openstreetmap.josm.data.osm.Filter; public class SearchAction extends JosmAction{ public static final int SEARCH_HISTORY_SIZE = 10; public static enum SearchMode { - replace, add, remove + replace, add, remove, in_selection } public static final LinkedList searchHistory = new LinkedList(); @@ -56,33 +57,46 @@ } SearchSetting s = lastSearch; if (s == null) { - s = new SearchSetting("", false, false, SearchMode.replace); + s = new SearchSetting("", SearchMode.replace, false, false); } - showSearchDialog(s); + SearchSetting se = showSearchDialog(s); + if(se != null) searchWithHistory(se); } - public void showSearchDialog(SearchSetting initialValues) { - JLabel label = new JLabel(tr("Please enter a search string.")); + public static SearchSetting showSearchDialog(SearchSetting initialValues) { + JLabel label = new JLabel( initialValues instanceof Filter ? tr("Please enter a filter string.") : tr("Please enter a search string.")); final JTextField input = new JTextField(initialValues.text); input.selectAll(); input.requestFocusInWindow(); JRadioButton replace = new JRadioButton(tr("replace selection"), initialValues.mode == SearchMode.replace); JRadioButton add = new JRadioButton(tr("add to selection"), initialValues.mode == SearchMode.add); JRadioButton remove = new JRadioButton(tr("remove from selection"), initialValues.mode == SearchMode.remove); + JRadioButton in_selection = new JRadioButton(tr("find in selection"), initialValues.mode == SearchMode.in_selection); ButtonGroup bg = new ButtonGroup(); bg.add(replace); bg.add(add); bg.add(remove); + bg.add(in_selection); JCheckBox caseSensitive = new JCheckBox(tr("case sensitive"), initialValues.caseSensitive); JCheckBox regexSearch = new JCheckBox(tr("regular expression"), initialValues.regexSearch); JPanel left = new JPanel(new GridBagLayout()); + + JTextField finput = null; + if(initialValues instanceof Filter){ + JLabel fLabel = new JLabel(tr("Please enter a filter name.")); + finput = new JTextField(((Filter)initialValues).filterName); + left.add(fLabel, GBC.eop()); + left.add(finput, GBC.eop().fill(GBC.HORIZONTAL)); + } + left.add(label, GBC.eop()); left.add(input, GBC.eop().fill(GBC.HORIZONTAL)); left.add(replace, GBC.eol()); left.add(add, GBC.eol()); - left.add(remove, GBC.eop()); + left.add(remove, GBC.eol()); + left.add(in_selection, GBC.eop()); left.add(caseSensitive, GBC.eol()); left.add(regexSearch, GBC.eol()); @@ -119,21 +133,27 @@ p.add(right); ExtendedDialog dialog = new ExtendedDialog( Main.parent, - tr("Search"), - new String[] {tr("Start Search"), tr("Cancel")} + initialValues instanceof Filter ? tr("Filter") : tr("Search"), + new String[] { + initialValues instanceof Filter ? tr("Make filter") : tr("Start Search"), + tr("Cancel")} ); dialog.setButtonIcons(new String[] {"dialogs/search.png", "cancel.png"}); dialog.setContent(p); dialog.showDialog(); int result = dialog.getValue(); - if(result != 1) return; + if(result != 1) return null; // User pressed OK - let's perform the search SearchMode mode = replace.isSelected() ? SearchAction.SearchMode.replace - : (add.isSelected() ? SearchAction.SearchMode.add : SearchAction.SearchMode.remove); - SearchSetting setting = new SearchSetting(input.getText(), caseSensitive.isSelected(), regexSearch.isSelected(), mode); - searchWithHistory(setting); + : (add.isSelected() ? SearchAction.SearchMode.add + : (remove.isSelected() ? SearchAction.SearchMode.remove : SearchAction.SearchMode.in_selection)); + if(initialValues instanceof Filter){ + return new Filter(input.getText(), mode, caseSensitive.isSelected(), regexSearch.isSelected(), finput.getText()); + } else { + return new SearchSetting(input.getText(), mode, caseSensitive.isSelected(), regexSearch.isSelected()); + } } /** @@ -150,67 +170,48 @@ searchHistory.removeLast(); } lastSearch = s; - search(s.text, s.mode, s.caseSensitive, s.regexSearch); + search(s); } public static void searchWithoutHistory(SearchSetting s) { lastSearch = s; - search(s.text, s.mode, s.caseSensitive, s.regexSearch); + search(s); } - public static void search(String search, SearchMode mode, boolean caseSensitive, boolean regexSearch) { - // FIXME: This is confusing. The GUI says nothing about loading primitives from an URL. We'd like to *search* - // for URLs in the current data set. - // Disabling until a better solution is in place - // - // if (search.startsWith("http://") || search.startsWith("ftp://") || search.startsWith("https://") - // || search.startsWith("file:/")) { - // SelectionWebsiteLoader loader = new SelectionWebsiteLoader(search, mode); - // if (loader.url != null && loader.url.getHost() != null) { - // Main.worker.execute(loader); - // return; - // } - // } + public interface Function{ + public Boolean isSomething(OsmPrimitive o); + } + + public static Integer getSelection(SearchSetting s, Collection sel, Function f) { + Integer foundMatches = 0; try { - Collection sel = Main.main.getCurrentDataSet().getSelected(); - SearchCompiler.Match matcher = SearchCompiler.compile(search, caseSensitive, regexSearch); - int foundMatches = 0; + String searchText = s.text; + if(s instanceof Filter){ + searchText = ((Filter)s).inverted ? "-" : ""; + searchText = searchText + "(" + ((Filter)s).text + ")" + (((Filter)s).applyForChildren ? ("| child (" + ((Filter)s).text + ")"): ""); + } + /*System.out.println(searchText); */ + SearchCompiler.Match matcher = SearchCompiler.compile(searchText, s.caseSensitive, s.regexSearch); + foundMatches = 0; for (OsmPrimitive osm : Main.main.getCurrentDataSet().allNonDeletedCompletePrimitives()) { - if (mode == SearchMode.replace) { + if (s.mode == SearchMode.replace) { if (matcher.match(osm)) { sel.add(osm); ++foundMatches; } else { sel.remove(osm); } - } else if (mode == SearchMode.add && !osm.isSelected() && matcher.match(osm)) { + } else if (s.mode == SearchMode.add && !f.isSomething(osm) && matcher.match(osm)) { sel.add(osm); ++foundMatches; - } else if (mode == SearchMode.remove && osm.isSelected() && matcher.match(osm)) { + } else if (s.mode == SearchMode.remove && f.isSomething(osm) && matcher.match(osm)) { sel.remove(osm); ++foundMatches; + } else if (s.mode == SearchMode.in_selection && f.isSomething(osm)&& !matcher.match(osm)) { + sel.remove(osm); + ++foundMatches; } } - Main.main.getCurrentDataSet().setSelected(sel); - if (foundMatches == 0) { - String msg = null; - if (mode == SearchMode.replace) { - msg = tr("No match found for ''{0}''", search); - } else if (mode == SearchMode.add) { - msg = tr("Nothing added to selection by searching for ''{0}''", search); - } else if (mode == SearchMode.remove) { - msg = tr("Nothing removed from selection by searching for ''{0}''", search); - } - Main.map.statusLine.setHelpText(msg); - JOptionPane.showMessageDialog( - Main.parent, - msg, - tr("Warning"), - JOptionPane.WARNING_MESSAGE - ); - } else { - Main.map.statusLine.setHelpText(tr("Found {0} matches", foundMatches)); - } } catch (SearchCompiler.ParseError e) { JOptionPane.showMessageDialog( Main.parent, @@ -220,15 +221,64 @@ ); } + return foundMatches; } + + public static void search(String search, SearchMode mode, boolean caseSensitive, boolean regexSearch) { + search(new SearchSetting(search, mode, caseSensitive, regexSearch)); + } + public static void search(SearchSetting s) { + // FIXME: This is confusing. The GUI says nothing about loading primitives from an URL. We'd like to *search* + // for URLs in the current data set. + // Disabling until a better solution is in place + // + // if (search.startsWith("http://") || search.startsWith("ftp://") || search.startsWith("https://") + // || search.startsWith("file:/")) { + // SelectionWebsiteLoader loader = new SelectionWebsiteLoader(search, mode); + // if (loader.url != null && loader.url.getHost() != null) { + // Main.worker.execute(loader); + // return; + // } + // } + + Collection sel = Main.main.getCurrentDataSet().getSelected(); + int foundMatches = getSelection(s, sel, new Function(){ + public Boolean isSomething(OsmPrimitive o){ + return o.isSelected(); + } + }); + Main.main.getCurrentDataSet().setSelected(sel); + if (foundMatches == 0) { + String msg = null; + if (s.mode == SearchMode.replace) { + msg = tr("No match found for ''{0}''", s.text); + } else if (s.mode == SearchMode.add) { + msg = tr("Nothing added to selection by searching for ''{0}''", s.text); + } else if (s.mode == SearchMode.remove) { + msg = tr("Nothing removed from selection by searching for ''{0}''", s.text); + } else if (s.mode == SearchMode.in_selection) { + msg = tr("Nothing find in selection by searching for ''{0}''", s.text); + } + Main.map.statusLine.setHelpText(msg); + JOptionPane.showMessageDialog( + Main.parent, + msg, + tr("Warning"), + JOptionPane.WARNING_MESSAGE + ); + } else { + Main.map.statusLine.setHelpText(tr("Found {0} matches", foundMatches)); + } + } + public static class SearchSetting { - String text; - SearchMode mode; - boolean caseSensitive; - boolean regexSearch; + public String text; + public SearchMode mode; + public boolean caseSensitive; + public boolean regexSearch; - public SearchSetting(String text, boolean caseSensitive, boolean regexSearch, SearchMode mode) { + public SearchSetting(String text, SearchMode mode, boolean caseSensitive, boolean regexSearch) { super(); this.caseSensitive = caseSensitive; this.regexSearch = regexSearch; Index: src/org/openstreetmap/josm/actions/UnGlueAction.java =================================================================== --- src/org/openstreetmap/josm/actions/UnGlueAction.java (revision 2114) +++ src/org/openstreetmap/josm/actions/UnGlueAction.java (working copy) @@ -65,7 +65,7 @@ if (checkSelection(selection)) { int count = 0; for (Way w : getCurrentDataSet().ways) { - if (w.isDeleted() || w.incomplete || w.getNodesCount() < 1) { + if (w.isDeleted() || w.isDisabled() || w.incomplete || w.getNodesCount() < 1) { continue; } if (!w.containsNode(selectedNode)) { Index: src/org/openstreetmap/josm/actions/mapmode/DrawAction.java =================================================================== --- src/org/openstreetmap/josm/actions/mapmode/DrawAction.java (revision 2114) +++ src/org/openstreetmap/josm/actions/mapmode/DrawAction.java (working copy) @@ -766,7 +766,7 @@ public Way getWayForNode(Node n) { Way way = null; for (Way w : getCurrentDataSet().ways) { - if (w.isDeleted() || w.incomplete || w.getNodesCount() < 1) { + if (w.isDeleted() || w.isDisabled() || w.incomplete || w.getNodesCount() < 1) { continue; } Node firstNode = w.getNode(0); Index: src/org/openstreetmap/josm/actions/CombineWayAction.java =================================================================== --- src/org/openstreetmap/josm/actions/CombineWayAction.java (revision 2114) +++ src/org/openstreetmap/josm/actions/CombineWayAction.java (working copy) @@ -285,7 +285,7 @@ */ public void build(DataSet ds) { for (Relation r: ds.relations) { - if (r.isDeleted() || r.incomplete) { + if (r.isDeleted() || r.isDisabled() || r.incomplete) { continue; } Set referringWays = OsmPrimitive.getFilteredSet(r.getMemberPrimitives(), Way.class); Index: src/org/openstreetmap/josm/gui/SelectionManager.java =================================================================== --- src/org/openstreetmap/josm/gui/SelectionManager.java (revision 2114) +++ src/org/openstreetmap/josm/gui/SelectionManager.java (working copy) @@ -285,14 +285,14 @@ } else { // nodes for (Node n : nc.getCurrentDataSet().nodes) { - if (!n.isDeleted() && !n.incomplete && r.contains(nc.getPoint(n))) { + if (!n.isDeleted() && !n.incomplete && !n.isDisabled() && r.contains(nc.getPoint(n))) { selection.add(n); } } // ways for (Way w : nc.getCurrentDataSet().ways) { - if (w.isDeleted() || w.getNodesCount() == 0 || w.incomplete) { + if (w.isDeleted() || w.getNodesCount() == 0 || w.incomplete || w.isDisabled()) { continue; } if (alt) { Index: src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java =================================================================== --- src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java (revision 2114) +++ src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java (working copy) @@ -317,7 +317,7 @@ @Override public void visitBoundingBox(final BoundingXYVisitor v) { for (final Node n : data.nodes) - if (!n.isDeleted() && !n.incomplete) { + if (!n.isDeleted() && !n.isFiltered() && !n.incomplete) { v.visit(n); } } @@ -440,7 +440,7 @@ gpxData.storageFile = file; HashSet doneNodes = new HashSet(); for (Way w : data.ways) { - if (w.incomplete || w.isDeleted()) { + if (w.incomplete || w.isDeleted() || w.isFiltered()) { continue; } GpxTrack trk = new GpxTrack(); @@ -452,7 +452,7 @@ ArrayList trkseg = null; for (Node n : w.getNodes()) { - if (n.incomplete || n.isDeleted()) { + if (n.incomplete || w.isFiltered()) { trkseg = null; continue; } Index: src/org/openstreetmap/josm/gui/NavigatableComponent.java =================================================================== --- src/org/openstreetmap/josm/gui/NavigatableComponent.java (revision 2114) +++ src/org/openstreetmap/josm/gui/NavigatableComponent.java (working copy) @@ -306,7 +306,7 @@ if(ds == null) return null; for (Node n : ds.nodes) { - if (n.isDeleted() || n.incomplete) { + if (n.isDeleted() || n.incomplete || n.isDisabled()) { continue; } Point sp = getPoint(n); @@ -337,7 +337,7 @@ if(ds == null) return null; for (Way w : ds.ways) { - if (w.isDeleted() || w.incomplete) { + if (w.isDeleted() || w.incomplete || w.isDisabled()) { continue; } Node lastN = null; @@ -461,12 +461,12 @@ if(ds == null) return null; for (Way w : ds.ways) { - if (w.isDeleted() || w.incomplete) { + if (w.isDeleted() || w.incomplete || w.isDisabled()) { continue; } Node lastN = null; for (Node n : w.getNodes()) { - if (n.isDeleted() || n.incomplete) { + if (n.isDeleted() || n.incomplete || n.isDisabled()) { continue; } if (lastN == null) { @@ -487,7 +487,7 @@ } } for (Node n : ds.nodes) { - if (!n.isDeleted() && !n.incomplete + if (!n.isDeleted() && !n.incomplete && !n.isDisabled() && getPoint(n).distanceSq(p) < snapDistance) { nearest.add(n); } @@ -509,7 +509,7 @@ if(ds == null) return null; for (Node n : ds.nodes) { - if (!n.isDeleted() && !n.incomplete + if (!n.isDeleted() && !n.incomplete && !n.isDisabled() && getPoint(n).distanceSq(p) < snapDistance) { nearest.add(n); } Index: src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java =================================================================== --- src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java (revision 0) +++ src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java (revision 0) @@ -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(); + } +} Index: src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java =================================================================== --- src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java (revision 2114) +++ src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java (working copy) @@ -134,7 +134,7 @@ if (getNumRelations() > 0 ) { int i = 0; for (OsmPrimitive e : DataSet.sort(Main.main.getCurrentDataSet().relations)) { - if (!e.isDeleted() && !e.incomplete) { + if (!e.isDeleted() && !e.isFiltered() && !e.incomplete) { list.setElementAt(e, i++); } } Index: src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java =================================================================== --- src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java (revision 2114) +++ src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java (working copy) @@ -749,7 +749,7 @@ Map> roles = new HashMap>(); if (Main.main.getCurrentDataSet() != null) { for (Relation r : Main.main.getCurrentDataSet().relations) { - if (!r.isDeleted() && !r.incomplete) { + if (!r.isDeleted() && !r.isFiltered() && !r.isDisabled() && !r.incomplete) { for (RelationMember m : r.getMembers()) { if (newSelection.contains(m.getMember())) { Collection value = roles.get(r); Index: src/org/openstreetmap/josm/gui/MapFrame.java =================================================================== --- src/org/openstreetmap/josm/gui/MapFrame.java (revision 2114) +++ src/org/openstreetmap/josm/gui/MapFrame.java (working copy) @@ -28,6 +28,7 @@ import org.openstreetmap.josm.gui.dialogs.PropertiesDialog; import org.openstreetmap.josm.gui.dialogs.RelationListDialog; import org.openstreetmap.josm.gui.dialogs.SelectionListDialog; +import org.openstreetmap.josm.gui.dialogs.FilterDialog; import org.openstreetmap.josm.gui.dialogs.ToggleDialog; import org.openstreetmap.josm.gui.dialogs.UserListDialog; import org.openstreetmap.josm.tools.Destroyable; @@ -103,6 +104,7 @@ addToggleDialog(new PropertiesDialog(this)); addToggleDialog(new HistoryDialog()); addToggleDialog(new SelectionListDialog()); + addToggleDialog(new FilterDialog()); addToggleDialog(new UserListDialog()); addToggleDialog(conflictDialog = new ConflictDialog()); addToggleDialog(new CommandStackDialog(this)); Index: src/org/openstreetmap/josm/data/osm/Filters.java =================================================================== --- src/org/openstreetmap/josm/data/osm/Filters.java (revision 0) +++ src/org/openstreetmap/josm/data/osm/Filters.java (revision 0) @@ -0,0 +1,197 @@ +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; + +public class Filters extends AbstractTableModel{ + + public Filters(){ + loadPrefs(); + } + + private List filters = new LinkedList(); + public void filter(){ + Collection seld = new LinkedList (); + Collection self = new LinkedList (); + 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 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 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); + } + + + + @Override + public int getRowCount(){ + return filters.size(); + } + + @Override + public int getColumnCount(){ + return 6; + } + + @Override + public String getColumnName(int column){ + String[] names = { tr("F"), tr("D"), tr("Name"), tr("C"), tr("I"), tr("M") }; + return names[column]; + } + + @Override + public Class getColumnClass(int column){ + Class[] classes = { Boolean.class, Boolean.class, String.class, Boolean.class, Boolean.class, String.class }; + return classes[column]; + } + + @Override + public boolean isCellEditable(int row, int column){ + if(column < 5)return true; + return false; + } + @Override + 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; + } + } + + @Override + 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: src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java =================================================================== --- src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java (revision 2114) +++ src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java (working copy) @@ -148,7 +148,7 @@ require changing the colour while painting... */ //profilerN = 0; for (final OsmPrimitive osm : data.relations) - if (!osm.isDeleted() && !osm.isSelected()) + if (!osm.isDeleted() && !osm.isSelected() && !osm.isFiltered()) { osm.visit(this); // profilerN++; @@ -162,7 +162,7 @@ //profilerN = 0; for (final OsmPrimitive osm : data.ways) - if (!osm.isDeleted() && !osm.isSelected() && osm.isTagged()) + if (!osm.isDeleted() && !osm.isSelected() && !osm.isFiltered() && osm.isTagged()) { osm.visit(this); // profilerN++; @@ -170,7 +170,7 @@ displaySegments(); for (final OsmPrimitive osm : data.ways) - if (!osm.isDeleted() && !osm.isSelected() && !osm.isTagged()) + if (!osm.isDeleted() && !osm.isSelected() && !osm.isFiltered() && !osm.isTagged()) { osm.visit(this); // profilerN++; @@ -201,7 +201,7 @@ //profilerN = 0; for (final OsmPrimitive osm : data.nodes) - if (!osm.isDeleted() && !osm.isSelected()) + if (!osm.isDeleted() && !osm.isSelected() && !osm.isFiltered()) { osm.visit(this); // profilerN++; @@ -219,7 +219,7 @@ // profilerN = 0; currentColor = nodeColor; for (final OsmPrimitive osm : data.ways) - if (!osm.isDeleted()) + if (!osm.isDeleted() && !osm.isDisabled() && !osm.isFiltered()) { visitVirtual((Way)osm); // profilerN++; @@ -248,7 +248,7 @@ public void visit(Node n) { if (n.incomplete) return; - if (inactive) { + if (inactive || n.isDisabled()) { drawNode(n, inactiveColor, unselectedNodeSize, unselectedNodeRadius, fillUnselectedNode); } else if (n.highlighted) { drawNode(n, highlightColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode); @@ -311,7 +311,7 @@ boolean showOnlyHeadArrowOnly = showThisDirectionArrow && !w.isSelected() && showHeadArrowOnly; Color wayColor; - if (inactive) { + if (inactive || w.isDisabled()) { wayColor = inactiveColor; } else if(w.highlighted) { wayColor = highlightColor; @@ -344,7 +344,7 @@ if (r.incomplete) return; Color col; - if (inactive) { + if (inactive || r.isDisabled()) { col = inactiveColor; } else if (r.isSelected()) { col = selectedColor; Index: src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java =================================================================== --- src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java (revision 2114) +++ src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java (working copy) @@ -158,6 +158,8 @@ drawNode(n, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode); } else if (n.isTagged()) { drawNode(n, nodeColor, taggedNodeSize, taggedNodeRadius, fillUnselectedNode); + } else if (n.isDisabled()) { + drawNode(n, inactiveColor, unselectedNodeSize, unselectedNodeRadius, fillUnselectedNode); } else { drawNode(n, nodeColor, unselectedNodeSize, unselectedNodeRadius, fillUnselectedNode); } @@ -306,6 +308,8 @@ color = highlightColor; } else if(w.isSelected()) { color = selectedColor; + } else if(w.isDisabled()) { + color = inactiveColor; } /* draw overlays under the way */ @@ -529,7 +533,7 @@ { for (RelationMember m : r.getMembers()) { - if (m.isNode() && !m.getMember().incomplete && !m.getMember().isDeleted()) + if (m.isNode() && !m.getMember().incomplete && !m.getMember().isDeleted() && !m.getMember().isFiltered()) { drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember()) : null, true, true); } @@ -550,7 +554,7 @@ { for (RelationMember m : r.getMembers()) { - if (m.isWay() && !m.getMember().incomplete && !m.getMember().isDeleted()) /* nodes drawn on second call */ + if (m.isWay() && !m.getMember().incomplete && !m.getMember().isDeleted() && !m.getMember().isFiltered()) /* nodes drawn on second call */ { drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember()) : null, true, true); @@ -1394,7 +1398,7 @@ // profilerN = 0; for (final Relation osm : data.relations) { - if(!osm.isDeleted() && !osm.incomplete && osm.mappaintVisibleCode != viewid) + if(!osm.isDeleted() && !osm.isFiltered() && !osm.incomplete && osm.mappaintVisibleCode != viewid) { osm.visit(this); // profilerN++; @@ -1411,7 +1415,7 @@ // profilerN = 0; for (final Way osm : data.ways) { - if (!osm.incomplete && !osm.isDeleted() + if (!osm.incomplete && !osm.isDeleted() && !osm.isFiltered() && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid) { if(isPrimitiveArea(osm) && osm.mappaintDrawnAreaCode != paintid) @@ -1452,7 +1456,7 @@ /*** WAYS (filling disabled) ***/ // profilerN = 0; for (final OsmPrimitive osm : data.ways) - if (!osm.incomplete && !osm.isDeleted() && !osm.isSelected() + if (!osm.incomplete && !osm.isDeleted() && !osm.isFiltered() && !osm.isSelected() && osm.mappaintVisibleCode != viewid ) { osm.visit(this); @@ -1471,7 +1475,7 @@ selectedCall = true; //profilerN = 0; for (final OsmPrimitive osm : data.getSelected()) { - if (!osm.incomplete && !osm.isDeleted() && !(osm instanceof Node) + if (!osm.incomplete && !osm.isDeleted() && !osm.isFiltered() && !(osm instanceof Node) && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid) { osm.visit(this); @@ -1491,7 +1495,7 @@ /*** NODES ***/ //profilerN = 0; for (final OsmPrimitive osm : data.nodes) - if (!osm.incomplete && !osm.isDeleted() + if (!osm.incomplete && !osm.isDeleted() && !osm.isFiltered() && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid) { osm.visit(this); @@ -1511,7 +1515,7 @@ // profilerN = 0; currentColor = nodeColor; for (final OsmPrimitive osm : data.ways) - if (!osm.incomplete && !osm.isDeleted() + if (!osm.incomplete && !osm.isDeleted() && !osm.isDisabled() && !osm.isFiltered() && osm.mappaintVisibleCode != viewid ) { /* TODO: move this into the SimplePaint code? */ Index: src/org/openstreetmap/josm/data/osm/Filter.java =================================================================== --- src/org/openstreetmap/josm/data/osm/Filter.java (revision 0) +++ src/org/openstreetmap/josm/data/osm/Filter.java (revision 0) @@ -0,0 +1,48 @@ +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; + +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 (String) version + ";" + + text + ";" + mode + ";" + caseSensitive + ";" + regexSearch + ";" + + filterName + ";" + filtered + ";" + disabled + ";" + + inverted + ";" + applyForChildren; + } +} Index: src/org/openstreetmap/josm/data/osm/DataSet.java =================================================================== --- src/org/openstreetmap/josm/data/osm/DataSet.java (revision 2114) +++ src/org/openstreetmap/josm/data/osm/DataSet.java (working copy) @@ -183,6 +183,52 @@ return getSelected(relations); } + public void setFiltered(Collection selection) { + clearFiltered(nodes); + clearFiltered(ways); + clearFiltered(relations); + for (OsmPrimitive osm : selection) { + osm.setFiltered(true); + } + } + + public void setFiltered(OsmPrimitive... osm) { + if (osm.length == 1 && osm[0] == null) { + setFiltered(); + return; + } + clearFiltered(nodes); + clearFiltered(ways); + clearFiltered(relations); + for (OsmPrimitive o : osm) + if (o != null) { + o.setFiltered(true); + } + } + + public void setDisabled(Collection selection) { + clearDisabled(nodes); + clearDisabled(ways); + clearDisabled(relations); + for (OsmPrimitive osm : selection) { + osm.setDisabled(true); + } + } + + public void setDisabled(OsmPrimitive... osm) { + if (osm.length == 1 && osm[0] == null) { + setDisabled(); + return; + } + clearDisabled(nodes); + clearDisabled(ways); + clearDisabled(relations); + for (OsmPrimitive o : osm) + if (o != null) { + o.setDisabled(true); + } + } + public void setSelected(Collection selection) { clearSelection(nodes); clearSelection(ways); @@ -209,6 +255,29 @@ } /** + * Remove the filtered parameter from every value in the collection. + * @param list The collection to remove the filtered parameter from. + */ + private void clearFiltered(Collection list) { + if (list == null) + return; + for (OsmPrimitive osm : list) { + osm.setFiltered(false); + } + } + /** + * Remove the disabled parameter from every value in the collection. + * @param list The collection to remove the disabled parameter from. + */ + private void clearDisabled(Collection list) { + if (list == null) + return; + for (OsmPrimitive osm : list) { + osm.setDisabled(false); + } + } + + /** * Remove the selection from every value in the collection. * @param list The collection to remove the selection from. */ Index: src/org/openstreetmap/josm/data/osm/OsmPrimitive.java =================================================================== --- src/org/openstreetmap/josm/data/osm/OsmPrimitive.java (revision 2114) +++ src/org/openstreetmap/josm/data/osm/OsmPrimitive.java (working copy) @@ -123,6 +123,18 @@ private boolean visible = true; /** + * true, if the object has been set inactive + * + */ + public boolean disabled = false; + + /** + * true, if the object has been filtered out + * + */ + public boolean filtered = false; + + /** * User that last modified this primitive, as specified by the server. * Never changed by JOSM. */ @@ -174,6 +186,40 @@ /* ------------------------------------------------------------------------------------ */ /** + * Sets whether this primitive is disabled or not. + * + * @param selected true, if this primitive is disabled; false, otherwise + */ + public void setDisabled(boolean disabled) { + this.disabled = disabled; + } + + /** + * Replies true, if this primitive is disabled. + * + * @return true, if this primitive is disabled + */ + public boolean isDisabled() { + return disabled; + } + /** + * Sets whether this primitive is filtered out or not. + * + * @param selected true, if this primitive is filtered out; false, otherwise + */ + public void setFiltered(boolean filtered) { + this.filtered = filtered; + } + /** + * Replies true, if this primitive is filtered out. + * + * @return true, if this primitive is filtered out + */ + public boolean isFiltered() { + return filtered; + } + + /** * Sets whether this primitive is selected or not. * * @param selected true, if this primitive is selected; false, otherwise Index: images/dialogs/filter.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: images/dialogs/filter.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream