/*******************************************************************************
* 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.controller;
import java.util.ArrayList;
import java.util.List;
import edu.cmu.cs.hcii.cogtool.CogToolLID;
import edu.cmu.cs.hcii.cogtool.model.Design;
import edu.cmu.cs.hcii.cogtool.model.ISimilarityDictionary;
import edu.cmu.cs.hcii.cogtool.model.ITermSimilarity;
import edu.cmu.cs.hcii.cogtool.model.Project;
import edu.cmu.cs.hcii.cogtool.model.WidgetAttributes;
import edu.cmu.cs.hcii.cogtool.model.ISimilarityDictionary.DictEntry;
import edu.cmu.cs.hcii.cogtool.model.ISimilarityDictionary.DictValue;
import edu.cmu.cs.hcii.cogtool.ui.DictionaryEditorLID;
import edu.cmu.cs.hcii.cogtool.ui.DictionaryEditorUI;
import edu.cmu.cs.hcii.cogtool.ui.FrameEditorLID;
import edu.cmu.cs.hcii.cogtool.ui.Interaction;
import edu.cmu.cs.hcii.cogtool.ui.PendingDictEntry;
import edu.cmu.cs.hcii.cogtool.ui.ProjectLID;
import edu.cmu.cs.hcii.cogtool.ui.UI;
import edu.cmu.cs.hcii.cogtool.util.AListenerAction;
import edu.cmu.cs.hcii.cogtool.util.AUndoableEdit;
import edu.cmu.cs.hcii.cogtool.util.CompoundUndoableEdit;
import edu.cmu.cs.hcii.cogtool.util.IListenerAction;
import edu.cmu.cs.hcii.cogtool.util.IUndoableEdit;
import edu.cmu.cs.hcii.cogtool.util.IUndoableEditSequence;
import edu.cmu.cs.hcii.cogtool.util.L10N;
import edu.cmu.cs.hcii.cogtool.util.PrecisionUtilities;
import edu.cmu.cs.hcii.cogtool.util.UndoManager;
public class DictionaryEditorController extends DefaultController
{
protected static final String ADD_TERM =
L10N.get("DEC.AddTerm", "Add Term");
protected static final String MODIFY_TERM =
L10N.get("DEC.ModifyTerm", "Modify Term");
protected static final String SET_SIMILARITY =
L10N.get("DEC.SetSimilarity", "Set Similarity");
protected static final String SET_ALGORITHM =
L10N.get("DEC.SetAlgorithm", "Set Algorithm");
protected static final String CREATE_ROW =
L10N.get("DEC.CreateRow", "Create Row");
protected static final String DELETE_ROW =
L10N.get("DEC.DeleteRow", "Delete Row");
protected static final String DELETE_ROWS =
L10N.get("DEC.DeleteRows", "Delete Rows");
protected static final String ALG_UNCHANGED =
L10N.get("DEC.UnchangedAlg", "Algorithm was not changed.");
protected static final String ALG_CHANGED =
L10N.get("DEC.ChangedAlg", "Algorithm changed successfully.");
protected static final String SIMIL_UNCHANGED =
L10N.get("DEC.UnchangedSimil", "Similarity was not changed.");
protected static final String STRING_UNCHANGED =
L10N.get("DEC.UnchangedString", "String was not changed.");
protected static final String ERROR_TITLE =
L10N.get("DEC.ErrorTitle", "Dictionary Error");
protected static final String NO_ENTRY =
L10N.get("DEC.NoEntry", "Cannot edit a nonexistant entry.");
protected static final String NO_SELECTION =
L10N.get("DEC.NoSelection", "Nothing is selected.");
protected static final String ENTRY_EXISTS =
L10N.get("DEC.EntryExists",
"This entry already exists in the dictionary.");
protected DictionaryEditorUI ui;
protected ISimilarityDictionary dictionary;
protected Interaction interaction;
protected PendingDictEntry pendingEntry;
protected Design design;
public DictionaryEditorController(ISimilarityDictionary dict,
Design d,
Project proj)
{
super(proj);
dictionary = dict;
design = d;
undoMgr =
UndoManager.getUndoManager(dictionary,
project);
pendingEntry = new PendingDictEntry(dictionary);
ui = new DictionaryEditorUI(dictionary, design, pendingEntry, project, undoMgr);
interaction = ui.getStandardInteraction();
assignActions();
ui.setVisible(true);
}
@Override
public void assignActions()
{
super.assignActions();
// Enable undo & redo
ui.setAction(FrameEditorLID.Undo,
new UndoController.UndoAction(undoMgr,
interaction));
ui.setAction(FrameEditorLID.Redo,
new UndoController.RedoAction(undoMgr,
interaction));
ui.setAction(DictionaryEditorLID.StartNewEntry,
createAddNewTermAction());
ui.setAction(DictionaryEditorLID.SetGoalString,
createSetStringAction(0));
ui.setAction(DictionaryEditorLID.SetSearchString,
createSetStringAction(1));
ui.setAction(DictionaryEditorLID.CreateNewEntry,
createAddNewEntryAction());
ui.setAction(DictionaryEditorLID.SetSimilarity,
createSetSimilarityAction());
ui.setAction(DictionaryEditorLID.ComputeSimilarity,
createComputeSimilarityAction());
ui.setAction(DictionaryEditorLID.SetAlgorithm,
createSetAlgorithmAction());
ui.setAction(DictionaryEditorLID.Delete,
createDeleteEntryAction());
ui.setAction(ProjectLID.ExportDictToCSV,
new AListenerAction() {
public boolean performAction(Object actionParms)
{
return DictionaryEditorCmd.exportDictionaryToCSV(dictionary,
interaction);
}
});
ui.setAction(ProjectLID.ImportDict,
new AListenerAction() {
public boolean performAction(Object actionParms)
{
return DictionaryEditorCmd.importDictionary(design,
dictionary,
WidgetAttributes.NO_DICTIONARY,
interaction,
undoMgr, null);
}
});
ui.setAction(CogToolLID.SelectAll,
new AListenerAction() {
public boolean performAction(Object actionParms)
{
ui.selectAll();
return true;
}
});
}
protected double computeSimilarity(String goal,
String search,
ITermSimilarity alg)
{
List<String> errors = new ArrayList<String>();
double similarity = alg.determineSimilarity(goal,
search,
errors,
null);
if (errors.size() > 0) {
interaction.reportProblems("Encountered:", errors);
}
return similarity;
}
protected IListenerAction createAddNewTermAction()
{
return new IListenerAction() {
public Class<?> getParameterClass()
{
return DictionaryEditorUI.AddStringParms.class;
}
public boolean performAction(Object actionParms)
{
final DictionaryEditorUI.AddStringParms parms = (DictionaryEditorUI.AddStringParms) actionParms;
final String oldString;
if (parms.isGoal) {
oldString = pendingEntry.getDictEntry().goalWord;
if (parms.newString.equals(oldString)) {
interaction.setStatusMessage(STRING_UNCHANGED);
return true;
}
pendingEntry.setGoal(parms.newString);
}
else {
oldString = pendingEntry.getDictEntry().searchWord;
if (parms.newString.equals(oldString)) {
interaction.setStatusMessage(STRING_UNCHANGED);
return true;
}
pendingEntry.setSearch(parms.newString);
}
undoMgr.addEdit(new AUndoableEdit(DictionaryEditorLID.StartNewEntry)
{
@Override
public String getPresentationName()
{
return ADD_TERM;
}
@Override
public void redo()
{
super.redo();
if (parms.isGoal) {
pendingEntry.setGoal(parms.newString);
}
else {
pendingEntry.setSearch(parms.newString);
}
}
@Override
public void undo()
{
super.undo();
if (parms.isGoal) {
pendingEntry.setGoal(oldString);
}
else {
pendingEntry.setSearch(oldString);
}
}
});
return true;
}
};
}
protected IListenerAction createDeleteEntryAction()
{
return new IListenerAction() {
public Class<?> getParameterClass()
{
return int[].class;
}
public boolean performAction(Object actionParms)
{
final int[] rows = (int[]) actionParms;
final DictEntry[] deletedEntries = new DictEntry[rows.length];
final DictValue[] deletedValues = new DictValue[rows.length];
for (int i = rows.length - 1; i >= 0; i--) {
deletedEntries[i] = dictionary.getEntry(rows[i]);
if (deletedEntries[i] == null) {
interaction.reportProblem(ERROR_TITLE, NO_ENTRY);
continue;
}
deletedValues[i] = dictionary.getValue(deletedEntries[i]);
dictionary.removeEntry(rows[i]);
}
undoMgr.addEdit(new AUndoableEdit(DictionaryEditorLID.Delete)
{
@Override
public String getPresentationName()
{
return (rows.length == 1) ? DELETE_ROW : DELETE_ROWS;
}
@Override
public void redo()
{
super.redo();
for (int i = rows.length - 1; i >= 0; i--) {
dictionary.removeEntry(rows[i]);
}
}
@Override
public void undo()
{
super.undo();
for (int i = 0; i < rows.length; i++) {
dictionary.insertEntry(deletedEntries[i],
deletedValues[i],
rows[i]);
}
}
});
return true;
}
};
}
protected IListenerAction createAddNewEntryAction()
{
return new IListenerAction() {
public Class<?> getParameterClass()
{
return DictionaryEditorUI.ComputeSimilarityParms.class;
}
public boolean performAction(Object actionParms)
{
final DictionaryEditorUI.ComputeSimilarityParms parms =
(DictionaryEditorUI.ComputeSimilarityParms) actionParms;
final ITermSimilarity oldAlg =
pendingEntry.getDictEntry().algorithm;
final double oldSimilarity = pendingEntry.getSimilarity();
final double similarity;
if (checkNewEntry(parms.goalString,
parms.searchString,
parms.algorithm))
{
interaction.reportProblem(ERROR_TITLE, ENTRY_EXISTS);
return false;
}
if (parms.algorithm == ITermSimilarity.MANUAL) {
similarity = oldSimilarity;
}
else {
similarity = computeSimilarity(parms.goalString,
parms.searchString,
parms.algorithm);
}
final String oldGoal = pendingEntry.getDictEntry().goalWord;
final String oldSearch = pendingEntry.getDictEntry().searchWord;
pendingEntry.clear();
final DictValue value = new DictValue(similarity);
dictionary.setSimilarity(parms.goalString,
parms.searchString,
parms.algorithm,
value,
parms.rowIndex);
undoMgr.addEdit(new AUndoableEdit(DictionaryEditorLID.CreateNewEntry) {
@Override
public String getPresentationName()
{
return CREATE_ROW;
}
@Override
public void redo()
{
super.redo();
pendingEntry.clear();
dictionary.setSimilarity(parms.goalString,
parms.searchString,
parms.algorithm,
value,
parms.rowIndex);
}
@Override
public void undo()
{
super.undo();
dictionary.removeEntry(parms.rowIndex);
pendingEntry.setGoal(oldGoal);
pendingEntry.setSearch(oldSearch);
pendingEntry.setAlgorithm(oldAlg);
pendingEntry.setSimilarity(oldSimilarity);
}
});
return true;
}
};
}
protected IListenerAction createSetAlgorithmAction()
{
return new IListenerAction() {
public Class<?> getParameterClass()
{
return DictionaryEditorUI.SetAlgorithmParms.class;
}
public boolean performAction(Object actionParms)
{
DictionaryEditorUI.SetAlgorithmParms parms =
(DictionaryEditorUI.SetAlgorithmParms) actionParms;
double similarity;
if (parms.rowIndices.length == 0) {
interaction.reportProblem(ERROR_TITLE, NO_SELECTION);
return false;
}
CompoundUndoableEdit editSeq =
new CompoundUndoableEdit(SET_ALGORITHM,
DictionaryEditorLID.SetAlgorithm);
for (int rowIndice : parms.rowIndices) {
DictEntry entry = dictionary.getEntry(rowIndice);
if (entry == null) {
final ITermSimilarity oldAlg =
pendingEntry.getDictEntry().algorithm;
final double oldSimilarity =
pendingEntry.getSimilarity();
final ITermSimilarity newAlg = parms.algorithm;
boolean equal = (newAlg == null) ? oldAlg == null
: newAlg.equals(oldAlg);
if (equal) {
interaction.setStatusMessage(ALG_UNCHANGED);
continue;
}
pendingEntry.setAlgorithm(newAlg);
pendingEntry.setSimilarity(ITermSimilarity.UNKNOWN);
editSeq.addEdit(new AUndoableEdit(DictionaryEditorLID.SetAlgorithm) {
@Override
public String getPresentationName()
{
return SET_ALGORITHM;
}
@Override
public void redo()
{
super.redo();
pendingEntry.setAlgorithm(newAlg);
pendingEntry.setSimilarity(ITermSimilarity.UNKNOWN);
}
@Override
public void undo()
{
super.undo();
pendingEntry.setAlgorithm(oldAlg);
pendingEntry.setSimilarity(oldSimilarity);
}
});
interaction.setStatusMessage(ALG_CHANGED);
continue;
}
if (parms.algorithm.equals(entry.algorithm)) {
interaction.setStatusMessage(ALG_UNCHANGED);
continue;
}
if (checkNewEntry(entry.goalWord,
entry.searchWord,
parms.algorithm))
{
interaction.reportProblem(ERROR_TITLE, ENTRY_EXISTS);
continue;
}
if (parms.algorithm != ITermSimilarity.MANUAL) {
similarity = computeSimilarity(entry.goalWord,
entry.searchWord,
parms.algorithm);
}
else {
similarity = dictionary.getValue(entry).similarity;
}
setSimilarity(rowIndice,
similarity,
parms.algorithm,
editSeq);
}
editSeq.end();
if (editSeq.isSignificant()) {
undoMgr.addEdit(editSeq);
interaction.setStatusMessage(ALG_CHANGED);
}
return true;
}
};
}
/**
* Return true if an entry with these components already exists
* (Don't allow an entry to be modified into a duplicate of another existing
* entry.)
*/
protected boolean checkNewEntry(String goalWord,
String searchWord,
ITermSimilarity algorithm)
{
DictEntry testEntry = new DictEntry(goalWord, searchWord, algorithm);
return dictionary.containsEntry(testEntry);
}
protected IListenerAction createComputeSimilarityAction()
{
return new IListenerAction() {
public Class<?> getParameterClass()
{
return DictionaryEditorUI.ComputeSimilarityParms.class;
}
public boolean performAction(Object actionParms)
{
DictionaryEditorUI.ComputeSimilarityParms parms =
(DictionaryEditorUI.ComputeSimilarityParms) actionParms;
double similarity;
if ("".equals(parms.goalString) ||
"".equals(parms.searchString))
{
interaction.reportProblem(ERROR_TITLE, NO_ENTRY);
return true;
}
similarity = computeSimilarity(parms.goalString,
parms.searchString,
parms.algorithm);
setSimilarity(parms.rowIndex, similarity, parms.algorithm,
undoMgr);
return true;
}
};
}
protected IListenerAction createSetSimilarityAction()
{
return new IListenerAction() {
public Class<?> getParameterClass()
{
return DictionaryEditorUI.SetSimilarityParms.class;
}
public boolean performAction(Object actionParms)
{
DictionaryEditorUI.SetSimilarityParms parms = (DictionaryEditorUI.SetSimilarityParms) actionParms;
DictEntry entry = dictionary.getEntry(parms.rowIndex);
if (entry == null) {
final double oldSimil = pendingEntry.getSimilarity();
final double newSimil = parms.similarity;
if (PrecisionUtilities.withinEpsilon(oldSimil,
newSimil,
0.001))
{
interaction.setStatusMessage(SIMIL_UNCHANGED);
return true;
}
final ITermSimilarity oldAlg =
pendingEntry.getDictEntry().algorithm;
pendingEntry.setSimilarity(newSimil);
pendingEntry.setAlgorithm(ITermSimilarity.MANUAL);
undoMgr.addEdit(new AUndoableEdit(DictionaryEditorLID.SetSimilarity) {
@Override
public String getPresentationName()
{
return SET_SIMILARITY;
}
@Override
public void redo()
{
super.redo();
pendingEntry.setSimilarity(newSimil);
pendingEntry.setAlgorithm(ITermSimilarity.MANUAL);
}
@Override
public void undo()
{
super.undo();
pendingEntry.setSimilarity(oldSimil);
pendingEntry.setAlgorithm(oldAlg);
}
});
return true;
}
if (PrecisionUtilities.withinEpsilon(dictionary.getValue(entry).similarity,
parms.similarity,
0.001))
{
interaction.setStatusMessage(SIMIL_UNCHANGED);
return true;
}
setSimilarity(parms.rowIndex,
parms.similarity,
ITermSimilarity.MANUAL,
undoMgr);
return true;
}
};
}
protected void setSimilarity(final int rowIndex,
final double similarity,
final ITermSimilarity algorithm,
IUndoableEditSequence editSeq)
{
DictEntry entry = dictionary.getEntry(rowIndex);
final String goal = entry.goalWord;
final String search = entry.searchWord;
DictValue oldV = dictionary.getValue(entry);
final DictValue oldValue = new DictValue(oldV.similarity,
oldV.editedDate);
final DictValue newValue = new DictValue(similarity);
if (PrecisionUtilities.withinEpsilon(oldValue.similarity,
similarity,
0.001))
{
interaction.setStatusMessage(SIMIL_UNCHANGED);
return;
}
final ITermSimilarity oldAlg = entry.algorithm;
dictionary.setSimilarity(goal, search, algorithm,
newValue, rowIndex);
editSeq.addEdit(new AUndoableEdit(DictionaryEditorLID.SetSimilarity) {
@Override
public String getPresentationName()
{
return SET_SIMILARITY;
}
@Override
public void redo()
{
super.redo();
dictionary.setSimilarity(goal, search, algorithm,
newValue, rowIndex);
}
@Override
public void undo()
{
super.undo();
dictionary.setSimilarity(goal, search, oldAlg,
oldValue, rowIndex);
}
});
}
protected IListenerAction createSetStringAction(final int column)
{
return new IListenerAction() {
public Class<?> getParameterClass()
{
return DictionaryEditorUI.SetStringParms.class;
}
public boolean performAction(Object actionParms)
{
DictionaryEditorUI.SetStringParms p = (DictionaryEditorUI.SetStringParms) actionParms;
if (p != null) {
final int rowIndex = p.rowIndex;
final String newString = p.string;
IUndoableEdit edit = null;
DictEntry entry = dictionary.getEntry(rowIndex);
if (entry == null) {
interaction.reportProblem(ERROR_TITLE, NO_ENTRY);
return true;
}
CogToolLID lid;
final String goal;
final String search;
final String oldGoal;
final String oldSearch;
if (column == 0) {
goal = newString;
oldGoal = entry.goalWord;
if (goal.equals(oldGoal)) {
interaction.setStatusMessage(STRING_UNCHANGED);
return true;
}
search = entry.searchWord;
oldSearch = search;
lid = DictionaryEditorLID.SetGoalString;
}
else {
goal = entry.goalWord;
oldGoal = goal;
search = newString;
oldSearch = entry.searchWord;
if (search.equals(oldSearch)) {
interaction.setStatusMessage(STRING_UNCHANGED);
return true;
}
lid = DictionaryEditorLID.SetSearchString;
}
if (checkNewEntry(goal, search, entry.algorithm)) {
interaction.reportProblem(ERROR_TITLE, ENTRY_EXISTS);
return false;
}
dictionary.updateEntry(rowIndex, goal, search);
CompoundUndoableEdit editSeq =
new CompoundUndoableEdit(MODIFY_TERM, lid);
edit =
new AUndoableEdit(lid)
{
@Override
public String getPresentationName()
{
return MODIFY_TERM;
}
@Override
public void redo()
{
super.redo();
dictionary.updateEntry(rowIndex,
goal,
search);
}
@Override
public void undo()
{
super.undo();
dictionary.updateEntry(rowIndex,
oldGoal,
oldSearch);
}
};
editSeq.addEdit(edit);
if (entry.algorithm != ITermSimilarity.MANUAL) {
double similarity = computeSimilarity(goal,
search,
entry.algorithm);
setSimilarity(rowIndex,
similarity,
entry.algorithm,
editSeq);
}
editSeq.end();
undoMgr.addEdit(editSeq);
}
return true;
}
};
}
@Override
protected Object getModelObject()
{
return dictionary;
}
@Override
public UI getUI()
{
return ui;
}
public void setCurrentAlgorithm(ITermSimilarity alg)
{
pendingEntry.setAlgorithm(alg);
}
public ITermSimilarity getCurrentAlgorithm()
{
return pendingEntry.getDictEntry().algorithm;
}
/**
* Creates a new DictionaryEditorController instance for viewing the scripts
* in a task group
* @param d
* @return the Controller instance for the given DictionaryEditorController
*/
public static DictionaryEditorController openController(ISimilarityDictionary dict,
Design d,
Project taProj)
{
// Check whether this project is already open
DictionaryEditorController controller =
(DictionaryEditorController)
ControllerRegistry.ONLY.findOpenController(dict);
// If already open, just bring it to front
if (controller != null) {
controller.takeFocus();
}
else {
// if this project isn't open, create a new controller
controller = new DictionaryEditorController(dict, d, taProj);
ControllerRegistry.ONLY.addOpenController(controller);
}
controller.setCurrentAlgorithm(dict.getCurrentAlgorithm());
return controller;
}
}