/*******************************************************************************
* 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.ui;
import java.util.List;
import java.util.Set;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
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.Text;
import edu.cmu.cs.hcii.cogtool.CogToolPref;
import edu.cmu.cs.hcii.cogtool.model.AUndertaking;
import edu.cmu.cs.hcii.cogtool.model.CachedGoogleSimilarity;
import edu.cmu.cs.hcii.cogtool.model.Design;
import edu.cmu.cs.hcii.cogtool.model.Frame;
import edu.cmu.cs.hcii.cogtool.model.GoogleSimilarity;
import edu.cmu.cs.hcii.cogtool.model.GroupNature;
import edu.cmu.cs.hcii.cogtool.model.ISitedTermSimilarity;
import edu.cmu.cs.hcii.cogtool.model.ITermSimilarity;
import edu.cmu.cs.hcii.cogtool.model.LSASimilarity;
import edu.cmu.cs.hcii.cogtool.model.GensimLSASimilarity;
import edu.cmu.cs.hcii.cogtool.model.Project;
import edu.cmu.cs.hcii.cogtool.model.SNIFACTPredictionAlgo.SNIFACTGroupParameters;
import edu.cmu.cs.hcii.cogtool.model.SNIFACTPredictionAlgo.SNIFACTParameters;
import edu.cmu.cs.hcii.cogtool.model.TaskParent;
import edu.cmu.cs.hcii.cogtool.model.URLCrawlEntry;
import edu.cmu.cs.hcii.cogtool.uimodel.DictionaryEditorUIModel;
import edu.cmu.cs.hcii.cogtool.util.ComboWithEnableFix;
import edu.cmu.cs.hcii.cogtool.util.FontUtils;
import edu.cmu.cs.hcii.cogtool.util.L10N;
import edu.cmu.cs.hcii.cogtool.util.OSUtils;
import edu.cmu.cs.hcii.cogtool.util.TextWithEnableFix;
import edu.cmu.cs.hcii.cogtool.util.WindowUtil;
import edu.cmu.cs.hcii.cogtool.util.WindowUtil.PromptDialog;
import edu.cmu.cs.hcii.cogtool.view.AboutView;
import edu.cmu.cs.hcii.cogtool.view.MenuFactory;
import edu.cmu.cs.hcii.cogtool.view.View;
/**
* Implementation of the user interaction that is specific to the
* Project Editor interface.
*
* @author mlh
*/
public class ProjectInteraction extends DefaultInteraction
{
protected static final String needSelectionMsg =
L10N.get("PM.NeedSelection",
"You must select a design or task first; click on a design's column header or a task's row.");
protected static final String needTaskApplicationMsg =
L10N.get("PM.NeedTaskApplication",
"You must select a cell that has a valid script and/or result.");
protected static final String tooManySelectedTasks =
L10N.get("PM.TooManySelectedTasks",
"There are too many tasks selected for this operation.");
protected static final String cannotMoveTaskEarlier =
L10N.get("PM.CannotMoveTaskEarlier",
"Cannot move the first child task earlier");
protected static final String cannotMoveTaskLater =
L10N.get("PM.CannotMoveTaskLater",
"Cannot move the last child task later");
protected static final String confirmDeleteDesignMsg =
L10N.get("PM.ConfirmDeleteDesign",
"Please confirm the deletion of the following Design:");
protected static final String confirmOverwriteScriptMsg =
L10N.get("PM.ConfirmDeleteScript",
"The script in this cell will be deleted. Would you like to continue?");
protected static final String designNotUniqueMsg =
L10N.get("PM.NotUniqueDesignName",
"Design names must be unique; would you like to try again?");
protected static final String designEmptyNameMsg =
L10N.get("PM.EmptyDesignName",
"Design names must not be empty; would you like to try again?");
protected static final String noDeviceTypesMsg =
L10N.get("PM.NoDeviceTypes",
"At least one device type must be chosen; would you like to try again?");
protected static final String confirmDeleteTasksMsg =
L10N.get("PM.ConfirmDeleteTask",
"Please confirm the deletion of the following Task(s):");
protected static final String confirmDeleteTasksChildrenMsg =
L10N.get("PM.ConfirmDeleteTask",
"Please confirm the deletion of the following Task(s) and Task Group(s), plus any group members:");
protected static final String taskNotUniqueMsg =
L10N.get("PM.NotUniqueTaskName",
"Task names must be unique within the containing group; would you like to try again?");
protected static final String taskEmptyNameMsg =
L10N.get("PM.EmptyTaskName",
"Task names must not be empty; would you like to try again?");
protected static final String pasteTaskReuseTitle =
L10N.get("PM.PasteTaskReuseTitle", "Paste Design");
protected static final String pasteTaskReuseMsg =
L10N.get("PM.PasteTaskReuseMsg",
"Should paste re-use the following existing task\n('Yes' to re-use, 'No' to create a new task)?");
protected static final String errorTitle =
L10N.get("PM.ErrorTitle", "Project Error");
protected static final String confirmTitle =
L10N.get("PM.ConfirmTitle", "Confirm Deletion");
protected static final String recomputeTitle =
L10N.get("PC.Recompute", "Recompute");
protected static final String scriptRegenerationRequired =
L10N.get("PC.NeedRegeneration",
"Some demonstrated scripts require regeneration before recomputation; regenerate and then compute?");
/**
* Dialog box specific to soliciting information for a task
* (name, nature, position).
*
* @author mlh
*/
public static class NewTaskDialog extends WindowUtil.PromptDialog
{
protected ProjectInteraction.TaskRequestData requestData;
protected Button meanOption;
protected Button sumOption;
protected Button maxOption;
protected Button minOption;
/**
* Initialize dialog box modal to the given parent window
* and with initial values specified by the given task request data.
*
* @param parentWin window the dialog box should be modal to
* @param data the initial values for the tsk information
* @author mlh
*/
public NewTaskDialog(Shell parentWin, ProjectInteraction.TaskRequestData data)
{
super(parentWin,
L10N.get("PM.NewTaskTitle", "New Task"),
SWT.PRIMARY_MODAL,
L10N.get("CT.TaskNameLabel", "Task name:"),
L10N.get("PM.AskNewTaskName",
"What is the new task's name?"),
data.taskName);
requestData = data;
}
/**
* Region for the radio buttons representing the nature and
* positioning choices.
*
* @return region for the radio buttons representing the nature and
* positioning choices
*/
protected Composite addRadioSet()
{
Composite radioSet = new Composite(dialog, SWT.NONE);
radioSet.setLayout(new FillLayout());
GridData radioSetLayout = new GridData();
radioSetLayout.horizontalSpan = 2;
radioSet.setLayoutData(radioSetLayout);
return radioSet;
}
/**
* Add radio button to given region.
*
* @param radioSet the given region to hold the radio button
* @param optionText the label for the radio button
* @param isSelected whether the box is initially selected
* @param isEnabled whether the user can actually choose this option
* @param optionListener how to react to a click on the radio button
*/
protected Button addOption(Composite radioSet,
String optionText,
boolean isSelected,
boolean isEnabled,
SelectionListener optionListener)
{
Button option = new Button(radioSet, SWT.RADIO);
option.setSelection(isSelected);
option.setEnabled(isEnabled);
option.setText(optionText);
option.addSelectionListener(optionListener);
return option;
}
/**
* Add the given text as a label to the dialog box.
*
* @param lblText the text to add as a label
* @return the SWT label object
*/
protected Label addLabel(String lblText)
{
// Label in left-most column, right-justified
Label lbl = new Label(dialog, SWT.NONE);
lbl.setText(lblText);
GridData lblLayout = new GridData(GridData.HORIZONTAL_ALIGN_END);
lbl.setLayoutData(lblLayout);
return lbl;
}
/**
* Add an empty cell as padding in the layout grid.
*/
protected void addEmptyCell()
{
Label emptyCell = new Label(dialog, SWT.NONE);
GridData emptyCellLayout = new GridData();
emptyCellLayout.grabExcessHorizontalSpace = true;
emptyCell.setLayoutData(emptyCellLayout);
}
/**
* Populate the dialog box.
*/
@Override
protected void addMoreFields()
{
super.addMoreFields();
// If asking for before/after placement, add radio button set
if ((requestData.flags & ProjectInteraction.TaskRequestData.ASK_IF_BEFORE) != 0)
{
addLabel(L10N.get("PM.PlaceNewTask", "Place:"));
Composite radioSet = addRadioSet();
addOption(radioSet,
L10N.get("RADIO.After", "after"),
requestData.addAfter,
true,
new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt)
{
requestData.addAfter = true;
}
});
addOption(radioSet,
L10N.get("RADIO.Before", "before"),
! requestData.addAfter,
true,
new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt)
{
requestData.addAfter = false;
}
});
addEmptyCell();
}
// If asking if new task is a group, add radio button set
if ((requestData.flags & ProjectInteraction.TaskRequestData.ASK_IF_GROUP)
== ProjectInteraction.TaskRequestData.ASK_IF_GROUP)
{
addLabel(L10N.get("PM.IsNewTaskGroup", "As a group:"));
Composite radioSet = addRadioSet();
addOption(radioSet,
L10N.get("RADIO.SingleTask", "a single task"),
requestData.addAsTask,
true,
new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt)
{
requestData.addAsTask = true;
meanOption.setEnabled(false);
sumOption.setEnabled(false);
maxOption.setEnabled(false);
minOption.setEnabled(false);
}
});
addOption(radioSet,
L10N.get("RADIO.TaskGroup",
"groups other tasks"),
! requestData.addAsTask,
true,
new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt)
{
requestData.addAsTask = false;
meanOption.setEnabled(true);
sumOption.setEnabled(true);
maxOption.setEnabled(true);
minOption.setEnabled(true);
}
});
addEmptyCell();
}
// Add nature button set
if ((requestData.flags & ProjectInteraction.TaskRequestData.ASK_NATURE) != 0) {
addLabel(L10N.get("PM.NewTaskNature", "Nature:"));
Composite radioSet = addRadioSet();
boolean isEnabled =
(! requestData.addAsTask) ||
((requestData.flags & ProjectInteraction.TaskRequestData.ASK_IF_GROUP)
!= ProjectInteraction.TaskRequestData.ASK_IF_GROUP);
meanOption =
addOption(radioSet,
L10N.get("RADIO.MEAN", "MEAN"),
requestData.nature == GroupNature.MEAN,
isEnabled,
new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt)
{
requestData.nature = GroupNature.MEAN;
}
});
sumOption =
addOption(radioSet,
L10N.get("RADIO.SUM", "SUM"),
requestData.nature == GroupNature.SUM,
isEnabled,
new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt)
{
requestData.nature = GroupNature.SUM;
}
});
maxOption =
addOption(radioSet,
L10N.get("RADIO.MAX", "MAX"),
requestData.nature == GroupNature.MAX,
isEnabled,
new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt)
{
requestData.nature = GroupNature.MAX;
}
});
minOption =
addOption(radioSet,
L10N.get("RADIO.MIN", "MIN"),
requestData.nature == GroupNature.MIN,
isEnabled,
new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt)
{
requestData.nature = GroupNature.MIN;
}
});
addEmptyCell();
}
} // addMoreFields
}
public static class GenerateDictEntriesDialog extends PromptDialog
{
protected Combo algCombo;
protected String algString;
protected boolean computeAll;
protected Combo spaceCombo;
protected String spaceString;
protected Text urlText;
protected String urlString;
protected Button regenerate;
protected Button recompute;
protected boolean hasDict;
protected ITermSimilarity defaultAlg;
public GenerateDictEntriesDialog(Shell parentWin,
String requestQuestion,
ITermSimilarity alg,
String defaultSite,
String defaultSpace,
String defaultURL,
boolean hasDictionary)
{
super(parentWin,
L10N.get("PM.GenerateParms", "Generation Details"),
SWT.PRIMARY_MODAL,
L10N.get("PM.Site", "Limiting Site") + ": ",
requestQuestion,
defaultSite);
spaceString = defaultSpace;
urlString = defaultURL;
disableOK = false;
hasDict = hasDictionary;
defaultAlg = alg;
}
/**
* What to do when the OK button is selected by the user.
*
* @author mlh
*/
@Override
protected void onOK()
{
int algIndex = algCombo.getSelectionIndex();
algString = algCombo.getItem(algIndex);
spaceString = spaceCombo.getText();
urlString = urlText.getText();
computeAll = (! hasDict || recompute.getSelection());
super.onOK();
}
public ITermSimilarity getAlgorithm()
{
return DictionaryEditorUIModel.computeAlgorithm(algString, urlString, spaceString, promptResponse);
}
public ProjectInteraction.GenerateEntriesData getData()
{
return new ProjectInteraction.GenerateEntriesData(getAlgorithm(), computeAll);
}
/**
* Populate the dialog box.
*/
@Override
protected void addMoreFields()
{
Label lbl = new Label(dialog, SWT.NONE);
lbl.setText(L10N.get("PC.GenerateEntries",
"Parameters for dictionary entry generation"));
GridData lblLayout = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
lblLayout.grabExcessHorizontalSpace = true;
lblLayout.horizontalAlignment = SWT.FILL;
lblLayout.horizontalSpan = 4;
lbl.setLayoutData(lblLayout);
super.addMoreFields();
responseBox.setEnabled(defaultAlg instanceof GoogleSimilarity ||
defaultAlg instanceof CachedGoogleSimilarity);
lbl = new Label(dialog, SWT.NONE);
lbl.setText(L10N.get("PM.Algorithm", "Algorithm") + ": ");
lblLayout = new GridData(GridData.HORIZONTAL_ALIGN_END);
lbl.setLayoutData(lblLayout);
SelectionListener listener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt)
{
Combo c = (Combo) evt.widget;
int index = c.getSelectionIndex();
responseBox.setEnabled((index == DictionaryEditorUIModel.GOOGLE_WORD_INDEX) ||
(index == DictionaryEditorUIModel.GOOGLE_PHRASE_INDEX));
spaceCombo.setEnabled((index == DictionaryEditorUIModel.LSA_INDEX) ||
(index == DictionaryEditorUIModel.GENSIM_LSA_INDEX));
urlText.setEnabled((index == DictionaryEditorUIModel.LSA_INDEX) ||
(index == DictionaryEditorUIModel.GENSIM_LSA_INDEX));
if (index == DictionaryEditorUIModel.GENSIM_LSA_INDEX){
spaceCombo.setItems(GensimLSASimilarity.KNOWN_SPACES);
spaceCombo.setText(GensimLSASimilarity.DEFAULT_SPACE);
urlText.setText(GensimLSASimilarity.DEFAULT_LSA_URL);
responseBox.setText("");
}
else {
spaceCombo.setItems(LSASimilarity.KNOWN_SPACES);
spaceCombo.setText(LSASimilarity.DEFAULT_SPACE);
urlText.setText(LSASimilarity.DEFAULT_LSA_URL);
responseBox.setText("");
}
}
};
algCombo =
DictionaryEditorUIModel.createAlgCombo(dialog,
defaultAlg,
listener);
GridData itemLayout =
new GridData(GridData.HORIZONTAL_ALIGN_FILL);
itemLayout.grabExcessHorizontalSpace = true;
itemLayout.horizontalSpan = 3;
algCombo.setLayoutData(itemLayout);
lbl = new Label(dialog, SWT.NONE);
lbl.setText(L10N.get("PM.LSASpace", "LSA Space") + ": ");
lblLayout = new GridData(GridData.HORIZONTAL_ALIGN_END);
lbl.setLayoutData(lblLayout);
SelectionListener spaceListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt)
{
Combo c = (Combo) evt.widget;
int algIndex = algCombo.getSelectionIndex();
String alg = algCombo.getItem(algIndex);
int index = c.getSelectionIndex();
if (algIndex == DictionaryEditorUIModel.GENSIM_LSA_INDEX){
if (index == 1){
urlText.setText(GensimLSASimilarity.GENSIM_STRIPPED_LSA_URL);
}
else if (index == 2){
urlText.setText(GensimLSASimilarity.GENSIM_SECTIONS_LSA_URL);
}
else if (index == 3){
urlText.setText(GensimLSASimilarity.GENSIM_PARAGRAPHS_LSA_URL);
}
else if (index == 4){
urlText.setText(GensimLSASimilarity.GENSIM_SIMPLE_LSA_URL);
}
else {
urlText.setText(GensimLSASimilarity.DEFAULT_LSA_URL);
}
}
}
};
spaceCombo =
new ComboWithEnableFix(dialog, SWT.DROP_DOWN | SWT.BORDER);
spaceCombo.addSelectionListener(spaceListener);
//spaceCombo.setItems(LSASimilarity.KNOWN_SPACES);
int algIndex = algCombo.getSelectionIndex();
if (algIndex == DictionaryEditorUIModel.GENSIM_LSA_INDEX){
spaceCombo.setItems(GensimLSASimilarity.KNOWN_SPACES);
}
else {
spaceCombo.setItems(LSASimilarity.KNOWN_SPACES);
}
spaceCombo.setText(spaceString);
itemLayout = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
itemLayout.grabExcessHorizontalSpace = true;
itemLayout.horizontalSpan = 3;
spaceCombo.setLayoutData(itemLayout);
lbl = new Label(dialog, SWT.NONE);
lbl.setText(L10N.get("PM.LSA_URL", "LSA URL") + ": ");
lblLayout = new GridData(GridData.HORIZONTAL_ALIGN_END);
lbl.setLayoutData(lblLayout);
urlText =
new TextWithEnableFix(dialog, SWT.SINGLE | SWT.BORDER);
urlText.setText(urlString);
itemLayout = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
itemLayout.grabExcessHorizontalSpace = true;
itemLayout.horizontalSpan = 3;
urlText.setLayoutData(itemLayout);
if (hasDict) {
Group useSelectionGroup = new Group(dialog, SWT.SHADOW_NONE);
useSelectionGroup.setLayout(new GridLayout());
regenerate = new Button(useSelectionGroup, SWT.RADIO);
regenerate.setText(L10N.get("PM.Regenerate",
"Recompute only entries affected by changes to the model"));
regenerate.setSelection(true);
recompute = new Button(useSelectionGroup, SWT.RADIO);
recompute.setText(L10N.get("PM.ComputeAll",
"Recompute similarity for all entries in the dictionary"));
GridData groupLayout =
new GridData(GridData.HORIZONTAL_ALIGN_FILL);
groupLayout.grabExcessHorizontalSpace = true;
groupLayout.horizontalSpan = 4;
useSelectionGroup.setLayoutData(groupLayout);
recompute.setLayoutData(new GridData());
regenerate.setLayoutData(new GridData());
}
}
}
/**
* The return value of <code>open</code> when the user selects "Create".
*/
public static final String CREATE = new String("CREATE");
/**
* The return value of <code>open</code> when the user selects "Open".
*/
public static final String OPEN = new String("OPEN");
/**
* Initialize interaction with the given window that pop-up dialog
* boxes are modal to.
*
* @param v target window for dialog box modality
* @author mlh
*/
public ProjectInteraction(View v)
{
super(v);
}
/**
* Complain that no design or task has been selected.
*
* @author mlh
*/
public void protestNoSelection()
{
reportProblem(errorTitle, needSelectionMsg);
}
/**
* Complain that the operation applies only to a single task.
*/
public void protestTooManySelectedTasks()
{
reportProblem(errorTitle, tooManySelectedTasks);
}
/**
* Complain that no task application exists.
*
* @author mlh
*/
public void protestNoTaskApplication()
{
reportProblem(errorTitle, needTaskApplicationMsg);
}
/**
* Complain that the given task cannot be earlier relative to its siblings
*/
public void protestCannotMoveEarlier()
{
reportProblem(errorTitle, cannotMoveTaskEarlier);
}
/**
* Complain that the given task cannot be later relative to its siblings
*/
public void protestCannotMoveLater()
{
reportProblem(errorTitle, cannotMoveTaskLater);
}
/**
* Request new information (name, device type set) about a new or
* existing dictionary.
*/
public ProjectInteraction.GenerateEntriesData requestGenerateDictionaryParms(String request,
ITermSimilarity defaultAlg,
boolean hasDict)
{
String defaultSite = "";
String defaultSpace = "";
String defaultURL = "";
if (defaultAlg instanceof ISitedTermSimilarity) {
defaultSite =
((ISitedTermSimilarity) defaultAlg).getContextSite();
}
else if (defaultAlg instanceof LSASimilarity) {
LSASimilarity algLSA = (LSASimilarity) defaultAlg;
defaultSpace = algLSA.getSpace();
defaultURL = algLSA.getURL();
}
else if (defaultAlg instanceof GensimLSASimilarity) {
GensimLSASimilarity algLSA = (GensimLSASimilarity) defaultAlg;
defaultSpace = algLSA.getSpace();
defaultURL = algLSA.getURL();
}
GenerateDictEntriesDialog dictDialog =
new GenerateDictEntriesDialog(window,
request,
defaultAlg,
defaultSite,
defaultSpace,
defaultURL,
hasDict);
ProjectInteraction.GenerateEntriesData data = null;
boolean notDone = true;
while (notDone) {
Object response = dictDialog.open();
if ((response != null) &&
response.equals(WindowUtil.PromptDialog.OK))
{
data = dictDialog.getData();
notDone = false;
}
else {
notDone = false;
}
}
return data;
}
/**
* Request a new design name. The given string provides the
* initial value for the dialog box.
*
* @param oldDesignName the initial value for the dialog box
* @return the new name if not canceled; <code>null</code> otherwise
* @author mlh
*/
public String requestDesignRename(String oldDesignName)
{
WindowUtil.PromptDialog askName =
new WindowUtil.PromptDialog
(window,
L10N.get("PM.RenameDesignTitle",
"Rename Design"),
SWT.PRIMARY_MODAL,
L10N.get("CT.DesignNameLabel",
"Design name:"),
L10N.get("PM.AskNewDesignName",
"What is the design's new name?"),
oldDesignName);
Object response = askName.open();
return
(response != null) && response.equals(WindowUtil.PromptDialog.OK)
? askName.getPromptResponse()
: null;
}
/**
* Complain that the specified design is not unique;
* allow the user to retry.
*
* @return true if and only if the user wishes to retry; false
* indicates a desire to cancel
* @author mlh
*/
public boolean protestNotUniqueDesignName()
{
return reportAndRetry(errorTitle, designNotUniqueMsg);
}
/**
* Complain that the design name is empty; allow the user to retry.
*
* @return true if and only if the user wishes to retry; false
* indicates a desire to cancel
* @author mlh
*/
public boolean protestEmptyDesignName()
{
return reportAndRetry(errorTitle, designEmptyNameMsg);
}
/**
* Complain that the specified device set is empty;
* allow the user to retry.
*
* @return true if and only if the user wishes to retry; false
* indicates a desire to cancel
* @author mlh
*/
public boolean protestNoDeviceTypes()
{
return reportAndRetry(errorTitle, noDeviceTypesMsg);
}
/**
* Complain that the attempt to recompute was prevented by scripts
* that require regeneration. Ask whether to regenerate then compute
* or to cancel. Returns <code>true</code> if the user indicated
* to regenerate then compute.
*
* @author mlh
*/
public boolean reportRegenerationRequired()
{
return SWT.OK == WindowUtil.presentMessageDialog(window,
recomputeTitle,
scriptRegenerationRequired,
SWT.OK | SWT.CANCEL,
SWT.ICON_WARNING,
SWT.PRIMARY_MODAL);
}
/**
* Ask the user to confirm that the given design may be deleted.
*
* @param design the design that will be deleted
* @return true if the user indicated that the operation should proceed;
* false indicates a desire to cancel the operation
* @author mlh
*/
public boolean confirmDeleteDesign(Design design)
{
String msg = confirmDeleteDesignMsg + "\n " + design.getName();
return (SWT.OK == WindowUtil.presentConfirmDialog(window,
confirmTitle,
msg));
}
/**
* Request new information (name, group nature) about a new or
* existing task. The given data initializes the values for
* the interaction.
*
* @param requestData the initial values for the dialog box
* @return true if the user indicated that the operation should proceed;
* false indicates a desire to cancel the operation
* @author mlh
*/
public boolean requestNewTaskName(ProjectInteraction.TaskRequestData requestData)
{
NewTaskDialog askName = new NewTaskDialog(window, requestData);
Object response = askName.open();
if ((response != null) && response.equals(WindowUtil.PromptDialog.OK))
{
requestData.taskName = askName.getPromptResponse();
return true;
}
return false;
}
/**
* Ask the user to confirm that the given tasks may be deleted.
*
* @param selectedTasks the tasks that will be deleted
* @return true if the user indicated that the operation should proceed;
* false indicates a desire to cancel the operation
* @author mlh
*/
public boolean confirmDeleteTasks(AUndertaking[] selectedTasks)
{
String msg = confirmDeleteTasksMsg;
// Specialize the message depending on whether any task group
// is in the selected set to be deleted.
for (int i = 0; i < selectedTasks.length; ++i)
{
if (selectedTasks[i].isTaskGroup()) {
msg = confirmDeleteTasksChildrenMsg;
break;
}
}
return (SWT.OK == WindowUtil.presentConfirmItemsDialog(window,
confirmTitle,
msg,
selectedTasks));
}
/**
* Complain that the specified task name is not unique;
* allow the user to retry.
*
* @return true if and only if the user wishes to retry; false
* indicates a desire to cancel
* @author mlh
*/
public boolean protestNotUniqueTaskName()
{
return reportAndRetry(errorTitle, taskNotUniqueMsg);
}
/**
* Complain that the specified task name is empty; allow the user to retry.
*
* @return true if and only if the user wishes to retry; false
* indicates a desire to cancel
* @author mlh
*/
public boolean protestEmptyTaskName()
{
return reportAndRetry(errorTitle, taskEmptyNameMsg);
}
/**
* Ask whether the user wants to use an existing corresponding task
* (i.e., one with the same name as the given task in the given taskParent)
* when pasting a design between projects.
*/
public Boolean askToReuseTaskOnPaste(AUndertaking task,
TaskParent taskParent)
{
String msg = pasteTaskReuseMsg + "\n " + task.getName();
if (WindowUtil.presentYesNoQuestionDialog(window,
pasteTaskReuseTitle,
msg) == SWT.YES)
{
return Boolean.TRUE;
}
return Boolean.FALSE;
}
/**
* Opening question to the user: Create-new vs. open existing project?
*/
public static class StartUpDialog extends AboutView
{
// Available for alignment
protected Combo openRecent = null;
protected Button createButton;
protected Button openButton;
protected ShellListener modalFaker = null;
public StartUpDialog(Shell parentWin)
{
super(parentWin,
L10N.get("CGTL.StartUp", "CogTool Start-up"),
OSUtils.MACOSX ? SWT.MODELESS : SWT.PRIMARY_MODAL);
}
/**
* Construct the contents of the dialog window.
* <p>
* First, the question/instructions, if specified.<br>
*
* @author mlh
*/
@Override
protected void addButtons()
{
Label msgCell = new Label(dialog, SWT.NONE);
Font fnt = msgCell.getFont();
msgCell.setFont(FontUtils.getAdjustedFont(fnt, 14, SWT.BOLD));
msgCell.setText(L10N.get("CGTL.CreateOrOpen",
"Create a new project or open an existing project?"));
GridData msgCellLayout = new GridData();
msgCellLayout.horizontalSpan = 4;
msgCellLayout.grabExcessHorizontalSpace = true;
msgCellLayout.verticalIndent = 25;
msgCell.setLayoutData(msgCellLayout);
Label emptyCell = new Label(dialog, SWT.NONE);
GridData emptyCellLayout = new GridData();
emptyCellLayout.grabExcessHorizontalSpace = true;
emptyCell.setLayoutData(emptyCellLayout);
if (CogToolPref.hasRecent()) {
openRecent = new Combo(dialog, SWT.DROP_DOWN | SWT.READ_ONLY);
openRecent.add(L10N.get("B.RECENT", "Open Recent"));
for (String pathName : CogToolPref.getRecent()) {
if (! MenuFactory.UNSET_FILE.equals(pathName)) {
openRecent.add(pathName);
}
}
openRecent.select(0);
}
openButton = new Button(dialog, SWT.PUSH);
createButton = new Button(dialog, SWT.PUSH);
if (buttonFont != null) {
createButton.setFont(buttonFont);
openButton.setFont(buttonFont);
}
openButton.setText(L10N.get("B.OPEN", "Open..."));
createButton.setText(L10N.get("B.CREATE", "Create"));
dialog.setDefaultButton(createButton);
GridData recentLayout = null;
GridData cancelLayout = null;
GridData okLayout = null;
if (OSUtils.MACOSX) {
if (openRecent != null) {
recentLayout = new GridData();
recentLayout.widthHint = 130;
}
cancelLayout = new GridData();
okLayout = new GridData();
// See Apple HIGs:
// http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGControls/chapter_18_section_2.html#//apple_ref/doc/uid/TP30000359-TPXREF186
cancelLayout.widthHint = 82;
okLayout.widthHint = 82;
}
else {
if (openRecent != null) {
recentLayout = new GridData(GridData.HORIZONTAL_ALIGN_END);
}
okLayout = new GridData(GridData.HORIZONTAL_ALIGN_END);
cancelLayout = new GridData(GridData.HORIZONTAL_ALIGN_END);
}
okLayout.verticalIndent = 7;
cancelLayout.verticalIndent = okLayout.verticalIndent;
if (recentLayout != null) {
recentLayout.verticalIndent = 4;
}
if (openRecent != null) {
openRecent.setLayoutData(recentLayout);
}
openButton.setLayoutData(cancelLayout);
createButton.setLayoutData(okLayout);
if (openRecent != null) {
openRecent.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
int i = openRecent.getSelectionIndex();
if (i > 0) {
userResponse = openRecent.getItem(i);
dialog.close();
}
}
});
}
// Dismiss the dialog box when OK button selected, with success
createButton.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
userResponse = ProjectInteraction.CREATE;
dialog.close();
}
});
// Dismiss the dialog box when Cancel button selected, with failure
openButton.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
userResponse = ProjectInteraction.OPEN;
dialog.close();
}
});
// SWT in its infinite wisdom disables the Quit menu item whenever
// a modal dialog is up on Macintosh. We really want to be able to
// quit when this guy is up, though, so this dialog is actually
// modeless, but we fake making it modal by refusing to let its
// parent become active.
//
// Sigh. The following used to work fine. But as of the update
// to SWT in October 2007 it no longer does -- for thoroughly
// mysterious reasons, now whenever you do this forceActive() it
// causes a further activate event on the parent to be queued. The
// end result is essentially an infinite recursion, but through
// the event posting mechanism, not through this method so we
// can't even get a decent handle on it (that is, the following
// code returns fine; it's just that in executing it the event
// processing code arranges that it will be called again Real Soon.
// Allowing the parent window to become active isn't too bad as
// it still can't come to the front, and even if manipulated bad
// things don't actually seem to happen. So just comment this
// stuff out for now. I'm going to file a bug report with the SWT
// people and see if maybe it can be fixed in the future, though.
// if (OSUtils.MACOSX) {
// this.modalFaker = new ShellAdapter() {
// public void shellActivated(ShellEvent evt)
// {
// if (! StartUpDialog.this.dialog.isDisposed()) {
// StartUpDialog.this.dialog.forceActive();
// }
// }
// };
//
// this.parent.addShellListener(this.modalFaker);
// }
}
public void removeModalFaker()
{
if (OSUtils.MACOSX && (modalFaker != null)) {
parent.removeShellListener(modalFaker);
modalFaker = null;
}
}
}
/**
* Data needed when creating/editing a task or task group.
* The flags control whether creating/editing a task or a task group,
* and whether to ask for how to place the new instance.
*/
public static class TaskRequestData
{
// Flags that may be OR'ed together
public static final int ASK_NOTHING = 0;
public static final int ASK_NATURE = 1;
public static final int ASK_IF_GROUP = 3; // subsumes ASK_NATURE
public static final int ASK_IF_BEFORE = 4;
public int flags;
public String taskName;
public GroupNature nature;
public boolean addAfter = true;
public boolean addAsTask = true;
}
public static class GenerateEntriesData
{
public ITermSimilarity algorithm;
public boolean computeAll;
public GenerateEntriesData(ITermSimilarity alg, boolean recompute)
{
algorithm = alg;
computeAll = recompute;
}
}
/**
* Data returned by requesting a web crawl import.
*/
public static interface IWebCrawlImport
{
/**
* Value returned from getMaxPages() and getDefaultDepth()
* when the system default should be used.
*/
public static final int USE_SYSTEM_DEFAULT = -1;
/**
* Returns the name of the design into which to import web pages as
* frames. If null returned, a new design should be created.
*/
public String getDesignName();
/**
* Returns the maximum number of pages that should be crawled; if
* USE_SYSTEM_DEFAULT, then the system's default count should be used.
*/
public int getMaxPages();
/**
* Returns the default depth to which initially specified URLs
* that do not set their own depth should be crawled; if
* USE_SYSTEM_DEFAULT, then the system's default depth should be used.
*/
public int getDefaultDepth();
/**
* Returns a list of URLs to crawl. If not null, the returned
* List will consist of WebCrawler.URLCrawlEntry instances, each
* of which contains a URL string and a depth integer.
*
*/
public List<URLCrawlEntry> getURLsToCrawl();
/**
* Returns whether to prune the web crawl when a URL is encountered
* that the Design into which the web pages are imported as Frames
* contains a Frame with the same name as the URL (keeping the
* Frame as it currently is). The other choice is to replace the Frame
* with the new page as crawled and continue crawling its links
* if the depth specifier allows.
*
* Please note that, if pruning the web crawl, it only applies
* to Frames that exist in the Design prior to the web crawl. Thus,
* this option only has an effect if resuming the web crawl for an
* existing Design.
*/
public boolean pruneSameURLs();
/**
* Returns whether or not to capture web page images
*/
public boolean captureImages();
/**
* Returns the desired width of the browser page.
*/
public int getBrowserWidth();
/**
* Returns the desired height of the browser page.
*/
public int getBrowserHeight();
}
/**
* Request whether to start the application by creating a new project
* or opening an existing project.
*
* @return CREATE if a new project is desired, OPEN if
* the user wishes to open an existing project,
* <code>null</code> if the user cancels.
* @author mlh
*/
public String createNewOrOpenExisting()
{
StartUpDialog dialog = null;
try {
dialog = new StartUpDialog(window);
return (String) dialog.open();
}
finally {
if (OSUtils.MACOSX) {
dialog.removeModalFaker();
}
}
}
public ProjectInteraction.IWebCrawlImport requestWebCrawlParms(Project project,
int defaultMaxToCrawl)
{
WebCrawlImportDialog dialog =
new WebCrawlImportDialog(window, project, defaultMaxToCrawl);
Object notCanceled = dialog.open();
if (notCanceled != null) {
return dialog;
}
return null;
}
public SNIFACTGroupParameters requestSNIFACTParameters(boolean hasScript,
List<Frame> sortedFrames,
SNIFACTParameters parms,
Set<ITermSimilarity> algSet,
int addGroupMode)
{
if (hasScript) {
String msg = confirmOverwriteScriptMsg;
if (SWT.OK != WindowUtil.presentConfirmDialog(window,
confirmTitle,
msg))
{
return null;
}
}
SNIFACTDialog dialog =
new SNIFACTDialog(window, sortedFrames, parms, algSet, addGroupMode);
Object notCanceled = dialog.open();
if (notCanceled != null) {
return dialog.getParameters();
}
return null;
}
}