/*
* 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.Iterator;
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.deidentifier.arx.gui.view.def.IComponent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabFolder2Adapter;
import org.eclipse.swt.custom.CTabFolderEvent;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionAdapter;
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.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
/**
* This class implements a titled folder.
*
* @author Fabian Prasser
*/
public class ComponentTitledFolder implements IComponent {
/**
* An entry in a folder
*
* @author Fabian Prasser
*/
private class TitledFolderEntry {
/** Field */
private String text;
/** Field */
private Control control;
/** Field */
private Image image;
/** Field */
private int index;
/** Field */
private boolean hideable;
/**
* Creates a new instance
* @param text
* @param control
* @param image
* @param index
* @param hideable
*/
public TitledFolderEntry(String text, Control control, Image image, int index, boolean hideable) {
this.text = text;
this.control = control;
this.image = image;
this.index = index;
this.hideable = hideable;
}
}
/** Entries*/
private List<TitledFolderEntry> entries = new ArrayList<TitledFolderEntry>();
/** The folder */
private final CTabFolder folder;
/** Flag */
private final boolean supportsHidingElements;
/** Listener */
private SelectionListener itemVisibilityListener;
/**
* Creates a new instance.
*
* @param parent
* @param controller
* @param bar
* @param id
*/
public ComponentTitledFolder(Composite parent, Controller controller, ComponentTitledFolderButtonBar bar, String id){
this(parent, controller, bar, id, null, false, false);
}
/**
* Creates a new instance.
*
* @param parent
* @param controller
* @param bar
* @param id
* @param bottom
*/
public ComponentTitledFolder(Composite parent,
Controller controller,
ComponentTitledFolderButtonBar bar,
String id,
boolean bottom,
boolean supportsHidingElements){
this(parent, controller, bar, id, null, bottom, supportsHidingElements);
}
/**
* Creates a new instance.
*
* @param parent
* @param controller
* @param bar
* @param id
* @param helpids
*/
public ComponentTitledFolder(Composite parent, Controller controller, ComponentTitledFolderButtonBar bar, String id, Map<Composite, String> helpids){
this(parent, controller, bar, id, helpids, false, false);
}
/**
* Creates a new instance.
*
* @param parent
* @param controller
* @param bar
* @param id
* @param bottom
*/
public ComponentTitledFolder(Composite parent,
Controller controller,
ComponentTitledFolderButtonBar bar,
String id,
Map<Composite, String> helpids,
boolean bottom,
boolean supportsHidingElements){
int flags = SWT.BORDER | SWT.FLAT;
if (bottom) flags |= SWT.BOTTOM;
else flags |= SWT.TOP;
this.supportsHidingElements = supportsHidingElements;
this.folder = new CTabFolder(parent, flags);
this.folder.setUnselectedCloseVisible(false);
this.folder.setSimple(false);
// Create help button
if (bar == null) SWTUtil.createHelpButton(controller, folder, id, helpids);
else createBar(controller, folder, bar);
// Prevent closing
this.folder.addCTabFolder2Listener(new CTabFolder2Adapter() {
@Override
public void close(final CTabFolderEvent event) {
event.doit = false;
}
});
}
/**
* @param arg0
* @param arg1
* @see org.eclipse.swt.widgets.Widget#addListener(int, org.eclipse.swt.widgets.Listener)
*/
public void addListener(int arg0, Listener arg1) {
folder.addListener(arg0, arg1);
}
/**
* Adds a selection listener.
*
* @param listener
*/
public void addSelectionListener(SelectionListener listener) {
folder.addSelectionListener(listener);
}
/**
* Creates a new entry in the folder.
*
* @param title
* @param image
* @return
*/
public Composite createItem(String title, Image image){
return createItem(title, image, getItemCount(), false);
}
/**
* Creates a new entry in the folder.
*
* @param title
* @param image
* @param hideable
* @return
*/
public Composite createItem(String title, Image image, boolean hideable){
return createItem(title, image, getItemCount(), hideable);
}
/**
* Creates a new entry in the folder.
*
* @param title
* @param image
* @param index
* @param hideable
* @return
*/
public Composite createItem(String title, Image image, int index, boolean hideable){
Composite composite = new Composite(folder, SWT.NONE);
composite.setLayout(new GridLayout());
CTabItem item = new CTabItem(folder, SWT.NULL, index);
item.setText(title);
if (image!=null) item.setImage(image);
item.setShowClose(false);
item.setControl(composite);
entries.add(new TitledFolderEntry(title, composite, image, index, hideable));
return composite;
}
/**
* Disposes the given item.
*
* @param text
*/
public void disposeItem(String text) {
for (CTabItem item : folder.getItems()) {
if (item.getText().equals(text)) {
item.dispose();
}
}
}
/**
* Returns the button item for the given text.
*
* @param text
* @return
*/
public ToolItem getButtonItem(String text) {
Control c = folder.getTopRight();
if (c == null) return null;
if (!(c instanceof ToolBar)) return null;
ToolBar t = (ToolBar)c;
for (ToolItem i : t.getItems()){
if (i.getToolTipText().equals(text)) return i;
}
return null;
}
/**
* Returns the number of items in the folder.
*
* @return
*/
public int getItemCount() {
return folder.getItemCount();
}
/**
* Returns the selected control
* @return
*/
public Control getSelectedControl() {
return folder.getSelection().getControl();
}
/**
* Returns the currently selected index.
*
* @return
*/
public int getSelectionIndex() {
return folder.getSelectionIndex();
}
/**
* @return
* @see org.eclipse.swt.widgets.Control#getSize()
*/
public Point getSize() {
return folder.getSize();
}
/**
* Returns the tab item for the given text.
*
* @param text
* @return
*/
public CTabItem getTabItem(String text) {
for (CTabItem item : folder.getItems()){
if (item.getText().equals(text)) {
return item;
}
}
return null;
}
/**
* Returns all visible items
* @return
*/
public List<String> getVisibleItems() {
List<String> result = new ArrayList<String>();
for (CTabItem item : folder.getItems()) {
result.add(item.getText());
}
return result;
}
/**
* Enables/disables the component.
*
* @param b
*/
public void setEnabled(boolean b) {
folder.setEnabled(b);
}
/**
* Sets the item visibility listener
* @param listener
*/
public void setItemVisibilityListener(SelectionListener listener) {
this.itemVisibilityListener = listener;
}
/**
* Sets layout data.
*
* @param data
*/
public void setLayoutData(Object data){
folder.setLayoutData(data);
}
/**
* Selects the item with the given control
* @param c
*/
public void setSelectedControl(Control c) {
for (CTabItem item : folder.getItems()) {
if (item.getControl() == c) {
folder.setSelection(item);
return;
}
}
}
/**
* Sets the current selection.
*
* @param index
*/
public void setSelection(int index) {
folder.setSelection(index);
}
/**
* Sets the given items as visible
* @param item
*/
public void setVisibleItems(List<String> items) {
boolean changed = false;
for (String item : getAllHideableItems()) {
if (items.contains(item)) {
changed |= setVisible(item, true);
if (this.folder.getItemCount() == 1) {
this.folder.setSelection(0);
}
} else {
changed |= setVisible(item, false);
}
}
if (changed && this.itemVisibilityListener != null) {
Event event = new Event();
event.widget = this.folder;
this.itemVisibilityListener.widgetSelected(new SelectionEvent(event));
}
}
/**
* Creates the bar .
*
* @param controller
* @param folder
* @param bar
*/
private void createBar(final Controller controller, final CTabFolder folder, final ComponentTitledFolderButtonBar bar) {
ToolBar toolbar = new ToolBar(folder, SWT.FLAT);
folder.setTopRight( toolbar, SWT.RIGHT );
if (this.supportsHidingElements) {
ToolItem item = new ToolItem( toolbar, SWT.PUSH );
item.setImage(controller.getResources().getManagedImage("manage.png")); //$NON-NLS-1$
item.setToolTipText(Resources.getMessage("General.1")); //$NON-NLS-1$
SWTUtil.createDisabledImage(item);
item.addSelectionListener(new SelectionAdapter(){
@Override
public void widgetSelected(SelectionEvent arg0) {
List<String> result = controller.actionShowMultiSelectionDialog(folder.getShell(),
Resources.getMessage("ComponentTitledFolder.0"), //$NON-NLS-1$
Resources.getMessage("ComponentTitledFolder.1"), //$NON-NLS-1$
getAllHideableItems(),
getVisibleItems());
if (result != null) {
setVisibleItems(result);
}
}
});
}
for (String title : bar.getTitles()){
final String key = title;
ToolItem item = null;
if (bar.isToggle(title)) item = new ToolItem( toolbar, SWT.CHECK);
else item = new ToolItem( toolbar, SWT.PUSH);
item.setImage(bar.getImage(key));
item.setToolTipText(title);
SWTUtil.createDisabledImage(item);
item.addSelectionListener(new SelectionAdapter(){
@Override
public void widgetSelected(SelectionEvent arg0) {
bar.getRunnable(key).run();
}
});
}
ToolItem item = new ToolItem( toolbar, SWT.PUSH );
item.setImage(controller.getResources().getManagedImage("help.png")); //$NON-NLS-1$
item.setToolTipText(Resources.getMessage("General.0")); //$NON-NLS-1$
SWTUtil.createDisabledImage(item);
item.addSelectionListener(new SelectionAdapter(){
@Override
public void widgetSelected(SelectionEvent arg0) {
if (bar.getHelpIds() == null || bar.getHelpIds().get(folder.getSelection().getControl()) == null) {
controller.actionShowHelpDialog(bar.getHelpId());
} else {
controller.actionShowHelpDialog(bar.getHelpIds().get(folder.getSelection().getControl()));
}
}
});
int height = toolbar.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
folder.setTabHeight(Math.max(height, folder.getTabHeight()));
}
/**
* Returns all items
* @return
*/
private List<String> getAllHideableItems() {
List<String> result = new ArrayList<String>();
for (TitledFolderEntry entry : this.entries) {
if (entry.hideable) {
result.add(entry.text);
}
}
return result;
}
/**
* Returns a list of all invisible entries
* @return
*/
private List<TitledFolderEntry> getInvisibleEntries() {
List<TitledFolderEntry> result = new ArrayList<TitledFolderEntry>();
result.addAll(this.entries);
for (CTabItem item : folder.getItems()){
Iterator<TitledFolderEntry> iter = result.iterator();
while (iter.hasNext()) {
if (item.getText().equals(iter.next().text)) {
iter.remove();
}
}
}
return result;
}
/**
* Sets the given item invisible
* @param item
*/
private boolean setInvisible(String text) {
for (CTabItem item : folder.getItems()){
label: if (item.getText().equals(text)) {
for (TitledFolderEntry entry : this.entries) {
if (entry.text.equals(text) && !entry.hideable) {
break label;
}
}
item.dispose();
return true;
}
}
return false;
}
/**
* Sets an entry visible
* @return
*/
private boolean setVisible(String text) {
List<TitledFolderEntry> list = getInvisibleEntries();
// Find
for (TitledFolderEntry entry : list) {
if (entry.text.equals(text)) {
// Shift
int index = entry.index;
for (TitledFolderEntry other : list) {
if (other.index < entry.index) {
index--;
}
}
// Show
CTabItem item = new CTabItem(folder, SWT.NULL, index);
item.setText(entry.text);
if (entry.image!=null) item.setImage(entry.image);
item.setShowClose(false);
item.setControl(entry.control);
return true;
}
}
return false;
}
/**
* Sets the according item visible
* @param item
* @param visible
*/
private boolean setVisible(String item, boolean visible) {
if (!supportsHidingElements) {
return false;
}
if (visible) {
return this.setVisible(item);
} else {
return this.setInvisible(item);
}
}
}