// Copyright 2012 Georg-August-Universität Göttingen, Germany
//
// 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 de.ugoe.cs.autoquest.ui.swt;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
import org.eclipse.swt.widgets.Label;
/**
*
* a dialog to inspect the tasks and task instances of a task model
*
*
* @author Patrick Harms
*/
public class ShowTaskTreeDialog extends Dialog {
/** the main shell */
protected Shell shell;
/** the tree of task instances on the left */
private Tree instanceTree;
/** the tree of tasks (model) on the right*/
private Tree modelTree;
/** the displayed task model */
protected ITaskModel taskModel;
/**
* creates the dialog
*/
public ShowTaskTreeDialog(Shell parent, int style, ITaskModel taskModel, String taskTreeName) {
super(parent, style);
setText("Task Model " + taskTreeName);
this.taskModel = taskModel;
}
/**
* displays the dialog
*/
public void open() {
createContents();
shell.open();
shell.layout();
Display display = getParent().getDisplay();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* creates the two views, one on the task instances on the left, on on the task models on the
* right. Also adds a selection adapter to the task instances so that for a selected task
* instance always the respective model is presented.
*/
private void createContents() {
shell = new Shell(getParent(), SWT.SHELL_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL);
shell.setSize(750, 800);
shell.setText(getText());
shell.setLayout(new GridLayout(4, false));
SashForm sashForm = new SashForm(shell, SWT.HORIZONTAL);
sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1));
instanceTree = new Tree(sashForm, SWT.BORDER | SWT.MULTI);
instanceTree.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
modelTree.removeAll();
TreeItem[] selectedItems = instanceTree.getSelection();
if (selectedItems.length == 1) {
if (selectedItems[0].getData() instanceof ITaskInstance) {
buildModelTree((ITaskInstance) selectedItems[0].getData());
}
else if (selectedItems[0].getData() instanceof ITaskModel) {
buildModelTree((ITaskModel) selectedItems[0].getData());
}
}
}
});
buildInstanceTree();
modelTree = new Tree(sashForm, SWT.BORDER | SWT.MULTI);
buildModelTree(taskModel);
Button btnExpandAll = new Button(shell, SWT.NONE);
btnExpandAll.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
expandAll(instanceTree, true);
}
});
btnExpandAll.setText("Expand all");
Button btnCollapseAll = new Button(shell, SWT.NONE);
btnCollapseAll.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
expandAll(instanceTree, false);
}
});
btnCollapseAll.setText("Collapse all");
//new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
new Label(shell, SWT.NONE);
}
/**
* convenience method for creating the display of the instances
*/
private void buildInstanceTree() {
List sessions = taskModel.getUserSessions();
TreeItem root = new TreeItem(instanceTree, SWT.NULL);
root.setText(sessions.size() + " sessions");
root.setData(taskModel);
for (IUserSession session : sessions) {
buildInstanceTree(root, session);
}
}
/**
* convenience method for creating the display of the instances
*/
private void buildInstanceTree(TreeItem currentParent, ITaskInstanceList taskInstanceList) {
TreeItem child = new TreeItem(currentParent, SWT.NULL);
child.setText(taskInstanceList.toString());
child.setData(taskInstanceList);
for (ITaskInstanceList childTask : taskInstanceList) {
buildInstanceTree(child, childTask);
}
}
/**
* convenience method for creating the display of the task model
*/
private void buildModelTree(ITaskModel taskModel) {
modelTree.removeAll();
// load the correct children on expansion
if (modelTree.getListeners(SWT.Expand).length == 0) {
modelTree.addListener(SWT.Expand, new Listener() {
public void handleEvent(final Event event) {
ensureChildren((TreeItem) event.item);
((TreeItem) event.item).setExpanded(true);
}
});
}
Collection tasks = taskModel.getTasks();
TreeItem root = new TreeItem(modelTree, SWT.NULL);
root.setText(tasks.size() + " tasks in model (showing only root tasks)");
root.setData(taskModel);
tasks = createSortedTaskList(tasks);
for (ITask task : tasks) {
createTreeItemFor(task, root);
}
root.setExpanded(true);
}
/**
* convenience method for creating the display of the task model
*/
private void buildModelTree(ITaskInstance taskInstance) {
modelTree.removeAll();
TreeItem root = new TreeItem(modelTree, SWT.NULL);
root.setText("model of instance " + taskInstance);
root.setData(taskInstance);
createTreeItemFor(taskInstance.getTask(), root);
expandAll(root, true, 20);
}
/**
* reduces the list of tasks in a model so that it only contains root nodes and that it is
* sorted starting with the most complex task first
*/
private List createSortedTaskList(Collection tasks) {
Set resultSet = new HashSet(tasks);
for (ITask task : tasks) {
removeChildren(task, resultSet);
}
List result = new LinkedList(resultSet);
Collections.sort(result, new Comparator() {
@Override
public int compare(ITask task1, ITask task2) {
return depth(task2) - depth(task1);
}
private int depth(ITask task) {
int maxChildDepth = 0;
if (task instanceof IStructuringTemporalRelationship) {
for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) {
maxChildDepth = Math.max(maxChildDepth, depth(child));
}
}
else if (task instanceof IMarkingTemporalRelationship) {
maxChildDepth = Math.max
(maxChildDepth, depth(((IMarkingTemporalRelationship) task).getMarkedTask()));
}
return maxChildDepth + 1;
}
});
return result;
}
/**
* convenience method for removed all non root tasks of the provided list
*/
private void removeChildren(ITask task, Set result) {
if (task instanceof IStructuringTemporalRelationship) {
for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) {
result.remove(child);
}
}
else if (task instanceof IMarkingTemporalRelationship) {
result.remove(((IMarkingTemporalRelationship) task).getMarkedTask());
}
}
/**
* expands all nodes in the tree
*/
private void expandAll(Tree tree, boolean expanded) {
for (TreeItem item : tree.getItems()) {
expandAll(item, expanded, Integer.MAX_VALUE);
}
}
/**
* expands all nodes in the tree
*/
private void expandAll(TreeItem item, boolean expanded, int maxChildrenToExpand) {
if (expanded) {
ensureChildren(item);
}
if (item.getItems().length < maxChildrenToExpand) {
item.setExpanded(expanded);
for (TreeItem childItem : item.getItems()) {
expandAll(childItem, expanded, maxChildrenToExpand);
}
}
}
/**
* ensures, that the children of a specific node are loaded
*/
private void ensureChildren(TreeItem parent) {
if (parent.getData() instanceof ITask) {
TreeItem[] items = parent.getItems();
if ((items == null) || (items.length == 0) || (items[0].getData() == null)) {
if (items != null) {
for (int i = 0; i < items.length; i++) {
items[i].dispose();
}
}
ITask task = (ITask) parent.getData();
if (task instanceof IStructuringTemporalRelationship) {
for (ITask subTask : ((IStructuringTemporalRelationship) task).getChildren()) {
createTreeItemFor(subTask, parent);
}
}
else if (task instanceof IMarkingTemporalRelationship) {
createTreeItemFor
(((IMarkingTemporalRelationship) task).getMarkedTask(), parent);
}
}
}
}
/**
* convenience method to create a tree item for a task
*/
private void createTreeItemFor(ITask task, TreeItem parent) {
TreeItem item = new TreeItem(parent, SWT.NULL);
item.setText(task.toString());
item.setData(task);
// simulate a child
if ((task instanceof IStructuringTemporalRelationship) ||
(task instanceof IMarkingTemporalRelationship))
{
new TreeItem(item, SWT.NULL);
}
}
}