use of edu.cmu.cs.hcii.cogtool.model.IWidget in project cogtool by cogtool.
the class DesignEditorCmd method repositionChildren.
/**
* TODO: If we ever allow children above or left of a parent,
* we need to pass in childrenLocation here in addition to the group.
*/
public static void repositionChildren(SimpleWidgetGroup group, double x, double y) {
int orientation = group.getOrientation();
if (orientation == SimpleWidgetGroup.FREEFORM) {
return;
}
Iterator<IWidget> groupIter = group.iterator();
while (groupIter.hasNext()) {
IWidget widget = groupIter.next();
widget.setWidgetOrigin(x, y);
if (orientation == SimpleWidgetGroup.HORIZONTAL) {
x += widget.getEltBounds().width;
} else if (orientation == SimpleWidgetGroup.VERTICAL) {
y += widget.getEltBounds().height;
}
if (widget instanceof AParentWidget) {
repositionChildren((AParentWidget) widget);
}
}
}
use of edu.cmu.cs.hcii.cogtool.model.IWidget in project cogtool by cogtool.
the class DesignEditorCmd method pasteElements.
// pasteFrameElementGroup
public static int pasteElements(Design design, final Frame frame, Collection<Object> objects, DemoStateManager mgr, IUndoableEditSequence editSequence) {
// If given objects contain widgets, insert into the given frame
if ((objects != null) && (objects.size() > 0)) {
Iterator<Object> objIt = objects.iterator();
Set<SimpleWidgetGroup> addedGroups = new HashSet<SimpleWidgetGroup>();
final Set<IWidget> addedRemoteLabels = new HashSet<IWidget>();
final Set<FrameElementGroup> addedEltGroups = new HashSet<FrameElementGroup>();
int numPasted = 0;
// May need to add a device
int currentDeviceTypes = DeviceType.buildDeviceSet(design.getDeviceTypes());
// create them.
while (objIt.hasNext()) {
Object o = objIt.next();
if (o instanceof IWidget) {
IWidget widget = (IWidget) o;
numPasted += pasteWidget(widget, design, currentDeviceTypes, frame, mgr, editSequence, addedEltGroups, addedRemoteLabels);
SimpleWidgetGroup group = widget.getParentGroup();
if (group != null) {
addedGroups.add(group);
}
} else if (o instanceof FrameElementGroup) {
numPasted += pasteFrameElementGroup((FrameElementGroup) o, design, currentDeviceTypes, frame, mgr, editSequence, addedEltGroups, addedRemoteLabels);
}
}
Iterator<SimpleWidgetGroup> groupsIter = addedGroups.iterator();
while (groupsIter.hasNext()) {
SimpleWidgetGroup group = groupsIter.next();
repositionChildren(group);
if (group instanceof GridButtonGroup) {
((GridButtonGroup) group).recalculateOffsets();
}
addedEltGroups.addAll(group.getEltGroups());
}
Iterator<FrameElementGroup> eltGroups = addedEltGroups.iterator();
while (eltGroups.hasNext()) {
frame.addEltGroup(eltGroups.next());
}
Iterator<IWidget> remoteLabels = addedRemoteLabels.iterator();
while (remoteLabels.hasNext()) {
IWidget remoteLabel = remoteLabels.next();
if (!frame.containsWidget(remoteLabel)) {
String uniqueName = NamedObjectUtil.makeNameUnique(remoteLabel.getName(), frame.getWidgets());
remoteLabel.setName(uniqueName);
frame.addWidget(remoteLabel);
}
}
IUndoableEdit edit = new AUndoableEdit(CogToolLID.Paste) {
@Override
public String getPresentationName() {
return PASTE;
}
@Override
public void redo() {
super.redo();
Iterator<FrameElementGroup> eltGroups = addedEltGroups.iterator();
while (eltGroups.hasNext()) {
frame.addEltGroup(eltGroups.next());
}
Iterator<IWidget> remoteLabels = addedRemoteLabels.iterator();
while (remoteLabels.hasNext()) {
IWidget remoteLabel = remoteLabels.next();
if (!frame.containsWidget(remoteLabel)) {
frame.addWidget(remoteLabel);
}
}
}
@Override
public void undo() {
super.undo();
Iterator<FrameElementGroup> eltGroups = addedEltGroups.iterator();
while (eltGroups.hasNext()) {
frame.removeEltGroup(eltGroups.next());
}
Iterator<IWidget> remoteLabels = addedRemoteLabels.iterator();
while (remoteLabels.hasNext()) {
IWidget remoteLabel = remoteLabels.next();
if (frame.containsWidget(remoteLabel)) {
frame.removeWidget(remoteLabel);
}
}
}
};
editSequence.addEdit(edit);
return numPasted;
}
return 0;
}
use of edu.cmu.cs.hcii.cogtool.model.IWidget in project cogtool by cogtool.
the class DemoScriptCmd method exportScriptToCSV.
public static boolean exportScriptToCSV(Script script, Project project, Interaction interaction, IUndoableEditSequence editSeq) {
Demonstration demo = script.getDemonstration();
TaskApplication ta = demo.getTaskApplication();
Design design = ta.getDesign();
AUndertaking task = ta.getTask();
String name = project.getName();
name += "_" + design.getName();
name += "_" + task.getName();
File dest = null;
if (interaction != null) {
dest = interaction.selectCSVFileDest(name);
} else {
dest = new File(CogTool.exportCSVKludgeDir, name + ".txt");
}
if (dest == null) {
return false;
}
FileWriter fw = null;
BufferedWriter buffer = null;
try {
fw = new FileWriter(dest);
buffer = new BufferedWriter(fw);
CSVSupport.writeCell("Format version:", buffer);
CSVSupport.addSeparator(buffer);
CSVSupport.writeCell(FORMAT_VERSION, buffer);
CSVSupport.addLineEnding(buffer);
Date now = new Date();
String date = DateFormat.getDateTimeInstance().format(now);
CSVSupport.writeCell("Date and Time:", buffer);
CSVSupport.addSeparator(buffer);
CSVSupport.writeCell(date, buffer);
CSVSupport.addLineEnding(buffer);
CSVSupport.writeCell("Project Name:", buffer);
CSVSupport.addSeparator(buffer);
CSVSupport.writeCell(project.getName(), buffer);
CSVSupport.addLineEnding(buffer);
CSVSupport.writeCell("Design Name:", buffer);
CSVSupport.addSeparator(buffer);
CSVSupport.writeCell(design.getName(), buffer);
CSVSupport.addLineEnding(buffer);
CSVSupport.writeCell("Task Hierarchy:", buffer);
String taskName = task.getFullName();
String[] cells = taskName.split(":");
for (String cell : cells) {
CSVSupport.addSeparator(buffer);
CSVSupport.writeCell(cell, buffer);
}
CSVSupport.addLineEnding(buffer);
CSVSupport.addSeparator(buffer);
CSVSupport.addLineEnding(buffer);
buffer.write("\"Frame\",\"Action\",\"Widget-Name\"," + "\"Displayed-Label\",\"Widget-Type\"");
CSVSupport.addLineEnding(buffer);
IWidget lastMovedToWidget = null;
Iterator<DefaultModelGeneratorState> stepStates = script.getStepStates().iterator();
while (stepStates.hasNext()) {
DefaultModelGeneratorState stepState = stepStates.next();
AScriptStep step = stepState.getScriptStep();
TransitionSource stepFocus = step.getStepFocus();
String frameName = step.getCurrentFrame().getName();
String actionName = KeyDisplayUtil.convertActionToMenuText(step.getLocalizedString());
if ((!(step instanceof LookAtScriptStep)) && (!(step instanceof ThinkScriptStep)) && (!(step instanceof TextActionSegment))) {
actionName = step.getLocalizedActionString(actionName, lastMovedToWidget);
}
lastMovedToWidget = stepState.getLastMovedToWidget();
String widgetName = "";
String widgetType = "";
String widgetTitle = "";
if (stepFocus != null) {
widgetName = stepFocus.getName();
if (stepFocus instanceof IWidget) {
IWidget w = (IWidget) stepFocus;
widgetType = w.getWidgetType().toString();
String s = w.getTitle();
if (s != null) {
widgetTitle = s;
}
}
}
CSVSupport.writeCell(frameName, buffer);
CSVSupport.addSeparator(buffer);
CSVSupport.writeCell(actionName, buffer);
CSVSupport.addSeparator(buffer);
CSVSupport.writeCell(widgetName, buffer);
CSVSupport.addSeparator(buffer);
CSVSupport.writeCell(widgetTitle, buffer);
CSVSupport.addSeparator(buffer);
CSVSupport.writeCell(widgetType, buffer);
CSVSupport.addLineEnding(buffer);
}
Frame resultFrame = demo.getResultFrame();
if (resultFrame != null) {
CSVSupport.writeCell(resultFrame.getName(), buffer);
}
if (interaction != null) {
interaction.setStatusMessage(L10N.get("DSO.ExportCompletedPre", "Export completed to ") + dest + L10N.get("DSO.ExportCompletePost", "."));
}
} catch (IOException e) {
if (interaction != null) {
interaction.reportProblem("File I/O Error", e.getMessage());
} else {
e.printStackTrace();
}
return false;
} finally {
try {
if (buffer != null) {
buffer.close();
}
if (fw != null) {
fw.close();
}
} catch (IOException e) {
if (interaction != null) {
interaction.reportProblem("File I/O Error on Close", e.getMessage());
} else {
e.printStackTrace();
}
return false;
}
}
return true;
}
use of edu.cmu.cs.hcii.cogtool.model.IWidget in project cogtool by cogtool.
the class BalsamiqButtonAPIConverter method parseBMMLWidget.
/** Helper function used by parseFrame
* This method is used to parse the tags of each control tag in Balsamiq XML. A control tag
* represents a Balsamiq Widget.
*
* @param node a node of the tree that represents a Balsamiq widget
* @frame frame that the widget is being added to
* @group parent group
* @groupX x coordinate of parent group
* @groupY y coordinate of parent group
* @return the newly created widget
*/
protected Widget parseBMMLWidget(Node node, Frame frame, SimpleWidgetGroup group, double groupX, double groupY) throws IOException {
System.out.println("parseBMMLWidget " + group + " x: " + groupX + "y: " + groupY);
NodeList children = node.getChildNodes();
Widget widget = null;
WidgetType widgetType = null;
String balsamiqControlType = getAttributeValue(node, CONTROL_TYPE_ATTR);
String widgetTypeString = (balsamiqControlType == null) ? null : getBMMLWidgetType(balsamiqControlType);
String widgetName = getAttributeValue(node, CONTROL_ID_ATTR);
if (widgetName == null) {
//TODO: make a random widget name and move on. report to the user. need to be unique within the frame. Frame.java has a method for this
}
System.out.println("462- wN " + widgetName + "widT " + widgetTypeString);
if (widgetTypeString == null) {
//TODO: report to the user
} else {
widgetType = getWidgetType(widgetTypeString);
//Parse the widget name, location and size from the attributes of the XML tag
//TODO: Error check all of the getAttributeValues()
double x = Double.parseDouble(getAttributeValue(node, X_ATTR));
double y = Double.parseDouble(getAttributeValue(node, Y_ATTR));
//TODO: difference between w and measuredW, same for height
double width = Integer.parseInt(getAttributeValue(node, BWIDTH_ATTR));
double height = Integer.parseInt(getAttributeValue(node, BHEIGHT_ATTR));
double measWidth = Integer.parseInt(getAttributeValue(node, MEASURED_WIDTH_ATTR));
double measHeight = Integer.parseInt(getAttributeValue(node, MEASURED_HEIGHT_ATTR));
if (//TODO: make sure the dimensions are positive
width == -1 && height == -1) {
System.out.println("493- changing widget dimensions");
width = measWidth;
height = measHeight;
}
/*bounds is the size and location of the widget*/
if (group != null) {
System.out.println("488-Group is not null");
DoubleRectangle rect = group.getGroupBounds();
if (rect != null) {
System.out.println("500-rect is not null");
//x += groupX;
//y += groupY;
}
}
x += groupX;
y += groupY;
System.out.println("new widget has dimens:" + x + " " + y);
DoubleRectangle bounds = new DoubleRectangle(x, y, width, height);
if (widgetType == WidgetType.Check) {
System.out.println("505-The widget is a check so now make a group for it");
if (group == null) {
group = new GridButtonGroup();
//give it a random widget name
group.setName("newName");
groupRegistry.put("newName", group);
}
//if(group instanceof GridButtonGroup)
//{
int eltCount = group.elementCount();
System.out.println("513-group is gridbuttongroup " + group.getName() + " " + eltCount);
if (eltCount > 0) {
//TODO: check if the widgets align best horizontally or vertically
//align the widgets to average coord, first, left or rightmost
IWidget wid = group.getElement(group.elementCount() - 1);
DoubleRectangle bounds2 = wid.getEltBounds();
System.out.println("530 " + bounds2.getX() + " " + bounds2.getWidth() + " " + bounds2.getY() + " " + bounds2.getHeight());
double diffX = Math.abs(x - bounds2.getX());
double diffY = Math.abs(y - bounds2.getY());
System.out.println("diffX " + diffX + " " + diffY);
DoubleRectangle bounds3 = new DoubleRectangle(bounds2.getX() + bounds2.getWidth(), bounds2.getY(), width, height);
if (diffX < diffY) {
bounds3 = new DoubleRectangle(bounds2.getX(), bounds2.getY() + bounds2.getHeight(), width, height);
}
widget = new CheckBox((GridButtonGroup) group, bounds3, widgetName);
} else {
widget = new CheckBox((GridButtonGroup) group, bounds, widgetName);
}
widget.setWidgetType(widgetType);
/*}
else
{
System.out.println("517-group2 is gridbuttongroup");
GridButtonGroup group2 = new GridButtonGroup();
group2.setName("newNameCheck");
groupRegistry.put("newNameCheck", group2);
widget = new CheckBox(group2, bounds, widgetName);
//group.addElement((IWidget) group2);
}*/
} else {
widget = new Widget(bounds, widgetType);
}
widget.setName(widgetName);
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
String nodeName = child.getNodeName();
/*Whitespace in the DOM tree is represented as #text. Ignore these nodes. Anywhere between the open and closed tag*/
if (!nodeName.equals("#text")) {
if (nodeName.equalsIgnoreCase(CONTROL_PROP_ELT)) {
NodeList controlTags = child.getChildNodes();
for (int j = 0; j < controlTags.getLength(); j++) {
Node controlTag = controlTags.item(j);
String propertyTag = controlTag.getNodeName();
//CogTool widget Display Label
if (propertyTag.equalsIgnoreCase(BALSAMIQ_TEXT_ELT)) {
/*Must decode the title. For instance the title in
Balsamiq, "First%20Frame" is "First Frame" in CogTool*/
String title = getElementText(controlTag);
title = URLDecoder.decode(title, "UTF-8");
widget.setTitle(title);
} else //CogTool transition on the present widget
if (propertyTag.equalsIgnoreCase(HREF_ELT)) {
String destinationFileName = getElementText(controlTag);
File destinationFile = new File(designPathName, destinationFileName);
//Make sure the file exists before attempting to parse the file
if (destinationFile.exists()) {
parseBalsamiqFile(destinationFile);
parseTransition(destinationFileName, widget);
}
} else if (propertyTag.equalsIgnoreCase(STATE_ELT)) {
//TODO: work on states
//A Balsamiq Button can be normal, selected, or disabled
String state = getElementText(controlTag);
if (state.equals("selected")) {
widget.setAttribute(WidgetAttributes.IS_SELECTED_ATTR, Boolean.TRUE);
} else {
//TODO: Other Balsamiq states like "disabled", "disabled and selected"
}
}
// END OF STATE OF BUTTON
}
// END OF PROPERTY TAG
}
// END OF CONTROL PROPERTIES TAG
}
}
}
widget.setRendered(true);
return widget;
}
use of edu.cmu.cs.hcii.cogtool.model.IWidget in project cogtool by cogtool.
the class DesignExportToHTML method buildFrameHTML.
/**
* Build the HTML around a single frame.
* This really just involves building an image map over the
* areas specified by the widgets, as well as the GraphicalDevices
* Since the graphical Devices don't really have a "Name"
* Also, since the Graphical devices and the frame name are not in the
* Normal frame... (and we are using a frame not a design)
* Need to add graphical devices using normal HTML.
*
* Requires the name of the frame image to be passed in.
*
* A copy of overlib.js needs to be copied to the output directory as well.
* InputStream stream =
* ClassLoader.getSystemResourceAsStream
* ("edu/cmu/cs/hcii/cogtool/resources/overlib.js");
*
* @param frame
* @param frameImageName
* @return
*/
protected String buildFrameHTML(Frame frame) {
String notHelpString = NOT_HELP_DEFAULT;
StringBuilder html = new StringBuilder();
html.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
html.append("<html>\n");
html.append("<title>");
html.append(frame.getName());
html.append("</title>\n");
//html.append("<style type='text/css'> body { margin:0; padding:0; } </style>\n");
html.append("<link rel='stylesheet' type='text/css' href='build/fonts-min.css' />\n");
html.append("<link rel='stylesheet' type='text/css' href='build/menu.css' />\n");
html.append("<script type='text/javascript' src='build/yahoo-dom-event.js'></script>\n");
html.append("<script type='text/javascript' src='build/container_core.js'></script>\n");
html.append("<script type='text/javascript' src='build/menu.js'></script>\n");
// Add javascript load for overlay code.
html.append("<script type='text/javascript' ");
html.append(" src='build/overlib.js' ");
html.append(" language='JavaScript'></script>\n");
html.append("<style type='text/css'> div.yuimenu { position: absolute; visibility: hidden; } </style>\n");
html.append("<body style=\"cursor:default;\" class=' yui-skin-sam' onload=\"onLoad()\" onkeydown=\"checkKey(event)\">\n");
// Create the table with the frame name.
html.append("<table border=1>\n");
html.append("<tr>\n");
// -------------------------
// Add the frame title
// -------------------------
html.append("<td align='center'>\n");
html.append(frame.getName());
html.append("</td>\n");
html.append("</tr>\n");
// -------------------------
// Add the device interfaces.
// -------------------------
html.append("<tr>\n");
html.append("<td>\n");
html.append("<img align=center src='");
html.append(getFrameURL(frame, ".jpg"));
//Overlib is a javascript biult-in function that shows a nice pop-up box. DEMONSTRATE!
//I have added a map for this image so that this image will follow a map in the case of "HotSpots"
html.append("' onclick=\"" + NOT_ACCOMPLISH_GOAL + "\" usemap=\"#Button_Map\" />\n");
html.append("</td>\n</tr>\n</table>\n");
// save any menus encountered to create them in javascript later
List<AMenuWidget> menus = new ArrayList<AMenuWidget>();
// only build a group of radio buttons or list box items once
Set<SimpleWidgetGroup> visitedGroups = new HashSet<SimpleWidgetGroup>();
// loop over all widgets
Iterator<IWidget> widgetIterator = frame.getWidgets().iterator();
//NoticS: while function to go over all widgets
while (widgetIterator.hasNext()) {
IWidget widget = widgetIterator.next();
//html.append(buildWidgetHTML(widget, visitedGroups));
widgetHTML += buildWidgetHTML(widget, visitedGroups, frame);
if ((widget instanceof MenuHeader) || (widget instanceof ContextMenu)) {
menus.add((AMenuWidget) widget);
}
}
mapHTML += "</map>\n";
html.append(mapHTML);
html.append(widgetHTML);
mapHTML = "<map name=\"Button_map\">\n";
widgetHTML = "";
//javascript functions
html.append("<script type='text/javascript'>\n");
html.append("var isIE = navigator.appName.indexOf(\"Microsoft\")!=-1;\n");
html.append("var isWin = navigator.appVersion.indexOf(\"Win\")!=-1;\n");
html.append("var notAccomplishGoal = \"" + notHelpString + "\";\n");
html.append("var keyboardString = \"\";\n");
html.append("var hoverElt = null;\n");
html.append("var keyTransitionMap = new Object();\n");
html.append("var clickMap = null;\n");
html.append("var curEvt = null;\n");
html.append("var numClicks = 0;\n");
html.append("var focusString = \"\";\n");
html.append("var focusTransitionMaps = new Object();\n");
html.append("var curFocusMap = null;\n");
int devTypes = DeviceType.buildDeviceSet(frame.getDesign().getDeviceTypes());
if (DeviceType.Keyboard.isMember(devTypes) || DeviceType.Touchscreen.isMember(devTypes)) {
html.append(buildKeyTransitionMap(frame.getInputDevices(), frame.getWidgets()));
}
// Function to account for IE versus Firefox differences in
// mouse events - they use a different set of mouse button constants
html.append("\nfunction getMouseButton(button)\n{\n");
html.append(" if (button == " + LEFT_MOUSE + ") {\n");
html.append(" return isIE ? 1 : 0;\n }\n");
html.append(" if (button == " + MIDDLE_MOUSE + ") {\n");
html.append(" return isIE ? 4 : 1;\n }\n");
html.append(" if (button == " + RIGHT_MOUSE + ") {\n");
html.append(" return isIE ? 2 : 2;\n }\n}\n\n");
html.append("function onLoad()\n{\n");
html.append(" var str = document.location.search;\n");
html.append(" if (str != null) {\n");
html.append(" str = str.substr(1);\n");
html.append(" var search = str.split(\"&\");\n");
html.append(" var searchCount = search.length;\n");
html.append(" for (i = 0; i < searchCount; i++) {\n");
html.append(" var check = search[0].split(\"=\");\n");
html.append(" if ((check.length == 2) && (check[0] == \"focusID\")) {\n");
html.append(" var elt = document.getElementById(decodeURIComponent(check[1]));\n");
html.append(" if (elt != null) {\n");
html.append(" elt.focus();\n");
html.append(" if (elt.type == 'radio') {\n");
html.append(" elt.checked = true;\n }\n");
html.append(" else if (elt.type == 'checkbox') {\n");
html.append(" elt.checked = ! elt.checked;\n");
html.append(" }\n");
html.append(" }\n");
html.append(" break;\n");
html.append(" }\n }\n }\n} // onLoad\n\n");
// The following two methods are only used for Yahoo menu events.
// newframe is a string representing the html file of the frame to be
// transitioned to; button is the mouse button that causes that
// transition, and e is the actual event that is checked against
html.append("function checkMenuTransitions(newFrame, button, e)\n{\n");
html.append(" return (newFrame && (button == e.button));\n}\n\n");
// The Yahoo menus use this function, so it requires three parameters.
// The first we don't use, the second stores the event, and the third
// is an array of strings representing html files. The function above
// takes this information plus a mapping from the index in that array
// to the mouse button that effects the corresponding transition, and
// determines whether a transition should occur. If so, it changes
// the location of the document.
html.append("function menuTransition(ignore, p_aArgs, p_oValue)\n{\n");
html.append(" var transitionIndex = -1;\n for (i = 0; i < p_oValue.length; i++) {\n");
html.append(" if (checkMenuTransitions(p_oValue[i], getMouseButton(i+1), p_aArgs[0])) {\n");
html.append(" if ((p_oValue[i] == " + IGNORE_LEFT_CLICK + ")) {\n");
html.append(" return;\n }\n");
html.append(" transitionIndex = i;\n }\n }\n");
html.append(" if (transitionIndex >= 0) {\n");
html.append(" document.location.href = p_oValue[transitionIndex];\n }\n");
html.append(" else {\n " + NOT_ACCOMPLISH_GOAL + "\n }\n}\n\n");
// Return an integer representing the modifier state of the current
// event object (NOTE: event has "metaKey" but no fnKey or cmdKey)
html.append("function getModifiers(e)\n{\n");
html.append(" var result = 0;\n if (e.shiftKey) {\n");
html.append(" result += " + AAction.SHIFT + ";\n }\n");
html.append(" if (e.ctrlKey) {\n result += " + AAction.CTRL + ";\n }\n");
html.append(" if (e.altKey) {\n result += " + AAction.ALT + ";\n }\n\n");
html.append(" return result;\n}\n\n");
// The following two functions are used for transitions from regular
// HTML elements. This one takes the current event object, the set
// of values to be considered, and the number of clicks that have
// occurred and determines whether a transition should be followed.
html.append("function checkTransitions(clicks, params, event)\n{\n");
html.append(" if (clicks != params[1]) {\n return false;\n }\n\n");
html.append(" var modifiers = getModifiers(event);\n");
html.append(" var button = event.button;\n");
html.append(" if ((params[0] == " + RIGHT_MOUSE + ") &&");
html.append(" (modifiers & " + AAction.CTRL + ") && (! isWin)) {\n");
html.append(" button = getMouseButton(" + RIGHT_MOUSE + ");\n");
html.append(" modifiers -= " + AAction.CTRL + ";\n }\n\n");
html.append(" if (getMouseButton(params[0]) != button) {\n");
html.append(" return false;\n }\n if (modifiers != params[2]) {\n");
html.append(" return false;\n }\n\n return true;\n}\n\n");
// clicks is the number of clicks performed on the widget (1, 2, or 3),
// and event is the HTML event object. transitionMap is an array of
// arrays. The sub-arrays have four elements that together define a
// mouse transition: which button, how many clicks, the keyboard
// modifier state, and the destination frame, in that order.
html.append("function followTransition(clicks, event, transitionMap)\n{\n");
html.append(" var frame = null;\n");
html.append(" for (i = 0; i < transitionMap.length; i++) {\n");
html.append(" var params = transitionMap[i];\n");
html.append(" if (checkTransitions(clicks, params, event)) {\n");
html.append(" frame = params[3];\n");
html.append(" if ((frame == " + IGNORE_LEFT_CLICK + ") && (clicks == 1)) return;\n }\n }\n\n");
html.append(" if (frame != null) {\n");
html.append(" document.location.href = frame;\n");
html.append(" return true;\n }\n");
html.append(" " + NOT_ACCOMPLISH_GOAL + "\n return false;\n}\n\n");
// Used for context menus to put the menu where the mouse was clicked
html.append("function displayContextMenu(event, menu)\n{\n");
html.append(" menu.cfg.setProperty(\"x\", event.clientX);\n");
html.append(" menu.cfg.setProperty(\"y\", event.clientY);\n");
html.append(" menu.show();\n}\n\n");
// This function allows clicking on the label of a checkbox to toggle
// it instead of only being able to click on the box itself. CogTool
// checkbox widgets work this way.
html.append("function toggleCheckbox(eltId)\n{\n");
html.append(" var elt = document.getElementById(eltId);\n");
html.append(" if (typeof(elt) != 'undefined') {\n");
html.append(" if (elt.type == 'checkbox') {\n");
html.append(" elt.checked = ! elt.checked;\n }\n }\n}\n");
// Similar to toggleCheckbox, but for radio buttons
html.append("function selectRadio(eltId)\n{\n");
html.append(" var elt = document.getElementById(eltId);\n");
html.append(" if (typeof(elt) != 'undefined') {\n");
html.append(" if (elt.type == 'radio') {\n");
html.append(" elt.checked = true;\n }\n }\n}\n\n");
// There is no notion of "hover" in html, only mouse over. So if
// there is a hover transition, it needs to save the frame to be
// transitioned to in a global variable and start a timer to see
// if the cursor remains hovered over the element.
html.append("function timeHover(frame)\n{\n hoverElt = frame;\n");
html.append(" window.setTimeout(\"checkHover()\", 1000);\n}\n\n");
// When the timer is up, if the cursor is still there, it does the
// transition.
html.append("function checkHover()\n{\n if (hoverElt) {\n");
html.append(" document.location.href = hoverElt;\n }\n");
html.append(/*else {\n" + NOT_ACCOMPLISH_GOAL + "\n}\n*/
"}\n\n");
// If there is a mouse out event on any widget, it discards the hover
// information.
html.append("function cancelHover()\n{\n hoverElt = null;\n}\n\n");
// Used for keyboard transitions. Taking into account regexp special
// characters, it uses a regular expression to test whether the string
// str (the string that collects keyboard input) ends with the string
// s (the string that causes a transition)
html.append("function endsWith(str, s)\n{\n");
html.append(" s = s.replace(/\\\\|\\(|\\)|\\*|\\^|\\$|\\+|\\?|\\.|\\||\\{|\\}|\\[|\\]/g, escaper);\n");
html.append(" var reg = new RegExp(s + \"$\");\n");
html.append(" return reg.test(str);\n}\n\n");
// Called when a key is pressed; adds the new key to the keyboard
// string and, if applicable, the string for the widget that has the
// focus (first), and checks whether it should do a transition
// TODO NOTE: Widgets for which key transitions don't work:
// radio buttons, links, menu items, pull-down items, list box items
html.append("function checkKey(e)\n{\n if (curFocusMap) {\n");
html.append(" focusString += String.fromCharCode(e.keyCode);\n");
html.append(" var result = checkStrings(focusString, curFocusMap);\n");
html.append(" if (result) {\n document.location.href = result;\n");
html.append(" return;\n }\n }\n");
html.append(" keyboardString += String.fromCharCode(e.keyCode);\n");
html.append(" var result = checkStrings(keyboardString, keyTransitionMap);\n");
html.append(" if (result) {\n document.location.href = result;\n }\n}\n\n");
// Returns the longest string that matches the currently collected
// input, or null
html.append("function checkStrings(collector, map)\n{\n");
html.append(" var longest = null;\n");
html.append(" for (var i in map) {\n");
html.append(" if (endsWith(collector.toLowerCase(), i)) {\n");
html.append(" if (! longest) {\n longest = i;\n }\n");
html.append(" if (i.length > longest.length) {\n longest = i;\n");
html.append(" }\n }\n }\n");
html.append(" if (longest) {\n return map[longest];\n }\n");
html.append(" return null;\n}\n\n");
// adds escape characters to special keys so the regexp doesn't
// get confused
html.append("function escaper(c)\n{\n return \'\\\\\' + c;\n}\n\n");
// html detects left double-clicks but not middle or right double clicks,
// so the next two functions handle that. This one is called on mouse
// up (onclick doesn't detect right clicks, see buildWidgetHTML()).
// transitionMap is an array of arrays (see the comments above
// followTransition). It starts a timer after it is called; if
// it is called again before the timer runs out (as determined by the
// state of the global numClicks variable), it starts another timer,
// otherwise it checks a single click transition. If the second timer
// runs out, it checks a double click transition, but if this function
// is called a third time, it checks a triple click transition.
// TODO: NOTE: Even with onmouseup, html seems to fail to detect middle
// clicks in Firefox, so this solution works only with right clicks.
html.append("function checkClicks(transitionMap, e)\n{\n");
html.append(" curEvt = e;\n numClicks++;\n\n");
html.append(" if (numClicks == 3) {\n");
html.append(" if (followTransition(3, e, transitionMap)) {\n");
html.append(" window.clearTimeout();\n }\n\n");
html.append(" numClicks = 0;\n }\n else {\n");
html.append(" clickMap = transitionMap;\n");
html.append(" if (numClicks == 1) {\n");
html.append(" window.setTimeout(\"doClick1()\", 500);\n }\n");
html.append(" else if (numClicks == 2) {\n");
html.append(" window.clearTimeout();\n");
html.append(" window.setTimeout(\"doClick2()\", 300);\n }\n }\n}\n\n");
// If there was only a single click, it uses the saved
// map to try to perform a transition with one click, and clears the state.
html.append("function doClick1()\n{\n");
html.append(" if ((clickMap != null) && (numClicks == 1)) {\n");
html.append(" followTransition(1, curEvt, clickMap);\n");
html.append(" clickMap = null;\n numClicks = 0;\n }\n}\n\n");
// If there was a double click, it uses the saved
// map to try to perform a transition with two clicks, and clears the state.
html.append("function doClick2()\n{\n");
html.append(" if ((clickMap != null) && (numClicks == 2)) {\n");
html.append(" followTransition(2, curEvt, clickMap);\n");
html.append(" clickMap = null;\n numClicks = 0;\n }\n}\n\n");
// Called when any widget gets the focus (html's onfocus). Uses the
// widgets ID to index into the map of widgets' keyboard transitions.
html.append("function onFocus(eltID)\n{\n");
html.append(" keyboardString = \"\";\n");
html.append(" var map = focusTransitionMaps[eltID];\n");
html.append(" if (typeof(map) != 'undefined') {\n");
html.append(" curFocusMap = focusTransitionMaps[eltID];\n }\n}\n\n");
// Clears the current focus map so it knows that no widget has the focus
html.append("function onBlur()\n{\n curFocusMap = null;\n}\n\n");
html.append("YAHOO.util.Event.onDOMReady(function () {\n");
// use yahoo javascript library to build up menus
if (menus.size() > 0) {
for (int i = 0; i < menus.size(); i++) {
AMenuWidget menu = menus.get(i);
String menuVar = "oMenu" + i;
String context = "";
if (menu instanceof MenuHeader) {
// associate it with the corresponding menu header
context = ", { context: [\"" + menu.getName() + "\", \"tl\", \"bl\"]}";
}
// else, if it is a context menu, have it appear wherever the
// mouse is clicked (in a javascript method)
// create the javascript menu object
html.append(" var " + menuVar + " = new YAHOO.widget.Menu(\"menu" + i + "\"" + context + ");\n");
html.append(" " + menuVar + ".addItems(" + buildItemsString(menu.getChildren().iterator()) + ");\n");
html.append(" " + menuVar + ".showEvent.subscribe(function () { this.focus(); });\n");
html.append(" " + menuVar + ".render(document.body);\n");
if (menu instanceof MenuHeader) {
html.append(" YAHOO.util.Event.addListener(\"" + menu.getName() + "\", \"click\", " + menuVar + ".show, null, " + menuVar + ");\n");
} else if (menu instanceof ContextMenu) {
html.append(" YAHOO.util.Event.addListener(\"" + menu.getName() + "\", \"contextmenu\", displayContextMenu, " + menuVar + ", " + menuVar + ");\n");
}
}
}
html.append("\n document.body.oncontextmenu = function () {\n return false;\n }\n});\n\n");
html.append("</script>\n");
html.append("</body>\n");
html.append("</html>\n");
return html.toString();
}
Aggregations