source: trunk/autoquest-ui-swt/src/main/java/de/ugoe/cs/autoquest/ui/swt/ShowUsabilityEvaluationResultDialog.java @ 1495

Last change on this file since 1495 was 1495, checked in by pharms, 10 years ago
  • state of the HCSE 2014 Paper. An appropriate tag will follow.
File size: 17.3 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.ui.swt;
16
17import java.awt.GraphicsDevice;
18import java.awt.GraphicsEnvironment;
19import java.util.ArrayList;
20import java.util.Collection;
21import java.util.HashMap;
22import java.util.List;
23import java.util.Map;
24
25import org.eclipse.swt.SWT;
26import org.eclipse.swt.custom.SashForm;
27import org.eclipse.swt.custom.StyleRange;
28import org.eclipse.swt.custom.StyledText;
29import org.eclipse.swt.events.SelectionAdapter;
30import org.eclipse.swt.events.SelectionEvent;
31import org.eclipse.swt.events.ShellAdapter;
32import org.eclipse.swt.events.ShellEvent;
33import org.eclipse.swt.graphics.Font;
34import org.eclipse.swt.graphics.FontData;
35import org.eclipse.swt.layout.GridData;
36import org.eclipse.swt.layout.GridLayout;
37import org.eclipse.swt.widgets.Dialog;
38import org.eclipse.swt.widgets.Display;
39import org.eclipse.swt.widgets.Event;
40import org.eclipse.swt.widgets.Listener;
41import org.eclipse.swt.widgets.Shell;
42import org.eclipse.swt.widgets.Tree;
43import org.eclipse.swt.widgets.TreeColumn;
44import org.eclipse.swt.widgets.TreeItem;
45
46import de.ugoe.cs.autoquest.eventcore.IEventTarget;
47import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship;
48import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;
49import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
50import de.ugoe.cs.autoquest.usability.UsabilityDefect;
51import de.ugoe.cs.autoquest.usability.UsabilityDefectSeverity;
52import de.ugoe.cs.autoquest.usability.UsabilityEvaluationResult;
53
54/**
55 * <p>
56 * a dialog to inspect the results of a usability evaluation
57 * </p>
58 *
59 * @author Patrick Harms
60 */
61public class ShowUsabilityEvaluationResultDialog extends Dialog {
62
63    /** the main shell */
64    protected Shell shell;
65
66    /** the table containing all defects */
67    private Tree defectList;
68
69    /** the description label of a selected defect */
70    private StyledText description;
71   
72    /** the tree of involved GUI elements of a specific task on the right bottom */
73    private Tree involvedTargetsTree;
74
75    /** the table containing the parents tasks of a displayed task */
76    private Tree involvedTasks;
77
78    /** the displayed task model */
79    private UsabilityEvaluationResult usabilityEvalResult;
80   
81    /** task tree dialog to show task details */
82    private ShowTaskTreeDialog showTaskTreeDialog;
83
84    /**
85     * creates the dialog
86     */
87    public ShowUsabilityEvaluationResultDialog(Shell                     parent,
88                                               int                       style,
89                                               UsabilityEvaluationResult usabilityEvalResult,
90                                               String                    dataSetName)
91    {
92        super(parent, style);
93        setText("Usability Evaluation Result " + dataSetName);
94        this.usabilityEvalResult = usabilityEvalResult;
95    }
96
97    /**
98     * displays the dialog
99     */
100    public void open() {
101        showTaskTreeDialog = new ShowTaskTreeDialog
102            (super.getParent(), SWT.NONE, usabilityEvalResult.getTaskModel(),
103             "task details of usability defects");
104
105        createContents();
106        shell.open();
107        shell.layout();
108       
109        shell.addShellListener(new ShellAdapter() {
110            @Override
111            public void shellClosed(ShellEvent e) {
112                showTaskTreeDialog.dispose();
113            }
114        });
115       
116        Display display = getParent().getDisplay();
117        while (!shell.isDisposed()) {
118            if (!display.readAndDispatch()) {
119                display.sleep();
120            }
121        }
122    }
123
124    /**
125     * creates the two views, one on the task instances on the left, on on the task models on the
126     * right. Also adds a selection adapter to the task instances so that for a selected task
127     * instance always the respective model is presented.
128     */
129    private void createContents() {
130        shell = new Shell(getParent(), SWT.SHELL_TRIM | SWT.BORDER);
131        GraphicsDevice gd =
132            GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
133
134        shell.setSize(gd.getDisplayMode().getWidth(), gd.getDisplayMode().getHeight());
135        shell.setText(getText());
136
137        shell.setLayout(new GridLayout(1, false));
138
139        SashForm mainSashForm = new SashForm(shell, SWT.HORIZONTAL);
140        mainSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
141       
142        defectList = new Tree(mainSashForm, SWT.BORDER | SWT.SINGLE | SWT.VIRTUAL);
143        defectList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
144        defectList.setHeaderVisible(true);
145        defectList.setLinesVisible(true);
146
147        TreeColumn treeColumn = new TreeColumn(defectList, SWT.NONE);
148        treeColumn.setWidth(200);
149        treeColumn.setText("defects");
150
151        buildDefectTree();
152       
153        defectList.addSelectionListener(new SelectionAdapter() {
154            @Override
155            public void widgetSelected(SelectionEvent e) {
156                TreeItem[] selectedItems = defectList.getSelection();
157                if ((selectedItems.length == 1) &&
158                    (selectedItems[0].getData() instanceof UsabilityDefect))
159                {
160                    displayDefectDetails((UsabilityDefect) selectedItems[0].getData());
161                }
162                else {
163                    clearDefectDetails();
164                }
165            }
166        });
167
168        SashForm detailsSashForm = new SashForm(mainSashForm, SWT.VERTICAL);
169        detailsSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
170       
171        description = new StyledText(detailsSashForm, SWT.READ_ONLY | SWT.BORDER | SWT.WRAP);
172        description.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
173
174        SashForm detailsBottomSashForm = new SashForm(detailsSashForm, SWT.HORIZONTAL);
175        detailsBottomSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
176       
177        involvedTasks = VisualizationUtils.createTaskDetailsTree
178            (detailsBottomSashForm, "involved tasks", usabilityEvalResult.getTaskModel());
179       
180        VisualizationUtils.addItemSpecificContextMenu
181            (involvedTasks, ITask.class, "show details", new SelectionAdapter()
182        {
183            @Override
184            public void widgetSelected(SelectionEvent e) {
185                showTaskTreeDialog.open((ITask) involvedTasks.getSelection()[0].getData());
186            }
187        });
188       
189        VisualizationUtils.addExpansionListener(involvedTasks, new Listener() {
190            public void handleEvent(final Event event) {
191                ensureChildren((TreeItem) event.item);
192                ((TreeItem) event.item).setExpanded(true);
193            }
194        });
195       
196        involvedTargetsTree =
197            VisualizationUtils.createTargetsTree(detailsBottomSashForm, "involved GUI elements");
198       
199        VisualizationUtils.addInvolvedTargetsHighlighting(involvedTasks, involvedTargetsTree);
200       
201        detailsBottomSashForm.setWeights(new int[] { 1, 1 });
202        detailsSashForm.setWeights(new int[] { 1, 3 });
203        mainSashForm.setWeights(new int[] { 1, 3 });
204
205        //indexColumn.pack();
206        //severityColumn.pack();
207        //descriptionColumn.pack();
208        //defectList.pack();
209    }
210
211    /**
212     * convenience method for creating the display of the instances
213     */
214    private void buildDefectTree() {
215        List<UsabilityDefect> defects = usabilityEvalResult.getAllDefects();
216
217        final Map<UsabilityDefectSeverity, Map<String, List<UsabilityDefect>>> sortedDefects =
218            new HashMap<UsabilityDefectSeverity, Map<String, List<UsabilityDefect>>>();
219        sortedDefects.put(UsabilityDefectSeverity.HIGH,
220                          new HashMap<String, List<UsabilityDefect>>());
221        sortedDefects.put(UsabilityDefectSeverity.MEDIUM,
222                          new HashMap<String, List<UsabilityDefect>>());
223        sortedDefects.put(UsabilityDefectSeverity.LOW,
224                          new HashMap<String, List<UsabilityDefect>>());
225        sortedDefects.put(UsabilityDefectSeverity.INFO,
226                          new HashMap<String, List<UsabilityDefect>>());
227       
228        for (UsabilityDefect defect : defects) {
229            Map<String, List<UsabilityDefect>> defectMap = sortedDefects.get(defect.getSeverity());
230           
231            List<UsabilityDefect> defectList = defectMap.get(defect.getBriefDescription());
232           
233            if (defectList == null) {
234                defectList = new ArrayList<UsabilityDefect>();
235                defectMap.put(defect.getBriefDescription(), defectList);
236            }
237           
238            defectList.add(defect);
239        }
240       
241        if (defectList.getListeners(SWT.Expand).length == 0) {
242            defectList.addListener(SWT.Expand, new Listener() {
243               public void handleEvent(final Event event) {
244                   ensureChildren((TreeItem) event.item);
245                   ((TreeItem) event.item).setExpanded(true);
246               }
247           });
248        }
249
250        createRootItem("high", sortedDefects.get(UsabilityDefectSeverity.HIGH));
251        createRootItem("medium", sortedDefects.get(UsabilityDefectSeverity.MEDIUM));
252        createRootItem("low", sortedDefects.get(UsabilityDefectSeverity.LOW));
253        createRootItem("info", sortedDefects.get(UsabilityDefectSeverity.INFO));
254    }
255
256    /**
257     *
258     */
259    private void createRootItem(String name, Map<String, List<UsabilityDefect>> defects) {
260        TreeItem defectItem = new TreeItem(defectList, SWT.NULL);
261       
262        int count = 0;
263        for (Map.Entry<String, List<UsabilityDefect>> entry : defects.entrySet()) {
264            count += entry.getValue().size();
265        }
266
267        defectItem.setText(name + " severity (" + count + " defects)");
268        defectItem.setData(defects);
269       
270        if (count > 0) {
271            // simulate a child
272            new TreeItem(defectItem, SWT.NULL);
273        }
274    }
275
276    /**
277     *
278     */
279    private void clearDefectDetails() {
280        description.setText("");
281        involvedTargetsTree.removeAll();
282        involvedTasks.removeAll();
283    }
284
285    /**
286     *
287     */
288    private void displayDefectDetails(UsabilityDefect defect) {
289        clearDefectDetails();
290       
291        FontData data = description.getFont().getFontData()[0];
292        int height = (int) (data.getHeight() * 1.5);
293        Font defaultFont = new Font
294            (description.getDisplay(), data.getName(), height, data.getStyle());
295       
296        Font boldFont = new Font
297            (description.getDisplay(), data.getName(), height, data.getStyle() | SWT.BOLD);
298       
299        for (Object fragment : defect.getDescriptionFragments()) {
300            int color;
301            Font font;
302           
303            if (fragment instanceof String) {
304                color = SWT.COLOR_BLACK;
305                font = defaultFont;
306            }
307            else {
308                color = SWT.COLOR_DARK_GREEN;
309                font = boldFont;
310            }
311           
312            StyleRange styleRange = new StyleRange
313                (description.getText().length(), fragment.toString().length(),
314                 description.getDisplay().getSystemColor(color), null);
315
316            styleRange.font = font;
317           
318            if (fragment instanceof Collection<?>) {
319                int counter = 1;
320                for (Object elem : ((Collection<?>) fragment)) {
321                    description.append("\n");
322                    description.append(Integer.toString(counter++));
323                    description.append(".: ");
324                    description.append(elem.toString());
325                }
326            }
327            else {
328                description.append(fragment.toString());
329            }
330            description.setStyleRange(styleRange);
331            description.append(" ");
332        }
333        description.setLeftMargin(50);
334        description.setRightMargin(50);
335        description.setTopMargin(50);
336        description.setBottomMargin(50);
337
338       
339        StyleRange styleRange = new StyleRange();
340        styleRange.font = new Font(description.getDisplay(), "Courier", 12, SWT.NORMAL);
341        description.setStyleRange(styleRange);
342       
343        List<ITask> involvedTaskList = getInvolvedTasks(defect);
344        for (ITask involvedTask : involvedTaskList) {
345            VisualizationUtils.createTreeItemFor
346                (involvedTask, involvedTasks, usabilityEvalResult.getTaskModel(), true);
347        }
348       
349        List<IEventTarget> involvedTargets = getInvolvedTargets(defect);
350        if (involvedTargets.size() <= 0) {
351            for (ITask involvedTask : involvedTaskList) {
352                VisualizationUtils.getInvolvedTargets(involvedTask, involvedTargets);
353            }
354        }
355       
356        VisualizationUtils.addInvolvedTargets(involvedTargetsTree, involvedTargets);
357       
358        int weightLeft = involvedTaskList.size() == 0 ? 1 :
359            Math.min(4, Math.max(3, involvedTaskList.size()));
360        int weightRight = involvedTargets.size() == 0 ? 1 :
361            Math.min(3, Math.max(1, involvedTargets.size()));
362        ((SashForm) involvedTasks.getParent()).setWeights(new int[] { weightLeft, weightRight });
363       
364        VisualizationUtils.expandAll(involvedTasks, true);
365        VisualizationUtils.updateColumnWidths(involvedTasks);
366    }
367   
368    /**
369     *
370     */
371    private void ensureChildren(TreeItem parent) {
372        if ((parent.getItemCount() == 0) || (parent.getItems()[0].getData() != null)) {
373            return;
374        }
375       
376        for (int i = 0; i < parent.getItems().length; i++) {
377            parent.getItems()[i].dispose();
378        }
379       
380        if (parent.getData() instanceof Map<?, ?>) {
381            @SuppressWarnings("unchecked")
382            Map<String, List<UsabilityDefect>> map =
383                (Map<String, List<UsabilityDefect>>) parent.getData();
384           
385            for (Map.Entry<String, List<UsabilityDefect>> entry : map.entrySet()) {
386                TreeItem child = new TreeItem(parent, SWT.NULL);       
387                child.setText(entry.getKey() + " (" + entry.getValue().size() + " defects)");
388                child.setData(entry);
389               
390                if (entry.getValue().size() > 0) {
391                    // simulate child
392                    new TreeItem(child, SWT.NULL);
393                }
394            }
395        }
396        else if (parent.getData() instanceof Map.Entry<?, ?>) {
397            @SuppressWarnings("unchecked")
398            Map.Entry<String, List<UsabilityDefect>> entry =
399                (Map.Entry<String, List<UsabilityDefect>>) parent.getData();
400           
401            int count = 0;
402            for (UsabilityDefect defect : entry.getValue()) {
403                TreeItem child = new TreeItem(parent, SWT.NULL);       
404                child.setData(defect);
405                child.setText("defect " + ++count);
406            }
407        }
408        else if (parent.getData() instanceof ITask) {
409            ITask task = (ITask) parent.getData();
410
411            if (task instanceof IStructuringTemporalRelationship) {
412                for (ITask subTask : ((IStructuringTemporalRelationship) task).getChildren()) {
413                    VisualizationUtils.createTreeItemFor
414                        (subTask, parent, usabilityEvalResult.getTaskModel(), true);
415                }
416            }
417            else if (task instanceof IMarkingTemporalRelationship) {
418                VisualizationUtils.createTreeItemFor
419                    (((IMarkingTemporalRelationship) task).getMarkedTask(), parent,
420                     usabilityEvalResult.getTaskModel(), true);
421            }
422        }
423    }
424   
425    /**
426     *
427     */
428    private List<ITask> getInvolvedTasks(UsabilityDefect defect) {
429        List<Object> fragments = defect.getDescriptionFragments();
430        List<ITask> involvedTasks = new ArrayList<ITask>();
431       
432        for (Object fragment : fragments) {
433            if (fragment instanceof ITask) {
434                involvedTasks.add((ITask) fragment);
435            }
436        }
437       
438        return involvedTasks;
439    }
440
441    /**
442     *
443     */
444    private List<IEventTarget> getInvolvedTargets(UsabilityDefect defect) {
445        List<Object> fragments = defect.getDescriptionFragments();
446        List<IEventTarget> involvedTargets = new ArrayList<IEventTarget>();
447       
448        for (Object fragment : fragments) {
449            if (fragment instanceof IEventTarget) {
450                involvedTargets.add((IEventTarget) fragment);
451            }
452            else if (fragment instanceof Collection<?>) {
453                for (Object elem : (Collection<?>) fragment) {
454                    if (elem instanceof IEventTarget) {
455                        involvedTargets.add((IEventTarget) elem);
456                    }
457                }
458            }
459        }
460       
461        return involvedTargets;
462    }
463}
Note: See TracBrowser for help on using the repository browser.