/*
* 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.wizard;
import org.deidentifier.arx.aggregates.AggregateFunction;
import org.deidentifier.arx.gui.resources.Resources;
import org.deidentifier.arx.gui.view.SWTUtil;
import org.deidentifier.arx.gui.view.impl.wizard.HierarchyWizard.HierarchyWizardView;
import org.deidentifier.arx.gui.view.impl.wizard.HierarchyWizardEditorFunction.IHierarchyFunctionEditorParent;
import org.deidentifier.arx.gui.view.impl.wizard.HierarchyWizardEditorRenderer.RenderedComponent;
import org.deidentifier.arx.gui.view.impl.wizard.HierarchyWizardEditorRenderer.RenderedGroup;
import org.deidentifier.arx.gui.view.impl.wizard.HierarchyWizardEditorRenderer.RenderedInterval;
import org.deidentifier.arx.gui.view.impl.wizard.HierarchyWizardModelGrouping.HierarchyWizardGroupingGroup;
import org.deidentifier.arx.gui.view.impl.wizard.HierarchyWizardModelGrouping.HierarchyWizardGroupingInterval;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
/**
* The general editor for hierarchies.
*
* @author Fabian Prasser
* @param <T>
*/
public class HierarchyWizardEditor<T> implements HierarchyWizardView, IHierarchyFunctionEditorParent<T> {
/** Var. */
private HierarchyWizardModelGrouping<T> model;
/** Var. */
private Composite composite;
/** Var. */
private Composite canvascomposite;
/** Var. */
private ScrolledComposite scrolledcomposite;
/** Var. */
private CTabFolder folder;
/** Var. */
private HierarchyWizardEditorMenu<T> menu;
/** Var. */
private HierarchyWizardEditorFunction<T> editor;
/**
* Creates a new instance.
*
* @param parent
* @param model
*/
public HierarchyWizardEditor(Composite parent, HierarchyWizardModelGrouping<T> model) {
this.model = model;
this.model.register(this);
this.composite = new Composite(parent, SWT.NONE);
this.composite.setLayoutData(SWTUtil.createFillGridData());
this.composite.setLayout(SWTUtil.createGridLayout(1));
this.scrolledcomposite = new ScrolledComposite(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
this.scrolledcomposite.setMinSize(200, 200);
this.scrolledcomposite.setExpandHorizontal(true);
this.scrolledcomposite.setExpandVertical(true);
this.scrolledcomposite.setLayoutData(SWTUtil.createFillGridData());
this.canvascomposite = new Composite(scrolledcomposite, SWT.NONE);
this.scrolledcomposite.setContent(canvascomposite);
this.canvascomposite.addPaintListener(new PaintListener(){
@Override
public void paintControl(PaintEvent e){
paint(e.gc);
}
});
this.canvascomposite.addMouseListener(new MouseAdapter(){
@Override public void mouseUp(MouseEvent arg0) {
if (HierarchyWizardEditor.this.model.getRenderer().select(arg0.x, arg0.y)){
HierarchyWizardEditor.this.model.updateUI(HierarchyWizardEditor.this);
canvascomposite.redraw();
Object selected = HierarchyWizardEditor.this.model.getSelectedElement();
if (selected instanceof HierarchyWizardGroupingInterval){
if (HierarchyWizardEditor.this.model.isShowIntervals()) folder.setSelection(2);
} else if (selected instanceof HierarchyWizardGroupingGroup){
if (HierarchyWizardEditor.this.model.isShowIntervals()) folder.setSelection(3);
else folder.setSelection(1);
}
}
if ((arg0.stateMask & SWT.BUTTON3) != 0 && HierarchyWizardEditor.this.model.getSelectedElement() != null){
menu.show(arg0.x, arg0.y);
}
}
});
this.menu = new HierarchyWizardEditorMenu<T>(canvascomposite, model);
this.folder = new CTabFolder(composite, SWT.BORDER);
this.folder.setSimple(false);
this.folder.setLayoutData(SWTUtil.createFillHorizontallyGridData());
this.createGeneralTab(folder);
if (model.isShowIntervals()) this.createRangeTab(folder);
if (model.isShowIntervals()) this.createIntervalTab(folder);
this.createGroupTab(folder);
this.folder.setSelection(0);
this.model.update();
}
@Override
public void setFunction(AggregateFunction<T> function) {
model.setDefaultFunction(function);
editor.setFunction(function);
model.update();
}
/**
* Set the controls layout data.
*
* @param object
*/
public void setLayoutData(Object object){
this.composite.setLayoutData(object);
}
@Override
public void update() {
this.canvascomposite.redraw();
this.editor.update();
}
/**
* Create a tab.
*
* @param tabFolder
*/
private void createGeneralTab(CTabFolder tabFolder) {
CTabItem tabItem1 = new CTabItem(tabFolder, SWT.NULL);
tabItem1.setText(Resources.getMessage("HierarchyWizardEditor.0")); //$NON-NLS-1$
Composite parent = new Composite(tabFolder, SWT.NULL);
parent.setLayout(SWTUtil.createGridLayout(2, false));
parent.setLayoutData(SWTUtil.createFillHorizontallyGridData());
editor = new HierarchyWizardEditorFunction<T>(this, model, parent, true);
editor.setFunction(model.getDefaultFunction());
tabItem1.setControl(parent);
}
/**
* Create a tab.
*
* @param tabFolder
*/
private void createGroupTab(CTabFolder tabFolder) {
CTabItem tabItem3 = new CTabItem(tabFolder, SWT.NULL);
tabItem3.setText(Resources.getMessage("HierarchyWizardEditor.1")); //$NON-NLS-1$
Composite parent = new Composite(tabFolder, SWT.NULL);
parent.setLayout(SWTUtil.createGridLayout(1, false));
new HierarchyWizardEditorGroup<T>(parent, model);
tabItem3.setControl(parent);
}
/**
* Create a tab.
*
* @param tabFolder
*/
private void createIntervalTab(CTabFolder tabFolder) {
CTabItem tabItem2 = new CTabItem(tabFolder, SWT.NULL);
tabItem2.setText(Resources.getMessage("HierarchyWizardEditor.2")); //$NON-NLS-1$
Composite parent = new Composite(tabFolder, SWT.NULL);
parent.setLayout(SWTUtil.createGridLayout(2, false));
new HierarchyWizardEditorInterval<T>(parent, model);
tabItem2.setControl(parent);
}
/**
* Create a tab.
*
* @param tabFolder
*/
private void createRangeTab(CTabFolder tabFolder) {
CTabItem tabItem4 = new CTabItem(tabFolder, SWT.NULL);
tabItem4.setText(Resources.getMessage("HierarchyWizardEditor.3")); //$NON-NLS-1$
Composite parent = new Composite(tabFolder, SWT.NULL);
parent.setLayout(SWTUtil.createGridLayout(2, false));
new HierarchyWizardEditorRange<T>(parent, model, true);
new HierarchyWizardEditorRange<T>(parent, model, false);
tabItem4.setControl(parent);
}
/**
* Draws a string.
*
* @param gc
* @param string
* @param r
*/
private void drawString(GC gc, String string, Rectangle r) {
gc.setFont(HierarchyWizardEditorRenderer.FONT);
Point extent = gc.textExtent(string);
int xx = r.x + (r.width - extent.x) / 2;
int yy = r.y + (r.height - extent.y) / 2;
gc.drawText(string, xx, yy, true);
}
/**
* Is the component selected.
*
* @param component
* @return
*/
private boolean isSelected(RenderedComponent<T> component) {
if (model.getSelectedElement() == null) return false;
if (component instanceof RenderedInterval) {
return ((RenderedInterval<T>)component).interval.equals(model.getSelectedElement());
} else {
return ((RenderedGroup<T>)component).group.equals(model.getSelectedElement());
}
}
/**
* Paints the intervals and fanouts.
*
* @param gc
*/
protected void paint(GC gc) {
model.getRenderer().update(gc);
gc.setBackground(HierarchyWizardEditorRenderer.WIDGET_BACKGROUND);
Point size = canvascomposite.getSize();
gc.fillRectangle(0, 0, size.x, size.y);
for (RenderedComponent<T> component : model.getRenderer().getComponents()) {
Color foreground = HierarchyWizardEditorRenderer.NORMAL_FOREGROUND;
Color alternative = HierarchyWizardEditorRenderer.ALTERNATIVE_FOREGROUND;
Color background = HierarchyWizardEditorRenderer.NORMAL_BACKGROUND;
if (isSelected(component)) {
background = HierarchyWizardEditorRenderer.SELECTED_BACKGROUND;
alternative = background;
}
if (!component.enabled) {
foreground = HierarchyWizardEditorRenderer.DISABLED_FOREGROUND;
background = HierarchyWizardEditorRenderer.DISABLED_BACKGROUND;
alternative = background;
}
gc.setBackground(background);
gc.fillRectangle(component.rectangle1);
gc.setForeground(foreground);
gc.drawRectangle(component.rectangle1);
drawString(gc, component.bounds, component.rectangle1);
gc.setBackground(foreground);
gc.fillRectangle(component.rectangle2);
gc.drawRectangle(component.rectangle2);
gc.setForeground(alternative);
drawString(gc, component.label, component.rectangle2);
}
scrolledcomposite.setMinSize(model.getRenderer().getMinSize());
}
}