// 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.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
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.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import de.ugoe.cs.autoquest.eventcore.IEventTarget;
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.usability.UsabilitySmell;
import de.ugoe.cs.autoquest.usability.UsabilitySmellIntensity;
import de.ugoe.cs.autoquest.usability.UsabilityEvaluationResult;
/**
*
* a dialog to inspect the results of a usability evaluation
* TODO update comments
*
*
* @author Patrick Harms
*/
public class ShowUsabilityEvaluationResultDialog extends Dialog {
/** the main shell */
protected Shell shell;
/** the table containing all smells */
private Tree smellList;
/** the description label of a selected smell */
private StyledText description;
/** the tree of involved GUI elements of a specific task on the right bottom */
private Tree involvedTargetsTree;
/** the table containing the parents tasks of a displayed task */
private Tree involvedTasks;
/** the displayed usability evaluation result */
private UsabilityEvaluationResult usabilityEvalResult;
/** task tree dialog to show task details */
private ShowTaskTreeDialog showTaskTreeDialog;
/**
* creates the dialog
*/
public ShowUsabilityEvaluationResultDialog(Shell parent,
int style,
UsabilityEvaluationResult usabilityEvalResult,
String dataSetName)
{
super(parent, style);
setText("Usability Evaluation Result " + dataSetName);
this.usabilityEvalResult = usabilityEvalResult;
}
/**
* displays the dialog
*/
public void open() {
showTaskTreeDialog = new ShowTaskTreeDialog
(super.getParent(), SWT.NONE, usabilityEvalResult.getTaskModel(),
"task details of usability smells");
createContents();
shell.open();
shell.layout();
shell.addShellListener(new ShellAdapter() {
@Override
public void shellClosed(ShellEvent e) {
showTaskTreeDialog.dispose();
}
});
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);
GraphicsDevice gd =
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
shell.setSize(gd.getDisplayMode().getWidth(), gd.getDisplayMode().getHeight());
shell.setText(getText());
shell.setLayout(new GridLayout(1, false));
SashForm mainSashForm = new SashForm(shell, SWT.HORIZONTAL);
mainSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
smellList = new Tree(mainSashForm, SWT.BORDER | SWT.SINGLE | SWT.VIRTUAL);
smellList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
smellList.setHeaderVisible(true);
smellList.setLinesVisible(true);
TreeColumn treeColumn = new TreeColumn(smellList, SWT.NONE);
treeColumn.setWidth(200);
treeColumn.setText("smells");
buildSmellTree();
smellList.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
TreeItem[] selectedItems = smellList.getSelection();
if ((selectedItems.length == 1) &&
(selectedItems[0].getData() instanceof UsabilitySmell))
{
displaySmellDetails((UsabilitySmell) selectedItems[0].getData());
}
else {
clearSmellDetails();
}
}
});
SashForm detailsSashForm = new SashForm(mainSashForm, SWT.VERTICAL);
detailsSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
description = new StyledText(detailsSashForm, SWT.READ_ONLY | SWT.BORDER | SWT.WRAP);
description.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
SashForm detailsBottomSashForm = new SashForm(detailsSashForm, SWT.HORIZONTAL);
detailsBottomSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
involvedTasks = VisualizationUtils.createTaskDetailsTree
(detailsBottomSashForm, "involved tasks", usabilityEvalResult.getTaskModel());
VisualizationUtils.addItemSpecificContextMenu
(involvedTasks, ITask.class, "show details", new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e) {
showTaskTreeDialog.open((ITask) involvedTasks.getSelection()[0].getData());
}
});
VisualizationUtils.addExpansionListener(involvedTasks, new Listener() {
public void handleEvent(final Event event) {
ensureChildren((TreeItem) event.item);
((TreeItem) event.item).setExpanded(true);
}
});
involvedTargetsTree =
VisualizationUtils.createTargetsTree(detailsBottomSashForm, "involved GUI elements");
VisualizationUtils.addInvolvedTargetsHighlighting(involvedTasks, involvedTargetsTree);
detailsBottomSashForm.setWeights(new int[] { 1, 1 });
detailsSashForm.setWeights(new int[] { 1, 3 });
mainSashForm.setWeights(new int[] { 1, 3 });
//indexColumn.pack();
//severityColumn.pack();
//descriptionColumn.pack();
//smellList.pack();
}
/**
* convenience method for creating the display of the instances
*/
private void buildSmellTree() {
int groupCount = 5;
int groupSize = 30;
List smells = usabilityEvalResult.getAllSmells();
final Map> sortedSmells = new HashMap<>();
for (UsabilitySmell smell : smells) {
List smellList = sortedSmells.get(smell.getBriefDescription());
if (smellList == null) {
smellList = new ArrayList();
sortedSmells.put(smell.getBriefDescription(), smellList);
}
ListIterator it = smellList.listIterator();
boolean added = false;
while (it.hasNext()) {
if (smell.getIntensity().getEventCoverage() >
it.next().getIntensity().getEventCoverage())
{
it.previous();
it.add(smell);
added = true;
break;
}
}
if (!added) {
smellList.add(smell);
}
}
final Map>> allSortedSmells =
new HashMap>>();
for (Map.Entry> entry : sortedSmells.entrySet()) {
// we create groupCount groups of size groupSize
int overallIndex = 0;
for (int i = 0; i < groupCount; i++) {
List smellList = new LinkedList<>();
for (int j = 0; overallIndex < entry.getValue().size() &&
((j < groupSize) || (i == (groupCount - 1))); j++)
{
UsabilitySmell smell = entry.getValue().get(overallIndex++);
int ratio = smell.getIntensity().getRatio();
int eventCoverage = smell.getIntensity().getEventCoverage();
int index = 0;
for (index = 0; index < smellList.size(); index++) {
UsabilitySmellIntensity candidate = smellList.get(index).getIntensity();
if ((ratio == candidate.getRatio()) &&
(eventCoverage > candidate.getEventCoverage()))
{
break;
}
else if (ratio > candidate.getRatio()) {
break;
}
}
smellList.add(index, smell);
}
if (smellList.size() > 0) {
Map> smellGroups = allSortedSmells.get(i);
if (smellGroups == null) {
smellGroups = new HashMap<>();
allSortedSmells.put(i, smellGroups);
}
smellGroups.put(entry.getKey(), smellList);
}
}
}
if (smellList.getListeners(SWT.Expand).length == 0) {
smellList.addListener(SWT.Expand, new Listener() {
public void handleEvent(final Event event) {
ensureChildren((TreeItem) event.item);
((TreeItem) event.item).setExpanded(true);
}
});
}
for (int i = 0; i < allSortedSmells.size(); i++) {
createRootItem("smells group " + (i + 1), allSortedSmells.get(i));
}
}
/**
* convenience method for creating the display of the instances
*/
/*private void buildSmellTree() {
List smells = usabilityEvalResult.getAllSmells();
int[] eventCoverageQuantileGroups = { 990, 975, 950, 0, -1 };
int[] minEventCoverages = new int[eventCoverageQuantileGroups.length];
int[] maxEventCoverages = new int[eventCoverageQuantileGroups.length];
final List