001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005import static org.openstreetmap.josm.tools.I18n.trc; 006 007import java.awt.Graphics2D; 008import java.util.Collection; 009import java.util.List; 010 011import javax.swing.table.AbstractTableModel; 012 013import org.openstreetmap.josm.data.osm.Filter; 014import org.openstreetmap.josm.data.osm.FilterModel; 015import org.openstreetmap.josm.data.osm.OsmPrimitive; 016import org.openstreetmap.josm.gui.MainApplication; 017import org.openstreetmap.josm.gui.MapFrame; 018import org.openstreetmap.josm.gui.autofilter.AutoFilterManager; 019import org.openstreetmap.josm.gui.widgets.OSDLabel; 020import org.openstreetmap.josm.tools.Logging; 021 022/** 023 * The model that is used for the table in the {@link FilterDialog}. 024 * 025 * @author Petr_DlouhĂ˝ 026 */ 027public class FilterTableModel extends AbstractTableModel { 028 029 /** 030 * The filter enabled column 031 */ 032 public static final int COL_ENABLED = 0; 033 /** 034 * The column indicating if the filter is hiding. 035 */ 036 public static final int COL_HIDING = 1; 037 /** 038 * The column that displays the filter text 039 */ 040 public static final int COL_TEXT = 2; 041 /** 042 * The column to invert the filter 043 */ 044 public static final int COL_INVERTED = 3; 045 046 /** 047 * The filter model 048 */ 049 final FilterModel model = new FilterModel(); 050 051 /** 052 * A helper for {@link #drawOSDText(Graphics2D)}. 053 */ 054 private final OSDLabel lblOSD = new OSDLabel(""); 055 056 /** 057 * Constructs a new {@code FilterTableModel}. 058 */ 059 public FilterTableModel() { 060 loadPrefs(); 061 } 062 063 private void updateFilters() { 064 AutoFilterManager.getInstance().setCurrentAutoFilter(null); 065 executeFilters(); 066 } 067 068 /** 069 * Runs the filters on the current edit data set. 070 */ 071 public void executeFilters() { 072 if (AutoFilterManager.getInstance().getCurrentAutoFilter() == null) { 073 model.executeFilters(); 074 updateMap(); 075 } 076 } 077 078 /** 079 * Runs the filter on a list of primitives that are part of the edit data set. 080 * @param primitives The primitives 081 */ 082 public void executeFilters(Collection<? extends OsmPrimitive> primitives) { 083 if (AutoFilterManager.getInstance().getCurrentAutoFilter() == null) { 084 model.executeFilters(primitives); 085 updateMap(); 086 } 087 } 088 089 private void updateMap() { 090 MapFrame map = MainApplication.getMap(); 091 if (map != null && model.isChanged()) { 092 map.filterDialog.updateDialogHeader(); 093 } 094 } 095 096 private void loadPrefs() { 097 model.loadPrefs("filters.entries"); 098 } 099 100 private void savePrefs() { 101 model.savePrefs("filters.entries"); 102 } 103 104 /** 105 * Adds a new filter to the filter list. 106 * @param filter The new filter 107 */ 108 public void addFilter(Filter filter) { 109 if (model.addFilter(filter)) { 110 savePrefs(); 111 updateFilters(); 112 int size = model.getFiltersCount(); 113 fireTableRowsInserted(size - 1, size - 1); 114 } 115 } 116 117 /** 118 * Moves down the filter in the given row. 119 * @param rowIndex The filter row 120 */ 121 public void moveDownFilter(int rowIndex) { 122 if (model.moveDownFilter(rowIndex)) { 123 savePrefs(); 124 updateFilters(); 125 fireTableRowsUpdated(rowIndex, rowIndex + 1); 126 } 127 } 128 129 /** 130 * Moves up the filter in the given row 131 * @param rowIndex The filter row 132 */ 133 public void moveUpFilter(int rowIndex) { 134 if (model.moveUpFilter(rowIndex)) { 135 savePrefs(); 136 updateFilters(); 137 fireTableRowsUpdated(rowIndex - 1, rowIndex); 138 } 139 } 140 141 /** 142 * Removes the filter that is displayed in the given row 143 * @param rowIndex The index of the filter to remove 144 */ 145 public void removeFilter(int rowIndex) { 146 if (model.removeFilter(rowIndex) != null) { 147 savePrefs(); 148 updateFilters(); 149 fireTableRowsDeleted(rowIndex, rowIndex); 150 } 151 } 152 153 /** 154 * Sets/replaces the filter for a given row. 155 * @param rowIndex The row index 156 * @param filter The filter that should be placed in that row 157 */ 158 public void setFilter(int rowIndex, Filter filter) { 159 model.setFilter(rowIndex, filter); 160 savePrefs(); 161 updateFilters(); 162 fireTableRowsUpdated(rowIndex, rowIndex); 163 } 164 165 /** 166 * Gets the filter by row index 167 * @param rowIndex The row index 168 * @return The filter in that row 169 */ 170 public Filter getFilter(int rowIndex) { 171 return model.getFilter(rowIndex); 172 } 173 174 @Override 175 public int getRowCount() { 176 return model.getFiltersCount(); 177 } 178 179 @Override 180 public int getColumnCount() { 181 return 5; 182 } 183 184 @Override 185 public String getColumnName(int column) { 186 String[] names = {/* translators notes must be in front */ 187 /* column header: enable filter */trc("filter", "E"), 188 /* column header: hide filter */trc("filter", "H"), 189 /* column header: filter text */trc("filter", "Text"), 190 /* column header: inverted filter */trc("filter", "I"), 191 /* column header: filter mode */trc("filter", "M")}; 192 return names[column]; 193 } 194 195 @Override 196 public Class<?> getColumnClass(int column) { 197 Class<?>[] classes = {Boolean.class, Boolean.class, String.class, Boolean.class, String.class}; 198 return classes[column]; 199 } 200 201 /** 202 * Determines if a cell is enabled. 203 * @param row row index 204 * @param column column index 205 * @return {@code true} if the cell at (row, column) is enabled 206 */ 207 public boolean isCellEnabled(int row, int column) { 208 return model.getFilter(row).enable || column == 0; 209 } 210 211 @Override 212 public boolean isCellEditable(int row, int column) { 213 return column < 4 && isCellEnabled(row, column); 214 } 215 216 @Override 217 public void setValueAt(Object aValue, int row, int column) { 218 if (row >= model.getFiltersCount()) { 219 return; 220 } 221 Filter f = model.getFilter(row); 222 switch (column) { 223 case COL_ENABLED: 224 f.enable = (Boolean) aValue; 225 setFilter(row, f); 226 break; 227 case COL_HIDING: 228 f.hiding = (Boolean) aValue; 229 setFilter(row, f); 230 break; 231 case COL_TEXT: 232 f.text = (String) aValue; 233 savePrefs(); 234 break; 235 case COL_INVERTED: 236 f.inverted = (Boolean) aValue; 237 setFilter(row, f); 238 break; 239 default: // Do nothing 240 } 241 if (column != 0) { 242 fireTableCellUpdated(row, column); 243 } 244 } 245 246 @Override 247 public Object getValueAt(int row, int column) { 248 if (row >= model.getFiltersCount()) { 249 return null; 250 } 251 Filter f = model.getFilter(row); 252 switch (column) { 253 case COL_ENABLED: 254 return f.enable; 255 case COL_HIDING: 256 return f.hiding; 257 case COL_TEXT: 258 return f.text; 259 case COL_INVERTED: 260 return f.inverted; 261 case 4: 262 switch (f.mode) { /* translators notes must be in front */ 263 case replace: /* filter mode: replace */ 264 return trc("filter", "R"); 265 case add: /* filter mode: add */ 266 return trc("filter", "A"); 267 case remove: /* filter mode: remove */ 268 return trc("filter", "D"); 269 case in_selection: /* filter mode: in selection */ 270 return trc("filter", "F"); 271 default: 272 Logging.warn("Unknown filter mode: " + f.mode); 273 } 274 break; 275 default: // Do nothing 276 } 277 return null; 278 } 279 280 /** 281 * Draws a text on the map display that indicates that filters are active. 282 * @param g The graphics to draw that text on. 283 */ 284 public void drawOSDText(Graphics2D g) { 285 model.drawOSDText(g, lblOSD, 286 tr("<h2>Filter active</h2>"), 287 tr("</p><p>Close the filter dialog to see all objects.<p></html>")); 288 } 289 290 /** 291 * Returns the list of filters. 292 * @return the list of filters 293 */ 294 public List<Filter> getFilters() { 295 return model.getFilters(); 296 } 297}