/******************************************************************************* * CogTool Copyright Notice and Distribution Terms * CogTool 1.3, Copyright (c) 2005-2013 Carnegie Mellon University * This software is distributed under the terms of the FSF Lesser * Gnu Public License (see LGPL.txt). * * CogTool is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * CogTool is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with CogTool; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * CogTool makes use of several third-party components, with the * following notices: * * Eclipse SWT version 3.448 * Eclipse GEF Draw2D version 3.2.1 * * Unless otherwise indicated, all Content made available by the Eclipse * Foundation is provided to you under the terms and conditions of the Eclipse * Public License Version 1.0 ("EPL"). A copy of the EPL is provided with this * Content and is also available at http://www.eclipse.org/legal/epl-v10.html. * * CLISP version 2.38 * * Copyright (c) Sam Steingold, Bruno Haible 2001-2006 * This software is distributed under the terms of the FSF Gnu Public License. * See COPYRIGHT file in clisp installation folder for more information. * * ACT-R 6.0 * * Copyright (c) 1998-2007 Dan Bothell, Mike Byrne, Christian Lebiere & * John R Anderson. * This software is distributed under the terms of the FSF Lesser * Gnu Public License (see LGPL.txt). * * Apache Jakarta Commons-Lang 2.1 * * This product contains software developed by the Apache Software Foundation * (http://www.apache.org/) * * jopt-simple version 1.0 * * Copyright (c) 2004-2013 Paul R. Holser, Jr. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Mozilla XULRunner 1.9.0.5 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (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.mozilla.org/MPL/. * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The J2SE(TM) Java Runtime Environment version 5.0 * * Copyright 2009 Sun Microsystems, Inc., 4150 * Network Circle, Santa Clara, California 95054, U.S.A. All * rights reserved. U.S. * See the LICENSE file in the jre folder for more information. ******************************************************************************/ package edu.cmu.cs.hcii.cogtool.view; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Text; import edu.cmu.cs.hcii.cogtool.model.Project; import edu.cmu.cs.hcii.cogtool.ui.SEDemoLID; import edu.cmu.cs.hcii.cogtool.uimodel.SEDemoUIModel; import edu.cmu.cs.hcii.cogtool.util.Draw2DContextMenuUtil; import edu.cmu.cs.hcii.cogtool.util.FontUtils; import edu.cmu.cs.hcii.cogtool.util.IFlatDraw2DMouseMotionListener; import edu.cmu.cs.hcii.cogtool.util.L10N; import edu.cmu.cs.hcii.cogtool.util.ListenerIdentifierMap; import edu.cmu.cs.hcii.cogtool.util.OSUtils; import edu.cmu.cs.hcii.cogtool.util.SWTContextMenuUtil; import edu.cmu.cs.hcii.cogtool.util.SashUtility; import edu.cmu.cs.hcii.cogtool.util.WindowUtil; import edu.cmu.cs.hcii.cogtool.util.Zoomable; import edu.cmu.cs.hcii.cogtool.util.ListenerIdentifier.ILIDTransmuter; import edu.cmu.cs.hcii.cogtool.util.MenuUtil.MenuItemDefinition; /** * View for the Demonstration task. * * Uses the InteractionEditor for properties and showing a single frame. * * Also has a special sash and side area for holding a history of actions. * * @author alexeiser * */ public class SEDemoView extends DefaultSEView { public static final String COMPUTE = L10N.get("SE.Compute", "Compute"); public static final String CLOSE_AND_COMPUTE = L10N.get("SE.CloseAndCompute", "Close and Compute"); public static final String REGENERATE_THEN_COMPUTE = L10N.get("SE.RegenerateThenCompute", "Regenerate then Compute"); protected static final String scriptStepListTitle = L10N.get("SE.ScriptStepList", "Script Step List"); protected static final String VIEW_ONLY = L10N.get("SE.ViewOnly", "View Only"); protected static final String predictionTitle = L10N.get("SE.PredictionTitle", "Prediction:"); protected static final String SHOW_VISUALIZATION = L10N.get("SE.ShowVisualization", "Show Visualization"); protected static final Font PREDICTION_LABEL_FONT = FontUtils.getAdjustedFont(WindowUtil.GLOBAL_DISPLAY.getSystemFont(), SWT.BOLD); // Container for history and hand location stuff protected Group historyProperties; // Properties Elements protected Label predictionResult; protected SWTListMultiColumn scriptSteps; protected Button insertThink; protected Text insertThinkNumber; protected Button insertDrive; // protected Button insertDelay; protected Button insertLookAt; protected Button deleteItem; protected Button regenerateItem; protected Button computeItem; protected boolean editable; protected static String[] columnTitles = new String[] { "", L10N.get("SDV.Frame", "Frame"), L10N.get("SDV.Action", "Action"), L10N.get("SDV.WidgetDevice", "Widget/Device") }; /** * Constructor for SEDemo View takes various objects needed for listeners * and callbacks. * * @param deviceTypes provide the device types needed to determine * start hand on mouse appearance * @param listenerIDMap * @param transformer * @param menuData * @param uiModel What to show in the interaction area * @param motionL The motion listener * @param clickL The click listener. * @param deviceL The context menu listener for non-screen devices. * @param loc The location to open the window * @param editable * @param tableCallback The call back to be used for table data. */ public SEDemoView(int deviceTypes, ListenerIdentifierMap listenerIDMap, ILIDTransmuter transformer, MenuFactory.IWindowMenuData<Project> menuData, final SEDemoUIModel uiModel, IFlatDraw2DMouseMotionListener motionL, Draw2DContextMenuUtil.MenuListener clickL, final SWTContextMenuUtil.MenuListener deviceL, final SWTContextMenuUtil.MenuListener frameL, Zoomable zoomer, Rectangle loc, boolean edit) { super(listenerIDMap, transformer, menuData, uiModel, deviceL, loc, DEFAULT_WIDTH, DEFAULT_HEIGHT); layoutHelper.reset(uiModel, deviceL, frameL, deviceTypes); editable = edit; editor = new InteractionDrawingEditor(uiModel.getCurrentFrame().getContents(), motionL, clickL, getShell(), zoomer, PROPERTIES_PANE_HEIGHT, SWT.BOTTOM, 0, WindowUtil.getCursor(WindowUtil.SELECT_CURSOR)) { @Override protected void addAndLayOutFields() { layoutHelper.addFrameNameDevices(bodyComposite, scrollComposite, scrollFormData); } }; // Lay out the table, providing the callback to be used in SWTList layOutWindow(deviceTypes, uiModel.getScriptUIModel().getRowRenderer()); // Set the minimum allowable shell size shell.setMinimumSize(575, 300); editor.getSWTEditorSubstrate().addListener(SWT.MenuDetect, clickL); } protected void positionStartLocParms(FormData data) { if (mouseHandStartLoc != null) { FormData handLayoutData = new FormData(); handLayoutData.bottom = new FormAttachment(deleteItem, -5, SWT.TOP); handLayoutData.left = new FormAttachment(userMouseHand, 0, SWT.LEFT); handLayoutData.right = new FormAttachment(100, 0); mouseHandStartLoc.setLayoutData(handLayoutData); data.bottom = new FormAttachment(userMouseHand, -5, SWT.TOP); } else if (deleteItem != null) { data.bottom = new FormAttachment(deleteItem, -5, SWT.TOP); } else { data.bottom = new FormAttachment(100, -5); } } public void resetDeviceTypes(int newDeviceTypes) { addHandOnKeyboardToStart(newDeviceTypes, historyProperties); positionStartLocParms((FormData) scriptSteps.getTable().getLayoutData()); historyProperties.layout(); } /** * Lay out the elements, and add listeners to communicate with "controller" */ protected void layOutPropertiesPane(Composite parent) { // Create a group for the properties Group widgetGroup = new Group(parent, SWT.NONE); widgetGroup.setLayout(new FormLayout()); // Tell the parent to use a fill layout so it will fill the area. parent.setLayout(new FillLayout()); // Lay out the insert think button insertThink = new Button(widgetGroup, SWT.PUSH); insertThink.setText(L10N.get("SE.Think", "Think")); insertThink.addSelectionListener( new SWTWidgetChangeHandler(SEDemoLID.InsertThink)); lIDMap.addWidget(SEDemoLID.InsertThink, insertThink, ListenerIdentifierMap.NORMAL); // since driving is not currently supported hide that button // this.insertDrive = new Button(widgetGroup, SWT.PUSH); // this.insertDrive.setText(L10N.get("SE.AttendDriving", // "Attend To Driving")); // this.insertDrive.addSelectionListener( // new WidgetChangeHandler(SEDemoLID.insertDrive)); // this.insertDrive.setVisible(false); // Insert delay button. // this.insertDelay = new Button(widgetGroup, SWT.PUSH); // this.insertDelay.setText(L10N.get("SE.WaitForSystem", // "Wait for System")); // this.insertDelay.addSelectionListener( // new SWTWidgetChangeHandler(SEDemoLID.InsertDelay)); // // this.lIDMap.addWidget(SEDemoLID.InsertDelay, // this.insertDelay, // ListenerIdentifierMap.NORMAL); // Insert the look at button insertLookAt = new Button(widgetGroup, SWT.TOGGLE); insertLookAt.setText(L10N.get("SE.LookAtWidget", "Look at Widget")); lIDMap.addWidget(SEDemoLID.InsertLookAt, insertLookAt, ListenerIdentifierMap.NORMAL); // The toggle button listener does not raise an alert, // UIModel needs to listen for its state change // on MacOSX, toggle button is not a standard size // To make things line up nicely we add a -5 offset. int displacementForWindows = 0; if (OSUtils.MACOSX) { // XXX: dirty hacks around SWT bugs displacementForWindows = 5; } FormData data = new FormData(); data.left = new FormAttachment(0, 5); data.top = new FormAttachment(insertThink, 0, SWT.CENTER); // data.bottom = new FormAttachment(this.insertThink, // // OSX Look At is larger, // // so shift it down // 0 - displacementForWindows, // SWT.BOTTOM); insertLookAt.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(insertLookAt, // OSXLook At is wider then normal. 5 + displacementForWindows, SWT.RIGHT); // on windows leave space on edges, macOSX doesn't need it data.bottom = new FormAttachment(100, -5 + displacementForWindows); // this.insertDelay.setLayoutData(data); // // data = new FormData(); // data.left = new FormAttachment(this.insertDelay, 5, SWT.RIGHT); // data.bottom = new FormAttachment(this.insertDelay, 0, SWT.BOTTOM); insertThink.setLayoutData(data); } /** * Lay out the window including the interactionDrawing editor * @param edit * * @param tableCallback */ public void layOutWindow(int deviceTypes, SWTListMultiColumn rowRenderer) { Shell shell = getShell(); // Set up the layouts shell.setLayout(new FormLayout()); // Create a group for the properties on the history historyProperties = new Group(shell, SWT.NONE); historyProperties.setLayout(new FormLayout()); if (editable) { // Create the delete Item button deleteItem = new Button(historyProperties, SWT.PUSH); deleteItem.setText(L10N.get("SE.DeleteStep", "Delete Step")); deleteItem.addSelectionListener( new SWTWidgetChangeHandler(SEDemoLID.Delete)); lIDMap.addWidget(SEDemoLID.Delete, deleteItem, ListenerIdentifierMap.NORMAL); // this.regenerateItem = new Button(this.historyProperties, SWT.PUSH); // this.regenerateItem.setText(L10N.get("SE.RegenerateScript", // "Regenerate Script")); // this.regenerateItem.addSelectionListener( // new SWTWidgetChangeHandler(SEDemoLID.RegenerateScript)); // // this.lIDMap.addWidget(SEDemoLID.RegenerateScript, // this.regenerateItem, // ListenerIdentifierMap.NORMAL); // Create the compute button computeItem = new Button(historyProperties, SWT.PUSH); computeItem.setText(COMPUTE); computeItem.addSelectionListener( new SWTWidgetChangeHandler(SEDemoLID.RecomputeScript)); lIDMap.addWidget(SEDemoLID.RecomputeScript, computeItem, ListenerIdentifierMap.NORMAL); } // Script scriptStepListLabel = new Label(historyProperties, SWT.CENTER); String scriptStepLabel = scriptStepListTitle; if (! editable) { scriptStepLabel += " (" + VIEW_ONLY + ")"; scriptStepListLabel.setBackground(NONEDITABLE_COLOR); } scriptStepListLabel.setText(scriptStepLabel); Table scriptStepTable = new Table(historyProperties, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION); scriptStepTable.setFont(FontUtils.SYMBOL_FONT); scriptSteps = rowRenderer; scriptSteps.setTable(scriptStepTable); scriptSteps.setColumnTitles(columnTitles); if (editable) { addHandOnKeyboardToStart(deviceTypes, historyProperties); } predictionResult = new Label(shell, SWT.LEFT); FormData editorData = new FormData(); editorData.top = new FormAttachment(0, 5); editorData.left = new FormAttachment(0, 5); editorData.bottom = new FormAttachment(100, -5); Label predictionLabel = new Label(shell, SWT.LEFT); predictionLabel.setText(predictionTitle); predictionLabel.setFont(PREDICTION_LABEL_FONT); Button showVisButton = new Button(shell, SWT.PUSH); FormData data = new FormData(); data.top = new FormAttachment(showVisButton, 0, SWT.CENTER); data.left = new FormAttachment(historyProperties, 5, SWT.LEFT); predictionLabel.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(showVisButton, 0, SWT.CENTER); data.left = new FormAttachment(predictionLabel, 5, SWT.RIGHT); data.right = new FormAttachment(showVisButton, 0, SWT.LEFT); predictionResult.setLayoutData(data); showVisButton.setText(SHOW_VISUALIZATION); data = new FormData(); data.top = new FormAttachment(0, 10); data.right = new FormAttachment(historyProperties, 0, SWT.RIGHT); showVisButton.setLayoutData(data); showVisButton.addSelectionListener( new SWTWidgetChangeHandler(SEDemoLID.ShowModelVisualization)); lIDMap.addWidget(SEDemoLID.ShowModelVisualization, showVisButton, ListenerIdentifierMap.NORMAL); data = new FormData(); data.top = new FormAttachment(showVisButton, 2, SWT.BOTTOM); data.right = new FormAttachment(100, -5); data.bottom = new FormAttachment(100, -5); SashUtility.createVerticalSash(getShell(), MIN_DRAWING_AREA_WIDTH, HISTORY_LIST_WIDTH, SWT.RIGHT, editor.bodyComposite, editorData, historyProperties, data); // Layout contents of widgetGroup data = new FormData(); data.top = new FormAttachment(predictionLabel, 0, SWT.BOTTOM); data.left = new FormAttachment(scriptStepTable, 0, SWT.LEFT); data.right = new FormAttachment(scriptStepTable, 0, SWT.RIGHT); scriptStepListLabel.setLayoutData(data); data = new FormData(); data.top = new FormAttachment(scriptStepListLabel, 5, SWT.BOTTOM); data.left = new FormAttachment(0, 0); data.right = new FormAttachment(100, 0); positionStartLocParms(data); scriptStepTable.setLayoutData(data); if (editable) { data = new FormData(); data.left = new FormAttachment(scriptStepTable, 0, SWT.LEFT); data.right = new FormAttachment(scriptStepTable, 0, SWT.RIGHT); data.bottom = new FormAttachment(computeItem, 0 , SWT.TOP); deleteItem.setLayoutData(data); // data = new FormData(); // data.left = new FormAttachment(scriptStepTable, 0, SWT.LEFT); // data.right = new FormAttachment(scriptStepTable, 0, SWT.RIGHT); // data.bottom = new FormAttachment(this.computeItem, 0 , SWT.TOP); // this.regenerateItem.setLayoutData(data); data = new FormData(); // use 0 here, since internal frame is set to -05, fix internal frame data.bottom = new FormAttachment(100, 0); data.left = new FormAttachment(scriptStepTable, 0, SWT.LEFT); data.right = new FormAttachment(scriptStepTable, 0, SWT.RIGHT); computeItem.setLayoutData(data); layOutPropertiesPane(editor.propertiesComposite); } } /** * Get the Multi Column List object. */ public SWTListMultiColumn getScriptEditorList() { return scriptSteps; } /** * Show the script step contextual menu. Currently only holds onto * the items to edit think's and delay's */ protected static final MenuItemDefinition[] SCRIPT_STEP_ITEMS = new MenuItemDefinition[] { MenuFactory.EDIT, MenuFactory.DELETE }; /** * Returns the set of context menus used by the view * @return the context menus */ @Override public MenuItemDefinition[][] getContextMenuDefinitions() { return new MenuItemDefinition[][] { STANDARD_ITEMS, SCRIPT_STEP_ITEMS }; } /** * show the script step contextual menu */ public void showScriptStepSelectionMenu() { contextMenus.setContextSelection(View.CONTEXT); contextMenus.getMenu(SCRIPT_STEP_MENU).setVisible(true); } /** * Add a selection listener to the scriptStepList. */ public void addSWTListSelectionHandler(SelectionListener l) { scriptSteps.addSelectionListener(l); } /** * Remove a listener from the script step list. */ public void removeSWTListSelectionHandler(SelectionListener l) { scriptSteps.removeSelectionListener(l); } /** * Set the look At Button "toggled" */ public void setLookAtSelected(boolean lookAtSelected) { if (! insertLookAt.isDisposed()) { insertLookAt.setSelection(lookAtSelected); } } public boolean isLookAtSelected() { return (! insertLookAt.isDisposed()) && insertLookAt.getSelection(); } public void updatePrediction(String prediction) { predictionResult.setText(prediction); } /** * Provide callers with direct access to the table. * Needed for selection listeners and the selection state. */ public Table getHistoryTable() { return scriptSteps.getTable(); } /** * Dispose of objects used in this view. * The scriptSteps, and the editor. */ @Override public void dispose() { shell.setVisible(false); scriptSteps.dispose(); super.dispose(); } }