/* * ARX: Powerful Data Anonymization * Copyright 2012 - 2017 Fabian Prasser, Florian Kohlmayer and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.deidentifier.arx.gui.view.impl.explore; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import org.deidentifier.arx.ARXLattice; import org.deidentifier.arx.ARXLattice.ARXNode; import org.deidentifier.arx.ARXResult; import org.deidentifier.arx.gui.Controller; import org.deidentifier.arx.gui.model.ModelEvent; import org.deidentifier.arx.gui.model.ModelEvent.ModelPart; import org.deidentifier.arx.gui.model.ModelNodeFilter; 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.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import cern.colt.Arrays; import de.linearbits.swt.tiles.DecoratorColor; import de.linearbits.swt.tiles.DecoratorInteger; import de.linearbits.swt.tiles.DecoratorString; import de.linearbits.swt.tiles.Filter; import de.linearbits.swt.tiles.TileLayoutDynamic; import de.linearbits.swt.tiles.Tiles; /** * This class implements a tiles view on selected nodes. * * @author Fabian Prasser * @author Florian Kohlmayer */ public class ViewTiles extends ViewSolutionSpace { /** The tiles. */ private final Tiles<ARXNode> tiles; /** Config */ private static final int NUM_COLUMNS = 10; /** Config */ private static final int NUM_ROWS = 20; /** Config */ private static final int MARGIN = 5; /** * Constructor * * @param parent * @param controller */ public ViewTiles(final Composite parent, final Controller controller) { // Super class super(parent, controller); tiles = new Tiles<ARXNode>(super.getPrimaryComposite(), SWT.BORDER); tiles.setLayoutData(SWTUtil.createFillGridData()); // Selection listener tiles.addSelectionListener(new SelectionAdapter(){ public void widgetSelected(SelectionEvent arg0) { ViewTiles.this.actionSelectNode(tiles.getSelectedItem()); } }); // Show menu tiles.addMouseListener(new MouseAdapter(){ @Override public void mouseUp(MouseEvent arg0) { if (arg0.button == 3) { if (getSelectedNode() != null) { Point display = tiles.toDisplay(arg0.x, arg0.y); getModel().setSelectedNode(getSelectedNode()); controller.update(new ModelEvent(ViewTiles.this, ModelPart.SELECTED_NODE, getSelectedNode())); actionShowMenu(display.x, display.y); } } } }); // Set layout tiles.setTileLayout(new TileLayoutDynamic(NUM_COLUMNS, NUM_ROWS, MARGIN, MARGIN)); tiles.setComparator(new Comparator<ARXNode>() { public int compare(ARXNode o1, ARXNode o2) { boolean unknown2 = o2.getLowestScore().compareTo(o2.getHighestScore())!=0 && asRelativeValue(o2.getLowestScore())==0d; boolean unknown1 = o1.getLowestScore().compareTo(o1.getHighestScore())!=0 && asRelativeValue(o1.getLowestScore())==0d; if (unknown1 && unknown2) return 0; else if (unknown1 && !unknown2) return +1; else if (!unknown1 && unknown2) return -1; else { try { int c1 = o1.getLowestScore().compareTo(o2.getLowestScore()); return c1 != 0 ? c1 : o1.getHighestScore().compareTo(o2.getHighestScore()); } catch (Exception e) { return 0; } } } }); tiles.setFilter(new Filter<ARXNode>() { public boolean accepts(ARXNode arg0) { return true; } }); tiles.setDecoratorLabel(new DecoratorString<ARXNode>() { @Override public String decorate(ARXNode node) { String text = Arrays.toString(node.getTransformation()); text = text.substring(1, text.length() - 1); return trimLabel(text); } }); tiles.setDecoratorBackgroundColor(createDecoratorBackgroundColor()); tiles.setDecoratorTooltip(super.getTooltipDecorator()); tiles.setDecoratorLineColor(createDecoratorLineColor()); tiles.setDecoratorLineWidth(createDecoratorLineWidth()); tiles.setBackground(tiles.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); tiles.update(); } /** * Resets the view. */ @Override public void reset() { super.reset(); tiles.setRedraw(false); tiles.setItems(new ArrayList<ARXNode>()); tiles.setRedraw(true); tiles.setFilter(new Filter<ARXNode>() { public boolean accepts(ARXNode arg0) { return true; } }); tiles.update(); SWTUtil.disable(tiles); } /** * Creates a background decorator * @return */ private DecoratorColor<ARXNode> createDecoratorBackgroundColor() { DecoratorColor<ARXNode> decorator = new DecoratorColor<ARXNode>() { @Override public Color decorate(ARXNode element) { return ViewTiles.this.getUtilityColor(element); } }; return decorator; } /** * Creates a decorator * @return */ private DecoratorColor<ARXNode> createDecoratorLineColor() { return new DecoratorColor<ARXNode>() { @Override public Color decorate(ARXNode node) { return getInnerColor(node); } }; } /** * Creates a decorator * @return */ private DecoratorInteger<ARXNode> createDecoratorLineWidth() { return new DecoratorInteger<ARXNode>() { @Override public Integer decorate(ARXNode node) { return getOuterStrokeWidth(node, (tiles.getSize().x - NUM_COLUMNS * MARGIN) / NUM_COLUMNS); } }; } /** * Updates the filter * * @param lattice * @param filter */ private void updateFilter(final ARXLattice lattice, final ModelNodeFilter filter) { if (filter == null) return; final ModelNodeFilter filterClone = filter.clone(); getController().getResources().getDisplay().asyncExec(new Runnable() { public void run() { tiles.setFilter(new Filter<ARXNode>() { public boolean accepts(ARXNode node) { return filterClone.isAllowed(lattice, node); } }); tiles.update(); } }); } /** * Updates the lattice * * @param lattice */ private void updateLattice(final ARXLattice lattice) { if (lattice == null) { reset(); return; } getController().getResources().getDisplay().asyncExec(new Runnable() { @Override public void run() { SWTUtil.enable(tiles); tiles.setRedraw(true); List<ARXNode> list = new ArrayList<ARXNode>(); for (final ARXNode[] level : lattice.getLevels()) { for (final ARXNode node : level) { list.add(node); } } // Set tiles.setItems(list); // Draw tiles.update(); } }); } @Override protected void actionRedraw() { this.tiles.redraw(); } @Override protected void eventFilterChanged(ARXResult result, ModelNodeFilter filter) { if (getModel() != null && result != null) { updateFilter(result.getLattice(), filter); } else { reset(); } } @Override protected void eventModelChanged() { if (getModel() != null && getModel().getResult() != null) { updateLattice(getModel().getResult().getLattice()); updateFilter(getModel().getResult().getLattice(), getModel().getNodeFilter()); } } @Override protected void eventNodeSelected() { tiles.setSelectedItem(super.getSelectedNode()); } @Override protected void eventResultChanged(ARXResult result) { if (result == null) { reset(); } else { updateLattice(result.getLattice()); } } }