/* * ARX: Powerful Data Anonymization * Copyright 2012 - 2017 Fabian Prasser, Florian Kohlmayer and contributors * * Licensed 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.deidentifier.arx.gui.view.impl.common; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.deidentifier.arx.gui.Controller; import org.deidentifier.arx.gui.resources.Resources; import org.deidentifier.arx.gui.view.SWTUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; /** * This class implements a table, in which properties can be filtered. * * @author Fabian Prasser */ public class ComponentFilterTable { /** Constant. */ private static final int LABEL_WIDTH = 100; /** Constant. */ private static final int CHECKBOX_WIDTH = 20; /** Image. */ private final Image IMAGE_ENABLED; /** Image. */ private final Image IMAGE_DISABLED; /** Widget. */ private final Table table; /** Widgets. */ private Map<String, TableItem> items; /** The registered listeners. */ private List<SelectionListener> listeners; /** The selection map. */ private Map<String, Map<String, Boolean>> selected; /** The list of properties. */ private Map<String, List<String>> itemProperties; /** The list of properties. */ private List<String> properties; /** The list of entries. */ private List<String> entries; /** Selected entry. */ private String selectedEntry = null; /** Selected property. */ private String selectedProperty = null; /** * Creates a new instance. * * @param parent * @param controller * @param properties */ public ComponentFilterTable(Composite parent, Controller controller, List<String> properties) { IMAGE_ENABLED = controller.getResources().getManagedImage("tick.png"); //$NON-NLS-1$ IMAGE_DISABLED = controller.getResources().getManagedImage("cross.png"); //$NON-NLS-1$ this.listeners = new ArrayList<SelectionListener>(); this.selected = new HashMap<String, Map<String, Boolean>>(); this.properties = new ArrayList<String>(properties); this.entries = new ArrayList<String>(); this.items = new HashMap<String, TableItem>(); this.itemProperties = new HashMap<String, List<String>>(); this.table = SWTUtil.createTable(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); this.table.setHeaderVisible(true); this.setProperties(properties); table.addMouseListener(new MouseAdapter(){ public void mouseDown(MouseEvent arg0) { int row = getItemRowAt(arg0.x, arg0.y); int column = getItemColumnAt(arg0.x, arg0.y); if (row != -1 && column > 0 && column <= ComponentFilterTable.this.properties.size()) { String property = ComponentFilterTable.this.properties.get(column-1); String entry = ComponentFilterTable.this.entries.get(row); if (itemProperties.get(entry).contains(property)) { selectedProperty = property; selectedEntry = entry; } else { selectedProperty = null; selectedEntry = null; } } else { selectedProperty = null; selectedEntry = null; } } }); table.addMouseListener(new MouseAdapter(){ public void mouseDown(MouseEvent arg0) { if (selectedProperty != null && selectedEntry != null) { boolean selected = isSelected(selectedEntry, selectedProperty); setSelected(selectedEntry, selectedProperty, !selected); fireSelectionEvent(); } } }); } /** * Adds a new entry, i.e., a row in the table * * @param entry * @param properties */ public void addEntry(String entry, List<String> properties) { if (!this.properties.containsAll(properties)) { throw new RuntimeException(Resources.getMessage("ComponentFilterTable.2")); //$NON-NLS-1$ } TableItem item = new TableItem(table, SWT.NONE); for (int i = 0; i < this.properties.size(); i++) { if (properties.contains(this.properties.get(i))) { item.setImage(i + 1, IMAGE_DISABLED); } } item.setImage(0, null); item.setText(0, entry); this.items.put(entry, item); this.itemProperties.put(entry, properties); this.entries.add(entry); table.redraw(); for (TableColumn c : table.getColumns()) { c.pack(); } } /** * Adds a selection listener. * * @param listener */ public void addSelectionListener(SelectionListener listener) { this.listeners.add(listener); } /** * Clears the table. */ public void clear() { this.table.setRedraw(false); for (TableItem item : table.getItems()) { item.dispose(); } for (TableColumn column : table.getColumns()) { column.dispose(); } this.table.removeAll(); this.table.setRedraw(true); this.table.redraw(); this.items.clear(); this.itemProperties.clear(); this.properties.clear(); this.entries.clear(); this.selected.clear(); } /** * Disposes this widget. */ public void dispose() { this.table.dispose(); } /** * Returns the entries. * * @return */ public List<String> getEntries() { return entries; } /** * Returns the properties. * * @return */ public List<String> getProperties() { return properties; } /** * Returns the currently selected entry. * * @return */ public String getSelectedEntry() { return selectedEntry; } /** * Returns the currently selected property. * * @return */ public String getSelectedProperty() { return selectedProperty; } /** * Returns whether the given property is selected for the given entry. * * @param entry * @param property * @return */ public boolean isSelected(String entry, String property) { if (!this.entries.contains(entry)) { throw new RuntimeException(Resources.getMessage("ComponentFilterTable.3")); //$NON-NLS-1$ } if (!this.properties.contains(property)) { throw new RuntimeException(Resources.getMessage("ComponentFilterTable.4")); //$NON-NLS-1$ } Map<String, Boolean> map = selected.get(entry); if (map == null) { return false; } else { Boolean b = map.get(property); return b == null ? false : b; } } /** * Removes a selection listener. * * @param listener */ public void removeSelectionListener(SelectionListener listener) { this.listeners.remove(listener); } /** * Enable/disable. * * @param enabled */ public void setEnabled(boolean enabled) { this.table.setEnabled(enabled); } /** * Sets layout data. * * @param layoutData */ public void setLayoutData(Object layoutData) { this.table.setLayoutData(layoutData); } /** * Sets new properties. Clears the table * @param properties */ public void setProperties(List<String> properties) { this.clear(); this.properties = new ArrayList<String>(properties); TableColumn column = new TableColumn(table, SWT.LEFT); column.setWidth(LABEL_WIDTH); column.setText(""); //$NON-NLS-1$ for (String property : properties) { column = new TableColumn(table, SWT.CENTER); column.setText(property); column.setWidth(CHECKBOX_WIDTH); } column = new TableColumn(table, SWT.LEFT); column.setText(""); //$NON-NLS-1$ } /** * Sets the given property selected for the given entry . * * @param entry * @param property * @param selected */ public void setSelected(String entry, String property, boolean selected) { if (!this.entries.contains(entry)) { return; } if (!this.properties.contains(property)) { return; } if (!this.selected.containsKey(entry)) { this.selected.put(entry, new HashMap<String, Boolean>()); } if (this.itemProperties.get(entry).contains(property)) { this.selected.get(entry).put(property, selected); int index = properties.indexOf(property); this.items.get(entry).setImage(index + 1, selected ? IMAGE_ENABLED : IMAGE_DISABLED); table.redraw(); } } /** * Fires a new event. */ private void fireSelectionEvent() { Event event = new Event(); event.display = table.getDisplay(); event.item = table; event.widget = table; SelectionEvent sEvent = new SelectionEvent(event); for (SelectionListener listener : listeners) { listener.widgetSelected(sEvent); } } /** * Returns the item at the given location. * * @param x * @param y * @return */ private int getItemColumnAt(int x, int y) { Point pt = new Point(x, y); int index = table.getTopIndex(); while (index < table.getItemCount()) { final TableItem item = table.getItem(index); for (int i = 0; i < table.getColumns().length; i++) { final Rectangle rect = item.getBounds(i); if (rect.contains(pt)) { return i; } } index++; } return -1; } /** * Returns the item at the given location. * * @param x * @param y * @return */ private int getItemRowAt(int x, int y) { Point pt = new Point(x, y); int index = table.getTopIndex(); while (index < table.getItemCount()) { final TableItem item = table.getItem(index); for (int i = 0; i < table.getColumns().length; i++) { final Rectangle rect = item.getBounds(i); if (rect.contains(pt)) { return index; } } index++; } return -1; } }