/**********************************************************************
* Copyright (c) 2012, 2014 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Bernd Hufmann - Initial API and implementation
**********************************************************************/
package org.eclipse.tracecompass.internal.lttng2.control.ui.views.dialogs;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.tracecompass.internal.lttng2.control.ui.Activator;
import org.eclipse.tracecompass.internal.lttng2.control.ui.views.messages.Messages;
/**
* <p>
* Dialog box for collecting information about contexts to be added to channels/events.
* </p>
*
* @author Bernd Hufmann
*/
public class AddContextDialog extends Dialog implements IAddContextDialog {
// ------------------------------------------------------------------------
// Constants
// ------------------------------------------------------------------------
/**
* The icon file for this dialog box.
*/
public static final String ADD_CONTEXT_ICON_FILE = "icons/elcl16/add-context.gif"; //$NON-NLS-1$
// ------------------------------------------------------------------------
// Attributes
// ------------------------------------------------------------------------
/**
* A tree viewer for displaying and selection of available contexts.
*/
private CheckboxTreeViewer fContextsViewer;
/**
* A Tree model for the checkbox tree viewer.
*/
private final ContextModel fContextModel = new ContextModel();
/**
* The contexts to add.
*/
private final List<String> fSelectedContexts = new ArrayList<>();
// ------------------------------------------------------------------------
// Constructors
// ------------------------------------------------------------------------
/**
* Constructor
* @param shell - a shell for the display of the dialog
*/
public AddContextDialog(Shell shell) {
super(shell);
setShellStyle(SWT.RESIZE | getShellStyle());
}
// ------------------------------------------------------------------------
// Accessors
// ------------------------------------------------------------------------
@Override
public void setAvalibleContexts(List<String> contexts) {
fContextModel.setAvalibleContexts(contexts);
}
@Override
public List<String> getContexts() {
List<String> ret = new ArrayList<>();
ret.addAll(fSelectedContexts);
return ret;
}
// ------------------------------------------------------------------------
// Operations
// ------------------------------------------------------------------------
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(Messages.TraceControl_AddContextDialogTitle);
newShell.setImage(Activator.getDefault().loadIcon(ADD_CONTEXT_ICON_FILE));
}
@Override
protected Control createDialogArea(Composite parent) {
// Main dialog panel
Composite dialogComposite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(1, true);
dialogComposite.setLayout(layout);
dialogComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
// Contexts list
Group contextGroup = new Group(dialogComposite, SWT.SHADOW_NONE);
contextGroup.setText(Messages.TraceControl_AddContextAvailableContextsLabel);
layout = new GridLayout(1, true);
contextGroup.setLayout(layout);
contextGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
fContextsViewer = new CheckboxTreeViewer(contextGroup, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
fContextsViewer.getTree().setToolTipText(Messages.TraceControl_AddContextAvailableContextsTooltip);
fContextsViewer.setContentProvider(new ContextsContentProvider());
fContextsViewer.setLabelProvider(new ContextsLabelProvider());
fContextsViewer.addCheckStateListener(new ContextCheckListener());
fContextsViewer.setInput(fContextModel);
fContextsViewer.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
getShell().setMinimumSize(new Point(500, 450));
return dialogComposite;
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, IDialogConstants.CANCEL_ID, "&Cancel", true); //$NON-NLS-1$
createButton(parent, IDialogConstants.OK_ID, "&Ok", true); //$NON-NLS-1$
}
@Override
protected void okPressed() {
fSelectedContexts.clear();
Object[] checkedElements = fContextsViewer.getCheckedElements();
for (int i = 0; i < checkedElements.length; i++) {
IContextModelComponent component = (IContextModelComponent)checkedElements[i];
if (!Messages.TraceControl_AddContextAllLabel.equals(component.getName())) {
fSelectedContexts.add(component.getName());
}
}
// validation successful -> call super.okPressed()
super.okPressed();
}
// ------------------------------------------------------------------------
// Helper classes and methods
// ------------------------------------------------------------------------
/**
* Content provider for the contexts tree
*/
public static final class ContextsContentProvider implements ITreeContentProvider {
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
@Override
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof IContextModelComponent) {
return ((IContextModelComponent)parentElement).getChildren();
}
return null;
}
@Override
public Object getParent(Object element) {
if (element instanceof IContextModelComponent) {
return ((IContextModelComponent)element).getParent();
}
return null;
}
@Override
public boolean hasChildren(Object element) {
if (element instanceof IContextModelComponent) {
return ((IContextModelComponent)element).hasChildren();
}
return false;
}
}
/**
* Label provider for the contexts tree
*/
public static final class ContextsLabelProvider extends ColumnLabelProvider {
@Override
public String getText(Object element) {
if ((element != null) && (element instanceof IContextModelComponent)) {
return ((IContextModelComponent)element).getName();
}
return "";//$NON-NLS-1$
}
}
/**
* Check state listener for the contexts tree.
*/
public final class ContextCheckListener implements ICheckStateListener {
@Override
public void checkStateChanged(CheckStateChangedEvent event) {
if (event.getChecked()) {
if (event.getElement() instanceof AllContexts) {
fContextsViewer.setSubtreeChecked(event.getElement(), true);
}
} else {
if (event.getElement() instanceof AllContexts) {
fContextsViewer.setSubtreeChecked(event.getElement(), false);
} else {
IContextModelComponent component = (IContextModelComponent) event.getElement();
fContextsViewer.setChecked(component.getParent(), false);
}
}
}
}
/**
* Model for the context tree viewer (root component)
*/
public static class ContextModel implements IContextModelComponent {
private final AllContexts fAllContexts;
/**
* Constructor
*/
public ContextModel() {
fAllContexts = new AllContexts(this);
}
/**
* Sets the available contexts
*
* @param contexts
* The contexts to set
*/
public void setAvalibleContexts(List<String> contexts) {
fAllContexts.setAvalibleContexts(contexts);
}
@Override
public String getName() {
return "root"; //$NON-NLS-1$
}
@Override
public Object getParent() {
return null;
}
@Override
public Object[] getChildren() {
Object[] ret = new Object[1];
ret[0] = fAllContexts;
return ret;
}
@Override
public boolean hasChildren() {
return true;
}
}
/**
* Model element (to select/deselect) all contexts) for the context tree viewer
*/
public static class AllContexts implements IContextModelComponent {
/**
* The available list of contexts.
*/
private List<Context> fAvailableContexts;
private final IContextModelComponent fParent;
/**
* Constructor
*
* @param parent
* The parent component
*/
public AllContexts(IContextModelComponent parent) {
fParent = parent;
}
/**
* Sets the available contexts
*
* @param contexts
* The contexts to set
*/
public void setAvalibleContexts(List<String> contexts) {
fAvailableContexts = new ArrayList<>();
if (contexts != null) {
for (Iterator<String> iterator = contexts.iterator(); iterator.hasNext();) {
String name = iterator.next();
fAvailableContexts.add(new Context(this, name));
}
}
}
@Override
public String getName() {
return Messages.TraceControl_AddContextAllLabel;
}
@Override
public Object[] getChildren() {
return fAvailableContexts.toArray();
}
@Override
public Object getParent() {
return fParent;
}
@Override
public boolean hasChildren() {
return true;
}
}
/**
* Model element (the context) for the context tree viewer
*/
public static class Context implements IContextModelComponent {
private final String fContextName;
private final IContextModelComponent fParent;
/**
* Constructor
*
* @param parent
* The parent component
* @param name
* The name of this context
*/
public Context(IContextModelComponent parent, String name) {
fParent = parent;
fContextName = name;
}
@Override
public String getName() {
return fContextName;
}
@Override
public Object getParent() {
return fParent;
}
@Override
public Object[] getChildren() {
return null;
}
@Override
public boolean hasChildren() {
return false;
}
}
/**
* Interface for the tree model used for the context tree viewer.
*/
public interface IContextModelComponent {
/**
* @return The name of this component
*/
String getName();
/**
* @return The parent component
*/
Object getParent();
/**
* @return The array of children of this component
*/
Object[] getChildren();
/**
* @return If this component has children or not
*/
boolean hasChildren();
}
}