bug#210212 (initial commit)
diff --git a/plugins/org.eclipse.actf.ai.fennec/.classpath b/plugins/org.eclipse.actf.ai.fennec/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.actf.ai.fennec/.cvsignore b/plugins/org.eclipse.actf.ai.fennec/.cvsignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/plugins/org.eclipse.actf.ai.fennec/.project b/plugins/org.eclipse.actf.ai.fennec/.project
new file mode 100644
index 0000000..6a55645
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.actf.ai.fennec</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.actf.ai.fennec/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.ai.fennec/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..738557c
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Eclipse ACTF Fennec Plug-in (Incubation)
+Bundle-SymbolicName: org.eclipse.actf.ai.fennec
+Bundle-Version: 0.0.1
+Bundle-Activator: org.eclipse.actf.ai.fennec.NVM3Plugin
+Bundle-Vendor: Eclipse.org
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.actf.util.vocab,
+ org.eclipse.actf.common,
+ org.eclipse.actf.model.dom.dombycom,
+ org.eclipse.actf.ai.query,
+ org.eclipse.actf.ai.xmlstore,
+ org.eclipse.swt
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.actf.ai.fennec,
+ org.eclipse.actf.ai.fennec.treemanager
diff --git a/plugins/org.eclipse.actf.ai.fennec/about.html b/plugins/org.eclipse.actf.ai.fennec/about.html
new file mode 100644
index 0000000..481dbcf
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/about.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>
+<h3>License</h3>
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content").
+Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor’s license
+that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.fennec/build.properties b/plugins/org.eclipse.actf.ai.fennec/build.properties
new file mode 100644
index 0000000..e1942be
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/build.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ about.html,\
+ .
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/INVM3Entry.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/INVM3Entry.java
new file mode 100644
index 0000000..cc7e42a
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/INVM3Entry.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec;
+
+import java.io.File;
+
+
+
+public interface INVM3Entry {
+ String getDocumentation();
+ boolean isUserEntry();
+ boolean export(File dest);
+}
+
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/INVM3Mediator.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/INVM3Mediator.java
new file mode 100644
index 0000000..c491712
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/INVM3Mediator.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeManager;
+
+
+
+public interface INVM3Mediator {
+ ITreeManager newTreeManager(INVM3Entry entry);
+ INVM3Entry getDefaultNVM3Entry();
+ INVM3Entry[] getNVM3Entries();
+ void release();
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/INVM3Service.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/INVM3Service.java
new file mode 100644
index 0000000..9620af5
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/INVM3Service.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec;
+
+import org.eclipse.actf.ai.fennec.treemanager.IAccessKeyList;
+import org.eclipse.actf.ai.fennec.treemanager.ISoundControl;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.fennec.treemanager.IVideoControl;
+import org.eclipse.actf.model.dom.dombycom.IFlashNode;
+import org.eclipse.actf.util.vocab.IProposition;
+import org.w3c.dom.Node;
+
+
+public interface INVM3Service {
+ int UNINIT = 0;
+ int NORMAL = 1;
+ int ERROR = 1 << 16;
+
+ int getStatus();
+ ITreeItem getLastTreeItem();
+ ISoundControl getSoundControl();
+ IVideoControl getVideoControl();
+ IAccessKeyList getAccessKeyList();
+ IFlashNode[] getFlashTopNodes();
+
+ int initialize() throws NVM3Exception;
+ int moveUpdate(ITreeItem target) throws NVM3Exception;
+ int moveUpdate(ITreeItem target, boolean update) throws NVM3Exception;
+ int clickUpdate(ITreeItem target) throws NVM3Exception;
+
+ int searchForward(IProposition prop) throws NVM3Exception;
+ int searchBackward(IProposition prop) throws NVM3Exception;
+
+ int analyze() throws NVM3Exception;
+
+ int skipToAnchor(String target) throws NVM3Exception;
+
+ // !!FN!!
+ ITreeItem expandWholeTree() throws NVM3Exception;
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3Exception.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3Exception.java
new file mode 100644
index 0000000..668d79e
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3Exception.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec;
+
+public class NVM3Exception extends Exception {
+ private static final long serialVersionUID = -4473389024467270039L;
+
+ public NVM3Exception(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3InterruptedException.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3InterruptedException.java
new file mode 100644
index 0000000..02c503a
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3InterruptedException.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec;
+
+public class NVM3InterruptedException extends NVM3Exception {
+ private static final long serialVersionUID = 503781748413609768L;
+
+ public NVM3InterruptedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public NVM3InterruptedException(String message) {
+ super(message, null);
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3Plugin.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3Plugin.java
new file mode 100644
index 0000000..64ad7b8
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3Plugin.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec;
+
+import org.eclipse.actf.ai.fennec.mediator.NVM3MediatorImpl;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.core.runtime.Plugin;
+import org.osgi.framework.BundleContext;
+
+
+
+
+public class NVM3Plugin extends Plugin {
+
+ //The shared instance.
+ private static NVM3Plugin plugin;
+
+ /**
+ * The constructor.
+ */
+ public NVM3Plugin() {
+ plugin = this;
+ }
+
+ /**
+ * This method is called upon plug-in activation
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /**
+ * This method is called when the plug-in is stopped
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Returns the shared instance.
+ */
+ public static NVM3Plugin getDefault() {
+ return plugin;
+ }
+
+ public INVM3Mediator newNVM3Mediator(IWebBrowserACTF webBrowser) {
+ return new NVM3MediatorImpl(webBrowser);
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3ServiceFactory.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3ServiceFactory.java
new file mode 100644
index 0000000..9399fec
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/NVM3ServiceFactory.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec;
+
+import org.eclipse.actf.ai.fennec.impl.NVM3ServiceImpl;
+import org.eclipse.actf.model.dom.dombycom.IDocumentEx;
+
+
+public class NVM3ServiceFactory {
+ public static INVM3Service newNVM3Service(INVM3Entry entry, IDocumentEx doc) throws NVM3Exception {
+ return new NVM3ServiceImpl(entry, doc);
+ }
+
+ public static INVM3Service newNVM3ServiceWithDefaultMetadata(IDocumentEx doc) {
+ return new NVM3ServiceImpl(doc);
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/autotranslator/AutoTranslator.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/autotranslator/AutoTranslator.java
new file mode 100644
index 0000000..05b77ad
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/autotranslator/AutoTranslator.java
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.autotranslator;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.actf.ai.fennec.impl.NVM3Mode;
+import org.eclipse.actf.ai.fennec.impl.TreeItemMark;
+import org.eclipse.actf.ai.fennec.impl.TreeItemNVM3;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.model.dom.dombycom.IFlashNode;
+import org.eclipse.actf.model.dom.dombycom.IImageElement;
+import org.eclipse.actf.model.dom.dombycom.INodeEx;
+import org.eclipse.actf.util.vocab.Vocabulary;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class AutoTranslator {
+ private static final boolean AUTO_COLLAPSE = true;
+
+ private static final boolean AUTO_INDENT = true;
+
+ private static boolean canCollapse(TreeItemNVM3 item) {
+ if (true) {
+ return Vocabulary.isReducible().eval(item);
+ } else {
+ if (Vocabulary.hasContent().eval(item))
+ return false;
+ ITreeItem[] cc = item.getChildItems();
+ for (int i = 0; i < cc.length; i++) {
+ TreeItemNVM3 item2 = (TreeItemNVM3) cc[i];
+ if (Vocabulary.hasContent().eval(item2))
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private static TreeItemNVM3 simplify(TreeItemNVM3 item, TreeItemNVM3 pItem) {
+ if (AUTO_COLLAPSE) {
+ // pattern pItem - item(X) - child => pItem - child
+ if (!Vocabulary.hasContent().eval(item)) {
+ ITreeItem[] cc = item.getChildItems();
+ if (cc.length == 0) {
+ return null;
+ }
+ if (cc.length == 1) {
+ TreeItemNVM3 item2 = (TreeItemNVM3) cc[0];
+ item2.forceParent(pItem);
+ item2.addMetadata(item);
+ return item2;
+ }
+ }
+
+ // pattern item - child(X) - grandChild => item - grandChild
+ ITreeItem[] childItems = item.getChildItems();
+ if (childItems.length == 1) {
+ TreeItemNVM3 item2 = (TreeItemNVM3) childItems[0];
+ if (!Vocabulary.hasContent().eval(item2)){
+ ITreeItem[] childItems2 = item2.getChildItems();
+ item.setChildItems(childItems2);
+ item.addMetadata(item2);
+ }
+ }
+ }
+
+ return item;
+ }
+
+ private static void adjustLabelIndent(TreeItemNVM3 item) {
+ // TODO
+ // var itemCount = item._childItems.length;
+ // if( itemCount>1 ) {
+ // var heading;
+ // var topIsLabel = true;
+ // for( var i=0, child; child=item._childItems[i]; i++ ) {
+ // if( topIsLabel ) {
+ // topIsLabel = child._childItems.length ? (i>0) : (i==0);
+ // }
+ // if( child.isHeadingNode() ) {
+ // // Collapse heading node tree
+ // child._join();
+ // heading = child._childItems.length==0 ? child : null;
+ // }
+ // else if( heading ) {
+ // // Move child item into heading item children
+ // heading._childItems.push(child);
+ // item._childItems.splice(i--,1);
+ // topIsLabel = false;
+ // heading._labelHead = true;
+ // }
+ // }
+ // if( topIsLabel ) {
+ // // 1st child is a label. Move item 2-n into item 1 children
+ // heading = item._childItems[0];
+ // heading._childItems = item._childItems.splice(1,item._childItems.length-1);
+ // heading._labelHead = true;
+ // }
+ // if( (item._childItems.length != itemCount) && Options.AUTO_COLLAPSE ) {
+ // // Re-adjust tree collaption because tree structure has changed
+ // for( var i=0, child; child=item._childItems[i]; i++ ) {
+ // child._simplify();
+ // }
+ // item._simplify();
+ // }
+ // }
+
+ }
+
+ private static List<ITreeItem> buildTreeItemContinued(NVM3Mode mode, TreeItemNVM3 item, INodeEx nex, int depth) {
+ List<ITreeItem> childItemList = new ArrayList<ITreeItem>();
+ ITreeItem lastItem = null;
+
+ if (nex instanceof IFlashNode) {
+ IFlashNode fn = (IFlashNode) nex;
+ nex = fn.getMSAA();
+ lastItem = new TreeItemMark(item, TreeItemMark.MarkType.FLASH_END);
+
+ if ((nex != null && Vocabulary.getNormalFlashMode() == Vocabulary.FlashMode.NO_FLASH)
+ || (nex == null && Vocabulary.getWindowlessFlashMode() == Vocabulary.FlashMode.NO_FLASH)) {
+ return childItemList;
+ }
+
+ if ((nex != null && Vocabulary.getNormalFlashMode() == Vocabulary.FlashMode.FLASH_DOM)
+ || (nex == null && Vocabulary.getWindowlessFlashMode() == Vocabulary.FlashMode.FLASH_DOM)) {
+ IFlashNode[] translated = fn.translate();
+ for (int i = 0; i < translated.length; i++) {
+ TreeItemNVM3 newItem = mode.generateItem(item, translated[i]);
+ if (newItem == null) continue;
+ childItemList.add(newItem);
+ }
+ if (Vocabulary.isFlashTopNode().eval(fn)) {
+ childItemList.add(lastItem);
+ }
+
+ item.setChildItems(childItemList);
+ return childItemList;
+ }
+ }
+
+ if (nex instanceof IImageElement) {
+ IImageElement image = (IImageElement) nex;
+ if (image.hasUsemap()) {
+ Element map = image.getMap();
+ if (map == null) return childItemList;
+ NodeList nl = map.getChildNodes();
+ for (int i = 0; i < nl.getLength(); i++) {
+ Node n = nl.item(i);
+ if (n instanceof Element) {
+ TreeItemNVM3 newItem = mode.generateItem(item, n);
+ childItemList.add(newItem);
+ }
+ }
+ item.setChildItems(childItemList);
+ return childItemList;
+ }
+ }
+
+ if (depth <= 0) {
+ item.setChildItems(childItemList);
+ return childItemList;
+ }
+
+ TreeItemNVM3 childItem = null;
+ NodeList nl = nex.getChildNodes();
+ int len = nl.getLength();
+ boolean hasContent = Vocabulary.hasContent().eval(item);
+ for (int i = 0; i < len; i++) {
+ Node cn = nl.item(i);
+
+ if (hasContent) {
+ childItem = buildTreeItem(mode, item, cn, depth - 1);
+ } else {
+ childItem = buildTreeItem(mode, item, cn, depth);
+ }
+ if (childItem == null)
+ continue;
+
+ if (true && AUTO_COLLAPSE && canCollapse(childItem)) {
+ ITreeItem[] cc = childItem.getChildItems();
+ if ((cc != null) && (cc.length > 0)) {
+ for (int j = 0; j < cc.length; j++) {
+ if (!(cc[j] instanceof TreeItemNVM3))
+ continue;
+ TreeItemNVM3 temp = (TreeItemNVM3) cc[j];
+ temp.addMetadata(childItem);
+ }
+ childItemList.addAll(Arrays.asList(cc));
+ }
+ } else {
+ childItemList.add(childItem);
+ }
+ }
+
+ if (lastItem != null)
+ childItemList.add(lastItem);
+
+ item.setChildItems(childItemList);
+ return childItemList;
+ }
+
+ private static TreeItemNVM3 buildTreeItem(NVM3Mode mode, TreeItemNVM3 pItem, Node n, int depth) {
+ if (!(n instanceof INodeEx)) {
+ return null;
+ }
+
+ INodeEx nex = (INodeEx) n;
+
+ if (!Vocabulary.isValidNode().eval(nex)) {
+ return null;
+ }
+
+ TreeItemNVM3 item = mode.generateItem(pItem, n);
+ if (item == null) return null;
+ buildTreeItemContinued(mode, item, nex, depth);
+
+ if (AUTO_INDENT) {
+ adjustLabelIndent(item);
+ }
+
+ return simplify(item, pItem);
+ }
+
+ public static TreeItemNVM3 translate(NVM3Mode mode, TreeItemNVM3 pItem, Node n) {
+
+ return buildTreeItem(mode, pItem, n, 1);
+ }
+
+ public static TreeItemNVM3 translateContinued(NVM3Mode mode, TreeItemNVM3 item, Node n) {
+ if (!(n instanceof INodeEx))
+ return item;
+ buildTreeItemContinued(mode, item, (INodeEx) n, 2);
+ // item = simplify(item, (TreeItemNVM3) item.getParent());
+ return item;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3BundleMetadata.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3BundleMetadata.java
new file mode 100644
index 0000000..015beb0
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3BundleMetadata.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.actf.ai.fennec.NVM3Exception;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.query.IQuery;
+import org.w3c.dom.Node;
+
+
+abstract class NVM3BundleMetadata extends NVM3Metadata {
+ private static final NVM3Metadata[] emptyChildMetadata = new NVM3Metadata[0];
+ protected final NVM3Metadata[] childMetadata;
+
+ protected NVM3BundleMetadata(NVM3ServiceImpl nvm3Service,
+ IQuery q, NVM3Mode mode, NVM3Metadata[] mds) {
+ super(nvm3Service, q, mode);
+ if (mds == null) {
+ mds = emptyChildMetadata;
+ }
+ this.childMetadata = mds;
+ }
+
+ protected NVM3BundleMetadata(NVM3ServiceImpl nvm3Service,
+ NVM3Mode mode,
+ Node node,
+ NVM3Metadata[] mds) {
+ super(nvm3Service, mode, node);
+ if (mds == null) {
+ mds = emptyChildMetadata;
+ }
+ this.childMetadata = mds;
+ }
+
+ @Override
+ List expand(TreeItemNVM3 pItem, int trigger) throws NVM3Exception {
+ ArrayList ret = new ArrayList();
+ for (int i = 0; i < childMetadata.length; i++) {
+ NVM3Metadata cmd = childMetadata[i];
+ List ret2 = cmd.buildItems(pItem, null, trigger);
+ if (ret2 != null) ret.addAll(ret2);
+ }
+ return ret;
+ }
+
+
+ NVM3Metadata[] getChildMetadata() {
+ return childMetadata;
+ }
+
+ // CoR pattern.
+ @Override
+ public String getAltText(ITreeItem item) {
+ for (int i = 0; i < childMetadata.length; i++) {
+ if (childMetadata[i].hasTargets()) continue;
+ if (!(childMetadata[i] instanceof NVM3SimpleMetadata)) continue;
+ String ret = childMetadata[i].getAltText(item);
+ if (ret == null) return null;
+ if (ret.length() > 0) return ret;
+ }
+ return "";
+ }
+
+ @Override
+ public String getDescription(ITreeItem item) {
+ for (int i = 0; i < childMetadata.length; i++) {
+ if (childMetadata[i].hasTargets()) continue;
+ if (!(childMetadata[i] instanceof NVM3SimpleMetadata)) continue;
+ String ret = childMetadata[i].getDescription(item);
+ if (ret == null) return null;
+ if (ret.length() > 0) return ret;
+ }
+ return "";
+ }
+
+ @Override
+ public short getHeadingLevel(ITreeItem item) {
+ for (int i = 0; i < childMetadata.length; i++) {
+ if (childMetadata[i].hasTargets()) continue;
+ if (!(childMetadata[i] instanceof NVM3SimpleMetadata)) continue;
+ short ret = childMetadata[i].getHeadingLevel(item);
+ if (ret == -1) return -1;
+ if (ret > 0) return ret;
+ }
+ return 0;
+ }
+}
+
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3DOMReader.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3DOMReader.java
new file mode 100644
index 0000000..5cd52b4
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3DOMReader.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+
+import org.eclipse.actf.ai.fennec.INVM3Entry;
+import org.eclipse.actf.ai.query.IQuery;
+import org.eclipse.actf.ai.query.QueryService;
+import org.eclipse.actf.ai.xmlstore.IXMLInfo;
+import org.eclipse.actf.ai.xmlstore.XMLStoreException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class NVM3DOMReader {
+ public static final String NVM3_NAMESPACE_URI = "http://www.ibm.com/xmlns/prod/aiBrowser/fennec";
+ public static final String NVM3_DOCUMENT_ELEMENT_NAME = "fennec";
+
+ private NVM3ServiceImpl nvm3Service;
+
+ private void error(String message) {
+ System.err.println(message);
+ }
+
+ private IQuery parseQuery(Element e, IQuery parentQuery) {
+ return QueryService.parse(e, parentQuery);
+ }
+
+ private NVM3Metadata parseNode(NVM3Mode mode, Element e, IQuery parentQuery) {
+ NodeList nl = e.getChildNodes();
+ IQuery q = parseQuery(e, parentQuery);
+ if (q != null) parentQuery = q;
+ NVM3Metadata[] mds = parseInternal(mode, nl, parentQuery);
+ return new NVM3GroupMetadata(nvm3Service, q, mode, mds);
+ }
+
+ private NVM3Metadata parseHeader(NVM3Mode mode, Element e, short level, IQuery parentQuery) {
+ // IQuery q = parseQuery(e, parentQuery);
+ return NVM3SimpleMetadata.newHeader(nvm3Service, null, mode, level);
+ }
+
+ private List parseTextFormat(Element e, IQuery parentQuery) {
+ NodeList nl = e.getChildNodes();
+ int len = nl.getLength();
+ if (len == 0) return null;
+ ArrayList al = new ArrayList();
+ for (int i = 0; i < len; i++) {
+ Node n = nl.item(i);
+ switch (n.getNodeType()) {
+ case Node.TEXT_NODE:
+ al.add(n.getNodeValue());
+ break;
+ case Node.ELEMENT_NODE:
+ Element ce = (Element) n;
+ if ("ref".equals(ce.getLocalName())) {
+ IQuery q = parseQuery((Element) n, parentQuery);
+ al.add(q);
+ } else {
+ error("Invalid element in text format:" + n.getNodeName());
+ }
+ break;
+ }
+ }
+ return al;
+ }
+
+ private NVM3Metadata parseAltText(NVM3Mode mode, Element e, IQuery parentQuery) {
+ IQuery q = parseQuery(e, parentQuery);
+ if (q != null) parentQuery = q;
+ List l = parseTextFormat(e, parentQuery);
+ return NVM3SimpleMetadata.newAltText(nvm3Service, q, mode, l);
+ }
+
+ private NVM3Metadata parseDescription(NVM3Mode mode, Element e, IQuery parentQuery) {
+ IQuery q = parseQuery(e, parentQuery);
+ if (q != null) parentQuery = q;
+ List l = parseTextFormat(e, parentQuery);
+ return NVM3SimpleMetadata.newDescription(nvm3Service, mode, q, l);
+ }
+
+ private boolean parseBoolean(String str) {
+ String str2 = str.trim();
+ if (str2.equals("0")) {
+ return false;
+ } else if (str2.equals("false")) {
+ return false;
+ } else if (str2.equals("1")) {
+ return true;
+ } else if (str2.equals("true")) {
+ return true;
+ }
+ error("Invalide boolean value:" + str2);
+ return false;
+ }
+
+ private int parseTrigger(String str) {
+ String str2 = str.trim();
+ if ("always".equals(str2)) {
+ return NVM3Mode.TRIGGER_ALWAYS;
+ } else if ("move".equals(str2)) {
+ return NVM3Mode.TRIGGER_MOVE;
+ } else if ("click".equals(str2)) {
+ return NVM3Mode.TRIGGER_CLICK;
+ } else if (str.length() == 0) {
+ return NVM3Mode.TRIGGER_ALWAYS;
+ } else {
+ error("Invalid trigger attribute:" + str2);
+ }
+ return NVM3Mode.TRIGGER_MOVE;
+ }
+
+ private NVM3Metadata parseInternalForElement(NVM3Mode mode, Element e, IQuery parentQuery) {
+ String name = e.getLocalName();
+ if (name.equals("node")) {
+ return parseNode(mode, e, parentQuery);
+ } else if (name.equals("table")) {
+ // TODO
+ } else if (name.equals("ul")) {
+ // TODO
+ } else if (name.equals("ol")) {
+ // TODO
+ } else if (name.equals("h-")) {
+ return parseHeader(mode, e, (short) -1, parentQuery);
+ } else if (name.equals("h1")) {
+ return parseHeader(mode, e, (short) 1, parentQuery);
+ } else if (name.equals("h2")) {
+ return parseHeader(mode, e, (short) 2, parentQuery);
+ } else if (name.equals("h3")) {
+ return parseHeader(mode, e, (short) 3, parentQuery);
+ } else if (name.equals("h4")) {
+ return parseHeader(mode, e, (short) 4, parentQuery);
+ } else if (name.equals("h5")) {
+ return parseHeader(mode, e, (short) 5, parentQuery);
+ } else if (name.equals("h6")) {
+ return parseHeader(mode, e, (short) 6, parentQuery);
+ } else if (name.equals("altText")) {
+ return parseAltText(mode, e, parentQuery);
+ } else if (name.equals("description")) {
+ return parseDescription(mode, e, parentQuery);
+ } else if (name.equals("metadata")) {
+ // TODO
+ } else if (name.equals("keyDescription")) {
+ // TODO
+ } else if (name.equals("attach")) {
+ NodeList nl = e.getChildNodes();
+ IQuery q = parseQuery(e, parentQuery);
+ if (q == null) {
+ // TODO;
+ }
+
+ String triggerStr = e.getAttributeNS(null, "trigger");
+ int trigger = parseTrigger(triggerStr);
+
+ String autoStr = e.getAttributeNS(null, "auto");
+ boolean auto;
+ if (autoStr.length() == 0) {
+ auto = true;
+ } else {
+ auto = parseBoolean(autoStr);
+ }
+ String changelessStr = e.getAttributeNS(null, "changeless");
+ boolean changeless;
+ if (changelessStr.length() == 0) {
+ changeless = false;
+ } else {
+ changeless = parseBoolean(changelessStr);
+ }
+ String waitContentsStr = e.getAttributeNS(null, "waitContents");
+ boolean waitContents;
+ if (waitContentsStr.length() == 0) {
+ waitContents = false;
+ } else {
+ waitContents = parseBoolean(waitContentsStr);
+ }
+
+ NVM3Mode nextMode = new NVM3Mode(NVM3Mode.TYPE_ATTACH, trigger,
+ auto, changeless, waitContents);
+
+ NVM3Metadata[] mds = parseInternal(nextMode, nl, q);
+ return NVM3RecombinantMetadata.newAttach(nvm3Service, q, mode, nextMode, mds);
+ } else if (name.equals("unwrap")) {
+ NodeList nl = e.getChildNodes();
+ IQuery q = parseQuery(e, parentQuery);
+ if (q == null) {
+ // TODO;
+ }
+
+ String triggerStr = e.getAttributeNS(null, "trigger");
+ int trigger = parseTrigger(triggerStr);
+
+ NVM3Mode nextMode = new NVM3Mode(NVM3Mode.TYPE_UNWRAP, trigger, false, false, false);
+
+ NVM3Metadata[] mds = parseInternal(nextMode, nl, q);
+ return NVM3RecombinantMetadata.newUnwrap(nvm3Service, q, mode, nextMode, mds);
+ }
+ return null;
+ }
+
+ private NVM3Metadata[] parseInternal(NVM3Mode mode, NodeList nl, IQuery parentQuery) {
+ ArrayList al = new ArrayList();
+ int len = nl.getLength();
+ for (int i = 0; i < len; i++) {
+ Node n = nl.item(i);
+ if (n.getNodeType() == Node.ELEMENT_NODE) {
+ String ns = n.getNamespaceURI();
+ if (ns.equals(NVM3_NAMESPACE_URI)) {
+ Element e = (Element) n;
+ NVM3Metadata md = parseInternalForElement(mode, e, parentQuery);
+ if (md != null) al.add(md);
+ }
+ }
+ }
+ return (NVM3Metadata[]) al.toArray(new NVM3Metadata[0]);
+ }
+
+ private NVM3Metadata parseTop(Element e) {
+ String namespaceURI = e.getNamespaceURI();
+ if (!namespaceURI.equals(NVM3_NAMESPACE_URI)) {
+ error("The namespace URI of the document element must be " + NVM3_NAMESPACE_URI);
+ return null;
+ }
+ String localName = e.getLocalName();
+ if (!(NVM3_DOCUMENT_ELEMENT_NAME.equals(localName))) {
+ error("The document element is not nvm3");
+ }
+ NVM3Mode rootMode = new NVM3Mode(NVM3Mode.TYPE_SIMPLE);
+
+ IQuery q = parseQuery(e, null);
+ NVM3Metadata[] mds = parseInternal(rootMode, e.getChildNodes(), q);
+ if (mds.length == 0) {
+ return null;
+ }
+
+ return new NVM3GroupMetadata(nvm3Service, q, rootMode, mds);
+ }
+
+ public NVM3Metadata parse(INVM3Entry entry) throws XMLStoreException {
+ NVM3EntryImpl ei = (NVM3EntryImpl) entry;
+ IXMLInfo info = ei.getIXMLInfo();
+ Node n = info.getRootNode();
+ Element e;
+ if (n instanceof Document) {
+ e = ((Document) n).getDocumentElement();
+ } else if (n instanceof Element) {
+ e = (Element) n;
+ } else {
+ throw new XMLStoreException("Failed to load NVM3.", null);
+ }
+ return parseTop(e);
+ }
+
+ NVM3DOMReader(NVM3ServiceImpl nvm3Service) {
+ this.nvm3Service = nvm3Service;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3EntryImpl.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3EntryImpl.java
new file mode 100644
index 0000000..4bfdb01
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3EntryImpl.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.io.File;
+
+import org.eclipse.actf.ai.fennec.INVM3Entry;
+import org.eclipse.actf.ai.xmlstore.IXMLInfo;
+import org.eclipse.actf.ai.xmlstore.XMLStorePlugin;
+
+
+
+
+public class NVM3EntryImpl implements INVM3Entry {
+ private IXMLInfo info;
+
+ public String getDocumentation() {
+ return info.getDocumentation();
+ }
+
+ public boolean isUserEntry() {
+ return info.isUserEntry();
+ }
+
+ public IXMLInfo getIXMLInfo() {
+ return info;
+ }
+
+ public NVM3EntryImpl(IXMLInfo info) {
+ this.info = info;
+ }
+
+ public boolean export(File dest) {
+ return XMLStorePlugin.getDefault().getXMLStoreService().exportMetadata(info, dest);
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3GeneratedMetadata.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3GeneratedMetadata.java
new file mode 100644
index 0000000..f885cca
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3GeneratedMetadata.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.actf.ai.fennec.NVM3Exception;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.model.dom.dombycom.INodeEx;
+import org.w3c.dom.Node;
+
+
+class NVM3GeneratedMetadata extends NVM3BundleMetadata {
+ private final Node node;
+
+ @Override
+ public String getAltText(ITreeItem item) {
+ String r = super.getAltText(item);
+ if (r == null) return null;
+ if (r.length() > 0)
+ return r;
+ if (node instanceof INodeEx) {
+ return ((INodeEx) node).extractString();
+ }
+ return "";
+ }
+
+ @Override
+ public String getDescription(ITreeItem item) {
+ return super.getDescription(item);
+ }
+
+ public short getHeadingLevelByMetadata(ITreeItem item) {
+ return super.getHeadingLevel(item);
+ }
+
+ @Override
+ public short getHeadingLevel(ITreeItem item) {
+ short r = super.getHeadingLevel(item);
+ if (r > 0)
+ return r;
+ if (r == -1)
+ return -1;
+ if (node instanceof INodeEx) {
+ return ((INodeEx) node).getHeadingLevel();
+ }
+ return 0;
+ }
+
+ @Override
+ List expand(TreeItemNVM3 pItem, int trigger) throws NVM3Exception {
+ ITreeItem[] childItems = pItem.getChildItems();
+ if (!mode.changed(pItem, trigger) && pItem.hasAlreadyChildRefreshed()) {
+ return Arrays.asList(childItems);
+ } else {
+ TreeItemNVM3 bItem = mode.buildItemContinued(node, pItem);
+ if ((bItem != null) && bItem.hasChild()) {
+ return Arrays.asList(bItem.getChildItems());
+ }
+ }
+ return null;
+ }
+
+ public static NVM3GeneratedMetadata generate(NVM3RecombinantMetadata metadata, NVM3Mode mode, Node node,
+ NVM3Metadata[] childMds) {
+ return new NVM3GeneratedMetadata(metadata.nvm3Service, mode, node, childMds);
+ }
+
+ private NVM3GeneratedMetadata(NVM3ServiceImpl nvm3Service, NVM3Mode mode, Node node, NVM3Metadata[] childMds) {
+ super(nvm3Service, mode, node, childMds);
+ this.node = node;
+ }
+
+ public static NVM3Metadata generate(NVM3GeneratedMetadata meta, NVM3GeneratedMetadata meta2) {
+ NVM3Metadata[] childMds = new NVM3Metadata[meta.childMetadata.length+meta2.childMetadata.length];
+ for(int i=0; i<meta.childMetadata.length; i++)
+ childMds[i] = meta.childMetadata[i];
+ for(int i=0; i<meta2.childMetadata.length; i++)
+ childMds[meta.childMetadata.length+i] = meta2.childMetadata[i];
+ return new NVM3GeneratedMetadata(meta.nvm3Service, meta.mode, meta.node, childMds);
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3GroupMetadata.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3GroupMetadata.java
new file mode 100644
index 0000000..174f1e5
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3GroupMetadata.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.query.IQuery;
+import org.eclipse.actf.model.dom.dombycom.INodeEx;
+
+
+class NVM3GroupMetadata extends NVM3BundleMetadata {
+
+ public String getAltText(ITreeItem item) {
+ String r = super.getAltText(item);
+ if (r == null) return null;
+ if (r.length() > 0) return r;
+ // If not specified, extract some string from the node.
+ return NodeUtil.extractString(item);
+ }
+
+ public short getHeadingLevel(ITreeItem item) {
+ short r = super.getHeadingLevel(item);
+ if (r > 0) return r;
+ if (r == -1) return -1;
+ Object baseNode = item.getBaseNode();
+ if (baseNode instanceof INodeEx) {
+ return ((INodeEx) baseNode).getHeadingLevel();
+ }
+ return 0;
+ }
+
+ NVM3GroupMetadata(NVM3ServiceImpl nvm3Service,
+ IQuery q, NVM3Mode mode,
+ NVM3Metadata[] childMds) {
+ super(nvm3Service, q, mode, childMds);
+ }
+
+}
+
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3Metadata.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3Metadata.java
new file mode 100644
index 0000000..367b524
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3Metadata.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.actf.ai.fennec.NVM3Exception;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.query.IQuery;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+abstract class NVM3Metadata {
+ protected final NVM3ServiceImpl nvm3Service;
+ private final IQuery query;
+
+ private final boolean hasTarget;
+ public boolean hasTargets() {
+ return hasTarget;
+ }
+
+ private static class EmptyNodeList implements NodeList {
+ public Node item(int index) {
+ return null;
+ }
+
+ public int getLength() {
+ return 0;
+ }
+ }
+ private static final NodeList emptyNodeList = new EmptyNodeList();
+
+ NodeList query(IQuery q, Node baseNode) {
+ if ((q == null) || (!q.hasTarget())) return emptyNodeList;
+ return q.query(baseNode);
+ }
+
+ NodeList query(IQuery q, ITreeItem baseItem) {
+ if ((q == null) || (!q.hasTarget())) return emptyNodeList;
+ Node baseNode;
+ for (baseNode = null;
+ (baseItem != null) && (baseNode == null);
+ baseItem = baseItem.getParent()) {
+ baseNode = (Node) baseItem.getBaseNode();
+ }
+ if (baseNode == null) {
+ baseNode = nvm3Service.getDocumentElement();
+ }
+ if (baseNode == null) return emptyNodeList;
+ return q.query(baseNode);
+ }
+
+ NodeList query(Node baseNode) {
+ return query(this.query, baseNode);
+ }
+
+ NodeList query(ITreeItem baseItem) {
+ return query(this.query, baseItem);
+ }
+
+ protected final NVM3Mode mode;
+
+ public abstract String getAltText(ITreeItem item);
+ public abstract String getDescription(ITreeItem item);
+ public abstract short getHeadingLevel(ITreeItem item);
+
+ List buildItems(TreeItemNVM3 baseItem, Node baseNode, int trigger) throws NVM3Exception {
+ if (hasTargets()) {
+ NodeList nl;
+ if (baseNode != null) {
+ nl = query(baseNode);
+ } else {
+ nl = query(baseItem);
+ }
+ int len = nl.getLength();
+ ArrayList result = new ArrayList(len);
+ for (int i = 0; i < len; i++) {
+ Node n = nl.item(i);
+ TreeItemNVM3 newItem = TreeItemNVM3.newTreeItem(this, baseItem, n);
+ if (newItem != null) {
+ result.add(newItem);
+ }
+ }
+ return result;
+ } else if (this instanceof NVM3BundleMetadata) {
+ ArrayList result = new ArrayList(1);
+ TreeItemNVM3 newItem = TreeItemNVM3.newTreeItem(this, baseItem, null);
+ if (newItem != null) {
+ result.add(newItem);
+ }
+ return result;
+ }
+ return null;
+ }
+
+ TreeItemNVM3 buildRootItem() throws NVM3Exception {
+ List items = buildItems(null, null, NVM3Mode.TRIGGER_MOVE);
+ if ((items == null) || (items.size() == 0)) {
+ return null;
+ }
+ if (items.size() == 1) {
+ TreeItemNVM3 root = (TreeItemNVM3) items.get(0);
+ return root.expand(NVM3Mode.TRIGGER_MOVE);
+ } else {
+ TreeItemNVM3 root = TreeItemNVM3.newTreeItem(this, null, nvm3Service.getDocumentElement());
+ if (root == null) return null;
+ root.setChildItems(items);
+ return root;
+ }
+ }
+
+ abstract List expand(TreeItemNVM3 pItem, int trigger) throws NVM3Exception;
+
+ protected NVM3Metadata(NVM3ServiceImpl nvm3Service,
+ IQuery q, NVM3Mode mode) {
+ this.nvm3Service = nvm3Service;
+ this.query = q;
+ if (q != null) {
+ this.hasTarget = q.hasTarget();
+ } else {
+ this.hasTarget = false;
+ }
+ this.mode = mode;
+ this.mode.addMetadata(this);
+ }
+
+ protected NVM3Metadata(NVM3ServiceImpl nvm3Service,
+ NVM3Mode mode,
+ Node node) {
+ this.nvm3Service = nvm3Service;
+ this.query = null;
+ this.hasTarget = false;
+ this.mode = mode;
+ this.mode.addMetadata(this);
+ }
+
+}
+
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3Mode.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3Mode.java
new file mode 100644
index 0000000..8a155d2
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3Mode.java
@@ -0,0 +1,292 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.eclipse.actf.ai.fennec.NVM3Exception;
+import org.eclipse.actf.ai.fennec.NVM3InterruptedException;
+import org.eclipse.actf.ai.fennec.autotranslator.AutoTranslator;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+// TODO I'd like to make it package-local.
+public class NVM3Mode {
+ static public final int TYPE_SIMPLE = 0;
+
+ static public final int TYPE_ATTACH = 1;
+
+ static public final int TYPE_UNWRAP = 2;
+
+ static public final int TYPE_BUILT = 2;
+
+ static public final int TRIGGER_MOVE = 1 << 0;
+
+ static public final int TRIGGER_CLICK = 1 << 1;
+
+ static public final int TRIGGER_KEEP = 1 << 2;
+
+ static public final int TRIGGER_WITHOUTCHANGE = 1 << 3;
+
+ static public final int TRIGGER_UNWRAP = 1 << 4;
+
+ static public final int TRIGGER_ALWAYS = (TRIGGER_MOVE
+ | TRIGGER_CLICK
+ | TRIGGER_KEEP
+ | TRIGGER_UNWRAP);
+
+ private final int type;
+
+ private final int trigger;
+
+ private final boolean automatic;
+
+ private final boolean changeless;
+
+ private final boolean waitContents;
+
+ private NVM3RecombinantMetadata baseMetadata;
+
+ private List<NVM3Metadata> belongingMetadata;
+
+ private HashMap<Node, ArrayList<NVM3Metadata>> metadataMap;
+
+ void addMetadata(NVM3Metadata md) {
+ if (false) {
+ // A mode manages its belonging metadata in order to manage substate, but
+ // currently it is not used... So now this part is disabled.
+ if (belongingMetadata == null) {
+ belongingMetadata = new ArrayList<NVM3Metadata>();
+ }
+ belongingMetadata.add(md);
+ }
+ }
+
+ void setBaseMetadata(NVM3RecombinantMetadata md) {
+ this.baseMetadata = md;
+ }
+
+ boolean changed(TreeItemNVM3 pItem, int trigger) {
+ // TODO:
+ // return true;
+ if ((trigger & TRIGGER_WITHOUTCHANGE) != 0)
+ return false;
+ if (changeless)
+ return false;
+ return true;
+ }
+
+ private TreeItemNVM3 currentTopItem;
+
+ TreeItemNVM3 buildItem(Node n, TreeItemNVM3 pItem) {
+ currentTopItem = pItem;
+ TreeItemNVM3 item = AutoTranslator.translate(this, pItem, n);
+ if (pItem != null)
+ pItem.markRefreshedChild();
+ return item;
+ }
+
+ TreeItemNVM3 buildItemContinued(Node n, TreeItemNVM3 item) {
+ currentTopItem = null;
+ TreeItemNVM3 newItem = AutoTranslator.translateContinued(this, item, n);
+ if (newItem != null)
+ newItem.markRefreshedChild();
+ return newItem;
+ }
+
+ private NVM3Metadata[] topMds;
+
+ private NVM3Metadata[] initMetadataMap(NVM3Metadata[] mds, Node n) {
+ if (topMds != null) return topMds;
+
+ metadataMap = new HashMap<Node, ArrayList<NVM3Metadata>>();
+ ArrayList<NVM3Metadata> mdList = new ArrayList<NVM3Metadata>();
+ for (int i = 0; i < mds.length; i++) {
+ if (mds[i].hasTargets()) {
+ registMetadata(metadataMap, mds[i], n);
+ } else {
+ mdList.add(mds[i]);
+ }
+ }
+ topMds = mdList.toArray(new NVM3Metadata[mdList.size()]);
+ return topMds;
+ }
+
+ public TreeItemNVM3 generateItem(TreeItemNVM3 pItem, Node n) {
+ NVM3Metadata[] cmds = null;
+
+ NVM3Metadata[] mds = baseMetadata.getChildMetadata();
+ if (mds != null) {
+ if (currentTopItem == pItem) {
+ // This item is top.
+ cmds = initMetadataMap(mds, n);
+ } else {
+ initMetadataMap(mds, n);
+ ArrayList<NVM3Metadata> aMeta = metadataMap.get(n);
+ if (aMeta != null) {
+ cmds = (NVM3Metadata[]) aMeta.toArray(new NVM3Metadata[aMeta.size()]);
+ }
+ }
+ }
+ NVM3Metadata md = NVM3GeneratedMetadata.generate(baseMetadata, this, n, cmds);
+
+ return TreeItemNVM3.newTreeItem(md, pItem, n);
+ }
+
+ private void registMetadata(HashMap<Node, ArrayList<NVM3Metadata>> metaMap, NVM3Metadata meta, Node base) {
+ NodeList list = meta.query(base);
+
+ for (int i = 0; i < list.getLength(); i++) {
+ Node node = list.item(i);
+ ArrayList<NVM3Metadata> aMeta = metaMap.get(node);
+ if (aMeta == null) {
+ aMeta = new ArrayList<NVM3Metadata>();
+ metaMap.put(node, aMeta);
+ }
+ if (meta instanceof NVM3BundleMetadata) {
+ NVM3Metadata[] m = ((NVM3BundleMetadata) meta).childMetadata;
+ for (int j = 0; j < m.length; j++) {
+ if (m[j].hasTargets()) {
+ registMetadata(metaMap, m[j], node);
+ } else {
+ aMeta.add(m[j]);
+ }
+ }
+ }
+ }
+ }
+
+ private List autoAttach(TreeItemNVM3 pItem, NodeList nl, int len, int trigger) throws NVM3Exception {
+ List l = new ArrayList(len);
+
+ for (int i = 0; i < len; i++) {
+ Node n = nl.item(i);
+ /*
+ if (n instanceof CacheableNode) {
+ CachableNode cn = (CachableNode) cn;
+ if (!cn.isChanged()) {
+ } else {
+ }
+ }
+ */
+ TreeItemNVM3 newItem = buildItem(n, pItem);
+ if (newItem != null)
+ l.add(newItem);
+ }
+ if (l.size() == 0) {
+ if (this.trigger == TRIGGER_CLICK) {
+ throw new NVM3InterruptedException("Could not attach the expected nodes.");
+ }
+ return null;
+ }
+ if (waitContents && (l.size() == 0)) {
+ throw new NVM3InterruptedException("Contents have not been prepared yet.");
+ }
+ return l;
+ }
+
+ private List manualAttach(TreeItemNVM3 pItem, NodeList nl, int len, int trigger) throws NVM3Exception {
+ List l = new ArrayList(len);
+
+ NVM3Metadata[] childMds = baseMetadata.getChildMetadata();
+ for (int j = 0; j < len; j++) {
+ for (int i = 0; i < childMds.length; i++) {
+ NVM3Metadata md = childMds[i];
+ List l2 = md.buildItems(pItem, nl.item(j), trigger);
+ if (l2 != null) {
+ if (l2.size() > 0) {
+ l.addAll(l2);
+ } else if (waitContents) {
+ throw new NVM3InterruptedException("Contents have not been prepared yet.");
+ }
+ }
+ }
+ }
+
+ return l;
+ }
+
+ private List unwrap(TreeItemNVM3 pItem, NodeList nl, int len, int trigger) {
+ //TODO
+ return null;
+ }
+
+ // TODO:
+ private HashMap cachedResult = new HashMap();
+
+ List expand(TreeItemNVM3 pItem, Node baseNode, int trigger) throws NVM3Exception {
+ if ((trigger != TRIGGER_KEEP) && ((trigger & this.trigger) == 0)) {
+ return null;
+ }
+ Object key;
+ if (baseNode != null) {
+ key = baseNode;
+ } else if (pItem == null) {
+ key = null;
+ } else {
+ key = pItem.getBaseNode();
+ }
+ if (!changed(pItem, trigger)) {
+ List l = (List) cachedResult.get(key);
+ if (l != null)
+ return l;
+ }
+
+ NodeList nl;
+ if (baseNode != null) {
+ nl = baseMetadata.query(baseNode);
+ } else {
+ nl = baseMetadata.query(pItem);
+ }
+ int len = nl.getLength();
+ List result = null;
+ switch (type) {
+ case TYPE_ATTACH:
+ if (len == 0) {
+ if (this.trigger == TRIGGER_CLICK) {
+ throw new NVM3InterruptedException("Could not attach the expected nodes.");
+ }
+ return null;
+ }
+ if (automatic) {
+ result = autoAttach(pItem, nl, len, trigger);
+ } else {
+ result = manualAttach(pItem, nl, len, trigger);
+ }
+ cachedResult.put(key, result);
+ return result;
+ case TYPE_UNWRAP:
+ // TODO;
+ }
+
+ return result;
+ }
+
+ NVM3Mode(int type, int trigger, boolean automatic, boolean changeless, boolean waitContents) {
+ this.type = type;
+ this.trigger = trigger;
+ this.automatic = automatic;
+ this.changeless = changeless;
+ this.waitContents = waitContents;
+ }
+
+ NVM3Mode(int type) {
+ this.type = type;
+ this.trigger = TRIGGER_ALWAYS;
+ this.automatic = false;
+ this.changeless = false;
+ this.waitContents = false;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3RecombinantMetadata.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3RecombinantMetadata.java
new file mode 100644
index 0000000..e5fcd4e
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3RecombinantMetadata.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.util.List;
+
+import org.eclipse.actf.ai.fennec.NVM3Exception;
+import org.eclipse.actf.ai.query.IQuery;
+import org.w3c.dom.Node;
+
+
+class NVM3RecombinantMetadata extends NVM3BundleMetadata {
+ static public final int TYPE_SIMPLE = 0;
+ static public final int TYPE_ATTACH = 1;
+ static public final int TYPE_UNWRAP = 2;
+
+ private final int type;
+ private NVM3Mode nextMode;
+
+ public NVM3Mode getNextMode() {
+ return nextMode;
+ }
+
+ List expand(TreeItemNVM3 pItem, int trigger) throws NVM3Exception {
+ return nextMode.expand(pItem, null, trigger);
+ }
+
+ List buildItems(TreeItemNVM3 baseItem, Node baseNode, int trigger) throws NVM3Exception {
+ return nextMode.expand(baseItem, baseNode, trigger);
+ }
+
+ TreeItemNVM3 buildRootItem() throws NVM3Exception {
+ TreeItemNVM3 root = super.buildRootItem();
+ if (root == null) {
+ throw new NVM3Exception("NVM3.EMPTY_PAGE", null);
+ }
+ return root;
+ }
+
+
+ static NVM3RecombinantMetadata newAttach(NVM3ServiceImpl nvm3Service,
+ IQuery q, NVM3Mode mode,
+ NVM3Mode nextMode,
+ NVM3Metadata[] mds) {
+ NVM3RecombinantMetadata md = new NVM3RecombinantMetadata(nvm3Service,
+ q, mode,
+ nextMode, mds,
+ TYPE_ATTACH);
+ return md;
+ }
+
+ static NVM3RecombinantMetadata newUnwrap(NVM3ServiceImpl nvm3Service,
+ IQuery q, NVM3Mode mode,
+ NVM3Mode nextMode,
+ NVM3Metadata[] mds) {
+ NVM3RecombinantMetadata md = new NVM3RecombinantMetadata(nvm3Service,
+ q, mode,
+ nextMode, mds,
+ TYPE_UNWRAP);
+ return md;
+ }
+
+ private NVM3RecombinantMetadata(NVM3ServiceImpl nvm3Service,
+ IQuery q,
+ NVM3Mode mode,
+ NVM3Mode nextMode,
+ NVM3Metadata[] mds,
+ int type) {
+ super(nvm3Service, q, mode, mds);
+ this.type = type;
+ this.nextMode = nextMode;
+ nextMode.setBaseMetadata(this);
+ }
+}
+
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3ServiceImpl.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3ServiceImpl.java
new file mode 100644
index 0000000..484849d
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3ServiceImpl.java
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import org.eclipse.actf.ai.fennec.INVM3Entry;
+import org.eclipse.actf.ai.fennec.INVM3Service;
+import org.eclipse.actf.ai.fennec.NVM3Exception;
+import org.eclipse.actf.ai.fennec.NVM3InterruptedException;
+import org.eclipse.actf.ai.fennec.treemanager.IAccessKeyList;
+import org.eclipse.actf.ai.fennec.treemanager.ISoundControl;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeManager;
+import org.eclipse.actf.ai.fennec.treemanager.IVideoControl;
+import org.eclipse.actf.ai.fennec.treemanager.TreeManagerException;
+import org.eclipse.actf.ai.query.IQuery;
+import org.eclipse.actf.ai.query.QueryService;
+import org.eclipse.actf.model.dom.dombycom.AnalyzedResult;
+import org.eclipse.actf.model.dom.dombycom.IDocumentEx;
+import org.eclipse.actf.model.dom.dombycom.IFlashNode;
+import org.eclipse.actf.model.dom.dombycom.INodeEx;
+import org.eclipse.actf.util.vocab.IProposition;
+import org.eclipse.actf.util.vocab.Vocabulary;
+import org.w3c.dom.Element;
+
+
+public class NVM3ServiceImpl implements INVM3Service {
+ private NVM3Metadata rootMetadata;
+
+ private int status;
+
+ private TreeItemNVM3 lastItem;
+
+ private IDocumentEx document;
+
+ private Element root;
+
+ private AnalyzedResult analyzedResult;
+
+ Element getDocumentElement() {
+ return root;
+ }
+
+ private void initDefaultMetadata() {
+ NVM3Mode rootMode = new NVM3Mode(NVM3Mode.TYPE_SIMPLE);
+ NVM3Mode nextMode = new NVM3Mode(NVM3Mode.TYPE_ATTACH, NVM3Mode.TRIGGER_ALWAYS, true, false, false);
+ // /HTML/FRAMESET/FRAME/HTML/BODY
+ //IQuery q = QueryService.createFromXPath("/HTML/BODY|/HTML/FRAMESET//FRAME/HTML/BODY");
+ //IQuery q = QueryService.createFromXPath("//HTML/BODY");
+ IQuery q = QueryService.createFromXPath("/HTML");
+ NVM3Metadata[] mds = new NVM3Metadata[1];
+ mds[0] = NVM3RecombinantMetadata.newAttach(this, q, rootMode, nextMode, null);
+ rootMetadata = new NVM3GroupMetadata(this, null, rootMode, mds);
+ }
+
+ public NVM3ServiceImpl(INVM3Entry entry, IDocumentEx document) throws NVM3Exception {
+ this.document = document;
+ this.root = document.getDocumentElement();
+ try {
+ NVM3DOMReader reader = new NVM3DOMReader(this);
+ rootMetadata = reader.parse(entry);
+ this.status = UNINIT;
+ } catch (Exception e) {
+ throw new NVM3Exception("Failed to load NVM3 data.", e);
+ }
+ }
+
+ public NVM3ServiceImpl(IDocumentEx document) {
+ this.document = document;
+ this.root = document.getDocumentElement();
+ initDefaultMetadata();
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public int analyze() throws NVM3Exception {
+ analyzedResult = new AnalyzedResult();
+ if (root instanceof INodeEx) {
+ cachedVideoControl = null;
+ cachedSoundControl = null;
+ analyzedResult = ((INodeEx) root).analyze(analyzedResult);
+ }
+ return ITreeManager.NOACTION;
+ }
+
+ private ISoundControl cachedSoundControl;
+
+ private IVideoControl cachedVideoControl;
+
+ private IAccessKeyList cachedAccessKeyList;
+
+ private IFlashNode[] cachedFlashTopNodes;
+
+ public int initialize() throws NVM3Exception {
+ if (analyzedResult == null) {
+ analyze();
+ }
+ lastItem = rootMetadata.buildRootItem();
+ if (lastItem == null) {
+ throw new NVM3Exception("Failed to initialize", null);
+ }
+ status = NORMAL;
+ return ITreeManager.MOVED;
+ }
+
+ public ITreeItem getLastTreeItem() {
+ return lastItem;
+ }
+
+ private int update(ITreeItem target, int trigger) throws NVM3Exception {
+ TreeItemNVM3 targetItem = (TreeItemNVM3) target;
+ if (targetItem.getParent() == null) {
+ return initialize();
+ } else {
+ targetItem = targetItem.expand(trigger);
+ if (targetItem == null) {
+ return ITreeManager.NOACTION;
+ }
+ }
+ if (targetItem == null) {
+ status = UNINIT;
+ throw new NVM3InterruptedException("Lost my way"); // $ NON-NLS-1
+ }
+ lastItem = targetItem;
+ return ITreeManager.MOVED;
+ }
+
+ public int moveUpdate(ITreeItem target) throws NVM3Exception {
+ return update(target, NVM3Mode.TRIGGER_MOVE);
+ }
+
+ public int moveUpdate(ITreeItem target, boolean update) throws NVM3Exception {
+ if (update) {
+ return update(target, NVM3Mode.TRIGGER_MOVE);
+ } else {
+ return update(target, NVM3Mode.TRIGGER_MOVE | NVM3Mode.TRIGGER_WITHOUTCHANGE);
+ }
+ }
+
+ public int clickUpdate(ITreeItem target) throws NVM3Exception {
+ return update(target, NVM3Mode.TRIGGER_CLICK) | ITreeManager.CLICKED;
+ }
+
+ private int searchForwardChildren(int idx, TreeItemNVM3 item, IProposition proposition) throws NVM3Exception {
+ int st;
+ item = item.expandChildItems(NVM3Mode.TRIGGER_KEEP);
+ ITreeItem[] childItems = item.getChildItems();
+ for (int i = idx; i < childItems.length; i++) {
+ TreeItemNVM3 cItem = (TreeItemNVM3) childItems[i];
+ if (proposition.eval(cItem)) {
+ return moveUpdate(cItem) | ITreeManager.FOUND;
+ }
+ st = searchForwardChildren(0, cItem, proposition);
+ if ((st & ITreeManager.FOUND) != 0)
+ return st;
+ }
+ return ITreeManager.NOACTION;
+ }
+
+ private int searchForwardInternal(int idx, TreeItemNVM3 item, IProposition proposition) throws NVM3Exception {
+ int st = searchForwardChildren(idx, item, proposition);
+ if ((st & ITreeManager.FOUND) != 0)
+ return st;
+ TreeItemNVM3 pItem = (TreeItemNVM3) item.getParent();
+ if (pItem == null)
+ return ITreeManager.NOACTION;
+ st = searchForwardInternal(item.getNth() + 1, pItem, proposition);
+ if ((st & ITreeManager.FOUND) != 0)
+ return st;
+
+ return ITreeManager.NOACTION;
+ }
+
+ public ITreeItem[] getSiblings() throws TreeManagerException {
+ ITreeItem parent = lastItem.getParent();
+ if (parent == null) {
+ ITreeItem[] itas = new ITreeItem[1];
+ itas[0] = lastItem;
+ return itas;
+ }
+ return parent.getChildItems();
+ }
+
+ public int searchForward(IProposition proposition) throws NVM3Exception {
+ return searchForwardInternal(0, lastItem, proposition);
+ }
+
+ private int searchBackwardInternal(boolean first, TreeItemNVM3 item, IProposition proposition) throws NVM3Exception {
+ TreeItemNVM3 pItem = (TreeItemNVM3) item.getParent();
+ if (pItem == null)
+ return ITreeManager.NOACTION;
+ int nth = item.getNth() - 1;
+ if (nth < 0) {
+ if (proposition.eval(pItem)) {
+ return moveUpdate(pItem) | ITreeManager.FOUND;
+ }
+ return searchBackwardInternal(false, pItem, proposition);
+ }
+ if (first) {
+ pItem = pItem.expandChildItems(NVM3Mode.TRIGGER_KEEP);
+ }
+ ITreeItem[] siblings = pItem.getChildItems();
+ if (nth >= siblings.length) {
+ nth = siblings.length - 1;
+ }
+ item = (TreeItemNVM3) siblings[nth];
+
+ while (true) {
+ item = item.expandChildItems(NVM3Mode.TRIGGER_KEEP);
+ ITreeItem[] childItems = item.getChildItems();
+ if (childItems.length == 0)
+ break;
+ item = (TreeItemNVM3) childItems[childItems.length - 1];
+ }
+ if (proposition.eval(item)) {
+ return moveUpdate(item) | ITreeManager.FOUND;
+ }
+ return searchBackwardInternal(false, item, proposition);
+ }
+
+ public int searchBackward(IProposition predicate) throws NVM3Exception {
+ return searchBackwardInternal(true, lastItem, predicate);
+ }
+
+ public ISoundControl getSoundControl() {
+ if (cachedSoundControl == null) {
+ cachedSoundControl = TreeItemSoundControl.newTreeItemSoundControl(analyzedResult);
+ }
+ return cachedSoundControl;
+ }
+
+ public IVideoControl getVideoControl() {
+ if (cachedVideoControl == null) {
+ cachedVideoControl = TreeItemVideoControl.newTreeItemVideoControl(analyzedResult, this);
+ }
+ return cachedVideoControl;
+ }
+
+ public IAccessKeyList getAccessKeyList() {
+ if (cachedAccessKeyList == null) {
+ cachedAccessKeyList = TreeItemAccessKeyList.newAccessKeyList(analyzedResult);
+ }
+ return cachedAccessKeyList;
+ }
+
+ public IFlashNode[] getFlashTopNodes() {
+ if (cachedFlashTopNodes == null) {
+ cachedFlashTopNodes = analyzedResult.getFlashTopNodes();
+ }
+ return cachedFlashTopNodes;
+ }
+
+ private void expandWholeTreeInternal(TreeItemNVM3 item) throws NVM3Exception {
+ item = item.expandChildItems(NVM3Mode.TRIGGER_KEEP);
+ ITreeItem[] childItems = item.getChildItems();
+ for (int i = 0; i < childItems.length; i++) {
+ expandWholeTreeInternal((TreeItemNVM3) childItems[i]);
+ }
+ }
+
+ private int skipToNode(Element e) throws NVM3Exception {
+ initialize();
+ return searchForward(Vocabulary.nodeLocation(e, false));
+ }
+
+ public int skipToAnchor(String target) throws NVM3Exception {
+ Element el = document.getTargetElement(target);
+ if (el != null)
+ return skipToNode(el);
+ return ITreeManager.NOACTION;
+ }
+
+ public ITreeItem expandWholeTree() throws NVM3Exception {
+ initialize();
+ if (lastItem instanceof TreeItemNVM3) {
+ expandWholeTreeInternal((TreeItemNVM3) lastItem);
+ }
+ return lastItem;
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3SimpleMetadata.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3SimpleMetadata.java
new file mode 100644
index 0000000..88efca3
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3SimpleMetadata.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.actf.ai.fennec.NVM3Exception;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.query.IQuery;
+import org.w3c.dom.NodeList;
+
+
+class NVM3SimpleMetadata extends NVM3Metadata {
+ static public final int TYPE_ALT_TEXT = 1;
+ static public final int TYPE_DESCRIPTION = 2;
+ static public final int TYPE_HEADER = 3;
+
+ private short headingLevel;
+ private int type;
+
+ private List stringFormat;
+
+ public short getHeadingLevel(ITreeItem item) {
+ return headingLevel;
+ }
+
+ public String getString(ITreeItem item) {
+ StringBuffer buf = new StringBuffer();
+ if (stringFormat == null) return null;
+ Iterator it = stringFormat.iterator();
+ while (it.hasNext()) {
+ Object o = it.next();
+ if (o instanceof String) {
+ buf.append((String) o);
+ } else if (o instanceof IQuery) {
+ IQuery q = (IQuery) o;
+ NodeList nl = query(q, item);
+ String str = NodeUtil.extractString(nl);
+ buf.append(str);
+ }
+ }
+ return buf.toString();
+ }
+
+ public String getAltText(ITreeItem item) {
+ if (type == TYPE_ALT_TEXT) return getString(item);
+ return "";
+ }
+
+ public String getDescription(ITreeItem item) {
+ if (type == TYPE_DESCRIPTION) return getString(item);
+ return "";
+ }
+
+ static NVM3SimpleMetadata newHeader(NVM3ServiceImpl nvm3Service,
+ IQuery q, NVM3Mode mode, short level) {
+ NVM3SimpleMetadata md = new NVM3SimpleMetadata(nvm3Service, q, mode);
+ md.type = TYPE_HEADER;
+ md.headingLevel = level;
+ return md;
+ }
+
+ static NVM3SimpleMetadata newAltText(NVM3ServiceImpl nvm3Service,
+ IQuery q, NVM3Mode mode, List stringFormat) {
+ NVM3SimpleMetadata md = new NVM3SimpleMetadata(nvm3Service, q, mode);
+ md.type = TYPE_ALT_TEXT;
+ md.stringFormat = stringFormat;
+ return md;
+ }
+
+ static NVM3SimpleMetadata newDescription(NVM3ServiceImpl nvm3Service,
+ NVM3Mode mode, IQuery q, List stringFormat) {
+ NVM3SimpleMetadata md = new NVM3SimpleMetadata(nvm3Service, q, mode);
+ md.type = TYPE_DESCRIPTION;
+ md.stringFormat = stringFormat;
+ return md;
+ }
+
+ private NVM3SimpleMetadata(NVM3ServiceImpl nvm3Service,
+ IQuery q, NVM3Mode mode) {
+ super(nvm3Service, q, mode);
+ }
+
+ List expand(TreeItemNVM3 pItem, int trigger) throws NVM3Exception {
+ return null;
+ }
+}
+
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3TableMetadata.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3TableMetadata.java
new file mode 100644
index 0000000..1c3229e
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3TableMetadata.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.query.IQuery;
+import org.eclipse.actf.model.dom.dombycom.INodeEx;
+
+
+class NVM3TableMetadata extends NVM3BundleMetadata {
+ private final NVM3TableRowMetadata[] rowMds;
+
+ public int getRowSize() {
+ return rowMds.length;
+ }
+
+ public NVM3TableRowMetadata getRow(int idx) {
+ return rowMds[idx];
+ }
+
+ public String getAltText(ITreeItem item) {
+ String r = super.getAltText(item);
+ if (r.length() > 0) return r;
+ // If not specified, extract some string from the node.
+ return NodeUtil.extractString(item);
+ }
+
+ public short getHeadingLevel(ITreeItem item) {
+ short r = super.getHeadingLevel(item);
+ if (r > 0) return r;
+ if (r == -1) return -1;
+ Object baseNode = item.getBaseNode();
+ if (baseNode instanceof INodeEx) {
+ return ((INodeEx) baseNode).getHeadingLevel();
+ }
+ return 0;
+ }
+
+ NVM3TableMetadata(NVM3ServiceImpl nvm3Service,
+ IQuery q, NVM3Mode mode,
+ NVM3Metadata[] childMds,
+ NVM3TableRowMetadata[] rowMds) {
+ super(nvm3Service, q, mode, childMds);
+ this.rowMds = rowMds;
+ }
+
+}
+
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3TableRowMetadata.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3TableRowMetadata.java
new file mode 100644
index 0000000..01d398f
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NVM3TableRowMetadata.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import org.w3c.dom.Node;
+
+class NVM3TableRowMetadata extends NVM3BundleMetadata {
+
+ protected NVM3TableRowMetadata(NVM3ServiceImpl nvm3Service,
+ NVM3Mode mode,
+ Node node,
+ NVM3Metadata[] mds) {
+ super(nvm3Service, mode, node, mds);
+ }
+}
+
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NodeUtil.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NodeUtil.java
new file mode 100644
index 0000000..e65e3a1
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/NodeUtil.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.impl;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.model.dom.dombycom.INodeEx;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+
+
+public class NodeUtil {
+ private static StringBuffer extractNodeString(StringBuffer buf, Node n) {
+ if (n instanceof INodeEx) {
+ INodeEx n2 = (INodeEx) n;
+
+ // TODO: should be rewritten!!
+ // changed by daisuke
+ String n2String = n2.extractString();
+ buf.append(n2String);
+ if (n2String != null && n2String.length() > 0) // if node has text
+ buf.append(" "); // insert default separator
+ }
+ NodeList nl = n.getChildNodes();
+ int len = nl.getLength();
+ for (int i = 0; i < len; i++) {
+ buf = extractNodeString(buf, nl.item(i));
+ }
+ return buf;
+ }
+
+ public static String extractString(NodeList nl) {
+ StringBuffer buf = new StringBuffer();
+ int len = nl.getLength();
+ for (int i = 0; i < len; i++) {
+ Node n = nl.item(i);
+ buf = extractNodeString(buf, n);
+ }
+ return buf.toString();
+ }
+
+ public static String extractString(Node n) {
+ StringBuffer buf = new StringBuffer();
+ buf = extractNodeString(buf, n);
+ return buf.toString();
+ }
+
+ public static String extractString(ITreeItem item) {
+ Node baseNode = (Node) item.getBaseNode();
+ if (baseNode != null) {
+ return extractString(baseNode);
+ }
+ return "";
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TableImpl.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TableImpl.java
new file mode 100644
index 0000000..7e55986
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TableImpl.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+
+package org.eclipse.actf.ai.fennec.impl;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITable;
+import org.eclipse.actf.ai.fennec.treemanager.ITableRow;
+
+
+
+public class TableImpl implements ITable {
+ private NVM3TableMetadata tableMetadata;
+
+ public ITableRow[] getRow(int row) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int getColumnSize() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getRowSize() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public String getTableString() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemAccessKeyList.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemAccessKeyList.java
new file mode 100644
index 0000000..b8d22c8
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemAccessKeyList.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.impl;
+
+import org.eclipse.actf.ai.fennec.treemanager.IAccessKeyList;
+import org.eclipse.actf.model.dom.dombycom.AnalyzedResult;
+import org.eclipse.actf.model.dom.dombycom.INodeEx;
+
+
+
+
+public class TreeItemAccessKeyList implements IAccessKeyList {
+ INodeEx[] accessKeyNodes;
+
+ public TreeItemAccessKeyList(AnalyzedResult analyzedResult) {
+ accessKeyNodes = analyzedResult.getAccessKeyNodes();
+ }
+
+ public char getAccessKeyAt(int index) {
+ if (accessKeyNodes.length <= index)
+ return 0;
+ return accessKeyNodes[index].getAccessKey();
+ }
+
+ public String getUIStringAt(int index) {
+ // TODO
+ return "";
+ }
+
+ public int size() {
+ return accessKeyNodes.length;
+ }
+
+ public static IAccessKeyList newAccessKeyList(AnalyzedResult analyzedResult) {
+ return new TreeItemAccessKeyList(analyzedResult);
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemMark.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemMark.java
new file mode 100644
index 0000000..c6e634f
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemMark.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.util.List;
+
+import org.eclipse.actf.ai.fennec.NVM3Exception;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.util.vocab.AbstractTerms;
+import org.eclipse.actf.util.vocab.IEvalTarget;
+
+
+
+
+public class TreeItemMark extends TreeItemNVM3 {
+ private static class TreeItemMarkTerms extends TreeItemTerms {
+ @Override
+ public boolean hasContent(IEvalTarget target) {
+ return true;
+ }
+
+ @Override
+ public boolean hasReadingContent(IEvalTarget target) {
+ return true;
+ }
+
+ @Override
+ public boolean isFlashLastNode(IEvalTarget node) {
+ if (node instanceof TreeItemMark) {
+ TreeItemMark mark = (TreeItemMark) node;
+ if (mark.getType() == MarkType.FLASH_END)
+ return true;
+ }
+ return false;
+ }
+
+ TreeItemMarkTerms() {
+ super(null);
+ }
+ }
+
+ private static TreeItemTerms treeItemMarkTermsInstance = new TreeItemMarkTerms();
+
+ public enum MarkType {
+ FLASH_END
+ }
+
+ @Override
+ public AbstractTerms getTerms() {
+ return treeItemMarkTermsInstance;
+ }
+
+ private MarkType type;
+
+ public TreeItemMark(ITreeItem parent, MarkType type) {
+ super(null, parent, null, treeItemMarkTermsInstance);
+ this.type = type;
+ }
+
+ @Override
+ public String getUIString() {
+ return "";
+ }
+
+ @Override
+ public String getNodeString() {
+ return "Mark";
+ }
+
+ public MarkType getType() {
+ return type;
+ }
+
+ @Override
+ TreeItemNVM3 expandChildItems(int trigger) throws NVM3Exception {
+ setChildItems((List) null);
+ return this;
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemNVM3.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemNVM3.java
new file mode 100644
index 0000000..3868efc
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemNVM3.java
@@ -0,0 +1,490 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.util.List;
+
+import org.eclipse.actf.ai.fennec.NVM3Exception;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeManager;
+import org.eclipse.actf.ai.fennec.treemanager.TreeManagerException;
+import org.eclipse.actf.ai.query.QueryService;
+import org.eclipse.actf.model.dom.dombycom.IElementEx;
+import org.eclipse.actf.model.dom.dombycom.INodeEx;
+import org.eclipse.actf.model.dom.dombycom.ISelectElement;
+import org.eclipse.actf.model.dom.dombycom.IElementEx.Position;
+import org.eclipse.actf.util.vocab.AbstractTerms;
+import org.eclipse.actf.util.vocab.IEvalTarget;
+import org.eclipse.actf.util.vocab.Vocabulary;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+// TODO I'd like to make it package-local.
+public class TreeItemNVM3 implements ITreeItem {
+ static private final TreeItemNVM3[] emptyChild = new TreeItemNVM3[0];
+
+ private Node baseNode;
+
+ private ITreeItem parent;
+
+ private ITreeItem[] childItems;
+
+ private NVM3Metadata metadata;
+
+ private boolean hasAlreadyChildRefreshed;
+
+ private int nth;
+
+ private TreeItemTerms terms;
+
+ // for terms
+ int distance = 0;
+
+ public static TreeItemNVM3 newTreeItem(NVM3Metadata metadata, ITreeItem parent, Node baseNode) {
+ if (baseNode == null) {
+ // TODO
+ return new TreeItemNVM3(metadata, parent, null, new TreeItemTerms(null));
+ }
+ if (!(baseNode instanceof IEvalTarget)) return null;
+ IEvalTarget evalTarget = (IEvalTarget) baseNode;
+ return new TreeItemNVM3(metadata, parent, baseNode, new TreeItemTerms(evalTarget));
+ }
+
+ protected TreeItemNVM3(NVM3Metadata metadata,
+ ITreeItem parent, Node baseNode,
+ TreeItemTerms terms) {
+ this.terms = terms;
+ this.metadata = metadata;
+ this.parent = parent;
+ this.baseNode = baseNode;
+ this.childItems = emptyChild;
+ this.nth = 0;
+ }
+
+
+ public AbstractTerms getTerms() {
+ return terms;
+ }
+
+ public ITreeItem getParent() {
+ return parent;
+ }
+
+ public int getNth() {
+ return nth;
+ }
+
+ private void setAsRoot() {
+ this.parent = null;
+ }
+
+ private void setParent() {
+ for (int i = 0; i < childItems.length; i++) {
+ TreeItemNVM3 c = (TreeItemNVM3) childItems[i];
+ c.parent = this;
+ c.nth = i;
+ }
+ }
+
+ public void setChildItems(List items) {
+ if (items == null) {
+ this.childItems = emptyChild;
+ } else {
+ this.childItems = (ITreeItem[]) items.toArray(emptyChild);
+ }
+ setParent();
+ }
+
+ public void setChildItems(ITreeItem[] items) {
+ if (items == null) {
+ this.childItems = emptyChild;
+ } else {
+ this.childItems = items;
+ }
+ setParent();
+ }
+
+ public void appendChildItems(ITreeItem[] items) {
+ if (items == null)
+ return;
+ ITreeItem[] newItems = new ITreeItem[childItems.length + items.length];
+ int i, j;
+ for (i = 0; i < childItems.length; i++) {
+ newItems[i] = childItems[i];
+ }
+ for (j = 0; j < items.length; i++, j++) {
+ TreeItemNVM3 c = (TreeItemNVM3) items[j];
+ c.parent = this;
+ newItems[i] = c;
+ }
+ this.childItems = newItems;
+ }
+
+ public boolean hasChild() {
+ return (childItems.length > 0);
+ }
+
+ public void forceParent(ITreeItem parent) {
+ this.parent = parent;
+ }
+
+ void markRefreshedChild() {
+ hasAlreadyChildRefreshed = true;
+ }
+
+ boolean hasAlreadyChildRefreshed() {
+ return hasAlreadyChildRefreshed;
+ }
+
+ TreeItemNVM3 expandChildItems(int trigger) throws NVM3Exception {
+ List newChildItems = metadata.expand(this, trigger);
+ setChildItems(newChildItems);
+ return this;
+ }
+
+ private Node getNearestNodeInternal(int idx) {
+ if (baseNode != null) return baseNode;
+ for (; idx < childItems.length; idx++) {
+ TreeItemNVM3 item = (TreeItemNVM3) childItems[idx];
+ return item.getNearestNodeInternal(0);
+ }
+ if (parent == null) return null;
+ return ((TreeItemNVM3) parent).getNearestNodeInternal(getNth());
+ }
+
+ Node getNearestNode() {
+ return getNearestNodeInternal(0);
+ }
+
+ private TreeItemNVM3 autoUnwrap(int trigger) throws NVM3Exception {
+ TreeItemNVM3 item = this;
+
+ for (;;) {
+ TreeItemNVM3 parent = (TreeItemNVM3) item.getParent();
+ if (parent == null) {
+ item.setChildItems(emptyChild);
+ return item;
+ }
+ int idx = item.getNth();
+ List newSiblings = parent.metadata.expand(parent, (NVM3Mode.TRIGGER_KEEP
+ | NVM3Mode.TRIGGER_UNWRAP));
+ if (newSiblings != null) {
+ int newSize = newSiblings.size();
+ if (newSize > 0) {
+ if (idx >= newSize) idx = newSize - 1;
+ item = (TreeItemNVM3) newSiblings.get(idx);
+
+ item = item.expandChildItems(trigger);
+ // success. Set parent's childItems.
+ parent.setChildItems(newSiblings);
+ return item;
+ }
+ }
+ item = parent;
+ }
+ }
+
+ TreeItemNVM3 expand(int trigger) throws NVM3Exception {
+ TreeItemNVM3 parent = (TreeItemNVM3) getParent();
+ if (parent != null) {
+ int idx = getNth();
+ List newSiblings = parent.metadata.expand(parent, NVM3Mode.TRIGGER_KEEP);
+ if (newSiblings == null) {
+ return parent.autoUnwrap(trigger);
+ }
+ int newSize = newSiblings.size();
+ if (newSize == 0) {
+ return parent.autoUnwrap(trigger);
+ }
+ if (idx >= newSize) {
+ idx = newSize - 1;
+ }
+ TreeItemNVM3 newTarget = (TreeItemNVM3) newSiblings.get(idx);
+ newTarget = newTarget.expandChildItems(trigger);
+ // success. Set parent's childItems.
+ parent.setChildItems(newSiblings);
+ return newTarget;
+ } else {
+ List newChildItems = metadata.expand(this, trigger);
+ setChildItems(newChildItems);
+ this.setAsRoot();
+ return this;
+ }
+ }
+
+ public ITreeItem[] getChildItems() {
+ return childItems;
+ }
+
+ public String getUIString() {
+ if (metadata != null) {
+ String r = metadata.getAltText(this);
+ if (r == null)
+ return "";
+ if (r.length() > 0)
+ return r;
+ }
+ if (baseNode instanceof INodeEx) {
+ INodeEx node2 = (INodeEx) baseNode;
+ return node2.extractString();
+ }
+ return "";
+ }
+
+ public String getDescription() {
+ if (metadata != null) {
+ String r = metadata.getDescription(this);
+ if (r == null)
+ return "";
+ if (r.length() > 0)
+ return r;
+ }
+ return "";
+ }
+
+ public String getNodeString() {
+ if (baseNode != null) {
+ return baseNode.getNodeName();
+ }
+ return "No Node";
+ }
+
+ public short getHeadingLevel() {
+ if (metadata != null)
+ return metadata.getHeadingLevel(this);
+ else
+ return 0;
+ }
+
+ public String getLinkURI() {
+ if (baseNode instanceof INodeEx) {
+ INodeEx node2 = (INodeEx) baseNode;
+ return node2.getLinkURI();
+ }
+ return null;
+ }
+
+ public Object getBaseNode() {
+ return baseNode;
+ }
+
+ public NVM3Metadata getMetadata() {
+ return metadata;
+ }
+
+ public int doClick() throws TreeManagerException {
+ if (baseNode instanceof INodeEx) {
+ ((INodeEx) baseNode).doClick();
+ return ITreeManager.CLICKED;
+ }
+ return ITreeManager.NOACTION;
+ }
+
+ public int stay() throws TreeManagerException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int highlight() throws TreeManagerException {
+ if (baseNode instanceof INodeEx) {
+ ((INodeEx) baseNode).highlight();
+ }
+ return ITreeManager.NOACTION;
+ }
+
+ public int unhighlight() throws TreeManagerException {
+ if (baseNode instanceof INodeEx) {
+ ((INodeEx) baseNode).unhighlight();
+ }
+ return ITreeManager.NOACTION;
+ }
+
+ public boolean setFocus() {
+ if (baseNode instanceof INodeEx) {
+ ((INodeEx) baseNode).setFocus();
+ }
+ return false;
+ }
+
+ // !FN!
+ public boolean isInputable() {
+ if (baseNode instanceof IEvalTarget) {
+ return Vocabulary.isInputable().eval((IEvalTarget) baseNode);
+ }
+ return false;
+ }
+
+ // !FN!
+ public boolean isClickable() {
+ if (baseNode instanceof IEvalTarget) {
+ return Vocabulary.isClickable().eval((IEvalTarget) baseNode);
+ }
+ return false;
+ }
+
+ // !FN!
+ public boolean isImage() {
+ if (baseNode instanceof IEvalTarget) {
+ return Vocabulary.isImage().eval((IEvalTarget) baseNode);
+ }
+ return false;
+ }
+
+ // !FN!
+ public String[] getStillPictureData() {
+ if (!(baseNode instanceof INodeEx)) {
+ return new String[3];
+ }
+ return ((INodeEx) baseNode).getStillPictureData();
+ }
+
+ public int setText(String text) throws TreeManagerException {
+ if (baseNode instanceof INodeEx) {
+ ((INodeEx) baseNode).setText(text);
+ }
+ return ITreeManager.NOACTION;
+ }
+
+ public String getText() throws TreeManagerException {
+ if (baseNode instanceof INodeEx) {
+ return ((INodeEx) baseNode).getText();
+ }
+ return "";
+ }
+
+ public void addMetadata(TreeItemNVM3 item) {
+ if (!(this.metadata instanceof NVM3GeneratedMetadata))
+ return;
+ if (!(item.metadata instanceof NVM3GeneratedMetadata))
+ return;
+
+ NVM3GeneratedMetadata meta = (NVM3GeneratedMetadata) this.metadata;
+ NVM3GeneratedMetadata meta2 = (NVM3GeneratedMetadata) item.metadata;
+
+ this.metadata = NVM3GeneratedMetadata.generate(meta, meta2);
+ }
+
+
+ private Position radioPosition;
+
+ private Position listPosition;
+
+ public int getRadioIndex() {
+ if (baseNode instanceof IElementEx) {
+ if (radioPosition == null)
+ radioPosition = ((IElementEx) baseNode).getRadioPosition();
+ if (radioPosition == null)
+ return 0;
+ return radioPosition.index;
+ }
+ return 0;
+ }
+
+ public int getRadioTotal() {
+ if (baseNode instanceof IElementEx) {
+ if (radioPosition == null)
+ radioPosition = ((IElementEx) baseNode).getRadioPosition();
+ if (radioPosition == null)
+ return 0;
+ return radioPosition.total;
+ }
+ return 0;
+ }
+
+ public int getListIndex() {
+ Node current = baseNode;
+ do {
+ if (current instanceof IElementEx) {
+ if (listPosition == null)
+ listPosition = ((IElementEx) current).getListPosition();
+ if (listPosition == null)
+ return 0;
+ return listPosition.index;
+ }
+ current = current.getParentNode();
+ } while (current != null);
+ return 0;
+ }
+
+ public int getListTotal() {
+ Node current = baseNode;
+ do {
+ if (current instanceof IElementEx) {
+ if (listPosition == null)
+ listPosition = ((IElementEx) current).getListPosition();
+ if (listPosition == null)
+ return 0;
+ return listPosition.total;
+ }
+ current = current.getParentNode();
+ } while (current != null);
+ return 0;
+ }
+
+ public String getFormLabel() {
+ if (!(baseNode instanceof IElementEx))
+ return "";
+ Element label = ((IElementEx) baseNode).getFormLabel();
+ if (label == null || !(label instanceof INodeEx))
+ return "";
+ NodeList nl = label.getChildNodes();
+ StringBuffer ret = new StringBuffer();
+ for (int i = 0; i < nl.getLength(); i++) {
+ Node node = nl.item(i);
+ if (node instanceof INodeEx)
+ ret.append(((INodeEx) node).extractString());
+ }
+ return ret.toString();
+ }
+
+ public void setSelectedIndices(int[] indices) {
+ if (baseNode instanceof ISelectElement) {
+ ((ISelectElement) baseNode).setSelectedIndices(indices);
+ }
+ }
+
+ public int[] getSelectedIndices() {
+ if (baseNode instanceof ISelectElement) {
+ return ((ISelectElement) baseNode).getSelectedIndices();
+ }
+ return null;
+ }
+
+ public int getOptionsCount() {
+ if (baseNode instanceof ISelectElement) {
+ return ((ISelectElement) baseNode).getOptionsCount();
+ }
+ return 0;
+ }
+
+ public String getOptionTextAt(int index) {
+ if (baseNode instanceof ISelectElement) {
+ return ((ISelectElement) baseNode).getOptionTextAt(index);
+ }
+ return "";
+ }
+
+ // For user annotation.
+ public Node serializeQuery(Node parent) {
+ if (baseNode == null)
+ return null;
+ return QueryService.serializeQuery(baseNode, parent);
+ }
+
+ public char getAccessKey() {
+ if (baseNode instanceof INodeEx) {
+ return ((INodeEx) baseNode).getAccessKey();
+ }
+ return 0;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemSoundControl.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemSoundControl.java
new file mode 100644
index 0000000..dc8c3d0
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemSoundControl.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.impl;
+
+import org.eclipse.actf.ai.fennec.treemanager.ISoundControl;
+import org.eclipse.actf.model.dom.dombycom.AnalyzedResult;
+import org.eclipse.actf.model.dom.dombycom.INodeExSound;
+
+
+
+public class TreeItemSoundControl implements ISoundControl {
+ private AnalyzedResult analyzedResult;
+
+ public boolean muteMedia() {
+ INodeExSound[] sounds = analyzedResult.getSoundNodes();
+ boolean r = true;
+ for (int i = 0; i < sounds.length; i++) {
+ boolean st = sounds[i].getMuteState();
+ r &= sounds[i].muteMedia(!st);
+ }
+ return r;
+ }
+
+ public VolumeState getVolumeState() {
+ INodeExSound[] sounds = analyzedResult.getSoundNodes();
+ boolean mute = true;
+ boolean max = true;
+ boolean min = true;
+ for (int i = 0; i < sounds.length; i++) {
+ mute &= sounds[i].getMuteState();
+ int vol = sounds[i].getVolume();
+ max &= (vol == INodeExSound.VOLUME_MAX);
+ min &= (vol == INodeExSound.VOLUME_MIN);
+ }
+ if (mute) return VolumeState.MUTE;
+ if (max) return VolumeState.MAX;
+ if (min) return VolumeState.MIN;
+
+ return VolumeState.OTHER;
+ }
+
+ private static final int VOLUME_TICK = 150;
+ private static final int VOLUME_TICK_MINIMAL = 10;
+
+ public boolean volumeDownMedia() {
+ return volumeDownMedia(VOLUME_TICK);
+ }
+
+ public boolean minimalVolumeDownMedia() {
+ return volumeDownMedia(VOLUME_TICK_MINIMAL);
+ }
+
+ private boolean volumeDownMedia(int tick) {
+ INodeExSound[] sounds = analyzedResult.getSoundNodes();
+ boolean r = true;
+ for (int i = 0; i < sounds.length; i++) {
+ int vol = sounds[i].getVolume();
+ if (vol < 0) {
+ return false;
+ } else if (vol < (INodeExSound.VOLUME_MIN + tick)) {
+ vol = INodeExSound.VOLUME_MIN;
+ } else {
+ vol -= tick;
+ }
+ r &= sounds[i].setVolume(vol);
+ }
+ return r;
+ }
+
+ public boolean volumeUpMedia() {
+ return volumeUpMedia(VOLUME_TICK);
+ }
+
+ public boolean minimalVolumeUpMedia() {
+ return volumeUpMedia(VOLUME_TICK_MINIMAL);
+ }
+
+ private boolean volumeUpMedia(int tick) {
+ INodeExSound[] sounds = analyzedResult.getSoundNodes();
+ boolean r = true;
+ for (int i = 0; i < sounds.length; i++) {
+ int vol = sounds[i].getVolume();
+ if (vol < 0) {
+ return false;
+ } else if (vol > (INodeExSound.VOLUME_MAX - tick)) {
+ vol = INodeExSound.VOLUME_MAX;
+ } else {
+ vol += tick;
+ }
+ r &= sounds[i].setVolume(vol);
+ }
+ return r;
+ }
+
+ public int getCount() {
+ INodeExSound[] sounds = analyzedResult.getSoundNodes();
+ return sounds.length;
+ }
+
+ public static ISoundControl newTreeItemSoundControl(AnalyzedResult ar) {
+ return new TreeItemSoundControl(ar);
+ }
+
+ private TreeItemSoundControl(AnalyzedResult ar) {
+ this.analyzedResult = ar;
+ }
+
+ public int[] getVolumes(){
+ INodeExSound[] sounds = analyzedResult.getSoundNodes();
+ boolean r = true;
+ int[] volumes = new int[sounds.length];
+ for (int i = 0; i < sounds.length; i++) {
+ volumes[i] = sounds[i].getVolume();
+
+ if (volumes[i] < 0) {
+ volumes[i] = 0;
+ }
+ }
+ return volumes;
+ }
+
+ public boolean setVolumes(int[] volumes) {
+ INodeExSound[] sounds = analyzedResult.getSoundNodes();
+ boolean r = true;
+ for (int i = 0; i < sounds.length; i++) {
+ r &= sounds[i].setVolume(volumes[i]);
+ }
+ return r;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemTerms.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemTerms.java
new file mode 100644
index 0000000..d16d1b6
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemTerms.java
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.util.ArrayList;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.model.dom.dombycom.INodeEx;
+import org.eclipse.actf.util.vocab.DelegationTerms;
+import org.eclipse.actf.util.vocab.IEvalTarget;
+import org.eclipse.actf.util.vocab.Vocabulary;
+import org.eclipse.swt.graphics.Rectangle;
+import org.w3c.dom.Node;
+
+
+
+
+public class TreeItemTerms extends DelegationTerms {
+
+ public TreeItemTerms(IEvalTarget delegationTarget) {
+ super(delegationTarget);
+ }
+
+ private boolean isSymbol(char c) {
+ int type = Character.getType(c);
+ if (type == Character.OTHER_SYMBOL || type == Character.MODIFIER_SYMBOL || type == Character.MATH_SYMBOL)
+ return true;
+ return false;
+ }
+
+ private boolean isSeparator(char c) {
+ switch (Character.getType(c)) {
+ case Character.SPACE_SEPARATOR:
+ case Character.LINE_SEPARATOR:
+ case Character.PARAGRAPH_SEPARATOR:
+ case Character.FORMAT:
+ case Character.CONTROL:
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isPunctuation(char c) {
+ int type = Character.getType(c);
+ if (type == Character.CONNECTOR_PUNCTUATION || type == Character.DASH_PUNCTUATION
+ || type == Character.START_PUNCTUATION || type == Character.END_PUNCTUATION
+ || type == Character.INITIAL_QUOTE_PUNCTUATION || type == Character.FINAL_QUOTE_PUNCTUATION
+ || type == Character.OTHER_PUNCTUATION)
+ return true;
+ return false;
+ }
+
+ private enum ContentCheckResult {
+ TRUE, FALSE, UNKNOWN
+ }
+ private ContentCheckResult contentCommonCheck(ITreeItem item) {
+ Object baseNode = item.getBaseNode();
+ if (baseNode instanceof IEvalTarget) {
+ if (Vocabulary.hasContent().eval((IEvalTarget) baseNode)) {
+ return ContentCheckResult.TRUE;
+ }
+ }
+
+ if (!isVisibleNode(item))
+ return ContentCheckResult.FALSE;
+ if (Vocabulary.isSelectOption().eval(item))
+ return ContentCheckResult.FALSE;
+
+ return ContentCheckResult.UNKNOWN;
+ }
+
+ @Override
+ public boolean hasContent(IEvalTarget target) {
+ if (!(target instanceof ITreeItem))
+ return false;
+ ITreeItem item = (ITreeItem) target;
+ switch (contentCommonCheck(item)) {
+ case TRUE:
+ return true;
+ case FALSE:
+ return false;
+ }
+
+ String str = item.getUIString();
+ if (str.length() == 0)
+ return false;
+ return true;
+ }
+
+ @Override
+ public boolean hasReadingContent(IEvalTarget target) {
+ if (!(target instanceof ITreeItem))
+ return false;
+ ITreeItem item = (ITreeItem) target;
+ switch (contentCommonCheck(item)) {
+ case TRUE:
+ return true;
+ case FALSE:
+ return false;
+ }
+
+ String str = item.getUIString();
+ // remove only punctuation
+ if (str.length() == 0) return false;
+
+ if (Vocabulary.isLink().eval(item))
+ return true;
+ for (int i = 0; i < str.length(); i++) {
+ if (isSeparator(str.charAt(i)) || isPunctuation(str.charAt(i)) //
+ || isSymbol(str.charAt(i)))
+ continue;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isVisibleNode(IEvalTarget target) {
+ return true;
+ }
+
+ @Override
+ public boolean isBlockJumpPointF(IEvalTarget node) {
+ return isBlockJumpPoint(false, node);
+ }
+
+ @Override
+ public boolean isBlockJumpPointB(IEvalTarget node) {
+ return isBlockJumpPoint(true, node);
+ }
+
+ public boolean isBlockJumpPoint(boolean back, IEvalTarget node) {
+ if (!(node instanceof TreeItemNVM3))
+ return false;
+ TreeItemNVM3 item = (TreeItemNVM3) node;
+
+ TreeItemNVM3 prev;
+ if (!back) {
+ if (item.getNth() > 0) {
+ prev = (TreeItemNVM3) item.getParent().getChildItems()[item.getNth() - 1];
+ while (prev.hasChild()) {
+ ITreeItem[] items = prev.getChildItems();
+ prev = (TreeItemNVM3) items[items.length - 1];
+ }
+ } else {
+ prev = (TreeItemNVM3) item.getParent();
+ }
+ } else {
+ if (item.getNth() == item.getParent().getChildItems().length - 1) {
+ ITreeItem parent = item.getParent();
+ if (parent == null)
+ return false;
+ while (parent.getNth() == parent.getParent().getChildItems().length - 1) {
+ parent = parent.getParent();
+ if (parent == null)
+ return false;
+ }
+ prev = (TreeItemNVM3) parent.getParent().getChildItems()[parent.getNth() + 1];
+ } else {
+ if (item.hasChild()) {
+ prev = (TreeItemNVM3) item.getChildItems()[0];
+ } else {
+ prev = (TreeItemNVM3) item.getParent().getChildItems()[item.getNth() + 1];
+ }
+ }
+ }
+ if (prev == null)
+ return false;
+
+ item.distance = prev.distance + 1;
+ prev.distance = 0;
+
+ if (!(item.getBaseNode() instanceof INodeEx))
+ return false;
+ if (!(prev.getBaseNode() instanceof INodeEx))
+ return false;
+
+ INodeEx nex = (INodeEx) item.getBaseNode();
+ INodeEx nex2 = (INodeEx) prev.getBaseNode();
+ if (nex == null || nex2 == null)
+ return false;
+
+ Rectangle r = nex.getLocation();
+ Rectangle r2 = nex2.getLocation();
+ if (r == null || r2 == null)
+ return false;
+
+ int dist = distance(r, r2);
+ item.distance += dist;
+
+ if (r.width < 20)
+ return false;
+ if (!Vocabulary.hasContent().eval(node))
+ return false;
+ if (!Vocabulary.hasReadingContent().eval(node))
+ return false;
+ if (Vocabulary.isClickable().eval(node))
+ return false;
+ if (item.getNth() > 2 && Vocabulary.isConnectable().eval(node))
+ return false;
+
+ if (item.distance > 800) {
+ item.distance = 0;
+ return true;
+ }
+
+ if (!back && !super.isBlockJumpPointF(node))
+ return false;
+ if (back && !super.isBlockJumpPointB(node))
+ return false;
+
+ if (item.distance > 200) {
+ item.distance = 0;
+ return true;
+ }
+ return false;
+ }
+
+ private int distance(Rectangle r, Rectangle r2) {
+ return (int) Math.sqrt(Math.abs(r.x - r2.x) * Math.abs(r.y - r2.y)) //
+ + Math.abs(r.x - r2.x) + Math.abs(r.y - r2.y);
+ }
+
+ @Override
+ public boolean isHeading(int level, IEvalTarget node) {
+ if (!(node instanceof ITreeItem))
+ return false;
+ ITreeItem item = (ITreeItem) node;
+ if (level == 0)
+ return (item.getHeadingLevel() > 0);
+ else
+ return item.getHeadingLevel() == level;
+ }
+
+ @Override
+ public boolean isHeadingJumpPoint(IEvalTarget node) {
+ if (!(node instanceof ITreeItem))
+ return false;
+ ITreeItem item = (ITreeItem) node;
+
+ ITreeItem current = item;
+ short r = 0;
+ do {
+ if (current == null)
+ return super.isHeadingJumpPoint(node);
+ NVM3Metadata meta = ((TreeItemNVM3) current).getMetadata();
+ if (meta instanceof NVM3GeneratedMetadata) {
+ r = ((NVM3GeneratedMetadata) meta).getHeadingLevelByMetadata(item);
+ if (r > 0)
+ return true;
+ else if (r == -1)
+ return false;
+ current = current.getParent();
+ } else
+ break;
+ } while (r == 0);
+
+ if (((TreeItemNVM3) item).getMetadata() == null)
+ return false;
+ return ((TreeItemNVM3) item).getMetadata().getHeadingLevel(item) > 0;
+ }
+
+ @Override
+ public boolean isConnectable(IEvalTarget node) {
+ if (!(node instanceof TreeItemNVM3))
+ return false;
+ TreeItemNVM3 item = (TreeItemNVM3) node;
+
+ if (item.hasChild())
+ return false;
+
+ int nth = item.getNth();
+ int nextNth = nth + 1;
+
+ ITreeItem parent = ((TreeItemNVM3) node).getParent();
+ if (parent == null)
+ return false;
+
+ ITreeItem[] items = parent.getChildItems();
+ if (nextNth >= items.length)
+ return false;
+
+ Object o = items[nextNth].getBaseNode();
+ if (o == null || !(o instanceof Node))
+ return false;
+ Node n = (Node) o;
+
+ return Vocabulary.isReachable(n).eval(node);
+ }
+
+ @Override
+ public boolean find(String str, boolean exact, IEvalTarget node) {
+ if (!(node instanceof ITreeItem))
+ return false;
+
+ ITreeItem item = (ITreeItem) node;
+ String uiString = item.getUIString();
+
+ if (!exact) {
+ uiString = uiString.toLowerCase();
+ str = str.toLowerCase();
+ }
+
+ if (uiString.indexOf(str) != -1)
+ return true;
+
+ /*
+ for (int len = str.length() - 1; len > 0; len--) {
+ if (uiString.lastIndexOf(str.substring(0, len)) == uiString.length() - len) {
+ if (hasChild()) {
+ if(Vocabulary.startsWith(str.substring(len), exact).eval(getChildItems()[0])){
+ return true;
+ }
+ continue;
+ }
+
+ int nth = item.getNth();
+ ITreeItem parent = item.getParent();
+ while (parent != null) {
+ ITreeItem[] items = parent.getChildItems();
+ if (nth + 1 < items.length) {
+ if(Vocabulary.startsWith(str.substring(len), exact).eval(items[nth + 1])){
+ return true;
+ }
+ break;
+ }
+ nth = parent.getNth();
+ parent = parent.getParent();
+ }
+ }
+ }*/
+ return false;
+ }
+
+ @Override
+ public boolean startsWith(String str, boolean exact, IEvalTarget node) {
+ if (!(node instanceof TreeItemNVM3))
+ return false;
+ TreeItemNVM3 item = (TreeItemNVM3) node;
+ String uiString = item.getUIString();
+
+ if (!exact) {
+ uiString = uiString.toLowerCase();
+ str = str.toLowerCase();
+ }
+
+ if (uiString.length() < str.length()) {
+ if (str.startsWith(uiString)) {
+ int len = uiString.length();
+ if (item.hasChild()) {
+ return Vocabulary.startsWith(str.substring(len), exact).eval(item.getChildItems()[0]);
+ }
+
+ int nth = item.getNth();
+ ITreeItem parent = item.getParent();
+ while (parent != null) {
+ ITreeItem[] items = parent.getChildItems();
+ if (nth + 1 < items.length) {
+ return Vocabulary.startsWith(str.substring(len), exact).eval(items[nth + 1]);
+ }
+ nth = parent.getNth();
+ parent = parent.getParent();
+ }
+ }
+ }
+
+ return uiString.startsWith(str);
+ }
+
+ @Override
+ public boolean nodeLocation(Node refNode, boolean backward, IEvalTarget node) {
+ if (!Vocabulary.hasContent().eval(node))
+ return false;
+ if (!(node instanceof TreeItemNVM3))
+ return false;
+ TreeItemNVM3 item = (TreeItemNVM3) node;
+
+ Node targetNode = item.getNearestNode();
+ if (targetNode == null) return false;
+
+ ArrayList<Node> refAncestors = getAncestors(refNode);
+ ArrayList<Node> ancestors = getAncestors(targetNode);
+ int i = refAncestors.size() - 1;
+ int j = ancestors.size() - 1;
+ while ((i >= 0) && (j >= 0)) {
+ Node refAncestor = refAncestors.get(i);
+ Node ancestor = ancestors.get(j);
+ if (!(ancestor.isSameNode(refAncestor))) {
+ if (!((ancestor instanceof INodeEx)) && (refAncestor instanceof INodeEx))
+ return false;
+
+ int ancestorNth = ((INodeEx) ancestor).getNth();
+ int refAncestorNth = ((INodeEx) refAncestor).getNth();
+ if (ancestorNth == refAncestorNth)
+ return true;
+ if (backward) {
+ return (ancestorNth < refAncestorNth);
+ } else {
+ return (ancestorNth > refAncestorNth);
+ }
+ }
+ i--;
+ j--;
+ }
+ return true;
+ }
+
+ private ArrayList<Node> getAncestors(Node n) {
+ ArrayList<Node> list = new ArrayList<Node>();
+ while (n != null) {
+ list.add(n);
+ n = n.getParentNode();
+ }
+ return list;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemVideoControl.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemVideoControl.java
new file mode 100644
index 0000000..5c67af6
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/impl/TreeItemVideoControl.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.impl;
+
+import java.util.ArrayList;
+
+import org.eclipse.actf.ai.fennec.INVM3Service;
+import org.eclipse.actf.ai.fennec.treemanager.IMediaSyncEventListener;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.fennec.treemanager.IVideoControl;
+import org.eclipse.actf.model.dom.dombycom.AnalyzedResult;
+import org.eclipse.actf.model.dom.dombycom.INodeEx;
+import org.eclipse.actf.model.dom.dombycom.INodeExVideo;
+import org.eclipse.actf.util.timer.WeakSyncTimer;
+import org.eclipse.actf.util.vocab.IProposition;
+import org.eclipse.actf.util.vocab.Vocabulary;
+
+
+
+public class TreeItemVideoControl implements IVideoControl {
+ private final INVM3Service nvm3Service;
+ private AnalyzedResult analyzedResult;
+
+ private INodeExVideo getCurrentNodeExVideo() {
+ INodeExVideo[] videos = analyzedResult.getVideoNodes();
+ if (videos.length == 0) return null;
+ if (videos.length == 1) return videos[0];
+
+ ITreeItem item = nvm3Service.getLastTreeItem();
+ for (int i = 0; i < videos.length; i++) {
+ INodeEx node = videos[i].getReferenceNode();
+ IProposition prop = Vocabulary.nodeLocation(node, true);
+ if (prop.eval(item)) return videos[i];
+ }
+ return videos[0];
+ }
+
+ public boolean previousTrack() {
+ INodeExVideo[] videos = analyzedResult.getVideoNodes();
+ boolean r = true;
+ for (int i = 0; i < videos.length; i++) {
+ r &= videos[i].previousTrack();
+ }
+ return r;
+ }
+
+ public boolean nextTrack() {
+ INodeExVideo[] videos = analyzedResult.getVideoNodes();
+ boolean r = true;
+ for (int i = 0; i < videos.length; i++) {
+ r &= videos[i].nextTrack();
+ }
+ return r;
+ }
+
+ public boolean stopMedia() {
+ INodeExVideo[] videos = analyzedResult.getVideoNodes();
+ boolean r = true;
+ for (int i = 0; i < videos.length; i++) {
+ r &= videos[i].stopMedia();
+ }
+ return r;
+ }
+
+ public boolean playMedia() {
+ INodeExVideo v = getCurrentNodeExVideo();
+
+ // Before playing the media, pause the other media to avoid audio interference.
+ INodeExVideo[] videos = analyzedResult.getVideoNodes();
+ for (int i = 0; i < videos.length; i++) {
+ if (videos[i] != v) {
+ videos[i].pauseMedia();
+ }
+ }
+ if (v != null) {
+ return v.playMedia();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean pauseMedia() {
+ INodeExVideo[] videos = analyzedResult.getVideoNodes();
+ boolean pause = false;
+ for (int i = 0; i < videos.length; i++) {
+ INodeExVideo.VideoState st = videos[i].getCurrentState();
+ if ((st == INodeExVideo.VideoState.STATE_PLAY)
+ || (st == INodeExVideo.VideoState.STATE_UNKNOWN)) {
+ pause = true;
+ break;
+ }
+ }
+
+ if (pause) {
+ boolean r = true;
+ for (int i = 0; i < videos.length; i++) {
+ r &= videos[i].pauseMedia();
+ }
+ return r;
+ } else {
+ INodeExVideo v = getCurrentNodeExVideo();
+ if (v != null) {
+ return v.playMedia();
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public IVideoControl.VideoState getVideoState() {
+ INodeExVideo[] videos = analyzedResult.getVideoNodes();
+ IVideoControl.VideoState st = IVideoControl.VideoState.STATE_OTHER;
+ for (int i = 0; i < videos.length; i++) {
+ INodeExVideo.VideoState stn = videos[i].getCurrentState();
+ switch (stn) {
+ case STATE_UNKNOWN:
+ break;
+ case STATE_PLAY:
+ st = IVideoControl.VideoState.STATE_PLAY;
+ break;
+ case STATE_STOP:
+ if (st == IVideoControl.VideoState.STATE_OTHER) {
+ st = IVideoControl.VideoState.STATE_STOP;
+ }
+ break;
+ case STATE_PAUSE:
+ if (st == IVideoControl.VideoState.STATE_OTHER) {
+ st = IVideoControl.VideoState.STATE_PAUSE;
+ }
+ break;
+ case STATE_WAITING:
+ if (st == IVideoControl.VideoState.STATE_OTHER) {
+ st = IVideoControl.VideoState.STATE_WAITING;
+ }
+ break;
+ case STATE_FASTFORWARD:
+ if (st != IVideoControl.VideoState.STATE_PLAY) {
+ st = IVideoControl.VideoState.STATE_FASTFORWARD;
+ }
+ break;
+ case STATE_FASTREVERSE:
+ if (st != IVideoControl.VideoState.STATE_PLAY) {
+ st = IVideoControl.VideoState.STATE_FASTREVERSE;
+ }
+ }
+ }
+ return st;
+ }
+
+ public boolean fastReverse() {
+ INodeExVideo v = getCurrentNodeExVideo();
+ if (v != null) {
+ return v.fastReverse();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean fastForward() {
+ INodeExVideo v = getCurrentNodeExVideo();
+ if (v != null) {
+ return v.fastForward();
+ } else {
+ return false;
+ }
+ }
+
+ public double getCurrentPosition() {
+ INodeExVideo v = getCurrentNodeExVideo();
+ if (v != null) {
+ return v.getCurrentPosition();
+ } else {
+ return 0;
+ }
+ }
+
+ public double getTotalLength() {
+ INodeExVideo v = getCurrentNodeExVideo();
+ if (v != null) {
+ return v.getTotalLength();
+ } else {
+ return 0;
+ }
+ }
+
+ public int getCount() {
+ INodeExVideo[] videos = analyzedResult.getVideoNodes();
+ return videos.length;
+ }
+
+ public int getIndex() {
+ INodeExVideo[] videos = analyzedResult.getVideoNodes();
+ if (videos.length == 0) return -1;
+ if (videos.length == 1) return 0;
+
+ ITreeItem item = nvm3Service.getLastTreeItem();
+ for (int i = 0; i < videos.length; i++) {
+ INodeEx node = videos[i].getReferenceNode();
+ IProposition prop = Vocabulary.nodeLocation(node, true);
+ if (prop.eval(item)) return i;
+ }
+ return 0;
+ }
+
+
+ public static IVideoControl newTreeItemVideoControl(AnalyzedResult ar,
+ INVM3Service nvm3Service) {
+ return new TreeItemVideoControl(ar, nvm3Service);
+ }
+
+ private TreeItemVideoControl(AnalyzedResult ar,
+ INVM3Service nvm3Service) {
+ this.analyzedResult = ar;
+ this.nvm3Service = nvm3Service;
+ }
+
+ // This ArrayList ensures strong references of currently valid listeners.
+ private ArrayList<IMediaSyncEventListener> listeners;
+ public boolean addEventListener(IMediaSyncEventListener listener) {
+ WeakSyncTimer timer = WeakSyncTimer.getTimer();
+ timer.addEventListener(listener);
+ if (listeners == null) {
+ listeners = new ArrayList<IMediaSyncEventListener>(1);
+ }
+ listeners.add(listener);
+
+ return true;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/mediator/NVM3MediatorImpl.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/mediator/NVM3MediatorImpl.java
new file mode 100644
index 0000000..04f7a62
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/mediator/NVM3MediatorImpl.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.mediator;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.actf.ai.fennec.INVM3Entry;
+import org.eclipse.actf.ai.fennec.INVM3Mediator;
+import org.eclipse.actf.ai.fennec.INVM3Service;
+import org.eclipse.actf.ai.fennec.NVM3ServiceFactory;
+import org.eclipse.actf.ai.fennec.impl.NVM3DOMReader;
+import org.eclipse.actf.ai.fennec.impl.NVM3EntryImpl;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeManager;
+import org.eclipse.actf.ai.fennec.treemanager.TreeManagerFactory;
+import org.eclipse.actf.ai.xmlstore.IXMLInfo;
+import org.eclipse.actf.ai.xmlstore.IXMLSelector;
+import org.eclipse.actf.ai.xmlstore.IXMLStore;
+import org.eclipse.actf.ai.xmlstore.IXMLStoreService;
+import org.eclipse.actf.ai.xmlstore.XMLStorePlugin;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.actf.model.dom.dombycom.IDocumentEx;
+
+
+
+
+public class NVM3MediatorImpl implements INVM3Mediator {
+ private final IWebBrowserACTF webBrowser;
+
+ public ITreeManager newTreeManager(INVM3Entry entry) {
+ IDocumentEx doc = (IDocumentEx) webBrowser.getLiveDocument();
+
+ INVM3Service nvm3Service;
+ if (entry != null) {
+ try {
+ nvm3Service = NVM3ServiceFactory.newNVM3Service(entry, doc);
+ } catch (Exception e) {
+ nvm3Service = NVM3ServiceFactory.newNVM3ServiceWithDefaultMetadata(doc);
+ }
+ } else {
+ nvm3Service = NVM3ServiceFactory.newNVM3ServiceWithDefaultMetadata(doc);
+ }
+ return TreeManagerFactory.newITreeManager(nvm3Service);
+ }
+
+ private IXMLStore getNVM3Store(String url) {
+ IXMLStoreService ss = XMLStorePlugin.getDefault().getXMLStoreService();
+ IXMLSelector selector = ss.getSelectorWithDocElem(NVM3DOMReader.NVM3_DOCUMENT_ELEMENT_NAME,
+ NVM3DOMReader.NVM3_NAMESPACE_URI);
+ IXMLStore store = ss.getRootStore();
+ store = store.specify(selector);
+ if (store == null) return null;
+ selector = ss.getSelectorWithIRI(url);
+ return store.specify(selector);
+ }
+
+ public INVM3Entry getDefaultNVM3Entry() {
+ String url = webBrowser.getURL();
+ IXMLStore store = getNVM3Store(url);
+ if (store == null) return null;
+ Iterator<IXMLInfo> it = store.getInfoIterator();
+ if (it == null) return null;
+ if (!it.hasNext()) return null;
+ IXMLInfo info = it.next();
+ return new NVM3EntryImpl(info);
+ }
+
+ public INVM3Entry[] getNVM3Entries() {
+ String url = webBrowser.getURL();
+ IXMLStore store = getNVM3Store(url);
+ if (store == null) return null;
+ Iterator<IXMLInfo> it = store.getInfoIterator();
+ if (it == null) return null;
+ ArrayList<NVM3EntryImpl> entries = new ArrayList<NVM3EntryImpl>();
+ while (it.hasNext()) {
+ IXMLInfo info = it.next();
+ if (info == null) continue;
+ entries.add(new NVM3EntryImpl(info));
+ }
+ INVM3Entry[] ea = new INVM3Entry[entries.size()];
+ ea = entries.toArray(ea);
+ return ea;
+ }
+
+ public void release() {
+ // this.dombycom.release();
+ }
+
+ public NVM3MediatorImpl(IWebBrowserACTF webBrowser) {
+ this.webBrowser = webBrowser;
+ }
+}
+
+
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/IAccessKeyList.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/IAccessKeyList.java
new file mode 100644
index 0000000..3c98741
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/IAccessKeyList.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.treemanager;
+
+
+public interface IAccessKeyList {
+ int size();
+ char getAccessKeyAt(int index);
+ String getUIStringAt(int index);
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ILocation.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ILocation.java
new file mode 100644
index 0000000..44e7781
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ILocation.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.treemanager;
+
+
+public interface ILocation {
+
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/IMediaSyncEventListener.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/IMediaSyncEventListener.java
new file mode 100644
index 0000000..7563bf3
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/IMediaSyncEventListener.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.treemanager;
+
+import org.eclipse.actf.util.timer.SyncEventListener;
+
+
+
+public interface IMediaSyncEventListener extends SyncEventListener {
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ISoundControl.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ISoundControl.java
new file mode 100644
index 0000000..78b6471
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ISoundControl.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.treemanager;
+
+
+public interface ISoundControl {
+ public enum VolumeState {
+ MIN,
+ MAX,
+ OTHER,
+ MUTE
+ }
+
+ boolean muteMedia();
+
+ VolumeState getVolumeState();
+
+ boolean volumeDownMedia();
+
+ boolean volumeUpMedia();
+
+ boolean minimalVolumeDownMedia();
+
+ boolean minimalVolumeUpMedia();
+
+ int getCount();
+
+ int[] getVolumes();
+
+ boolean setVolumes(int[] volumes);
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITable.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITable.java
new file mode 100644
index 0000000..6c22468
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITable.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.treemanager;
+
+
+
+public interface ITable {
+ ITableRow[] getRow(int idx);
+ int getColumnSize();
+ int getRowSize();
+ String getTableString();
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITableCell.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITableCell.java
new file mode 100644
index 0000000..96ebac5
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITableCell.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.treemanager;
+
+
+
+public interface ITableCell {
+ int getColumn();
+ int getRow();
+ ITreeItem getItem();
+
+ boolean isConnectedWithUpCell();
+ boolean isConnectedWithLeftCell();
+
+ ITreeItem getRowHeader();
+ ITreeItem getColumnHeader();
+
+ boolean isHeader();
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITableRow.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITableRow.java
new file mode 100644
index 0000000..10d2c33
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITableRow.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.treemanager;
+
+
+
+public interface ITableRow {
+ ITableCell[] getTableCell();
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITreeItem.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITreeItem.java
new file mode 100644
index 0000000..a833b35
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITreeItem.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.treemanager;
+
+import org.eclipse.actf.util.vocab.AbstractTerms;
+import org.eclipse.actf.util.vocab.IEvalTarget;
+import org.w3c.dom.Node;
+
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public interface ITreeItem extends IEvalTarget {
+ // Get the parent item. If this is the root, return null.
+ ITreeItem getParent();
+
+ // Get the child items.
+ // Even if it has no children, return an empty array (size == 0) instead of null.
+ ITreeItem[] getChildItems();
+
+ // return nth of the children of this parent.
+ int getNth();
+
+ // short text.
+ String getUIString();
+
+ // long descriptive text.
+ String getDescription();
+
+ // Return a text to represent the node.
+ // This text is inappropriate to be notified to users.
+ String getNodeString();
+
+ // Heading level. 0 means this node is not a heading.
+ short getHeadingLevel();
+
+ // Return the URI of the link of this tree item if it has a link.
+ String getLinkURI();
+
+ // This is a deprecated API. It may breaks independence on content types.
+ Object getBaseNode();
+
+ AbstractTerms getTerms();
+
+ // Return true if this item accepts some input.
+ // !FN!
+ boolean isInputable();
+
+ // Return true if this item accepts click operations.
+ // !FN!
+ boolean isClickable();
+
+ // Return true if this item contains some image.
+ // !FN!
+ boolean isImage();
+
+ // [0]...mimetype [1]...URI [2] ... png clut URI
+ // !FN!
+ String[] getStillPictureData();
+
+ // Return the URI of the image.
+ // String getImageURI();
+
+ // Click this item.
+ int doClick() throws TreeManagerException;
+
+ // Optional API. Do not use it currently.
+ int stay() throws TreeManagerException;
+
+ // Highlight this item.
+ int highlight() throws TreeManagerException;
+
+ // Unhighlight this item.
+ int unhighlight() throws TreeManagerException;
+
+ // Set focus to this item.
+ // This method only sets the input focus if possible.
+ boolean setFocus();
+
+ // Set the text to this item. (This method may be used for a text edit widget)
+ int setText(String text) throws TreeManagerException;
+
+ // Return the set text.
+ String getText() throws TreeManagerException;
+
+ // Form
+ int getRadioIndex();
+
+ int getRadioTotal();
+
+ void setSelectedIndices(int[] indices);
+
+ int[] getSelectedIndices();
+
+ int getOptionsCount();
+
+ String getOptionTextAt(int i);
+
+ int getListIndex();
+
+ int getListTotal();
+
+ public String getFormLabel();
+
+ // User Annotation.
+ Node serializeQuery(Node parent);
+
+ char getAccessKey();
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITreeManager.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITreeManager.java
new file mode 100644
index 0000000..79a49b6
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/ITreeManager.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.treemanager;
+
+import org.eclipse.actf.util.vocab.IProposition;
+
+
+public interface ITreeManager {
+ // Status code.
+ int NOACTION = 0;
+ int MOVED = 1 << 0;
+ int LEVEL_CHANGED = 1 << 1;
+ int TRANSFERRED = 1 << 2;
+ int CLICKED = 1 << 3;
+ int CHANGED = 1 << 4;
+ int PARENT_CHANGED = 1 << 5;
+ int FOUND = 1 << 6;
+ int UNDONE = 1 << 8;
+ int ERROR = 1 << 16;
+
+ // Status API
+ int getLevel() throws TreeManagerException;
+
+ // Returns the active Item.
+ ITreeItem getActiveItem() throws TreeManagerException;
+
+ // Used for media control. It will be subject to change.
+ ISoundControl getSoundControl() throws TreeManagerException;
+
+ // Used for media control. It will be subject to change.
+ IVideoControl getVideoControl() throws TreeManagerException;
+
+ // Used for accesskey
+ IAccessKeyList getAccessKeyList() throws TreeManagerException;
+
+ // Returns the siblings of the active item.
+ ITreeItem[] getSiblings() throws TreeManagerException;
+
+ // initialize. API.
+ int initialize() throws TreeManagerException;
+
+ // Action APIs
+
+ // Tentative API. Do not use it currently.
+ int stay() throws TreeManagerException;
+
+ //
+ int click(boolean doClick) throws TreeManagerException;
+
+ // Tree Navigation API
+ int gotoParent() throws TreeManagerException;
+
+ int gotoFirstChild() throws TreeManagerException;
+
+ int gotoStartOfSiblings() throws TreeManagerException;
+
+ int gotoEndOfSiblings() throws TreeManagerException;
+
+ int gotoPreviousSibling() throws TreeManagerException;
+
+ int gotoNextSibling() throws TreeManagerException;
+
+ int gotoStartOfPage() throws TreeManagerException;
+
+ int gotoEndOfPage() throws TreeManagerException;
+
+ int traverse(boolean back) throws TreeManagerException;
+
+ // Search functions. (Extension)
+
+ int gotoPreviousLine() throws TreeManagerException;
+
+ int gotoNextLine() throws TreeManagerException;
+
+ int gotoStartOfLine() throws TreeManagerException;
+
+ int gotoEndOfLine() throws TreeManagerException;
+
+ int findNext(IProposition proposition) throws TreeManagerException;
+
+ int findPrevious(IProposition proposition) throws TreeManagerException;
+
+ int skipToAnchor(String target) throws TreeManagerException;
+
+ // Table Navigation API.
+
+ int gotoLeftCell() throws TreeManagerException;
+
+ int gotoRightCell() throws TreeManagerException;
+
+ int gotoUpCell() throws TreeManagerException;
+
+ int gotoDownCell() throws TreeManagerException;
+
+ int getActiveTableInfo() throws TreeManagerException;
+
+ int getActiveTableCellInfo() throws TreeManagerException;
+
+ // Optional API.
+ ITreeItem getCurrentRootItem() throws TreeManagerException;
+
+ // Experimental API.
+ int analyze() throws TreeManagerException;
+
+ ILocation getCurrentLocation() throws TreeManagerException;
+
+ int moveToLocation(ILocation location) throws TreeManagerException;
+
+ //
+ ITreeItem expandWholeTree() throws TreeManagerException;
+
+ int gotoEndOfPageForFind() throws TreeManagerException;
+
+ void repairFlash() throws TreeManagerException;
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/IVideoControl.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/IVideoControl.java
new file mode 100644
index 0000000..436c0a9
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/IVideoControl.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.treemanager;
+
+
+public interface IVideoControl {
+ boolean addEventListener(IMediaSyncEventListener listener);
+
+ public enum VideoState {
+ STATE_OTHER,
+ STATE_PLAY,
+ STATE_STOP,
+ STATE_PAUSE,
+ STATE_FASTFORWARD,
+ STATE_FASTREVERSE,
+ STATE_WAITING
+ }
+
+ VideoState getVideoState();
+
+ boolean previousTrack();
+
+ boolean nextTrack();
+
+ boolean stopMedia();
+
+ boolean playMedia();
+
+ boolean pauseMedia();
+
+ boolean fastReverse();
+
+ boolean fastForward();
+
+ double getCurrentPosition();
+
+ double getTotalLength();
+
+ int getCount();
+
+ int getIndex();
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerException.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerException.java
new file mode 100644
index 0000000..edb6452
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerException.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.treemanager;
+
+public class TreeManagerException extends Exception {
+ private static final long serialVersionUID = -715217633494025285L;
+
+ private final int status;
+
+ public int getStatus() {
+ return status;
+ }
+
+ public TreeManagerException(int status, String message, Throwable cause) {
+ super(message, cause);
+ this.status = status;
+ }
+
+ public TreeManagerException(int status, String message) {
+ super(message);
+ this.status = status;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerFactory.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerFactory.java
new file mode 100644
index 0000000..4b9cc63
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerFactory.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.treemanager;
+
+import org.eclipse.actf.ai.fennec.INVM3Service;
+import org.eclipse.actf.ai.fennec.treemanager.impl.TreeManagerImpl;
+
+
+public class TreeManagerFactory {
+ public static ITreeManager newITreeManager(INVM3Service nvm3Service) {
+ return new TreeManagerImpl(nvm3Service);
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerInterruptedException.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerInterruptedException.java
new file mode 100644
index 0000000..362d5ca
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerInterruptedException.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.treemanager;
+
+public class TreeManagerInterruptedException extends TreeManagerException {
+ private static final long serialVersionUID = -1029176053941063206L;
+
+ public TreeManagerInterruptedException(int status, String message, Throwable cause) {
+ super(status, message, cause);
+ }
+
+ public TreeManagerInterruptedException(int status, String message) {
+ super(status, message);
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerPlugin.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerPlugin.java
new file mode 100644
index 0000000..b870d11
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/TreeManagerPlugin.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.treemanager;
+
+import org.eclipse.core.runtime.Plugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class TreeManagerPlugin extends Plugin {
+
+ //The shared instance.
+ private static TreeManagerPlugin plugin;
+
+ /**
+ * The constructor.
+ */
+ public TreeManagerPlugin() {
+ plugin = this;
+ }
+
+ /**
+ * This method is called upon plug-in activation
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /**
+ * This method is called when the plug-in is stopped
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Returns the shared instance.
+ */
+ public static TreeManagerPlugin getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/impl/LocationImpl.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/impl/LocationImpl.java
new file mode 100644
index 0000000..69138fe
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/impl/LocationImpl.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.fennec.treemanager.impl;
+
+import org.eclipse.actf.ai.fennec.treemanager.ILocation;
+
+
+
+class LocationImpl implements ILocation {
+ private final int[] pos;
+
+ int[] getPos() {
+ return pos;
+ }
+
+ LocationImpl(int[] pos) {
+ this.pos = pos;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/impl/TreeManagerImpl.java b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/impl/TreeManagerImpl.java
new file mode 100644
index 0000000..45b74ae
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.fennec/src/org/eclipse/actf/ai/fennec/treemanager/impl/TreeManagerImpl.java
@@ -0,0 +1,604 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.fennec.treemanager.impl;
+
+import java.util.ArrayList;
+
+import org.eclipse.actf.ai.fennec.INVM3Service;
+import org.eclipse.actf.ai.fennec.NVM3Exception;
+import org.eclipse.actf.ai.fennec.NVM3InterruptedException;
+import org.eclipse.actf.ai.fennec.treemanager.IAccessKeyList;
+import org.eclipse.actf.ai.fennec.treemanager.ILocation;
+import org.eclipse.actf.ai.fennec.treemanager.ISoundControl;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeManager;
+import org.eclipse.actf.ai.fennec.treemanager.IVideoControl;
+import org.eclipse.actf.ai.fennec.treemanager.TreeManagerException;
+import org.eclipse.actf.ai.fennec.treemanager.TreeManagerInterruptedException;
+import org.eclipse.actf.model.dom.dombycom.IFlashNode;
+import org.eclipse.actf.util.vocab.IProposition;
+import org.eclipse.actf.util.vocab.Vocabulary;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class TreeManagerImpl implements ITreeManager {
+ private INVM3Service nvm3Service;
+
+ public TreeManagerImpl(INVM3Service nvm3Service) {
+ this.nvm3Service = nvm3Service;
+ }
+
+ public int getLevel() throws TreeManagerException {
+ int i = 0;
+ ITreeItem ita = getActiveItem();
+ if (ita == null)
+ return 0;
+ while (true) {
+ ita = ita.getParent();
+ if (ita == null)
+ break;
+ i++;
+ }
+ return i;
+ }
+
+ public ITreeItem getActiveItem() throws TreeManagerException {
+ return nvm3Service.getLastTreeItem();
+ }
+
+ public ITreeItem[] getSiblings() throws TreeManagerException {
+ ITreeItem item = getActiveItem();
+ if (item == null)
+ return null;
+ ITreeItem parent = item.getParent();
+ if (parent == null) {
+ ITreeItem[] itas = new ITreeItem[1];
+ itas[0] = getActiveItem();
+ return itas;
+ }
+ return parent.getChildItems();
+ }
+
+ private void initNVM3Service() throws TreeManagerException {
+ if (nvm3Service.getStatus() == INVM3Service.NORMAL)
+ return;
+ try {
+ nvm3Service.initialize();
+ } catch (NVM3InterruptedException e) {
+ throw new TreeManagerInterruptedException(ITreeManager.UNDONE, e.getMessage(), e);
+ } catch (NVM3Exception e) {
+ throw new TreeManagerException(ITreeManager.ERROR, e.getMessage(), e);
+ }
+ }
+
+ public int initialize() throws TreeManagerException {
+ initNVM3Service();
+ return ITreeManager.NOACTION;
+ }
+
+ private int moveUpdate(ITreeItem target, boolean update) throws TreeManagerException {
+ try {
+ return nvm3Service.moveUpdate(target, update);
+ } catch (NVM3InterruptedException e) {
+ throw new TreeManagerInterruptedException(ITreeManager.UNDONE, "Failed to update by move.", e);
+ } catch (NVM3Exception e) {
+ throw new TreeManagerException(ITreeManager.ERROR, "Failed to update by move.", e);
+ }
+ }
+
+ private int clickUpdate(ITreeItem target) throws TreeManagerException {
+ try {
+ return nvm3Service.clickUpdate(target);
+ } catch (NVM3InterruptedException e) {
+ throw new TreeManagerInterruptedException(ITreeManager.UNDONE, "Failed to update by click.", e);
+ } catch (NVM3Exception e) {
+ throw new TreeManagerException(ITreeManager.ERROR, "Failed to update by click.", e);
+ }
+ }
+
+ private int gotoRoot() throws TreeManagerException {
+ ITreeItem parent = getActiveItem().getParent();
+ if (parent == null)
+ return ITreeManager.NOACTION;
+ while (gotoParent() != ITreeManager.NOACTION)
+ ;
+ return ITreeManager.MOVED | ITreeManager.LEVEL_CHANGED;
+ }
+
+ public int stay() throws TreeManagerException {
+ initNVM3Service();
+ return getActiveItem().stay();
+ }
+
+ public int click(boolean doClick) throws TreeManagerException {
+ initNVM3Service();
+ ITreeItem item = getActiveItem();
+ if (doClick)
+ item.doClick();
+ return clickUpdate(item);
+ }
+
+ public int gotoParent() throws TreeManagerException {
+ initNVM3Service();
+ ITreeItem parent = getActiveItem().getParent();
+ if (parent != null) {
+ int st = moveUpdate(parent, true);
+ if ((st & ITreeManager.MOVED) != 0)
+ st |= ITreeManager.LEVEL_CHANGED;
+ return st;
+ }
+ return ITreeManager.NOACTION;
+ }
+
+ public int gotoFirstChild() throws TreeManagerException {
+ initNVM3Service();
+ ITreeItem active = getActiveItem();
+ ITreeItem[] childItems = active.getChildItems();
+ if (childItems.length == 0)
+ return ITreeManager.NOACTION;
+ int st = moveUpdate(childItems[0], true);
+ if ((st & ITreeManager.MOVED) != 0)
+ st |= ITreeManager.LEVEL_CHANGED;
+ return st;
+ }
+
+ private int gotoLastChild() throws TreeManagerException {
+ initNVM3Service();
+ ITreeItem active = getActiveItem();
+ ITreeItem[] childItems = active.getChildItems();
+ if (childItems.length == 0)
+ return ITreeManager.NOACTION;
+ int st = moveUpdate(childItems[childItems.length - 1], true);
+ if ((st & ITreeManager.MOVED) != 0)
+ st |= ITreeManager.LEVEL_CHANGED;
+ return st;
+ }
+
+ private int gotoSiblingIndex(int idx) throws TreeManagerException {
+ initNVM3Service();
+ ITreeItem active = getActiveItem();
+ ITreeItem[] siblingItems = getSiblings();
+ if ((idx < 0) || (siblingItems.length <= idx) || (active.equals(siblingItems[idx])))
+ return ITreeManager.NOACTION;
+ int st = moveUpdate(siblingItems[idx], true);
+ return st;
+ }
+
+ private int getActiveIndex() throws TreeManagerException {
+ initNVM3Service();
+ return getActiveItem().getNth();
+ }
+
+ public int gotoStartOfSiblings() throws TreeManagerException {
+ return gotoSiblingIndex(0);
+ }
+
+ public int gotoEndOfSiblings() throws TreeManagerException {
+ initNVM3Service();
+ ITreeItem[] siblingItems = getSiblings();
+ int st = moveUpdate(siblingItems[siblingItems.length - 1], true);
+ return st | ITreeManager.MOVED;
+ }
+
+ public int gotoPreviousSibling() throws TreeManagerException {
+ int idx = getActiveIndex();
+ return gotoSiblingIndex(idx - 1);
+ }
+
+ public int gotoNextSibling() throws TreeManagerException {
+ int idx = getActiveIndex();
+ return gotoSiblingIndex(idx + 1);
+ }
+
+ public int gotoStartOfPage() throws TreeManagerException {
+ ITreeItem item = getCurrentRootItem();
+ int st;
+ st = moveUpdate(item, true);
+ return ITreeManager.NOACTION;
+
+ /*
+ ITreeItem[] childItems = item.getChildItems();
+ int st;
+ if ((childItems != null) && (childItems.length > 0)) {
+ st = moveUpdate(childItems[0], true);
+ } else {
+ st = moveUpdate(item, true);
+ }
+ if ((st & ITreeManager.MOVED) != 0)
+ st |= ITreeManager.LEVEL_CHANGED;
+ return st;*/
+ }
+
+ public int gotoEndOfPageForFind() throws TreeManagerException {
+ // TODO
+ int st;
+ this.gotoStartOfPage();
+ do {
+ st = this.gotoEndOfSiblings();
+ } while (this.gotoFirstChild() != ITreeManager.NOACTION);
+
+ if ((st & ITreeManager.MOVED) != 0)
+ st |= ITreeManager.LEVEL_CHANGED;
+ return st;
+ }
+
+ public int gotoEndOfPage() throws TreeManagerException {
+ // TODO
+ int st;
+ this.gotoStartOfPage();
+ do {
+ st = this.gotoEndOfSiblings();
+ } while (this.gotoFirstChild() != ITreeManager.NOACTION);
+
+ ITreeItem item = getActiveItem();
+ while (!Vocabulary.hasReadingContent().eval(item)) {
+ st = this.traverse(true);
+ item = getActiveItem();
+ }
+
+ if ((st & ITreeManager.MOVED) != 0)
+ st |= ITreeManager.LEVEL_CHANGED;
+ return st;
+ }
+
+ public int gotoPreviousLine() throws TreeManagerException {
+ // TODO
+ return ITreeManager.NOACTION;
+ }
+
+ public int gotoNextLine() throws TreeManagerException {
+ // TODO
+ return ITreeManager.NOACTION;
+ }
+
+ public int gotoStartOfLine() throws TreeManagerException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int gotoEndOfLine() throws TreeManagerException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ private int findItem(boolean back, IProposition proposition) throws TreeManagerException {
+ try {
+ ITreeItem item;
+ int[] pos = getActivePos();
+ int level = pos.length;
+ int rc;
+ if (back) {
+ // First, traverse to the next item in order to skip the items
+ // connectable with the current item.
+ rc = traverse(true);
+ item = getActiveItem();
+ if (proposition.eval(item)) {
+ rc |= ITreeManager.FOUND;
+ } else {
+ rc = nvm3Service.searchBackward(proposition);
+ }
+ } else {
+ // Likewise.
+ rc = traverse(false);
+ item = getActiveItem();
+ if (proposition.eval(item)) {
+ rc |= ITreeManager.FOUND;
+ } else {
+ rc = nvm3Service.searchForward(proposition);
+ }
+ }
+ if ((rc & ITreeManager.FOUND) == 0) {
+ setActivePos(pos);
+ return rc;
+ }
+ item = getActiveItem();
+ if (back) {
+ // Skip to the interval start.
+ ITreeItem siblings[] = getSiblings();
+ int idx = item.getNth();
+ int st = intervalStart(siblings, idx);
+ if (idx != st) {
+ rc |= moveUpdate(siblings[st], false);
+ }
+ item = getActiveItem();
+ }
+ if (!Vocabulary.hasReadingContent().eval(item)) {
+ traverse(false);
+ }
+ if (level != getLevel()) {
+ rc |= ITreeManager.LEVEL_CHANGED;
+ }
+ return rc;
+ } catch (NVM3InterruptedException e) {
+ throw new TreeManagerInterruptedException(ITreeManager.UNDONE, "Failed to search.", e);
+ } catch (NVM3Exception e) {
+ throw new TreeManagerException(ITreeManager.ERROR, "Failed to search.", e);
+ }
+ }
+
+ private int[] getActivePos() throws TreeManagerException {
+ int[] ret = new int[getLevel()];
+ ITreeItem current = getActiveItem();
+ int count = ret.length;
+ while (count > 0) {
+ ret[count - 1] = current.getNth();
+ count--;
+ current = current.getParent();
+ }
+ return ret;
+ }
+
+ private int setActivePos(int[] indexes) throws TreeManagerException {
+ gotoRoot();
+ ITreeItem item;
+ int st = ITreeManager.NOACTION;
+ for (int i = 0; i < indexes.length; i++) {
+ item = getActiveItem();
+ ITreeItem[] children = item.getChildItems();
+ int idx = indexes[i];
+ if ((children == null) || (idx >= children.length))
+ break;
+ st |= moveUpdate(children[idx], true);
+ }
+ return st;
+ }
+
+ public int findNext(IProposition proposition) throws TreeManagerException {
+ return findItem(false, proposition);
+ }
+
+ public int findPrevious(IProposition proposition) throws TreeManagerException {
+ return findItem(true, proposition);
+ }
+
+ private int traverseForward(ITreeItem active) throws TreeManagerException {
+ ITreeItem[] childItems = active.getChildItems();
+ if (childItems.length != 0) {
+ int st = moveUpdate(childItems[0], false);
+ return st;
+ }
+ int idx = active.getNth();
+ ITreeItem[] siblings = getSiblings();
+ if ((idx >= 0) && ((idx + 1) < siblings.length)) {
+ int st = moveUpdate(siblings[idx + 1], false);
+ return st;
+ }
+
+ for (int upCount = 1;; upCount++) {
+ active = getActiveItem();
+ ITreeItem parent = active.getParent();
+ if (parent == null) {
+ for (; upCount > 0; upCount--) {
+ gotoLastChild();
+ }
+ return ITreeManager.NOACTION;
+ }
+ if (moveUpdate(parent, false) == ITreeManager.NOACTION) {
+ throw new TreeManagerException(ITreeManager.ERROR, "Internal Error.");
+ }
+ idx = getActiveIndex();
+ siblings = getSiblings();
+ if ((idx >= 0) && ((idx + 1) < siblings.length)) {
+ int st = moveUpdate(siblings[idx + 1], false);
+ return st;
+ }
+ }
+ }
+
+ private int traverseBackward() throws TreeManagerException {
+ int idx = getActiveIndex();
+ if (idx <= 0) {
+ ITreeItem active = getActiveItem();
+ ITreeItem parent = active.getParent();
+ if (parent == null)
+ return ITreeManager.NOACTION;
+ int st = moveUpdate(parent, false);
+ return st;
+ }
+ ITreeItem[] siblings = getSiblings();
+ int st = moveUpdate(siblings[idx - 1], false);
+
+ for (;;) {
+ ITreeItem active = getActiveItem();
+ ITreeItem[] childItems = active.getChildItems();
+ if (childItems.length == 0)
+ break;
+ st |= moveUpdate(childItems[0], false) | ITreeManager.LEVEL_CHANGED;
+ siblings = getSiblings();
+ if (siblings.length > 1) {
+ st |= moveUpdate(siblings[siblings.length - 1], false);
+ }
+ }
+ return st;
+ }
+
+ private int intervalStart(ITreeItem[] siblings, int st) {
+ for (st = st - 1;; st--) {
+ if (st < 0)
+ return 0;
+ if (!Vocabulary.isConnectable().eval(siblings[st]))
+ return st + 1;
+ }
+ }
+
+ private int intervalEnd(ITreeItem[] siblings, int end) {
+ for (; end < siblings.length; end++) {
+ if (!Vocabulary.isConnectable().eval(siblings[end]))
+ return end;
+ }
+ return end - 1;
+ }
+
+ public int traverse(boolean back) throws TreeManagerException {
+ initNVM3Service();
+ ITreeItem orig = getActiveItem();
+ ITreeItem current = orig;
+ int level = getLevel();
+ int rc = ITreeManager.NOACTION;
+
+ if (back) {
+ do {
+ rc = traverseBackward();
+ current = getActiveItem();
+ } while ((rc != ITreeManager.NOACTION)
+ && (!Vocabulary.hasReadingContent().eval(current)));
+ ITreeItem siblings[] = getSiblings();
+ int idx = current.getNth();
+ int st = intervalStart(siblings, idx);
+ if (idx != st) {
+ rc |= moveUpdate(siblings[st], false);
+ }
+ } else {
+ ITreeItem siblings[] = getSiblings();
+ int idx = current.getNth();
+ int end = intervalEnd(siblings, idx);
+ current = siblings[end];
+ do {
+ rc = traverseForward(current);
+ current = getActiveItem();
+ } while ((rc != ITreeManager.NOACTION)
+ && (!Vocabulary.hasReadingContent().eval(current)));
+ }
+
+ if (!orig.equals(current)) {
+ // rc |= ITreeManager.MOVED;
+ if (level != getLevel()) {
+ rc |= ITreeManager.LEVEL_CHANGED;
+ }
+ }
+
+ return rc;
+ }
+
+ public String[] getActiveStrings() throws TreeManagerException {
+ initNVM3Service();
+ ArrayList al = new ArrayList();
+ ITreeItem[] siblings = getSiblings();
+ for (int i = getActiveIndex(); i < siblings.length; i++) {
+ ITreeItem current = siblings[i];
+ String str = current.getUIString();
+ if (str.length() > 0) {
+ al.add(str);
+ }
+ ITreeItem[] childItems = current.getChildItems();
+ if (childItems.length > 0)
+ break;
+ }
+ return (String[]) al.toArray(new String[0]);
+ }
+
+ public int gotoLeftCell() throws TreeManagerException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int gotoRightCell() throws TreeManagerException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int gotoUpCell() throws TreeManagerException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int gotoDownCell() throws TreeManagerException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getActiveTableInfo() throws TreeManagerException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getActiveTableCellInfo() throws TreeManagerException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public ITreeItem getCurrentRootItem() throws TreeManagerException {
+ initNVM3Service();
+ ITreeItem parent, current;
+ current = getActiveItem();
+ while (true) {
+ parent = current.getParent();
+ if (parent == null)
+ break;
+ current = parent;
+ }
+ return current;
+ }
+
+ public ISoundControl getSoundControl() throws TreeManagerException {
+ initNVM3Service();
+ return nvm3Service.getSoundControl();
+ }
+
+ public IVideoControl getVideoControl() throws TreeManagerException {
+ initNVM3Service();
+ return nvm3Service.getVideoControl();
+ }
+
+ public IAccessKeyList getAccessKeyList() throws TreeManagerException {
+ initNVM3Service();
+ return nvm3Service.getAccessKeyList();
+ }
+
+ public int analyze() throws TreeManagerException {
+ initNVM3Service();
+ try {
+ return nvm3Service.analyze();
+ } catch (NVM3Exception e) {
+ throw new TreeManagerException(ITreeManager.ERROR, "Failed to analyze", e);
+ }
+ }
+
+ public ILocation getCurrentLocation() throws TreeManagerException {
+ initNVM3Service();
+ return new LocationImpl(getActivePos());
+ }
+
+ public int moveToLocation(ILocation location) throws TreeManagerException {
+ initNVM3Service();
+ LocationImpl loc = (LocationImpl) location;
+ int[] pos = loc.getPos();
+ return setActivePos(pos);
+ }
+
+ public ITreeItem expandWholeTree() throws TreeManagerException {
+ initNVM3Service();
+ try {
+ return nvm3Service.expandWholeTree();
+ } catch (NVM3Exception e) {
+ throw new TreeManagerException(ITreeManager.ERROR, "Failed to expand the whole tree", e);
+ }
+ }
+
+ public int skipToAnchor(String target) throws TreeManagerException {
+ initNVM3Service();
+ try {
+ return nvm3Service.skipToAnchor(target);
+ } catch (NVM3Exception e) {
+ throw new TreeManagerException(ITreeManager.ERROR, "Failed to find the target in the anchors", e);
+ }
+ }
+
+ public void repairFlash() throws TreeManagerException {
+ initNVM3Service();
+ IFlashNode[] node = nvm3Service.getFlashTopNodes();
+ for (int i = 0; i < node.length; i++) {
+ node[i].repairFlash();
+ }
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/.classpath b/plugins/org.eclipse.actf.ai.key.keyui/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/.cvsignore b/plugins/org.eclipse.actf.ai.key.keyui/.cvsignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/.project b/plugins/org.eclipse.actf.ai.key.keyui/.project
new file mode 100644
index 0000000..dde0dad
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.actf.ai.key.keyui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.ai.key.keyui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..b8c2599
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/META-INF/MANIFEST.MF
@@ -0,0 +1,14 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Eclipse ACTF Key UI Plug-in (Incubation)
+Bundle-SymbolicName: org.eclipse.actf.ai.key.keyui;singleton:=true
+Bundle-Version: 0.0.1
+Bundle-Activator: org.eclipse.actf.ai.key.keyui.KeyUIPlugin
+Bundle-Vendor: Eclipse.org
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.actf.ai.key.keyhook.win32,
+ org.eclipse.actf.ai.xmlstore,
+ org.eclipse.ui,
+ org.eclipse.actf.ai.navigator
+Eclipse-LazyStart: true
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/about.html b/plugins/org.eclipse.actf.ai.key.keyui/about.html
new file mode 100644
index 0000000..481dbcf
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/about.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>
+<h3>License</h3>
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content").
+Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor’s license
+that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/build.properties b/plugins/org.eclipse.actf.ai.key.keyui/build.properties
new file mode 100644
index 0000000..8f739ba
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/build.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ about.html,\
+ .,\
+ plugin.xml
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/plugin.xml b/plugins/org.eclipse.actf.ai.key.keyui/plugin.xml
new file mode 100644
index 0000000..c64fb80
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/plugin.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension
+ point="org.eclipse.actf.ai.navigator.Navigation">
+ <manipulator class="org.eclipse.actf.ai.key.keyui.impl.KeyUIImpl"/>
+ </extension>
+
+</plugin>
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/src/messages.properties b/plugins/org.eclipse.actf.ai.key.keyui/src/messages.properties
new file mode 100644
index 0000000..640b39e
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/src/messages.properties
@@ -0,0 +1,239 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+openTab=Open
+closeTab=Close
+
+traverseDown=Next Node
+traverseUp=Previous Node
+click=Click
+nextLink=Next Link
+previousLink=Previous Link
+
+searchNext=Find Next
+searchPrevious=Find Previous
+
+treeTop=Top Node
+treeBottom=Last Node
+
+nextHeader=Next Header
+previousHeader=Previous Header
+nextObject=Next Object
+previousObject=Previous Object
+nextInputable=Next Inputable
+previousInputable=Previous Inputable
+
+nextListItem=Next Item of List
+previousListItem=Previous Item of List
+
+nextBlock=Next Text Block
+previousBlock=Previous Text Block
+
+selectNextNVM3=Select Fennec data
+forceRestart=Content re-Aanalyse
+toggleDescriptionEnable=Audio Description On/Off
+
+showAccessKeyList=Show Accesskey List
+speakCurrentStatus=Speak Current Status
+speakMediaStatus=Speak Media Status
+
+nextTab=Next Tab
+prevTab=Previous Tab
+
+playMedia=Play Video
+stopMedia=Stop Video
+pauseMedia=Pause Video
+
+muteMedia=Mute Volume
+volumeDownMedia=Volume Down
+volumeUpMedia=Volume Up
+
+launchBrowser=Open in Default Browser
+toggleLeftViewsShowing=Open / Close Tree View
+speakAll=Say all
+
+importMetadata=Import Fennec data...
+exportMetadata=Export User Annotation...
+exportAllMetadata=Export All User Annotations...
+
+nextMedia=Next Media
+previousMedia=Previous Media
+
+saveUserInfo=Save Annotation
+removeUserInfo=Remove All Annotation
+editAltText=Edit Alt. Text
+makeLandmark=Set / Unset a Landmark
+nextAlterable=Next Alterable Item
+previousAlterable=Previous Alterable Item
+
+navigateRefresh=Refresh
+forward=Forward
+backward=Backward
+enterBrowserAddress=Enter Address
+
+nextHeader1=Next Header Level 1
+nextHeader2=Next Header Level 2
+nextHeader3=Next Header Level 3
+nextHeader4=Next Header Level 4
+nextHeader5=Next Header Level 5
+nextHeader6=Next Header Level 6
+
+previousHeader1=Previous Header Level 1
+previousHeader2=Previous Header Level 2
+previousHeader3=Previous Header Level 3
+previousHeader4=Previous Header Level 4
+previousHeader5=Previous Header Level 5
+previousHeader6=Previous Header Level 6
+
+minimalVolumeDownMedia=Volume Down (minimum step)
+minimalVolumeUpMedia=Volume Up (minimum step)
+speechSpeedDown=Speech Speed Down
+speechSpeedUp=Speech Speed Up
+
+repairFlash=Repair Flash content
+
+Key.OR=or
+
+
+CMD_PASSTHROUGH=Pass Through
+
+CMD_NOOP=No Operation
+
+CMD_MUTEMEDIA=Mute Volume
+
+CMD_VOLUMEDOWNMEDIA=Volume Down
+
+CMD_VOLUMEUPMEDIA=Volume Up
+
+CMD_PREVIOUSTRACK=Previous Track
+
+CMD_NEXTTRACK=Next Track
+
+CMD_STOPMEDIA=Stop Video
+
+CMD_PLAYMEDIA=Play Video
+
+CMD_PAUSEMEDIA=Pause Video
+
+CMD_FASTREVERSE=Rewind Video
+
+CMD_FASTFORWARD=Forward Video
+
+CMD_SPEECHSPEEDUP=Speed Up Speech
+
+CMD_SPEECHSPEEDDOWN=Speed Down Speech
+
+CMD_TREELEFT=Tree Left
+
+CMD_TREERIGHT=Tree Right
+
+CMD_TREEUP=Tree Up
+
+CMD_TREEDOWN=Tree Down
+
+CMD_TREETOP=Tree Top
+
+CMD_TREEBOTTOM=Tree Bottom
+
+CMD_TRAVERSENODEDOWN=Next Node
+
+CMD_TRAVERSENODEUP=Previous Node
+
+CMD_TRAVERSEDOWN=Next Item
+
+CMD_TRAVERSEUP=Previous Item
+
+CMD_CLICK=Click
+
+CMD_CELLLEFT=Cell Left
+
+CMD_CELLRIGHT=Cell Right
+
+CMD_CELLUP=Cell Up
+
+CMD_CELLDOWN=Cell Down
+
+CMD_STARTAUTOPLAY=Auto Play
+
+CMD_ENDAUTOPLAY=Stop Auto Play
+
+CMD_AUTOPLAYMINSPEED=Min Speed Auto Play
+
+CMD_AUTOPLAYMAXSPEED=Max Speed Auto Play
+
+CMD_AUTOPLAYDEFAULTSPEED=Default Speed Auto Play
+
+CMD_AUTOPLAYNOP=Auto Play No Operation
+
+CMD_AUTOPLAYSLOWER=Slower Auto Play
+
+CMD_AUTOPLAYFASTER=Faster Auto Play
+
+CMD_NEXTHEADER=Next Header
+
+CMD_PREVIOUSHEADER=Previous Header
+
+CMD_NEXTINPUTABLE=Next Input
+
+CMD_PREVIOUSINPUTABLE=Previous Input
+
+CMD_HOME=Go to top of page
+
+CMD_END=Go to end of page
+
+CMD_SELECTNEXTNVM3=Select Fennec data
+
+CMD_ENTERBROWSERADDRESS=Edit Address
+
+CMD_FORCERESTART=Content re-Aanalyse
+
+CMD_NAVIGATEREFRESH=Refrefh
+
+CMD_SPEAKCURRENTSTATUS=Speak Current Status
+
+CMD_NEXTLINK=Next Link
+
+CMD_PREVIOUSLINK=Previous Link
+
+CMD_NEXTOBJECT=Next Object
+
+CMD_PREVIOUSOBJECT=Previous Object
+
+CMD_EXIT_FORM_MODE=Exit Form Mode
+
+CMD_FORM_IGNORE_KEY=Form Ignore Key
+
+CMD_FORM_SUBMIT=Form Submit
+
+CMD_TOGGLE_DESCRIPTION_ENABLE=Audio Description
+
+CMD_TAKE_BACK_CONTROL=Take Back Control
+
+CMD_CLOSETAB=Close Tab
+
+CMD_NEXTTAB=Next Tab
+
+CMD_PREVTAB=Prev Tab
+
+CMD_GO_FORWARD=Go Forward
+
+CMD_GO_BACKWORD=Go Backward
+
+CMD_OPEN=Open
+
+CMD_SPEED_UP=Speed Up
+
+CMD_SPEED_DOWN=Speed Down
+
+CMD_PLAY_NEXT=Play Next
+
+CMD_PLAY_PREV=Play Prev
+
+CMD_START_RECORDING=Start Recording
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/src/messages_ja.properties b/plugins/org.eclipse.actf.ai.key.keyui/src/messages_ja.properties
new file mode 100644
index 0000000..14cf70f
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/src/messages_ja.properties
@@ -0,0 +1,239 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+openTab=\u958b\u304f
+closeTab=\u9589\u3058\u308b
+
+traverseDown=\u6b21\u306e\u9805\u76ee
+traverseUp=\u524d\u306e\u9805\u76ee
+click=\u30af\u30ea\u30c3\u30af
+nextLink=\u6b21\u306e\u30ea\u30f3\u30af
+previousLink=\u524d\u306e\u30ea\u30f3\u30af
+
+searchNext=\u6b21\u3092\u691c\u7d22
+searchPrevious=\u524d\u3092\u691c\u7d22
+
+treeTop=\u5148\u982d\u306e\u9805\u76ee\u3078
+treeBottom=\u6700\u5f8c\u306e\u9805\u76ee\u3078
+
+nextHeader=\u6b21\u306e\u898b\u51fa\u3057\u3078
+previousHeader=\u524d\u306e\u898b\u51fa\u3057\u3078
+nextObject=\u6b21\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3078
+previousObject=\u524d\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3078
+nextInputable=\u6b21\u306e\u30d5\u30a9\u30fc\u30e0\u3078
+previousInputable=\u524d\u306e\u30d5\u30a9\u30fc\u30e0\u3078
+
+nextListItem=\u6b21\u306e\u30ea\u30b9\u30c8\u9805\u76ee\u3078
+previousListItem=\u524d\u306e\u30ea\u30b9\u30c8\u9805\u76ee\u3078
+
+nextBlock=\u6b21\u306e\u30c6\u30ad\u30b9\u30c8\u30d6\u30ed\u30c3\u30af\u3078
+previousBlock=\u524d\u306e\u30c6\u30ad\u30b9\u30c8\u30d6\u30ed\u30c3\u30af\u3078
+
+selectNextNVM3=Fennec\u5916\u90e8\u60c5\u5831\u306e\u5207\u308a\u66ff\u3048
+forceRestart=\u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u518d\u89e3\u6790
+toggleDescriptionEnable=\u97f3\u58f0\u89e3\u8aac\u306e\u30aa\u30f3\u30fb\u30aa\u30d5
+
+showAccessKeyList=\u30a2\u30af\u30bb\u30b9\u30ad\u30fc\u306e\u30ea\u30b9\u30c8\u3092\u8868\u793a
+speakCurrentStatus=\u73fe\u5728\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u3092\u8aad\u4e0a\u3052\u308b
+speakMediaStatus=\u30e1\u30c7\u30a3\u30a2\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u3092\u8aad\u4e0a\u3052\u308b
+
+nextTab=\u6b21\u306e\u30bf\u30d6
+prevTab=\u524d\u306e\u30bf\u30d6
+
+playMedia=\u30d3\u30c7\u30aa\u306e\u518d\u751f
+stopMedia=\u30d3\u30c7\u30aa\u306e\u505c\u6b62
+pauseMedia=\u30d3\u30c7\u30aa\u306e\u4e00\u6642\u505c\u6b62
+
+muteMedia=\u6d88\u97f3
+volumeDownMedia=\u97f3\u91cf\u5c0f
+volumeUpMedia=\u97f3\u91cf\u5927
+
+launchBrowser=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30d6\u30e9\u30a6\u30b6\u3067\u958b\u304f
+toggleLeftViewsShowing=\u30c4\u30ea\u30fc\u30d3\u30e5\u30fc\u3092\u958b\u304f\uff0f\u9589\u3058\u308b
+speakAll=\u5168\u3066\u8aad\u4e0a\u3052
+
+importMetadata=Fennec \u30c7\u30fc\u30bf\u306e\u8aad\u307f\u8fbc\u307f...
+exportMetadata=\u6ce8\u91c8\u30c7\u30fc\u30bf\u306e\u66f8\u304d\u51fa\u3057...
+exportAllMetadata=\u5168\u3066\u306e\u6ce8\u91c8\u30c7\u30fc\u30bf\u306e\u66f8\u304d\u51fa\u3057...
+
+nextMedia=\u6b21\u306e\u30e1\u30c7\u30a3\u30a2
+previousMedia=\u524d\u306e\u30e1\u30c7\u30a3\u30a2
+
+saveUserInfo=\u6ce8\u91c8\u306e\u30bb\u30fc\u30d6
+removeUserInfo=\u6ce8\u91c8\u3092\u5168\u3066\u524a\u9664
+editAltText=\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u306e\u7de8\u96c6
+makeLandmark=\u3057\u304a\u308a\u306e\u8ffd\u52a0\uff0f\u524a\u9664
+nextAlterable=\u6b21\u306e\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u7de8\u96c6\u70b9
+previousAlterable=\u524d\u306e\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u7de8\u96c6\u70b9
+
+navigateRefresh=\u6700\u65b0\u306e\u60c5\u5831\u306b\u66f4\u65b0
+forward=\u9032\u3080
+backward=\u623b\u308b
+enterBrowserAddress=\u30a2\u30c9\u30ec\u30b9\u5165\u529b
+
+nextHeader1=\u6b21\u306e\u30ec\u30d9\u30eb\uff11\u306e\u898b\u51fa\u3057
+nextHeader2=\u6b21\u306e\u30ec\u30d9\u30eb\uff12\u306e\u898b\u51fa\u3057
+nextHeader3=\u6b21\u306e\u30ec\u30d9\u30eb\uff13\u306e\u898b\u51fa\u3057
+nextHeader4=\u6b21\u306e\u30ec\u30d9\u30eb\uff14\u306e\u898b\u51fa\u3057
+nextHeader5=\u6b21\u306e\u30ec\u30d9\u30eb\uff15\u306e\u898b\u51fa\u3057
+nextHeader6=\u6b21\u306e\u30ec\u30d9\u30eb\uff16\u306e\u898b\u51fa\u3057
+
+previousHeader1=\u524d\u306e\u30ec\u30d9\u30eb\uff11\u306e\u898b\u51fa\u3057
+previousHeader2=\u524d\u306e\u30ec\u30d9\u30eb\uff12\u306e\u898b\u51fa\u3057
+previousHeader3=\u524d\u306e\u30ec\u30d9\u30eb\uff13\u306e\u898b\u51fa\u3057
+previousHeader4=\u524d\u306e\u30ec\u30d9\u30eb\uff14\u306e\u898b\u51fa\u3057
+previousHeader5=\u524d\u306e\u30ec\u30d9\u30eb\uff15\u306e\u898b\u51fa\u3057
+previousHeader6=\u524d\u306e\u30ec\u30d9\u30eb\uff16\u306e\u898b\u51fa\u3057
+
+minimalVolumeDownMedia=\u97f3\u91cf\u5c0f\uff08\u6700\u5c0f\u5e45\uff09
+minimalVolumeUpMedia=\u97f3\u91cf\u5927\uff08\u6700\u5c0f\u5e45\uff09
+speechSpeedDown=\u8aad\u4e0a\u3052\u901f\u5ea6\u9045\u304f
+speechSpeedUp=\u8aad\u4e0a\u3052\u901f\u5ea6\u901f\u304f
+
+repairFlash=Flash\u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u4fee\u5fa9
+
+Key.OR=\u3082\u3057\u304f\u306f
+
+CMD_PASSTHROUGH=\u901a\u904e
+
+CMD_NOOP=\u64cd\u4f5c\u306a\u3057
+
+CMD_MUTEMEDIA=\u6d88\u97f3
+
+CMD_VOLUMEDOWNMEDIA=\u97f3\u91cf\u5927
+
+CMD_VOLUMEUPMEDIA=\u97f3\u91cf\u5c0f
+
+CMD_PREVIOUSTRACK=\u524d\u306e\u30c8\u30e9\u30c3\u30af\u3078
+
+CMD_NEXTTRACK=\u6b21\u306e\u30c8\u30e9\u30c3\u30af\u3078
+
+CMD_STOPMEDIA=\u30d3\u30c7\u30aa\u505c\u6b62
+
+CMD_PLAYMEDIA=\u30d3\u30c7\u30aa\u518d\u751f
+
+CMD_PAUSEMEDIA=\u30d3\u30c7\u30aa\u4e00\u6642\u505c\u6b62
+
+CMD_FASTREVERSE=\u30d3\u30c7\u30aa\u5dfb\u304d\u623b\u3057
+
+CMD_FASTFORWARD=\u30d3\u30c7\u30aa\u65e9\u9001\u308a
+
+CMD_SPEECHSPEEDUP=\u8aad\u4e0a\u3052\u901f\u5ea6\u901f\u304f
+
+CMD_SPEECHSPEEDDOWN=\u8aad\u4e0a\u3052\u901f\u5ea6\u9045\u304f
+
+CMD_TREELEFT=\u30c4\u30ea\u30fc\u5de6\u3078
+
+CMD_TREERIGHT=\u30c4\u30ea\u30fc\u53f3\u3078
+
+CMD_TREEUP=\u30c4\u30ea\u30fc\u4e0a\u3078
+
+CMD_TREEDOWN=\u30c4\u30ea\u30fc\u4e0b\u3078
+
+CMD_TREETOP=\u30c4\u30ea\u30fc\u6700\u521d\u3078
+
+CMD_TREEBOTTOM=\u30c4\u30ea\u30fc\u6700\u5f8c\u3078
+
+CMD_TRAVERSENODEDOWN=\u6b21\u306e\u30ce\u30fc\u30c9\u3078
+
+CMD_TRAVERSENODEUP=\u524d\u306e\u30ce\u30fc\u30c9\u3078
+
+CMD_TRAVERSEDOWN=\u6b21\u306e\u9805\u76ee\u3078
+
+CMD_TRAVERSEUP=\u524d\u306e\u9805\u76ee\u3078
+
+CMD_CLICK=\u30af\u30ea\u30c3\u30af
+
+CMD_CELLLEFT=\u5de6\u306e\u30bb\u30eb\u3078
+
+CMD_CELLRIGHT=\u53f3\u306e\u30bb\u30eb\u3078
+
+CMD_CELLUP=\u4e0a\u306e\u30bb\u30eb\u3078
+
+CMD_CELLDOWN=\u4e0b\u306e\u30bb\u30eb\u3078
+
+CMD_STARTAUTOPLAY=\u81ea\u52d5\u8aad\u4e0a\u3052
+
+CMD_ENDAUTOPLAY=\u81ea\u52d5\u8aad\u4e0a\u3052\u505c\u6b62
+
+CMD_AUTOPLAYMINSPEED=\u81ea\u52d5\u8aad\u4e0a\u3052\u3001\u6700\u5c0f\u901f\u5ea6
+
+CMD_AUTOPLAYMAXSPEED=\u81ea\u52d5\u8aad\u4e0a\u3052\u3001\u6700\u5927\u901f\u5ea6
+
+CMD_AUTOPLAYDEFAULTSPEED=\u81ea\u52d5\u8aad\u4e0a\u3052\u3001\u901a\u5e38\u901f\u5ea6
+
+CMD_AUTOPLAYNOP=\u81ea\u52d5\u8aad\u4e0a\u3052\u3001\u64cd\u4f5c\u306a\u3057
+
+CMD_AUTOPLAYSLOWER=\u81ea\u52d5\u8aad\u4e0a\u3052\u3001\u901f\u5ea6\u9045\u304f
+
+CMD_AUTOPLAYFASTER=\u81ea\u52d5\u8aad\u4e0a\u3052\u3001\u901f\u5ea6\u901f\u304f
+
+CMD_NEXTHEADER=\u6b21\u306e\u30d8\u30c3\u30c0\u30fc\u3078
+
+CMD_PREVIOUSHEADER=\u524d\u306e\u30d8\u30c3\u30c0\u30fc\u3078
+
+CMD_NEXTINPUTABLE=\u6b21\u306e\u30d5\u30a9\u30fc\u30e0\u3078
+
+CMD_PREVIOUSINPUTABLE=\u524d\u306e\u30d5\u30a9\u30fc\u30e0\u3078
+
+CMD_HOME=\u30da\u30fc\u30b8\u306e\u5148\u982d\u3078
+
+CMD_END=\u30da\u30fc\u30b8\u306e\u6700\u5f8c\u3078
+
+CMD_SELECTNEXTNVM3=Fennec \u30c7\u30fc\u30bf\u306e\u5207\u308a\u66ff\u3048
+
+CMD_ENTERBROWSERADDRESS=\u30a2\u30c9\u30ec\u30b9\u5165\u529b
+
+CMD_FORCERESTART=\u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u518d\u89e3\u6790
+
+CMD_NAVIGATEREFRESH=\u30ea\u30d5\u30ec\u30c3\u30b7\u30e5
+
+CMD_SPEAKCURRENTSTATUS=\u73fe\u5728\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u3092\u8aad\u4e0a\u3052\u308b
+
+CMD_NEXTLINK=\u6b21\u306e\u30ea\u30f3\u30af\u3078
+
+CMD_PREVIOUSLINK=\u524d\u306e\u30ea\u30f3\u30af\u3078
+
+CMD_NEXTOBJECT=\u6b21\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3078
+
+CMD_PREVIOUSOBJECT=\u524d\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3078
+
+CMD_EXIT_FORM_MODE=\u30d5\u30a9\u30fc\u30e0\u30e2\u30fc\u30c9\u7d42\u4e86
+
+CMD_FORM_IGNORE_KEY=Form Ignore Key
+
+CMD_FORM_SUBMIT=\u9001\u4fe1\u30dc\u30bf\u30f3
+
+CMD_TOGGLE_DESCRIPTION_ENABLE=\u97f3\u58f0\u89e3\u8aac
+
+CMD_TAKE_BACK_CONTROL=\u30c6\u30a4\u30af\u30d0\u30c3\u30af\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb
+
+CMD_CLOSETAB=\u30bf\u30d6\u3092\u9589\u3058\u308b
+
+CMD_NEXTTAB=\u6b21\u306e\u30bf\u30d6\u3078
+
+CMD_PREVTAB=\u524d\u306e\u30bf\u30d6\u3078
+
+CMD_GO_FORWARD=\u9032\u3080
+
+CMD_GO_BACKWORD=\u623b\u308b
+
+CMD_OPEN=\u958b\u304f
+
+CMD_SPEED_UP=\u901f\u5ea6\u901f\u304f
+
+CMD_SPEED_DOWN=\u901f\u5ea6\u9045\u304f
+
+CMD_PLAY_NEXT=\u6b21\u3092\u518d\u751f
+
+CMD_PLAY_PREV=\u524d\u3092\u518d\u751f
+
+CMD_START_RECORDING=\u9332\u97f3\u958b\u59cb
+
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/src/org/eclipse/actf/ai/key/keyui/KeyUIPlugin.java b/plugins/org.eclipse.actf.ai.key.keyui/src/org/eclipse/actf/ai/key/keyui/KeyUIPlugin.java
new file mode 100644
index 0000000..8d60c3a
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/src/org/eclipse/actf/ai/key/keyui/KeyUIPlugin.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.key.keyui;
+
+import org.eclipse.core.runtime.Plugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class KeyUIPlugin extends Plugin {
+
+ //The shared instance.
+ private static KeyUIPlugin plugin;
+
+ /**
+ * The constructor.
+ */
+ public KeyUIPlugin() {
+ plugin = this;
+ }
+
+ /**
+ * This method is called upon plug-in activation
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /**
+ * This method is called when the plug-in is stopped
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Returns the shared instance.
+ */
+ public static KeyUIPlugin getDefault() {
+ return plugin;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/src/org/eclipse/actf/ai/key/keyui/Messages.java b/plugins/org.eclipse.actf.ai.key.keyui/src/org/eclipse/actf/ai/key/keyui/Messages.java
new file mode 100644
index 0000000..fa1ebaf
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/src/org/eclipse/actf/ai/key/keyui/Messages.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.key.keyui;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+
+public class Messages {
+ private static final String BUNDLE_NAME = "messages"; //$NON-NLS-1$
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
+
+ private Messages() {
+ }
+
+ public static String getString(String key) {
+ // TODO Auto-generated method stub
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.key.keyui/src/org/eclipse/actf/ai/key/keyui/impl/KeyUIImpl.java b/plugins/org.eclipse.actf.ai.key.keyui/src/org/eclipse/actf/ai/key/keyui/impl/KeyUIImpl.java
new file mode 100644
index 0000000..c2ce68e
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.key.keyui/src/org/eclipse/actf/ai/key/keyui/impl/KeyUIImpl.java
@@ -0,0 +1,528 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.key.keyui.impl;
+
+import java.awt.event.KeyEvent;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.actf.ai.key.keyhook.win32.IKeyHook;
+import org.eclipse.actf.ai.key.keyhook.win32.IKeyHookListener;
+import org.eclipse.actf.ai.key.keyhook.win32.ISendEvent;
+import org.eclipse.actf.ai.key.keyhook.win32.KeyHookWin32Plugin;
+import org.eclipse.actf.ai.key.keyui.Messages;
+import org.eclipse.actf.ai.key.keyui.impl.KeyUIImpl.KC.Type;
+import org.eclipse.actf.ai.navigator.IBrowserControl;
+import org.eclipse.actf.ai.navigator.IManipulator;
+import org.eclipse.actf.ai.navigator.INavigatorUI;
+import org.eclipse.actf.ai.navigator.NavigatorPlugin;
+import org.eclipse.actf.ai.xmlstore.IXMLInfo;
+import org.eclipse.actf.ai.xmlstore.IXMLSelector;
+import org.eclipse.actf.ai.xmlstore.IXMLStore;
+import org.eclipse.actf.ai.xmlstore.IXMLStoreService;
+import org.eclipse.actf.ai.xmlstore.XMLStoreException;
+import org.eclipse.actf.ai.xmlstore.XMLStorePlugin;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.Separator;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+
+
+public class KeyUIImpl implements IKeyHookListener, IManipulator {
+ private static boolean initialized = false;
+
+ public static final String PREFERENCES_NS = "http://www.ibm.com/xmlns/prod/AcTF/aiBrowser/preferences/1.0";
+
+ public static final int CMD_PASSTHROUGH = -1;
+
+ public static final int CMD_NOOP = 9999;
+
+ // for demo
+ public static final int CMD_SPEED_UP = 1300;
+
+ public static final int CMD_SPEED_DOWN = 1301;
+
+ public static final int CMD_PLAY_NEXT = 1302;
+
+ public static final int CMD_PLAY_PREV = 1303;
+
+ public static final int CMD_START_RECORDING = 1304;
+
+ private static final int VK_RETURN = 13;
+
+ private IManipulator.Mode mode = null;
+
+ private IBrowserControl browserControl;
+
+ private INavigatorUI navigatorUI;
+
+ private HashMap<KeyEntry, KC> keyConfigMapForTreeNavigation = new HashMap<KeyEntry, KC>();
+
+ private static IKeyHook keyHook;
+
+ private static ISendEvent sendEvent;
+
+ public KeyUIImpl() {
+ if (!initialized) {
+ initialized = true;
+ initialize();
+ }
+ }
+
+ public void initialize() {
+ keyHook = KeyHookWin32Plugin.getDefault().newKeyHook(this);
+ sendEvent = KeyHookWin32Plugin.getDefault().newSendEvent();
+
+ IXMLStoreService xmlStoreService = XMLStorePlugin.getDefault().getXMLStoreService();
+ IXMLSelector selector = xmlStoreService.getSelectorWithDocElem("UserPreferences", PREFERENCES_NS);
+ IXMLStore rootStore = xmlStoreService.getRootStore();
+ IXMLStore specifiedStroe = rootStore.specify(selector);
+ for (Iterator<IXMLInfo> i = specifiedStroe.getInfoIterator(); i.hasNext();) {
+ IXMLInfo info = i.next();
+ try {
+ read(info.getRootNode());
+ } catch (XMLStoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ initAccessKey();
+ }
+
+ private void initAccessKey() {
+ for (int i = 0; i < 10; i++) {
+ KC kc = new KC(KC.Type.ACCESSKEY, KeyEvent.VK_0 + i, KeyEvent.SHIFT_MASK | KeyEvent.ALT_MASK, null);
+ register(kc);
+ }
+ for (int i = 0; i < 26; i++) {
+ KC kc = new KC(KC.Type.ACCESSKEY, KeyEvent.VK_A + i, KeyEvent.SHIFT_MASK | KeyEvent.ALT_MASK, null);
+ register(kc);
+ }
+ }
+
+ private void read(Node rootNode) {
+ NodeList children = rootNode.getChildNodes();
+
+ for (int i = 0; i < children.getLength(); i++) {
+ Node commands = children.item(i);
+ KC.Type type = KC.Type.COMMAND;
+
+ if (commands.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ if (commands.getLocalName().equals("Commands")) {
+ type = KC.Type.COMMAND;
+ } else if (commands.getLocalName().equals("Functions")) {
+ type = KC.Type.FUNCTION;
+ } else {
+ continue;
+ }
+
+ NodeList commandList = commands.getChildNodes();
+
+ for (int j = 0; j < commandList.getLength(); j++) {
+ Node command = commandList.item(j);
+
+ if (command.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ NodeList keyList = command.getChildNodes();
+
+ ArrayList<KC> array = new ArrayList<KC>();
+ for (int k = 0; k < keyList.getLength(); k++) {
+ Node key = keyList.item(k);
+
+ if (key.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ KC kc = createKC(type, command, key);
+ register(kc);
+
+ if (!"none".equals(((Element) key).getAttribute("display")))
+ array.add(kc);
+ }
+ addMenu(commands, command, array);
+ }
+ }
+ }
+
+ private KC createKC(Type type, Node command, Node key) {
+ String name = command.getLocalName();
+ int vkey = 0;
+ int mod = 0;
+ if ("key".equals(key.getLocalName()) && PREFERENCES_NS.equals(key.getNamespaceURI())) {
+ String stroke = key.getTextContent();
+ stroke = stroke.trim();
+ String[] keys = stroke.split("[ \n\t\r]+");
+ for (int j = 0; j < keys.length; j++) {
+ try {
+ if ("VK_RETURN".equals(keys[j])) {
+ vkey = VK_RETURN;
+ } else if (keys[j].startsWith("VK_")) {
+ Field f = KeyEvent.class.getField(keys[j]);
+ vkey = f.getInt(KeyEvent.class);
+ } else if (keys[j].endsWith("_MASK")) {
+ Field f = KeyEvent.class.getField(keys[j]);
+ mod |= f.getInt(KeyEvent.class);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return new KC(type, vkey, mod, name);
+ }
+
+ private void addMenu(Node commands, Node command, ArrayList<KC> kc) {
+ String menuName = ((Element) commands).getAttribute("menu");
+ if (menuName.length() == 0)
+ return;
+ String groupName = ((Element) commands).getAttribute("menuGroup");
+ if (groupName.length() == 0)
+ return;
+ String name = command.getLocalName();
+
+ IMenuManager menu = NavigatorPlugin.menuManager;
+ IMenuManager menu2 = menu.findMenuUsingPath(menuName);
+
+ if ("separator".equals(name)) {
+ menu2.appendToGroup(groupName, new Separator());
+ } else {
+ menu2.appendToGroup(groupName, new KeyAction(name, kc));
+ }
+ }
+
+ static class KeyEntry {
+ int vkey;
+
+ int mod;
+
+ @Override
+ public int hashCode() {
+ return (vkey | mod << 16);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof KeyEntry))
+ return false;
+ KeyEntry e = (KeyEntry) o;
+ return ((e.vkey == vkey) && (e.mod == mod));
+ }
+
+ KeyEntry(int vkey, int mod) {
+ this.vkey = vkey;
+ this.mod = mod;
+ }
+ }
+
+ private void register(KC kc) {
+ keyConfigMapForTreeNavigation.put(new KeyEntry(kc.vkey, kc.mod), kc);
+ keyHook.registerHookedKey(kc.vkey, kc.mod);
+ }
+
+ static class KC {
+ enum Type {
+ COMMAND, FUNCTION, NOOP, ACCESSKEY
+ }
+
+ int vkey;
+
+ int mod;
+
+ Type type;
+
+ String name;
+
+ enum Target {
+ INAVIGATORUI, IBROWSERCONTROL
+ }
+
+ Target target;
+
+ Method method;
+
+ int command;
+
+ private Method lookupMethod(Class clazz, String name) {
+ try {
+ return clazz.getMethod(name, new Class[0]);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ KC(Type type, int vkey, int mod, String name) {
+ this.type = type;
+ this.vkey = vkey;
+ this.mod = mod;
+ this.name = name;
+
+ if (type == Type.FUNCTION) {
+ method = lookupMethod(INavigatorUI.class, name);
+ if (method != null) {
+ target = Target.INAVIGATORUI;
+ } else {
+ method = lookupMethod(IBrowserControl.class, name);
+ if (method == null) {
+ System.err.println("No such method:" + name);
+ }
+ target = Target.IBROWSERCONTROL;
+ }
+ } else if (type == Type.COMMAND) {
+ try {
+ Field field = KeyUIImpl.class.getField("CMD_" + name);
+ command = field.getInt(KeyUIImpl.class);
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public boolean hookedKey(int vkey, int modifier, boolean isUp) {
+ if (mode == IManipulator.TREE_NAVIGATION_MODE) {
+ KC kc = (KC) keyConfigMapForTreeNavigation.get(new KeyEntry(vkey, modifier));
+ if (kc != null) {
+ if (kc.type == KC.Type.COMMAND && kc.command == CMD_NOOP)
+ return true;
+ if (kc.type != KC.Type.ACCESSKEY && kc.method == null)
+ return false;
+
+ /*
+ if (vkey == VK_RETURN) {
+ if (!isUp)
+ call(kc);
+ } else {
+ if (isUp)
+ call(kc);
+ }*/
+ if (!isUp)
+ call(kc);
+
+ return true;
+ }
+ } else if (mode == IManipulator.FORM_INPUT_MODE) {
+ switch (vkey) {
+ case KeyEvent.VK_TAB:
+ break;
+ case VK_RETURN:
+ // navigatorUI.submitForm();
+ sendEvent.postKey(vkey, isUp);
+ break;
+ case KeyEvent.VK_ESCAPE:
+ navigatorUI.exitFormMode();
+ break;
+ default:
+ return false;
+ }
+ return true;
+ } else if (mode == IManipulator.KEYHOOK_DISABLED_MODE) {
+ return false;
+ }
+ return false;
+ }
+
+ private void call(KC kc) {
+ if (kc.type == KC.Type.COMMAND) {
+ switch (kc.command) {
+ // for demo
+ case CMD_SPEED_UP:
+ sendKey(KeyEvent.VK_UP, true);
+ break;
+ case CMD_SPEED_DOWN:
+ sendKey(KeyEvent.VK_DOWN, true);
+ break;
+ case CMD_PLAY_NEXT:
+ sendKey(KeyEvent.VK_RIGHT, false);
+ break;
+ case CMD_PLAY_PREV:
+ sendKey(KeyEvent.VK_LEFT, false);
+ break;
+ case CMD_START_RECORDING:
+ sendKey(KeyEvent.VK_S, true);
+ break;
+ case CMD_NOOP:
+ case CMD_PASSTHROUGH:
+ break;
+ }
+ } else if (kc.type == KC.Type.FUNCTION) {
+ try {
+ switch (kc.target) {
+ case IBROWSERCONTROL:
+ if (browserControl != null)
+ kc.method.invoke(browserControl, new Object[0]);
+ break;
+ case INAVIGATORUI:
+ if (navigatorUI != null)
+ kc.method.invoke(navigatorUI, new Object[0]);
+ break;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else if (kc.type == KC.Type.ACCESSKEY) {
+ navigatorUI.jumpToAccessKey((char) kc.vkey);
+ }
+ }
+
+ private void sendKey(int key, boolean ctrlFlag) {
+ long h = sendEvent.findWindow("SWT_Window0", "Sound Controller");
+ if (ctrlFlag) {
+ sendEvent.postKeyToWindow(h, KeyEvent.VK_CONTROL, false);
+ }
+ sendEvent.postKeyToWindow(h, key, false);
+ sendEvent.postKeyToWindow(h, key, true);
+ if (ctrlFlag) {
+ sendEvent.postKeyToWindow(h, KeyEvent.VK_CONTROL, true);
+ }
+ }
+
+ public void setNavigator(INavigatorUI navigatorUI) {
+ this.navigatorUI = navigatorUI;
+ }
+
+ public void setBrowserControl(IBrowserControl browserControl) {
+ this.browserControl = browserControl;
+ }
+
+ public void dispose() {
+ keyHook.dispose();
+ }
+
+ public void setMode(Mode mode) {
+ this.mode = mode;
+ if (mode == IManipulator.FORM_INPUT_MODE) {
+ keyHook.hookAll(true);
+ } else if (mode == IManipulator.KEYHOOK_DISABLED_MODE) {
+ keyHook.hookAll(false);
+ } else {
+ keyHook.hookAll(false);
+ }
+ }
+
+ class KeyAction extends Action {
+ String name;
+
+ ArrayList<KC> kcs;
+
+ public KeyAction(String name, ArrayList<KC> kcs) {
+ super();
+ this.name = name;
+ this.kcs = kcs;
+
+ StringBuffer sb = new StringBuffer();
+ sb.append(Messages.getString(name));
+ if (kcs.size() > 0)
+ sb.append(" (" + getKey(kcs) + ")");
+
+ setText(sb.toString());
+ }
+
+ private String getKey(ArrayList<KC> kcs) {
+ StringBuffer sb = new StringBuffer();
+
+ for (int i = 0; i < kcs.size(); i++) {
+ if (i != 0)
+ sb.append(" " + Messages.getString("Key.OR") + " ");
+
+ int vkey = kcs.get(i).vkey;
+ int mod = kcs.get(i).mod;
+
+ if (is(mod, KeyEvent.CTRL_MASK)) {
+ sb.append("Ctrl+");
+ }
+ if (is(mod, KeyEvent.ALT_MASK)) {
+ sb.append("Alt+");
+ }
+ if (is(mod, KeyEvent.SHIFT_MASK)) {
+ sb.append("Shift+");
+ }
+ String key = "";
+ if (('0' <= vkey && vkey <= '9') || ('A' <= vkey && vkey <= 'Z')) {
+ key = "" + (char) vkey;
+ } else if (KeyEvent.VK_F1 <= vkey && vkey <= KeyEvent.VK_F24) {
+ key = "F" + (vkey - KeyEvent.VK_F1 + 1);
+ } else {
+ switch (vkey) {
+ case VK_RETURN:
+ key = "Enter";
+ break;
+ case KeyEvent.VK_UP:
+ key = "Up";
+ break;
+ case KeyEvent.VK_DOWN:
+ key = "Down";
+ break;
+
+ case KeyEvent.VK_LEFT:
+ key = "Left";
+ break;
+ case KeyEvent.VK_RIGHT:
+ key = "Right";
+ break;
+
+ case KeyEvent.VK_HOME:
+ key = "Home";
+ break;
+ case KeyEvent.VK_END:
+ key = "End";
+ break;
+ case KeyEvent.VK_PAGE_UP:
+ key = "PageUp";
+ break;
+ case KeyEvent.VK_PAGE_DOWN:
+ key = "PageDown";
+ break;
+
+ case KeyEvent.VK_TAB:
+ key = "Tab";
+ break;
+ case KeyEvent.VK_PAUSE:
+ key = "Pause";
+ break;
+ case KeyEvent.VK_SPACE:
+ key = "Space";
+ break;
+ }
+ }
+ sb.append(key);
+ }
+
+ return sb.toString();
+ }
+
+ private boolean is(int a, int b) {
+ return (a & b) == b;
+ }
+
+ @Override
+ public void run() {
+ if (kcs.size() > 0)
+ call(kcs.get(0));
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/.classpath b/plugins/org.eclipse.actf.ai.navigator/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.actf.ai.navigator/.cvsignore b/plugins/org.eclipse.actf.ai.navigator/.cvsignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/plugins/org.eclipse.actf.ai.navigator/.project b/plugins/org.eclipse.actf.ai.navigator/.project
new file mode 100644
index 0000000..9821f58
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.actf.ai.navigator</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.actf.ai.navigator/.settings/org.eclipse.core.resources.prefs b/plugins/org.eclipse.actf.ai.navigator/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..e613298
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Jun 06 23:23:23 JST 2007
+eclipse.preferences.version=1
+encoding//src/messages.properties=8859_1
diff --git a/plugins/org.eclipse.actf.ai.navigator/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.ai.navigator/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..3d3053b
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/META-INF/MANIFEST.MF
@@ -0,0 +1,21 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Eclipse ACTF Navigator Plug-in (Incubation)
+Bundle-SymbolicName: org.eclipse.actf.ai.navigator;singleton:=true
+Bundle-Version: 0.0.1
+Bundle-Activator: org.eclipse.actf.ai.navigator.NavigatorPlugin
+Bundle-Vendor: Eclipse.org
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.ui,
+ org.eclipse.actf.common,
+ org.eclipse.actf.ai.fennec,
+ org.eclipse.actf.util.vocab,
+ org.eclipse.actf.model.ui.editors.ie,
+ org.eclipse.actf.ai.xmlstore,
+ org.eclipse.actf.ai.audio.io,
+ org.eclipse.actf.ai.voice
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.actf.ai.navigator,
+ org.eclipse.actf.ai.navigator.ui,
+ org.eclipse.actf.ai.navigator.views
diff --git a/plugins/org.eclipse.actf.ai.navigator/about.html b/plugins/org.eclipse.actf.ai.navigator/about.html
new file mode 100644
index 0000000..481dbcf
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/about.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>
+<h3>License</h3>
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content").
+Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor’s license
+that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.navigator/build.properties b/plugins/org.eclipse.actf.ai.navigator/build.properties
new file mode 100644
index 0000000..bb3f22a
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/build.properties
@@ -0,0 +1,20 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ about.html,\
+ .,\
+ plugin.xml,\
+ plugin.properties,\
+ plugin_ja.properties,\
+ icons/,\
+ waiting.wav
diff --git a/plugins/org.eclipse.actf.ai.navigator/icons/treex16.gif b/plugins/org.eclipse.actf.ai.navigator/icons/treex16.gif
new file mode 100644
index 0000000..dd54021
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/icons/treex16.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.ai.navigator/icons/treex48.gif b/plugins/org.eclipse.actf.ai.navigator/icons/treex48.gif
new file mode 100644
index 0000000..ffe678f
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/icons/treex48.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.ai.navigator/plugin.properties b/plugins/org.eclipse.actf.ai.navigator/plugin.properties
new file mode 100644
index 0000000..862084d
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/plugin.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Daisuke SATO - initial configuration.
+###############################################################################
+
+DeleteAction.name=Clear metadata cache
+DeleteAction.tip=Clear metadata cache
+
+NavigationTreeView.name=Navigation by Tree View
+UserAnnotation=User Annotation
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.navigator/plugin.xml b/plugins/org.eclipse.actf.ai.navigator/plugin.xml
new file mode 100644
index 0000000..7b4bc16
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/plugin.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension-point id="Navigation" name="Navigation" schema="schema/Navigation.exsd"/>
+ <extension-point id="ScreenReaderController" name="ScreenReaderController" schema="schema/ScreenReaderController.exsd"/>
+ <extension-point id="MediaControl" name="MediaControl" schema="schema/MediaControl.exsd"/>
+ <extension-point id="MetadataCacheCleaner" name="MetadataCacheCleaner" schema="schema/MetadataCacheCleaner.exsd"/>
+ <extension
+ point="org.eclipse.ui.views">
+ <view
+ class="org.eclipse.actf.ai.navigator.views.NavigatorTreeView"
+ icon="icons/treex16.gif"
+ id="org.eclipse.actf.ai.navigator.views.NavigatorTreeView"
+ name="%NavigationTreeView.name"/>
+ </extension>
+ <extension
+ point="org.eclipse.actf.model.ui.editors.ie.WebBrowserEventListener">
+ <listener
+ class="org.eclipse.actf.ai.navigator.impl.WebEventListener"
+ id="org.eclipse.actf.ai.navigator.impl.WebEventListener"/>
+ </extension>
+ <extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ class="org.eclipse.actf.ai.navigator.preferences.UserInfoPreferencePage"
+ id="org.eclipse.actf.ai.navigator.preferences.UserInfoPreferencePage"
+ name="%UserAnnotation"/>
+ </extension>
+ <extension
+ point="org.eclipse.core.runtime.preferences">
+ <initializer class="org.eclipse.actf.ai.navigator.preferences.UserInfoPreferenceInitializer"/>
+ </extension>
+ <extension
+ point="org.eclipse.actf.ai.navigator.MetadataCacheCleaner">
+ <cleaner class="org.eclipse.actf.ai.navigator.impl.NVM3EntryCacheCleaner"/>
+ </extension>
+
+</plugin>
diff --git a/plugins/org.eclipse.actf.ai.navigator/plugin_ja.properties b/plugins/org.eclipse.actf.ai.navigator/plugin_ja.properties
new file mode 100644
index 0000000..d861478
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/plugin_ja.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Daisuke SATO - initial configuration.
+###############################################################################
+
+DeleteAction.name=\u30e1\u30bf\u30c7\u30fc\u30bf\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u524a\u9664
+DeleteAction.tip=\u30e1\u30bf\u30c7\u30fc\u30bf\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u524a\u9664\u3057\u307e\u3059
+
+NavigationTreeView.name=\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3\u30fb\u30c4\u30ea\u30fc\u30d3\u30e5\u30fc
+UserAnnotation=\u6ce8\u91c8
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.navigator/schema/MediaControl.exsd b/plugins/org.eclipse.actf.ai.navigator/schema/MediaControl.exsd
new file mode 100644
index 0000000..7d11d9d
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/schema/MediaControl.exsd
@@ -0,0 +1,109 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.actf.ai.navigator">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.actf.ai.navigator" id="MediaControl" name="MediaControl"/>
+ </appInfo>
+ <documentation>
+ [Enter description of this extension point.]
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="controller"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="controller">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn="org.eclipse.actf.ai.navigator.IMediaControl"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+ Copyright (c) 2007 IBM Corporation and others.<br>
+All rights reserved. This program and the accompanying materials are made
+available under the terms of the Eclipse Public License v1.0 which accompanies
+this distribution, and is available at <a
+href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/plugins/org.eclipse.actf.ai.navigator/schema/MetadataCacheCleaner.exsd b/plugins/org.eclipse.actf.ai.navigator/schema/MetadataCacheCleaner.exsd
new file mode 100644
index 0000000..3914cac
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/schema/MetadataCacheCleaner.exsd
@@ -0,0 +1,109 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.actf.ai.navigator">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.actf.ai.navigator" id="MetadataCacheClear" name="MetadataCacheClear"/>
+ </appInfo>
+ <documentation>
+ [Enter description of this extension point.]
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="cleaner"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="cleaner">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn="org.eclipse.actf.ai.navigator.IMetadataCacheCleaner"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+ Copyright (c) 2007 IBM Corporation and others.<br>
+All rights reserved. This program and the accompanying materials are made
+available under the terms of the Eclipse Public License v1.0 which accompanies
+this distribution, and is available at <a
+href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/plugins/org.eclipse.actf.ai.navigator/schema/Navigation.exsd b/plugins/org.eclipse.actf.ai.navigator/schema/Navigation.exsd
new file mode 100644
index 0000000..9041d45
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/schema/Navigation.exsd
@@ -0,0 +1,109 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.actf.ai.navigator">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.actf.ai.navigator" id="Navigation" name="Navigation"/>
+ </appInfo>
+ <documentation>
+ [Enter description of this extension point.]
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="manipulator"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="manipulator">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn="org.eclipse.actf.ai.navigator.IManipulator"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+ Copyright (c) 2007 IBM Corporation and others.<br>
+All rights reserved. This program and the accompanying materials are made
+available under the terms of the Eclipse Public License v1.0 which accompanies
+this distribution, and is available at <a
+href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/plugins/org.eclipse.actf.ai.navigator/schema/ScreenReaderController.exsd b/plugins/org.eclipse.actf.ai.navigator/schema/ScreenReaderController.exsd
new file mode 100644
index 0000000..4e7894d
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/schema/ScreenReaderController.exsd
@@ -0,0 +1,109 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.actf.ai.navigator">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.actf.ai.navigator" id="ScreenReaderController" name="ScreenReaderController"/>
+ </appInfo>
+ <documentation>
+ [Enter description of this extension point.]
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="controller"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="controller">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn="org.eclipse.actf.ai.navigator.IScreenReaderControl"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+ Copyright (c) 2007 IBM Corporation and others.<br>
+All rights reserved. This program and the accompanying materials are made
+available under the terms of the Eclipse Public License v1.0 which accompanies
+this distribution, and is available at <a
+href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/messages.properties b/plugins/org.eclipse.actf.ai.navigator/src/messages.properties
new file mode 100644
index 0000000..de8d0fd
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/messages.properties
@@ -0,0 +1,37 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Daisuke SATO - initial configuration.
+###############################################################################
+
+NavigatorTreeView.property=Property
+NavigatorTreeView.value=Value
+
+DialogOpenURL.Open_URL_2=Open a page
+
+IManipulator.TreeNavigaion=Tree Navigation
+IManipulator.FormInput=Form Input
+IManipulator.Input=Input
+FormInputDialog.Textarea=Text Area Input
+FormInputDialog.Password=Password Input
+FormInputDialog.Text=Text Input
+FormInputDialog.Search=Find Text
+FormInputDialog.Forward=&Forward
+FormInputDialog.Backward=&Backward
+FormInputDialog.Exact=&Case Sensitive
+
+FormSelectDialog.Single=Select an option
+FormSelectDialog.Multiple=Select options
+
+AccessKeyListDialog.Title=Access Key List
+
+AltInputDialog.Text=Alt Text Input
+
+UserInfo.PREFERENCES_NAME=User Annotation Preferences
+UserInfo.SAVE_ANNOTATION=&Save annotation automatically
+UserInfo.REFRESH_TREEVIEW=&Refresh Tree View automatically
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/messages_ja.properties b/plugins/org.eclipse.actf.ai.navigator/src/messages_ja.properties
new file mode 100644
index 0000000..0bc0958
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/messages_ja.properties
@@ -0,0 +1,39 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Daisuke SATO - initial configuration.
+###############################################################################
+
+NavigatorTreeView.property=\u30d7\u30ed\u30d1\u30c6\u30a3
+NavigatorTreeView.value=\u5024
+
+DialogOpenURL.Open_URL_2=\u30da\u30fc\u30b8\u3092\u958b\u304f
+
+IManipulator.TreeNavigaion=\u30c4\u30ea\u30fc\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3
+IManipulator.FormInput=\u30d5\u30a9\u30fc\u30e0\u5165\u529b
+IManipulator.Input=\u5165\u529b
+
+FormInputDialog.Textarea=\u30c6\u30ad\u30b9\u30c8\u30a8\u30ea\u30a2\u306e\u5165\u529b
+FormInputDialog.Password=\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u5165\u529b
+FormInputDialog.Text=\u30c6\u30ad\u30b9\u30c8\u306e\u5165\u529b
+
+FormInputDialog.Search=\u6587\u5b57\u5217\u306e\u691c\u7d22
+FormInputDialog.Forward=\u4e0b\u3078(&F)
+FormInputDialog.Backward=\u4e0a\u3078(&B)
+FormInputDialog.Exact=\u5927\u6587\u5b57\u3068\u5c0f\u6587\u5b57\u3092\u533a\u5225\u3059\u308b(&C)
+
+FormSelectDialog.Single=\u9805\u76ee\u306e\u9078\u629e
+FormSelectDialog.Multiple=\u9805\u76ee\u306e\u8907\u6570\u9078\u629e
+
+AccessKeyListDialog.Title=\u30a2\u30af\u30bb\u30b9\u30ad\u30fc\u306e\u30ea\u30b9\u30c8
+
+AltInputDialog.Text=\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u306e\u5165\u529b
+
+UserInfo.PREFERENCES_NAME=\u6ce8\u91c8\u306e\u8a2d\u5b9a
+UserInfo.SAVE_ANNOTATION=\u81ea\u52d5\u7684\u306b\u6ce8\u91c8\u3092\u4fdd\u5b58\u3059\u308b(&S)
+UserInfo.REFRESH_TREEVIEW=\u81ea\u52d5\u7684\u306b\u30c4\u30ea\u30fc\u30d3\u30e5\u30fc\u3092\u66f4\u65b0\u3059\u308b(&R)
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IBrowserControl.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IBrowserControl.java
new file mode 100644
index 0000000..cd469fc
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IBrowserControl.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator;
+
+
+public interface IBrowserControl {
+ void forward();
+ void backward();
+
+ void importMetadata();
+ void exportAllMetadata();
+
+ void openTab();
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IManipulator.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IManipulator.java
new file mode 100644
index 0000000..3f2eee6
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IManipulator.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator;
+
+
+public interface IManipulator {
+ public static class Mode {
+ public final String name;
+ public final int code;
+ private Mode(String name, int code) {
+ this.name = name;
+ this.code = code;
+ }
+ }
+ int TREE_NAVIGATION_MODE_CODE = 0;
+ Mode TREE_NAVIGATION_MODE = new Mode(Messages.getString("IManipulator.TreeNavigaion"), TREE_NAVIGATION_MODE_CODE); //$NON-NLS-1$
+ int FORM_INPUT_MODE_CODE = 1;
+ Mode FORM_INPUT_MODE = new Mode(Messages.getString("IManipulator.FormInput"), FORM_INPUT_MODE_CODE); //$NON-NLS-1$
+ int KEYHOOK_DISABLED_MODE_CODE = 2;
+ Mode KEYHOOK_DISABLED_MODE = new Mode(Messages.getString("IManipulator.Input"), KEYHOOK_DISABLED_MODE_CODE); //$NON-NLS-1$
+
+ void setBrowserControl(IBrowserControl browserControl);
+ void setNavigator(INavigatorUI navigatorUI);
+ void setMode(Mode mode);
+ void dispose();
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IMediaControl.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IMediaControl.java
new file mode 100644
index 0000000..7c3e0df
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IMediaControl.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator;
+
+import org.eclipse.actf.ai.fennec.treemanager.ISoundControl;
+import org.eclipse.actf.ai.fennec.treemanager.IVideoControl;
+import org.eclipse.actf.ai.voice.IVoice;
+import org.eclipse.actf.model.IWebBrowserACTF;
+
+
+
+
+public interface IMediaControl {
+
+ int TOGGLE_FAIL = 1;
+
+ int STATUS_ON = 2;
+
+ int STATUS_OFF = 4;
+
+ int STATUS_NOT_AVAILABLE = 8;
+
+ public interface IHandle {
+ IVideoControl getVideoControl();
+ ISoundControl getSoundControl();
+ IWebBrowserACTF getWebBrowser();
+ IVoice getVoice();
+ }
+
+ void start(IHandle handle);
+
+ void dispose(IHandle handle);
+
+ int toggleEnable();
+
+ boolean isAvailable();
+
+ boolean toggleViewShowing();
+
+ boolean isEnabled();
+
+ void speakInfo(boolean flush);
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IMetadataCacheCleaner.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IMetadataCacheCleaner.java
new file mode 100644
index 0000000..021e6fc
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IMetadataCacheCleaner.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator;
+
+
+public interface IMetadataCacheCleaner {
+ void clearCache();
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/INavigatorUI.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/INavigatorUI.java
new file mode 100644
index 0000000..454d3aa
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/INavigatorUI.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator;
+
+public interface INavigatorUI {
+ // Tree Navigation Mode
+ void muteMedia();
+ void volumeDownMedia();
+ void volumeUpMedia();
+
+ void minimalVolumeDownMedia();
+ void minimalVolumeUpMedia();
+
+ void previousTrack();
+ void nextTrack();
+ void stopMedia();
+ void playMedia();
+ void pauseMedia();
+ void fastReverse();
+ void fastForward();
+
+ void stopSpeak();
+
+ void speechSpeedUp();
+ void speechSpeedDown();
+
+ void treeLeft();
+ void treeRight();
+ void treeUp();
+ void treeDown();
+
+ void treeTop();
+ void treeBottom();
+
+ void traverseNodeUp();
+ void traverseNodeDown();
+ void traverseDown();
+ void traverseUp();
+
+ void click();
+ void speakCurrentStatus();
+ void speakMediaStatus();
+
+ void nextHeader();
+ void previousHeader();
+
+ void nextInputable();
+ void previousInputable();
+
+ void nextLink();
+ void previousLink();
+
+ void nextObject();
+ void previousObject();
+
+ void cellLeft();
+ void cellRight();
+ void cellUp();
+ void cellDown();
+
+ // Browser control
+ void navigateRefresh();
+ // void goForward();
+ // void goBackward();
+
+ // select NVM3;
+ void selectNextNVM3();
+
+ // Form Mode;
+ void exitFormMode();
+ void submitForm();
+
+ // browser address.
+ void enterBrowserAddress();
+
+ // tab operations.
+ void closeTab();
+
+ void searchNext();
+ void searchPrevious();
+
+ void nextHeader1();
+ void previousHeader1();
+ void nextHeader2();
+ void previousHeader2();
+ void nextHeader3();
+ void previousHeader3();
+ void nextHeader4();
+ void previousHeader4();
+ void nextHeader5();
+ void previousHeader5();
+ void nextHeader6();
+ void previousHeader6();
+
+ void nextListItem();
+ void previousListItem();
+ void nextBlock();
+ void previousBlock();
+
+ void nextMedia();
+ void previousMedia();
+
+ void launchBrowser();
+ void toggleLeftViewsShowing();
+ void speakAll();
+
+ void exportMetadata();
+
+ void jumpToAccessKey(char key);
+ void showAccessKeyList();
+
+ // force start.
+ void forceRestart();
+ void toggleDescriptionEnable();
+ void nextTab();
+ void prevTab();
+
+ // User Annotation Extension.
+ void nextAlterable();
+ void previousAlterable();
+ void editAltText();
+ void makeLandmark();
+ void saveUserInfo();
+ void removeUserInfo();
+
+ // repairt
+ void repairFlash();
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IScreenReaderControl.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IScreenReaderControl.java
new file mode 100644
index 0000000..248a54e
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/IScreenReaderControl.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator;
+
+import org.eclipse.actf.model.IWebBrowserACTF;
+
+
+
+public interface IScreenReaderControl {
+ boolean isAvailable();
+
+ void screenReaderOn();
+ void screenReaderOff();
+ void takeBackControl(IWebBrowserACTF browser);
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/Messages.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/Messages.java
new file mode 100644
index 0000000..ea41664
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/Messages.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+
+public class Messages {
+ private static final String BUNDLE_NAME = "messages"; //$NON-NLS-1$
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
+
+ private Messages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/NavigatorPlugin.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/NavigatorPlugin.java
new file mode 100644
index 0000000..5e6d267
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/NavigatorPlugin.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator;
+
+import org.eclipse.actf.ai.navigator.extension.MetadataCacheCleanerExtension;
+import org.eclipse.actf.ai.navigator.views.NavigatorTreeView;
+import org.eclipse.actf.ai.voice.internal.AbstractPreferenceUIPlugin;
+import org.eclipse.jface.action.IMenuManager;
+import org.osgi.framework.BundleContext;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class NavigatorPlugin extends AbstractPreferenceUIPlugin {
+
+ public static final String ID = "org.eclipse.actf.ai.navigator";
+ //The shared instance.
+ private static NavigatorPlugin plugin;
+ public static IMenuManager menuManager;
+
+ /**
+ * The constructor.
+ */
+ public NavigatorPlugin() {
+ plugin = this;
+ }
+
+ /**
+ * This method is called upon plug-in activation
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /**
+ * This method is called when the plug-in is stopped
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Returns the shared instance.
+ */
+ public static NavigatorPlugin getDefault() {
+ return plugin;
+ }
+
+ private INavigatorUI navigatorUI;
+
+ public void setNavigatorUI(INavigatorUI navigatorUI) {
+ this.navigatorUI = navigatorUI;
+ }
+
+
+ public INavigatorUI getNavigatorUI() {
+ return navigatorUI;
+ }
+
+ private NavigatorTreeView navigatorTreeView;
+
+ public void setNavigatorTreeView(NavigatorTreeView navigatorTreeView) {
+ this.navigatorTreeView = navigatorTreeView;
+ }
+
+ public NavigatorTreeView getNavigatorTreeView() {
+ return navigatorTreeView;
+ }
+
+ public void clearMetadataCache(){
+ MetadataCacheCleanerExtension.clearCache();
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/actions/DeleteCacheAction.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/actions/DeleteCacheAction.java
new file mode 100644
index 0000000..191b430
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/actions/DeleteCacheAction.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator.actions;
+
+import org.eclipse.actf.ai.navigator.extension.MetadataCacheCleanerExtension;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+
+public class DeleteCacheAction implements IWorkbenchWindowActionDelegate {
+
+ private IWorkbenchWindow window;
+
+ public void init(IWorkbenchWindow window) {
+ this.window = window;
+ }
+
+ public void dispose() {
+
+ }
+
+ public void run(IAction action) {
+ MetadataCacheCleanerExtension.clearCache();
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/broker/Mirror.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/broker/Mirror.java
new file mode 100644
index 0000000..02f6a84
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/broker/Mirror.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.broker;
+
+
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class Mirror {
+ final private Class class1;
+ final private Object object;
+
+ public Object getObject() {
+ return object;
+ }
+
+ private Class[] parseMethodSignature(String params) {
+ String[] paramArray;
+
+ paramArray = params.split(", *");
+ Class[] cs = new Class[paramArray.length];
+ try {
+ for (int i = 0; i < paramArray.length; i++) {
+ if ("int".equals(paramArray[i])) {
+ cs[i] = java.lang.Integer.TYPE;
+ } else if ("short".equals(paramArray[i])) {
+ cs[i] = java.lang.Short.TYPE;
+ } else if ("long".equals(paramArray[i])) {
+ cs[i] = java.lang.Long.TYPE;
+ } else if ("char".equals(paramArray[i])) {
+ cs[i] = java.lang.Character.TYPE;
+ } else if ("boolean".equals(paramArray[i])) {
+ cs[i] = java.lang.Boolean.TYPE;
+ } else if ("byte".equals(paramArray[i])) {
+ cs[i] = java.lang.Byte.TYPE;
+ } else if ("float".equals(paramArray[i])) {
+ cs[i] = java.lang.Float.TYPE;
+ } else if ("double".equals(paramArray[i])) {
+ cs[i] = java.lang.Double.TYPE;
+ } else {
+ cs[i] = Class.forName(paramArray[i], true, class1.getClassLoader());
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+
+ return cs;
+ }
+
+ public Method getMethod(String signature) {
+ String name;
+ Class[] params = null;
+ int posParam = signature.indexOf('(');
+ if (posParam == -1) {
+ name = signature;
+ } else {
+ name = signature.substring(0, posParam);
+ int posParamEnd = signature.lastIndexOf(')');
+ if (posParamEnd == -1) return null;
+ params = parseMethodSignature(signature.substring(posParam + 1, posParamEnd));
+ if (params == null) return null;
+ }
+
+ Method m = null;
+ for (Class c = class1; c != null; c = c.getSuperclass()) {
+ try {
+ if (params == null) {
+ Method[] ms = c.getDeclaredMethods();
+ for (int i = 0; i < ms.length; i++) {
+ if (name.equals(ms[i].getName())) {
+ m = ms[i];
+ }
+ }
+ } else {
+ m = c.getDeclaredMethod(name, params);
+ }
+ } catch (SecurityException e) {
+ continue;
+ } catch (NoSuchMethodException e) {
+ continue;
+ }
+ if (m != null) {
+ m.setAccessible(true);
+ return m;
+ }
+ }
+
+ return null;
+ }
+
+ public Object invoke(String signature, Object[] params) throws Exception {
+ Method m = getMethod(signature);
+ return m.invoke(object, params);
+ }
+
+ public Field getField(String name) {
+ Field f;
+
+ for (Class c = class1; c != null; c = c.getSuperclass()) {
+ try {
+ f = c.getDeclaredField(name);
+ } catch (SecurityException e) {
+ continue;
+ } catch (NoSuchFieldException e) {
+ continue;
+ }
+ if (f != null) {
+ f.setAccessible(true);
+ return f;
+ }
+ }
+ return null;
+ }
+
+ public Object getFieldObject(String name) throws IllegalAccessException {
+ return getField(name).get(object);
+ }
+
+ static private boolean isParamAccept(Class cp, Class c) {
+ if (cp.isAssignableFrom(c)) return true;
+
+ if ((java.lang.Integer.TYPE == cp)
+ && java.lang.Integer.class.equals(c))
+ return true;
+ if ((java.lang.Short.TYPE == cp)
+ && java.lang.Short.class.equals(c))
+ return true;
+ if ((java.lang.Long.TYPE == cp)
+ && java.lang.Long.class.equals(c))
+ return true;
+ if ((java.lang.Character.TYPE == cp)
+ && java.lang.Character.class.equals(c))
+ return true;
+ if ((java.lang.Boolean.TYPE == cp)
+ && java.lang.Boolean.class.equals(c))
+ return true;
+ if ((java.lang.Byte.TYPE == cp)
+ && java.lang.Byte.class.equals(c))
+ return true;
+ if ((java.lang.Float.TYPE == cp)
+ && java.lang.Float.class.equals(c))
+ if ((java.lang.Double.TYPE == cp)
+ && java.lang.Double.class.equals(c))
+ return true;
+
+ return false;
+ }
+
+ public Constructor findConstructor(Object[] params) {
+ Constructor[] cs = class1.getDeclaredConstructors();
+
+ nextConstructor:
+ for (int i = 0; i < cs.length; i++) {
+ Class[] cParams = cs[i].getParameterTypes();
+ if (params == null) {
+ if (cParams.length == 0) return cs[i];
+ continue nextConstructor;
+ }
+ if (cParams.length != params.length) continue nextConstructor;;
+ for (int j = 0; j < params.length; j++) {
+ if (!isParamAccept(cParams[j], params[j].getClass())) continue nextConstructor;
+ }
+ return cs[i];
+ }
+
+ return null;
+ }
+
+ public Object newInstance(Object[] params)
+ throws InvocationTargetException, IllegalAccessException, InstantiationException {
+ return findConstructor(params).newInstance(params);
+ }
+
+ public Mirror(String className) throws ClassNotFoundException {
+ this.class1 = Class.forName(className);
+ this.object = null;
+ }
+
+ public Mirror(Class cls) {
+ this.class1 = cls;
+ this.object = null;
+ }
+
+ public Mirror(Object object) {
+ this.class1 = object.getClass();
+ this.object = object;
+ }
+
+ public Mirror(String className, Object[] params)
+ throws ClassNotFoundException,
+ InvocationTargetException, IllegalAccessException, InstantiationException {
+ this.class1 = Class.forName(className);
+ this.object = newInstance(params);
+ }
+
+ public static void main(String[] args) throws Exception {
+ Mirror miS = new Mirror("java.lang.String");
+
+ System.out.println("java.lang.String.charAt:"
+ + miS.getMethod("charAt"));
+ System.out.println("java.lang.String.indexOf(int,int):"
+ + miS.getMethod("indexOf(int, int)"));
+
+ Mirror miS2 = new Mirror("java.lang.String", new Object[]{"test string"});
+ System.out.println("String instanciation test:" + miS2.getObject());
+
+ Mirror miI = new Mirror("java.lang.Integer", new Object[]{new Integer(100)});
+ System.out.println("Integer instanciation test:" + miI.getObject());
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/broker/RequestBroker.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/broker/RequestBroker.java
new file mode 100644
index 0000000..c912322
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/broker/RequestBroker.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator.broker;
+
+import java.lang.reflect.Method;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeManager;
+import org.eclipse.actf.ai.navigator.impl.NavigatorImpl;
+import org.eclipse.actf.ai.navigator.impl.WebEventListener;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.actf.util.timer.Yield;
+
+
+public class RequestBroker {
+ public static final int SHOW_STATUS = 100;
+
+ public static final int EVENT_NEW_URL = 101;
+
+ public static final int EVENT_NEWPAGE_READY = 1000;
+
+ public static final int EVENT_LOAD_STARTING = 1001;
+
+ public static final int EVENT_WAIT_FOR_PROCESSING = 1200;
+
+ public static final int EVENT_INFORMATION_UPDATED = 1201;
+
+ public static final int EVENT_TREE_MODIFIED = 1202;
+
+ public static final int EVENT_NOTIFICATION = 1203;
+
+ public static final int EVENT_ALERT_MODAL = 1204;
+
+ public static final int EVENT_AUTOMATIC_TRANSITION = 1205;
+
+ private final WebEventListener webEventListener;
+ private NavigatorImpl navigator;
+ private IWebBrowserACTF webBrowser;
+
+ private boolean enabled;
+
+ private Method registerRequestBrokerMethod;
+ private Method sendEventMethod;
+
+ public void setNavigator(NavigatorImpl navigator, IWebBrowserACTF webBrowser) {
+ this.navigator = navigator;
+ this.webBrowser = webBrowser;
+ }
+
+ private void registerProxy() {
+ if (!enabled) return;
+ try {
+ Object o = Thread.currentThread();
+ registerRequestBrokerMethod.invoke(o, new Object[] { this });
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void sendEvent(int id, Object param) {
+ if (!enabled) return;
+ System.err.println("EventRP:" + id + " Param:" + param);
+ try {
+ Object o = Thread.currentThread();
+ sendEventMethod.invoke(o, new Object[] { new Integer(id), param });
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void newPageReady() {
+ sendEvent(EVENT_NEW_URL, webBrowser.getURL());
+ sendEvent(EVENT_NEWPAGE_READY, null);
+ }
+
+ public Object invokeNavigator(String signature, Object[] args) throws Exception {
+ Mirror m = new Mirror(navigator);
+ Method method = m.getMethod(signature);
+ return Yield.syncInvoke(method, navigator, args);
+ }
+
+ public Object invokeTreeManager(String signature, Object[] args) throws Exception {
+ ITreeManager treeManager = navigator.getTreeManager();
+ Mirror m = new Mirror(treeManager);
+ Method method = m.getMethod(signature);
+ return Yield.syncInvoke(method, treeManager, args);
+ }
+
+ public Object invokeITreeItem(Object item, String signature, Object[] args) throws Exception {
+ Mirror m = new Mirror(item);
+ Method method = m.getMethod(signature);
+ return Yield.syncInvoke(method, item, args);
+ }
+
+ private void initialize() {
+ Object o = Thread.currentThread();
+ Class c = o.getClass();
+ try {
+ registerRequestBrokerMethod = c.getMethod("registerRequestBroker", new Class[] { Object.class });
+ sendEventMethod = c.getMethod("sendEvent", new Class[] { java.lang.Integer.TYPE, Object.class });
+ enabled = true;
+ } catch (NoSuchMethodException e) {
+ enabled = false;
+ }
+ }
+
+ public RequestBroker(WebEventListener webEventListener) {
+ this.webEventListener = webEventListener;
+ initialize();
+ registerProxy();
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/ManipulatorExtension.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/ManipulatorExtension.java
new file mode 100644
index 0000000..93fad37
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/ManipulatorExtension.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.extension;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.actf.ai.navigator.IBrowserControl;
+import org.eclipse.actf.ai.navigator.IManipulator;
+import org.eclipse.actf.ai.navigator.INavigatorUI;
+import org.eclipse.actf.ai.navigator.NavigatorPlugin;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.Platform;
+
+
+
+
+public class ManipulatorExtension {
+ private static final String TAG_MANIPULATOR = "manipulator";
+ private static final String ATTR_CLASS = "class";
+
+ private static ManipulatorExtension[] cachedExtensions;
+
+ public static ManipulatorExtension[] getExtensions() {
+ if (cachedExtensions != null) return cachedExtensions;
+
+ IExtension[] extensions = Platform.getExtensionRegistry()
+ .getExtensionPoint(NavigatorPlugin.ID, "Navigation")
+ .getExtensions();
+ List<ManipulatorExtension> l = new ArrayList<ManipulatorExtension>();
+ for (int i = 0; i < extensions.length; i++) {
+ IConfigurationElement[] configElements =
+ extensions[i].getConfigurationElements();
+ for (int j = 0; j < configElements.length; j++) {
+ ManipulatorExtension ex = parseExtension(configElements[j], l.size());
+ if (ex != null) l.add(ex);
+ }
+ }
+ cachedExtensions = l.toArray(new ManipulatorExtension[l.size()]);
+ return cachedExtensions;
+ }
+
+ private static ManipulatorExtension parseExtension(IConfigurationElement configElement, int idx) {
+ if (!configElement.getName().equals(TAG_MANIPULATOR))
+ return null;
+ try {
+ return new ManipulatorExtension(configElement);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ public static void disposeExtensions() {
+ if (cachedExtensions == null) return;
+ for (int i = 0; i < cachedExtensions.length; i++) {
+ cachedExtensions[i].dispose();
+ }
+ cachedExtensions = null;
+ }
+
+ public static void setBrowserControl(IBrowserControl browserControl) {
+ ManipulatorExtension[] exs = getExtensions();
+ if (exs == null) return;
+ for (int i = 0; i < exs.length; i++) {
+ exs[i].getManipulator().setBrowserControl(browserControl);
+ }
+ }
+
+ public static void setNavigator(INavigatorUI navigatorUI) {
+ ManipulatorExtension[] exs = getExtensions();
+ if (exs == null) return;
+ for (int i = 0; i < exs.length; i++) {
+ exs[i].getManipulator().setNavigator(navigatorUI);
+ }
+ }
+
+ public static void setMode(IManipulator.Mode mode) {
+ ManipulatorExtension[] exs = getExtensions();
+ if (exs == null) return;
+ for (int i = 0; i < exs.length; i++) {
+ exs[i].getManipulator().setMode(mode);
+ }
+ }
+
+ private final IConfigurationElement configElement;
+ private IManipulator manipulator;
+
+ private ManipulatorExtension(IConfigurationElement configElement) {
+ this.configElement = configElement;
+ }
+
+ private IManipulator getManipulator() {
+ if (manipulator != null) return manipulator;
+ try {
+ manipulator = (IManipulator) configElement.createExecutableExtension(ATTR_CLASS);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return manipulator;
+ }
+
+ private void dispose() {
+ if (manipulator == null) return;
+ manipulator.dispose();
+ manipulator = null;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/MediaControlExtension.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/MediaControlExtension.java
new file mode 100644
index 0000000..75869b3
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/MediaControlExtension.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.extension;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.actf.ai.navigator.IMediaControl;
+import org.eclipse.actf.ai.navigator.NavigatorPlugin;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.Platform;
+
+
+
+
+public class MediaControlExtension {
+ private static final String TAG_CONTROLLER = "controller";
+
+ private static final String ATTR_CLASS = "class";
+
+ private static MediaControlExtension[] cachedExtensions;
+
+ public static MediaControlExtension[] getExtensions() {
+ if (cachedExtensions != null)
+ return cachedExtensions;
+
+ IExtension[] extensions = Platform.getExtensionRegistry().getExtensionPoint(NavigatorPlugin.ID, "MediaControl")
+ .getExtensions();
+ List<MediaControlExtension> l = new ArrayList<MediaControlExtension>();
+ for (int i = 0; i < extensions.length; i++) {
+ IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
+ for (int j = 0; j < configElements.length; j++) {
+ MediaControlExtension ex = parseExtension(configElements[j], l.size());
+ if (ex != null)
+ l.add(ex);
+ }
+ }
+ cachedExtensions = l.toArray(new MediaControlExtension[l.size()]);
+ return cachedExtensions;
+ }
+
+ private static MediaControlExtension parseExtension(IConfigurationElement configElement, int idx) {
+ if (!configElement.getName().equals(TAG_CONTROLLER))
+ return null;
+ try {
+ return new MediaControlExtension(configElement);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ public static void disposeExtensions() {
+ if (cachedExtensions == null)
+ return;
+ for (int i = 0; i < cachedExtensions.length; i++) {
+ cachedExtensions[i].dispose();
+ }
+ cachedExtensions = null;
+ }
+
+ public static void start(IMediaControl.IHandle handle) {
+ MediaControlExtension[] exs = getExtensions();
+ if (exs == null)
+ return;
+ for (int i = 0; i < exs.length; i++) {
+ exs[i].getMediaControl().start(handle);
+ }
+ }
+
+ public static void doDispose(IMediaControl.IHandle handle) {
+ MediaControlExtension[] exs = getExtensions();
+ if (exs == null)
+ return;
+ for (int i = 0; i < exs.length; i++) {
+ exs[i].getMediaControl().dispose(handle);
+ }
+ }
+
+ private final IConfigurationElement configElement;
+
+ private IMediaControl controller;
+
+ private MediaControlExtension(IConfigurationElement configElement) {
+ this.configElement = configElement;
+ }
+
+ private IMediaControl getMediaControl() {
+ if (controller != null)
+ return controller;
+ try {
+ controller = (IMediaControl) configElement.createExecutableExtension(ATTR_CLASS);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return controller;
+ }
+
+ private void dispose() {
+ if (controller == null)
+ return;
+ controller = null;
+ }
+
+ public static int toggleEnable() {
+ MediaControlExtension[] exs = getExtensions();
+ int result = 0;
+ if (exs == null)
+ return IMediaControl.TOGGLE_FAIL;
+ for (int i = 0; i < exs.length; i++) {
+ result |= exs[i].getMediaControl().toggleEnable();
+ }
+ return result;
+ }
+
+ public static boolean isAvailable(){
+ MediaControlExtension[] exs = getExtensions();
+ if (exs == null)
+ return false;
+
+ boolean ret = false;
+ for (int i = 0; i < exs.length; i++) {
+ ret |= exs[i].getMediaControl().isAvailable();
+ }
+ return ret;
+ }
+
+ public static boolean toggleViewShowing() {
+ MediaControlExtension[] exs = getExtensions();
+ boolean result = true;
+ for (int i = 0; i < exs.length; i++) {
+ result = exs[i].getMediaControl().toggleViewShowing() && result;
+ }
+ return result;
+ }
+
+ public static boolean isEnabled() {
+ MediaControlExtension[] exs = getExtensions();
+ if (exs == null)
+ return false;
+
+ boolean ret = false;
+ for (int i = 0; i < exs.length; i++) {
+ ret |= exs[i].getMediaControl().isEnabled();
+ }
+ return ret;
+ }
+
+ public static void speakInfo(boolean flush) {
+ MediaControlExtension[] exs = getExtensions();
+ if (exs == null)
+ return;
+
+ for (int i = 0; i < exs.length; i++) {
+ exs[i].getMediaControl().speakInfo(flush);
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/MetadataCacheCleanerExtension.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/MetadataCacheCleanerExtension.java
new file mode 100644
index 0000000..c0f35e0
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/MetadataCacheCleanerExtension.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.extension;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.actf.ai.navigator.IMetadataCacheCleaner;
+import org.eclipse.actf.ai.navigator.NavigatorPlugin;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.Platform;
+
+
+
+
+public class MetadataCacheCleanerExtension {
+ private static final String TAG_CLEANER = "cleaner";
+ private static final String ATTR_CLASS = "class";
+
+ private static MetadataCacheCleanerExtension[] cachedExtensions;
+
+ public static MetadataCacheCleanerExtension[] getExtensions() {
+ if (cachedExtensions != null) return cachedExtensions;
+
+ IExtension[] extensions = Platform.getExtensionRegistry()
+ .getExtensionPoint(NavigatorPlugin.ID, "MetadataCacheCleaner")
+ .getExtensions();
+ List<MetadataCacheCleanerExtension> l = new ArrayList<MetadataCacheCleanerExtension>();
+ for (int i = 0; i < extensions.length; i++) {
+ IConfigurationElement[] configElements =
+ extensions[i].getConfigurationElements();
+ for (int j = 0; j < configElements.length; j++) {
+ MetadataCacheCleanerExtension ex = parseExtension(configElements[j], l.size());
+ if (ex != null) l.add(ex);
+ }
+ }
+ cachedExtensions = l.toArray(new MetadataCacheCleanerExtension[l.size()]);
+ return cachedExtensions;
+ }
+
+ private static MetadataCacheCleanerExtension parseExtension(IConfigurationElement configElement, int idx) {
+ if (!configElement.getName().equals(TAG_CLEANER))
+ return null;
+ try {
+ return new MetadataCacheCleanerExtension(configElement);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ public static void disposeExtensions() {
+ if (cachedExtensions == null) return;
+ for (int i = 0; i < cachedExtensions.length; i++) {
+ cachedExtensions[i].dispose();
+ }
+ cachedExtensions = null;
+ }
+
+ public static void clearCache(){
+ MetadataCacheCleanerExtension[] exs = getExtensions();
+ if (exs == null) return;
+ for (int i = 0; i < exs.length; i++) {
+ exs[i].getMetadataCacheCleaner().clearCache();
+ }
+ }
+
+ private final IConfigurationElement configElement;
+ private IMetadataCacheCleaner cleaner;
+
+ private MetadataCacheCleanerExtension(IConfigurationElement configElement) {
+ this.configElement = configElement;
+ }
+
+ private IMetadataCacheCleaner getMetadataCacheCleaner() {
+ if (cleaner != null) return cleaner;
+ try {
+ cleaner = (IMetadataCacheCleaner) configElement.createExecutableExtension(ATTR_CLASS);
+ } catch (Exception e) {
+ }
+ return cleaner;
+ }
+
+ private void dispose() {
+ if (cleaner == null) return;
+ cleaner = null;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/ScreenReaderExtension.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/ScreenReaderExtension.java
new file mode 100644
index 0000000..1c71c4f
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/extension/ScreenReaderExtension.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.extension;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.actf.ai.navigator.IScreenReaderControl;
+import org.eclipse.actf.ai.navigator.NavigatorPlugin;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.Platform;
+
+
+
+
+public class ScreenReaderExtension {
+ private static final String TAG_CONTROLLER = "controller";
+ private static final String ATTR_CLASS = "class";
+
+ private static ScreenReaderExtension[] cachedExtensions;
+
+ public static ScreenReaderExtension[] getExtensions() {
+ if (cachedExtensions != null) return cachedExtensions;
+
+ IExtension[] extensions = Platform.getExtensionRegistry()
+ .getExtensionPoint(NavigatorPlugin.ID, "ScreenReaderController")
+ .getExtensions();
+ List<ScreenReaderExtension> l = new ArrayList<ScreenReaderExtension>();
+ for (int i = 0; i < extensions.length; i++) {
+ IConfigurationElement[] configElements =
+ extensions[i].getConfigurationElements();
+ for (int j = 0; j < configElements.length; j++) {
+ ScreenReaderExtension ex = parseExtension(configElements[j], l.size());
+ if (ex != null) l.add(ex);
+ }
+ }
+ cachedExtensions = l.toArray(new ScreenReaderExtension[l.size()]);
+ return cachedExtensions;
+ }
+
+ private static ScreenReaderExtension parseExtension(IConfigurationElement configElement, int idx) {
+ if (!configElement.getName().equals(TAG_CONTROLLER))
+ return null;
+ try {
+ return new ScreenReaderExtension(configElement);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ public static void disposeExtensions() {
+ if (cachedExtensions == null) return;
+ for (int i = 0; i < cachedExtensions.length; i++) {
+ cachedExtensions[i].dispose();
+ }
+ cachedExtensions = null;
+ }
+
+ public static void screenReaderOn() {
+ ScreenReaderExtension[] exs = getExtensions();
+ if (exs == null) return;
+ for (int i = 0; i < exs.length; i++) {
+ exs[i].getScreenReaderControl().screenReaderOn();
+ }
+ }
+
+ public static void screenReaderOff() {
+ ScreenReaderExtension[] exs = getExtensions();
+ if (exs == null) return;
+ for (int i = 0; i < exs.length; i++) {
+ exs[i].getScreenReaderControl().screenReaderOff();
+ }
+ }
+
+ public static boolean isAvailable() {
+ ScreenReaderExtension[] exs = getExtensions();
+ if (exs == null) return false;
+ boolean result = false;
+ for (int i = 0; i < exs.length; i++) {
+ result |= exs[i].getScreenReaderControl().isAvailable();
+ }
+ return result;
+ }
+
+ public static void takeBackControl(IWebBrowserACTF browser) {
+ ScreenReaderExtension[] exs = getExtensions();
+ if (exs == null) return;
+ for (int i = 0; i < exs.length; i++) {
+ exs[i].getScreenReaderControl().takeBackControl(browser);
+ }
+ }
+
+ private final IConfigurationElement configElement;
+ private IScreenReaderControl controller;
+
+ private ScreenReaderExtension(IConfigurationElement configElement) {
+ this.configElement = configElement;
+ }
+
+ private IScreenReaderControl getScreenReaderControl() {
+ if (controller != null) return controller;
+ try {
+ controller = (IScreenReaderControl) configElement.createExecutableExtension(ATTR_CLASS);
+ } catch (Exception e) {
+ }
+ return controller;
+ }
+
+ private void dispose() {
+ if (controller == null) return;
+ controller = null;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/AccessKeyListDialog.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/AccessKeyListDialog.java
new file mode 100644
index 0000000..f2ba059
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/AccessKeyListDialog.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.impl;
+
+import org.eclipse.actf.ai.fennec.treemanager.IAccessKeyList;
+import org.eclipse.actf.ai.navigator.Messages;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Shell;
+
+
+
+
+public class AccessKeyListDialog extends Dialog {
+ IAccessKeyList accessKeyList;
+
+ private char selectedKey = 0;
+
+ private String[] names;
+
+ List list;
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+
+ newShell.setText(Messages.getString("AccessKeyListDialog.Title")); //$NON-NLS-1$
+
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite container = (Composite) super.createDialogArea(parent);
+ GridData gd;
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.widthHint = 200;
+ gd.heightHint = 200;
+ gd.horizontalSpan = ((GridLayout) parent.getLayout()).numColumns;
+
+ list = new List(container, SWT.V_SCROLL | SWT.BORDER);
+
+ list.setLayoutData(gd);
+
+ for (int i = 0; i < accessKeyList.size(); i++) {
+ char key = accessKeyList.getAccessKeyAt(i);
+ String str = accessKeyList.getUIStringAt(i);
+ list.add(key+" "+str);
+ }
+
+ names = new String[list.getItemCount()];
+ for (int i = 0; i < names.length; i++)
+ names[i] = list.getItem(i);
+
+ list.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ selectedKey = accessKeyList.getAccessKeyAt(list.getSelectionIndex());
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ selectedKey = accessKeyList.getAccessKeyAt(list.getSelectionIndex());
+ }
+ });
+ return container;
+ }
+
+ AccessKeyListDialog(Shell parent, IAccessKeyList list) {
+ super(parent);
+ this.accessKeyList = list;
+ }
+
+ public char getSelectedKey() {
+ return selectedKey;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/BrowserControlImpl.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/BrowserControlImpl.java
new file mode 100644
index 0000000..b703440
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/BrowserControlImpl.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.impl;
+
+import java.io.File;
+
+import org.eclipse.actf.ai.navigator.IBrowserControl;
+import org.eclipse.actf.ai.navigator.IManipulator;
+import org.eclipse.actf.ai.navigator.extension.ManipulatorExtension;
+import org.eclipse.actf.ai.navigator.ui.URLOpenDialog;
+import org.eclipse.actf.ai.navigator.voice.VoiceManager;
+import org.eclipse.actf.ai.xmlstore.XMLStorePlugin;
+import org.eclipse.actf.model.ModelServiceUtils;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.actf.model.ui.editor.events.IWebBrowserNavigationEventListener;
+import org.eclipse.actf.model.ui.editor.events.WebBrowserNavigationEvent;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+
+
+
+
+public class BrowserControlImpl implements IBrowserControl, IWebBrowserNavigationEventListener {
+ private final TripJournal tripJournal;
+
+ private final WebEventListener webEventListener;
+
+ private final VoiceManager voiceManager = new VoiceManager(null);
+
+ public void backward() {
+ tripJournal.backward(webEventListener.getFocused());
+ }
+
+ public void forward() {
+ tripJournal.forward(webEventListener.getFocused());
+ }
+
+ BrowserControlImpl(WebEventListener webEventListener, TripJournal tripJournal) {
+ this.tripJournal = tripJournal;
+ this.webEventListener = webEventListener;
+ }
+
+ public void goBack(WebBrowserNavigationEvent e) {
+ tripJournal.backward(webEventListener.getFocused());
+ }
+
+ public void goForward(WebBrowserNavigationEvent e) {
+ tripJournal.forward(webEventListener.getFocused());
+ }
+
+ public void refresh(WebBrowserNavigationEvent e) {
+ IWebBrowserACTF wb = e.getBrowser();
+ WebEventListener.BrowserState bs = webEventListener.getBrowserState(wb);
+ if (bs == null)
+ return;
+ bs.getNavigator().navigateRefresh();
+ }
+
+ public void stop(WebBrowserNavigationEvent e) {
+ IWebBrowserACTF wb = e.getBrowser();
+ wb.navigateStop();
+ }
+
+ public void exportAllMetadata() {
+ String[] ext = { "*.fnz" };
+
+ voiceManager.speakWithFormat("Navigator.EXPORT_ALL_ANNOTATIONS", true, true);
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ FileDialog fileDialog = new FileDialog(shell, SWT.OPEN);
+ fileDialog.setFilterExtensions(ext);
+ String path = fileDialog.open();
+
+ if (path != null) {
+ if (!path.endsWith(".fnz")) {
+ path = path + ".fnz";
+ }
+ File dest = new File(path);
+ if (dest.exists()) {
+ String title = voiceManager.getMessageFormatter().mes("Navigator.OVERWRITE_CONFIRM");
+ String message = voiceManager.getMessageFormatter().mes("Navigator.OVERWRITE_MESSAGE", dest.getName());
+ boolean ret = MessageDialog.openQuestion(shell, title, message);
+ if (!ret)
+ return;
+ }
+ if (XMLStorePlugin.getDefault().getXMLStoreService().exportAllAnnotations(dest)) {
+ voiceManager.speakWithFormat("Navigator.EXPORT_IS_SUCCEEDED", true, true);
+ } else {
+ voiceManager.speakWithFormat("Navigator.EXPORT_IS_FAILED", true, true);
+ }
+ }
+ }
+
+ public void importMetadata() {
+ String[] ext = { "*.fnc;*.fnz;*.xml" };
+
+ voiceManager.speakWithFormat("Navigator.IMPORT_FENNEC_FILE", true, true);
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ FileDialog fileDialog = new FileDialog(shell, SWT.OPEN);
+ fileDialog.setFilterExtensions(ext);
+ String path = fileDialog.open();
+
+ if (path != null) {
+ File src = new File(path);
+
+ boolean r = XMLStorePlugin.getDefault().getXMLStoreService().importMetadata(src);
+ XMLStorePlugin.getDefault().getXMLStoreService().getRootStore().refleshAll();
+ NavigatorImpl navigator = webEventListener.getFocused();
+ if (navigator != null)
+ navigator.forceRestart();
+ if (r) {
+ voiceManager.speakWithFormat("Navigator.IMPORT_IS_SUCCEEDED", true, true);
+ } else {
+ voiceManager.speakWithFormat("Navigator.IMPORT_IS_FAILED", true, true);
+ }
+ }
+ }
+
+
+ public void openTab() {
+ voiceManager.stop();
+
+ URLOpenDialog openURLDialog = new URLOpenDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
+ if (1 == openURLDialog.open()) {
+ ManipulatorExtension.setMode(IManipulator.FORM_INPUT_MODE);
+ String sUrl = openURLDialog.getUrl();
+ ModelServiceUtils.openInExistingEditor(sUrl);
+ ManipulatorExtension.setMode(IManipulator.TREE_NAVIGATION_MODE);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/FormInputDialog.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/FormInputDialog.java
new file mode 100644
index 0000000..55956d7
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/FormInputDialog.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.impl;
+
+import org.eclipse.actf.ai.navigator.Messages;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+
+
+
+public class FormInputDialog extends Dialog {
+ private String formInputString;
+
+ private Text formInputField;
+
+ private boolean multi;
+
+ private boolean pass;
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+
+ if(multi)
+ newShell.setText(Messages.getString("FormInputDialog.Textarea")); //$NON-NLS-1$
+ else if(pass)
+ newShell.setText(Messages.getString("FormInputDialog.Password")); //$NON-NLS-1$
+ else
+ newShell.setText(Messages.getString("FormInputDialog.Text")); //$NON-NLS-1$
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite container = (Composite) super.createDialogArea(parent);
+ GridData gd;
+ if (multi) {
+ formInputField = new Text(container, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL);
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.widthHint = 400;
+ gd.heightHint = 200;
+
+ formInputField.addKeyListener(new KeyListener(){
+ public void keyPressed(KeyEvent e) {
+ if (e.keyCode == java.awt.event.KeyEvent.VK_TAB) {
+ formInputField.traverse(SWT.TRAVERSE_TAB_NEXT);
+ e.doit = false;
+ }
+ }
+ public void keyReleased(KeyEvent e) {
+ }
+ });
+ } else {
+ if (pass)
+ formInputField = new Text(container, SWT.BORDER | SWT.PASSWORD);
+ else
+ formInputField = new Text(container, SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 400;
+ }
+ gd.horizontalSpan = ((GridLayout) parent.getLayout()).numColumns;
+ formInputField.setLayoutData(gd);
+ formInputField.setText(formInputString);
+
+ formInputField.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ formInputString = formInputField.getText();
+ }
+ });
+ return container;
+ }
+
+ String getResult() {
+ return formInputString;
+ }
+
+ FormInputDialog(Shell parent, String init, boolean multi, boolean pass){
+ super(parent);
+ this.formInputString = init;
+ this.multi = multi;
+ this.pass = pass;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/FormSelectDialog.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/FormSelectDialog.java
new file mode 100644
index 0000000..7790e6c
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/FormSelectDialog.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.impl;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.navigator.Messages;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Shell;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+
+
+public class FormSelectDialog extends Dialog {
+ ITreeItem selectItem;
+
+ private int[] selectedIndices;
+
+ private String[] names;
+
+ boolean multiple;
+
+ List list;
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+
+ if (multiple)
+ newShell.setText(Messages.getString("FormSelectDialog.Multiple")); //$NON-NLS-1$
+ else
+ newShell.setText(Messages.getString("FormSelectDialog.Single")); //$NON-NLS-1$
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite container = (Composite) super.createDialogArea(parent);
+ GridData gd;
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.widthHint = 200;
+ gd.heightHint = 200;
+ gd.horizontalSpan = ((GridLayout) parent.getLayout()).numColumns;
+
+ if (multiple)
+ list = new List(container, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER);
+ else
+ list = new List(container, SWT.V_SCROLL | SWT.BORDER);
+
+ list.setLayoutData(gd);
+
+ Object base = selectItem.getBaseNode();
+ if (base instanceof Node) {
+ Node node = (Node) base;
+ NodeList nl = node.getChildNodes();
+
+ for (int i = 0; i < nl.getLength(); i++) {
+ Node child = nl.item(i);
+
+ if ("OPTION".equals(child.getNodeName())) {
+ Node c = child.getFirstChild();
+ String text = "";
+ if (c != null)
+ text = c.getNodeValue();
+ list.add(text);
+ }
+ }
+ }
+
+ names = new String[list.getItemCount()];
+ for (int i = 0; i < names.length; i++)
+ names[i] = list.getItem(i);
+
+ if (selectedIndices != null) {
+ list.select(selectedIndices);
+ }
+
+ list.addSelectionListener(new SelectionListener(){
+ public void widgetSelected(SelectionEvent e) {
+ selectedIndices = list.getSelectionIndices();
+ }
+ public void widgetDefaultSelected(SelectionEvent e) {
+
+ selectedIndices = list.getSelectionIndices();
+ }
+ });
+ return container;
+ }
+
+ FormSelectDialog(Shell parent, ITreeItem item, boolean multi) {
+ super(parent);
+ this.selectItem = item;
+ this.multiple = multi;
+ this.selectedIndices = item.getSelectedIndices();
+ }
+
+ public int[] getSelectedIndices() {
+ return selectedIndices;
+ }
+
+ public String getTextAt(int index) {
+ if (0 <= index && index < names.length)
+ return names[index];
+ return "";
+ }
+
+ public int getLength() {
+ return names.length;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/NVM3EntryCacheCleaner.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/NVM3EntryCacheCleaner.java
new file mode 100644
index 0000000..ec2ac22
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/NVM3EntryCacheCleaner.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.impl;
+
+import org.eclipse.actf.ai.navigator.IMetadataCacheCleaner;
+
+
+
+public class NVM3EntryCacheCleaner implements IMetadataCacheCleaner {
+
+ public void clearCache() {
+ //NVM3Plugin.getDefault().initNVM3Entry();
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/NavigatorImpl.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/NavigatorImpl.java
new file mode 100644
index 0000000..f225ab1
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/NavigatorImpl.java
@@ -0,0 +1,2227 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator.impl;
+
+import java.awt.Toolkit;
+import java.io.File;
+import java.net.URL;
+
+import org.eclipse.actf.ai.audio.io.AudioFactory;
+import org.eclipse.actf.ai.audio.io.IAudioPipe;
+import org.eclipse.actf.ai.audio.io.IAudioReader;
+import org.eclipse.actf.ai.audio.io.IAudioWriter;
+import org.eclipse.actf.ai.fennec.INVM3Entry;
+import org.eclipse.actf.ai.fennec.INVM3Mediator;
+import org.eclipse.actf.ai.fennec.treemanager.IAccessKeyList;
+import org.eclipse.actf.ai.fennec.treemanager.ILocation;
+import org.eclipse.actf.ai.fennec.treemanager.IMediaSyncEventListener;
+import org.eclipse.actf.ai.fennec.treemanager.ISoundControl;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.fennec.treemanager.ITreeManager;
+import org.eclipse.actf.ai.fennec.treemanager.IVideoControl;
+import org.eclipse.actf.ai.fennec.treemanager.TreeManagerException;
+import org.eclipse.actf.ai.fennec.treemanager.TreeManagerInterruptedException;
+import org.eclipse.actf.ai.fennec.treemanager.ISoundControl.VolumeState;
+import org.eclipse.actf.ai.fennec.treemanager.IVideoControl.VideoState;
+import org.eclipse.actf.ai.navigator.IManipulator;
+import org.eclipse.actf.ai.navigator.IMediaControl;
+import org.eclipse.actf.ai.navigator.INavigatorUI;
+import org.eclipse.actf.ai.navigator.NavigatorPlugin;
+import org.eclipse.actf.ai.navigator.IMediaControl.IHandle;
+import org.eclipse.actf.ai.navigator.extension.ManipulatorExtension;
+import org.eclipse.actf.ai.navigator.extension.MediaControlExtension;
+import org.eclipse.actf.ai.navigator.extension.ScreenReaderExtension;
+import org.eclipse.actf.ai.navigator.util.MessageFormatter;
+import org.eclipse.actf.ai.navigator.views.NavigatorTreeView;
+import org.eclipse.actf.ai.navigator.voice.VoiceManager;
+import org.eclipse.actf.ai.voice.IVoice;
+import org.eclipse.actf.ai.voice.IVoiceEventListener;
+import org.eclipse.actf.model.IModelServiceHolder;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.actf.util.ApplicationArgumentUtil;
+import org.eclipse.actf.util.BrowserLaunch;
+import org.eclipse.actf.util.ui.PlatformUIUtil;
+import org.eclipse.actf.util.vocab.IProposition;
+import org.eclipse.actf.util.vocab.Vocabulary;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorReference;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+
+public abstract class NavigatorImpl implements INavigatorUI, IVoiceEventListener {
+ private static boolean isDemo = ApplicationArgumentUtil.isAvailable("-demo");
+
+ // private final WebEventListener webEventListener;
+
+ private IWebBrowserACTF webBrowser;
+
+ private INVM3Mediator nvm3Mediator;
+
+ private ITreeManager treeManager;
+
+ private final int maxRetry;
+
+ private final int retryInterval;
+
+ private Display display;
+
+ private IManipulator.Mode mode;
+
+
+ public NavigatorImpl(WebEventListener webEventListener, IWebBrowserACTF webBrowser, int maxRetry, int retryInterval) {
+ // this.webEventListener = webEventListener;
+ this.webBrowser = webBrowser;
+ this.maxRetry = maxRetry;
+ this.retryInterval = retryInterval;
+ this.display = Display.getCurrent();
+ }
+
+ public ITreeManager getTreeManager() {
+ return treeManager;
+ }
+
+ private NavigatorTreeView getNavigatorTreeView() {
+ return NavigatorPlugin.getDefault().getNavigatorTreeView();
+ }
+
+ private void sleep(int interval) {
+ long startTime = System.currentTimeMillis();
+ while (true) {
+ boolean busy = display.readAndDispatch();
+ if (!busy)
+ display.sleep();
+ if ((System.currentTimeMillis() - startTime) > interval)
+ break;
+ }
+ }
+
+ // -----------------------------------------------------------------------
+ // Sound Util
+ // -----------------------------------------------------------------------
+
+ private void beep() {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ private static IAudioPipe audio;
+
+ static {
+ if (true) {
+ // TODO replace audio file
+ URL url = NavigatorPlugin.getDefault().getBundle().getResource("waiting.wav");
+ IAudioReader reader = AudioFactory.createAudioReader(url);
+ IAudioWriter writer = AudioFactory.createDefaultWriter();
+ audio = AudioFactory.createLoopedAudioPipe(reader, writer);
+ audio.setBufferSize(100);
+ audio.setInterval(1);
+ audio.prepare();
+ }
+ }
+
+ private void startProgress() {
+ startProgress(2000);
+ }
+ private void startProgress(int msec) {
+ audio.start(msec);
+ }
+
+ private void endProgress() {
+ audio.stop();
+ }
+
+ // -----------------------------------------------------------------------
+ // Voice
+ // -----------------------------------------------------------------------
+
+ private final VoiceManager voiceManager = new VoiceManager(this);
+
+ protected MessageFormatter getMessageFormatter() {
+ return voiceManager.getMessageFormatter();
+ }
+
+ private VoiceManager getVoiceManager() {
+ return voiceManager;
+ }
+
+ public void indexReceived(int index) {
+ if (speakAllMode && (index == -1)) {
+ display.asyncExec(new Runnable() {
+ public void run() {
+ traverseDownAll();
+ }
+ });
+ } else if (index == -2) {
+ display.asyncExec(new Runnable() {
+ public void run() {
+ stopSpeak();
+ }
+ });
+ }
+ }
+
+ // -----------------------------------------------------------------------
+ // Speak basic
+ // -----------------------------------------------------------------------
+
+ protected void speakWithFormat(String str) {
+ speakWithFormat(str, false);
+ }
+
+ protected void speakWithFormat(String str, boolean flush) {
+ speak(getMessageFormatter().mes(str), flush, true);
+ }
+
+ protected void speak(String str, boolean flush) {
+ speak(str, flush, true);
+ }
+
+ protected void speak(String str, boolean flush, boolean maleVoice) {
+ if (speakAllMode) {
+ getVoiceManager().speakWithCallback(str, flush, maleVoice);
+ } else {
+ getVoiceManager().speak(str, flush, maleVoice);
+ }
+ }
+
+ private boolean speakAllMode = false;
+
+ private void stopSpeakAll() {
+ speakAllMode = false;
+ }
+
+ public void speakAll() {
+ speakAllMode = true;
+ try {
+ speakActiveItem(true, false, JumpMode.NONE);
+ } catch (TreeManagerException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void traverseDownAll() {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ return treeManager.traverse(false);
+ }
+
+ public void after(int st) throws TreeManagerException {
+ afterMoveForSpeakAll(st, "Navigator.BOTTOM");
+ }
+ });
+ }
+
+ private void afterMoveForSpeakAll(int st, String notMoved) throws TreeManagerException {
+ if ((st & ITreeManager.CLICKED) != 0) {
+ speakWithFormat("Navigator.CLICK");
+ }
+ if ((st & ITreeManager.MOVED) != 0) {
+ speakActiveItem(true, false, JumpMode.NONE);
+ sayLevel();
+ } else {
+ speakAllMode = false;
+ sayLevel(notMoved);
+ }
+ }
+
+ public void stopSpeak() {
+ endProgress();
+ stopSpeakAll();
+ getVoiceManager().stop();
+ }
+
+
+ // -----------------------------------------------------------------------
+ // Say, speak
+ // -----------------------------------------------------------------------
+
+ private void sayMode(IManipulator.Mode mode) {
+ speakWithFormat(mode.name + " mode");
+ }
+
+ private void sayLevel(String prefix) throws TreeManagerException {
+ String mes = getMessageFormatter().mes(prefix);
+ speak(mes + " " + getLevelMessage(), true, true);
+ }
+
+ private String getLevelMessage() throws TreeManagerException {
+ int level = treeManager.getLevel();
+ String mesLv;
+ if (level > 0) {
+ mesLv = getMessageFormatter().mes("Navigator.LEVEL", new Object[] { new Integer(level) });
+ } else {
+ mesLv = getMessageFormatter().mes("Navigator.TOP_LEVEL");
+ }
+ return mesLv;
+ }
+
+ private void sayLevel() throws TreeManagerException {
+ // speak(getLevelMessage(), false, true);
+ }
+
+ private void sayRetrial() {
+ speak(getMessageFormatter().mes("Navigator.UNDONE"), true, true);
+ }
+
+ private void speakVideoInfo(boolean flag) throws TreeManagerException {
+ IVideoControl vc = treeManager.getVideoControl();
+ if (flag || vcCount != vc.getCount()) {
+ vcCount = vc.getCount();
+ if (vcCount == 0) {
+ speakWithFormat("Navigator.NOVIDEO");
+ } else if (vcCount == 1) {
+ speakWithFormat("Navigator.SINGLEVIDEO");
+ } else {
+ String text = getMessageFormatter().mes("Navigator.VIDEOCOUNT", new Object[] { vcCount });
+ speak(text, false, false);
+ }
+ }
+ }
+
+ private void speakSoundInfo(boolean flag) throws TreeManagerException {
+ ISoundControl sc = treeManager.getSoundControl();
+ if (flag || scCount != sc.getCount()) {
+ scCount = sc.getCount();
+ if (scCount == 0) {
+ speakWithFormat("Navigator.NOSOUND");
+ } else if (scCount == 1) {
+ speakWithFormat("Navigator.SINGLESOUND");
+ } else {
+ String text = getMessageFormatter().mes("Navigator.SOUNDCOUNT", new Object[] { scCount });
+ speak(text, false, false);
+ }
+ }
+ }
+
+ private int vcCount, scCount;
+
+ private boolean mcAvailable = false;
+
+ private void speakMediaInfo() throws TreeManagerException {
+ IVideoControl vc = treeManager.getVideoControl();
+
+ StringBuffer buf = new StringBuffer();
+ if (vc.getCount() > 0) {
+ buf.append(getMessageFormatter().mes("Navigator.VIDEO_AT",
+ formatTime(vc.getCurrentPosition())));
+ }
+ if (vc.getTotalLength() > 0) {
+ buf.append(getMessageFormatter().mes("Navigator.VIDEO_TOTAL",
+ formatTime(vc.getTotalLength())));
+ }
+
+ vcCount = vc.getCount();
+ if (vcCount == 0) {
+ speakWithFormat("Navigator.NOVIDEO");
+ } else if (vcCount == 1) {
+ speakWithFormat("Navigator.SINGLEVIDEO");
+ } else {
+ int index = vc.getIndex();
+ String text = getMessageFormatter().mes("Navigator.VIDEOINDEX", new Object[] { index, vcCount });
+ speak(text, false, false);
+ }
+
+ speak(buf.toString(), false, false);
+ }
+
+ private String formatTime(double currentPosition) {
+ int s = (int) currentPosition;
+ int m = s / 60;
+ s %= 60;
+ int h = s / 60;
+ m %= 60;
+
+ if (h > 0) {
+ return getMessageFormatter().mes("Navigator.HH_MM_SS", new Object[] { s, m, h });
+ } else if (m > 0) {
+ return getMessageFormatter().mes("Navigator.MM_SS", new Object[] { s, m });
+ }
+ return getMessageFormatter().mes("Navigator.SS", new Object[] { s });
+ }
+
+ private void speakPageInfo() {
+ try {
+ speakVideoInfo(false);
+ speakSoundInfo(false);
+
+ MediaControlExtension.speakInfo(false);
+
+ /*
+ if (!mcAvailable && MediaControlExtension.isAvailable()) {
+ speakWithFormat("AudioDescription.available");
+ mcAvailable = true;
+ }*/
+
+ } catch (TreeManagerException e) {
+ }
+ }
+
+ private void sayNVM3Name(String nvm3Name, boolean flag) {
+ String text = getMessageFormatter().mes("Navigator.FENNEC_NAME",
+ new Object[] { nvm3Name });
+ speak(text, flag, true);
+ }
+
+ private void sayNoNVM3(boolean flag) {
+ speakWithFormat("Navigator.NO_FENNEC", flag);
+ }
+
+ public void speakCurrentStatus() {
+ sayMode(mode);
+ try {
+ speakActiveItem(false, true, JumpMode.NONE);
+ speakPageInfo();
+ } catch (TreeManagerException e) {
+ }
+ }
+
+ public void speakMediaStatus() {
+ try {
+ speakMediaInfo();
+ } catch (TreeManagerException e) {
+ }
+ }
+
+ public void speakTab(boolean flush) {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ IEditorPart editor = page.getActiveEditor();
+
+ IEditorReference[] erefs = page.getEditorReferences();
+ boolean found = false;
+ int index = 0, total = 0;
+ for (int i = 0; i < erefs.length; i++) {
+ if (!found)
+ index++;
+ total++;
+ if (erefs[i].getEditor(false).equals(editor)) {
+ found = true;
+ }
+ }
+
+ String buf = "";
+ if (total == 1)
+ buf = editor.getTitle();
+ else
+ buf = getMessageFormatter().mes("Navigator.MOVE_TAB", editor.getTitle(), index, total);
+
+ speak(buf, flush, false);
+ stopSpeakAll();
+ }
+
+
+ private ITreeItem lastHighlighted;
+
+ private void highlight(ITreeItem item) {
+ if (lastHighlighted != null) {
+ try {
+ lastHighlighted.unhighlight();
+ } catch (TreeManagerException e) {
+ }
+ }
+ try {
+ item.highlight();
+ } catch (TreeManagerException e) {
+ }
+ lastHighlighted = item;
+ sleep(1);
+ }
+
+ protected enum JumpMode {
+ HEADING,
+ LISTITEM_TOP,
+ LINK,
+ OBJECT,
+ BLOCK,
+ INPUT,
+ LISTITEM_BOTTOM,
+ ACCESSKEY,
+ MEDIA,
+ ALTALABLE,
+ NONE,
+ }
+
+ private boolean listJumping = false;
+
+ private void speakActiveItem(boolean flush, boolean verbose, JumpMode jumpMode) throws TreeManagerException {
+ endProgress();
+ ITreeItem item = treeManager.getActiveItem();
+ ITreeItem[] siblings = treeManager.getSiblings();
+
+ final MessageFormatter mf = getMessageFormatter();
+ if (item == null)
+ return;
+ // update view
+ highlight(item);
+ getNavigatorTreeView().showItem(item);
+
+ // get item's UI string
+ int idx = item.getNth();
+ int st = intervalStart(siblings, idx);
+ int end = intervalEnd(siblings, idx);
+ StringBuffer bufUIStr = new StringBuffer();
+ for (int i = st; i <= end; i++) {
+ if (i < siblings.length)
+ bufUIStr.append(siblings[i].getUIString());
+ else
+ System.err.println("st " + st + ", end " + end + ", siblings.length " + siblings.length);
+ }
+ char accessKey = item.getAccessKey();
+
+ String uiStr = bufUIStr.toString();
+ String label = item.getFormLabel();
+ String speak = uiStr;
+
+ boolean isLink = Vocabulary.isLink().eval(item);
+ int hl = item.getHeadingLevel();
+ boolean isHeading = hl > 0;
+ boolean isListItem = Vocabulary.isListItem().eval(item);
+ boolean isListTop = Vocabulary.isListTop().eval(item);
+ boolean isCheckbox = Vocabulary.isCheckbox().eval(item);
+ boolean isRadio = Vocabulary.isRadio().eval(item);
+ boolean isCombobox = Vocabulary.isCombobox().eval(item);
+ //boolean isMultiSelectable = Vocabulary.isMultiSelectable().eval(item);
+ boolean isButton = Vocabulary.isButton().eval(item);
+ boolean isPassword = Vocabulary.isPassword().eval(item);
+ boolean isTextbox = Vocabulary.isTextbox().eval(item);
+ boolean isTextarea = Vocabulary.isMultilineEdit().eval(item);
+ boolean isFileEdit = Vocabulary.isFileEdit().eval(item);
+ boolean isChecked = Vocabulary.isChecked().eval(item);
+ boolean isClickable = Vocabulary.isClickable().eval(item);
+ boolean isFlashTopNode = Vocabulary.isFlashTopNode().eval(item);
+ boolean isFlashLastNode = Vocabulary.isFlashLastNode().eval(item);
+ boolean isMedia = Vocabulary.isMedia().eval(item);
+
+
+
+ if (isButton) {
+ String widget = mf.mes("Navigator.BUTTON");
+ if (uiStr.matches("[0-9]+")) {
+ speak = mf.concat(widget, uiStr);
+ } else {
+ speak = mf.concat(uiStr, widget);
+ }
+ } else if (isLink) {
+ boolean isVisitedLink = Vocabulary.isVisitedLink().eval(item);
+ String widget = mf.mes(isVisitedLink ? "Navigator.VISITED_LINK" : "Navigator.LINK");
+ if (jumpMode == JumpMode.LINK) {
+ speak = mf.concat(uiStr, widget);
+ } else {
+ speak = mf.concat(widget, uiStr);
+ }
+ } else if (isPassword) {
+ if (uiStr.length() > 0)
+ uiStr = mf.mes("Navigator.PASSWORD_STAR3");
+ String widget = mf.mes("Navigator.PASSWORD");
+ if (jumpMode == JumpMode.LINK) {
+ speak = mf.concat(label, widget, uiStr);
+ } else {
+ speak = mf.concat(uiStr, widget);
+ }
+ } else if (isFileEdit) {
+ String widget = mf.mes("Navigator.FILE_UPLOAD");
+ if (jumpMode == JumpMode.LINK) {
+ speak = mf.concat(label, widget, uiStr);
+ } else {
+ speak = mf.concat(widget, uiStr);
+ }
+ } else if (isTextarea) {
+ String widget = mf.mes((uiStr.length() == 0) ? "Navigator.TEXTAREA_EMPTY" : "Navigator.TEXTAREA");
+ if (jumpMode == JumpMode.LINK) {
+ speak = mf.concat(label, widget);
+ } else {
+ speak = widget;
+ }
+ } else if (isTextbox) {
+ String widget = mf.mes("Navigator.TEXTBOX");
+
+ if (jumpMode == JumpMode.LINK) {
+ speak = mf.concat(label, widget, uiStr);
+ } else {
+ speak = mf.concat(widget, uiStr);
+ }
+ } else if (isCheckbox) {
+ String widget = mf.mes("Navigator.CHECKBOX");
+ String checked = mf.mes(isChecked ? "Navigator.CHECKED" : "Navigator.NOT_CHECKED");
+
+ if (jumpMode == JumpMode.LINK) {
+ speak = mf.concat(label, widget, checked);
+ } else {
+ speak = mf.concat(widget, checked, label);
+ }
+ } else if (isRadio) {
+ String widget = mf.mes("Navigator.RADIO");
+ String checked = mf.mes(isChecked ? "Navigator.CHECKED" : "Navigator.NOT_CHECKED");
+
+ int index = item.getRadioIndex();
+ int total = item.getRadioTotal();
+ String nm = "";
+ if (index != 0 && total != 0) {
+ nm = mf.mes("Navigator.N_OF_M", index, total);
+ }
+
+ if (jumpMode == JumpMode.LINK) {
+ speak = mf.concat(label, widget, checked, nm);
+ } else {
+ speak = mf.concat(widget, checked, nm, label);
+ }
+ } else if (isCombobox) {
+ int[] indices = item.getSelectedIndices();
+ int total = item.getOptionsCount();
+
+ if (indices.length > 0) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < indices.length; i++) {
+ sb.append(mf.mes("Navigator.COMBO_BOX") + " ");
+ sb.append(item.getOptionTextAt(indices[i]));
+ sb.append(" " + mf.mes("Navigator.N_OF_M", indices[i] + 1, total) + " ");
+ }
+ speak = mf.concat(uiStr, sb.toString());
+ } else {
+ speak = mf.concat(uiStr, mf.mes("Navigator.NO_SELECTION"));
+ }
+ if (jumpMode == JumpMode.LINK) {
+ speak = mf.concat(label, uiStr);
+ }
+ } else if (isFlashTopNode) {
+ boolean isMSAAFlash = Vocabulary.isMSAAFlash().eval(item);
+ if (isMSAAFlash)
+ speak = mf.concat(speak, mf.mes("Navigator.MSAA_FLASH_CONTENT"));
+ else
+ speak = mf.concat(speak, mf.mes("Navigator.FLASH_CONTENT"));
+ } else if (isFlashLastNode) {
+ speak = mf.mes("Navigator.FLASH_END");
+ }
+ if (speak.length() == 0) {
+ if (isClickable) {
+ speak = "Clickable";
+ }
+ }
+ if (isHeading) {
+ String widget = mf.mes("Navigator.HEADING");
+ String level = mf.mes("Navigator.LEVEL", hl);
+
+ if (jumpMode == JumpMode.HEADING) {
+ speak = mf.concat(speak, widget, level);
+ } else {
+ speak = mf.concat(widget, level, speak);
+ }
+ }
+
+ if (isMedia) {
+ String media = mf.mes("Navigator.MEDIA");
+ speak = mf.concat(media, speak);
+ }
+
+ if (isListItem) {
+ int index = item.getListIndex();
+ int total = item.getListTotal();
+ if (total > 1) {
+ String nm = mf.mes("Navigator.N_OF_M", index, total);
+ speak = mf.concat(speak, nm);
+ if (listJumping && ((jumpMode == JumpMode.LISTITEM_TOP && index == 1) //
+ || (jumpMode == JumpMode.LISTITEM_BOTTOM && index == total))) {
+ beep();
+ }
+ listJumping = true;
+ }
+ } else {
+ listJumping = false;
+ }
+ if (isListTop) {
+ ITreeItem[] children = item.getChildItems();
+ int n = 0;
+ for (int i = 0; i < children.length; i++) {
+ if (Vocabulary.isListItem().eval(children[i])) {
+ n++;
+ }
+ }
+ speak = mf.concat(speak, uiStr, mf.mes("Navigator.LIST_TOP", n));
+ }
+
+ if (accessKey != 0) {
+ speak = mf.concat(speak, mf.mes("Navigator.ACCESSKEY_GUIDE", accessKey));
+ }
+
+ if (verbose) {
+ String desc = item.getDescription();
+ if ((desc != null) && (desc.length() > 0)) {
+ speak = mf.concat(speak, desc);
+ }
+ }
+
+ speak(speak, flush, !isLink);
+ }
+
+ private int intervalStart(ITreeItem[] siblings, int st) {
+ if (siblings == null)
+ return 0;
+ for (st = st - 1;; st--) {
+ if (st < 0 || siblings.length <= st)
+ return 0;
+ if (!Vocabulary.isConnectable().eval(siblings[st]))
+ return st + 1;
+ }
+ }
+
+ private int intervalEnd(ITreeItem[] siblings, int end) {
+ if (siblings == null)
+ return 0;
+ for (; end < siblings.length; end++) {
+ if (!Vocabulary.isConnectable().eval(siblings[end]))
+ return end;
+ }
+ return end - 1;
+ }
+
+ // ---------------------------------------------------------------------
+ // Mode Control
+ // ---------------------------------------------------------------------
+
+ // Used by NavigatorImplExSub
+ protected void setMode(IManipulator.Mode mode) {
+ if (this.mode == mode)
+ return;
+ if (this.mode != null) {
+ //sayMode(mode);
+ }
+ this.mode = mode;
+ ManipulatorExtension.setMode(mode);
+ getNavigatorTreeView().setMode(mode);
+ switch (mode.code) {
+ case IManipulator.TREE_NAVIGATION_MODE_CODE:
+ ScreenReaderExtension.screenReaderOff();
+ if (ScreenReaderExtension.isAvailable()) {
+ webBrowser.showAddressText(false);
+ }
+ break;
+ case IManipulator.FORM_INPUT_MODE_CODE:
+ default:
+ ScreenReaderExtension.screenReaderOn();
+ break;
+ }
+ }
+
+ private void enterFormInputMode(ITreeItem item) {
+ setMode(IManipulator.FORM_INPUT_MODE);
+ item.setFocus();
+ }
+
+ private void enterFormInputMode() {
+ setMode(IManipulator.FORM_INPUT_MODE);
+ }
+
+ // --------------------------------------------------------------------------------
+ // NVM3 Control
+ // --------------------------------------------------------------------------------
+
+ private int currentNVM3Idx = 1;
+
+ private INVM3Entry currentEntry = null;
+
+ protected INVM3Entry getCurrentEntry() {
+ return currentEntry;
+ }
+
+ private void selectNVM3(boolean next, boolean flush) {
+ selectNVM3(next, flush, true);
+ }
+ private void selectNVM3(boolean next, boolean flush, boolean sayFlag) {
+ if (lastHighlighted != null) {
+ try {
+ lastHighlighted.unhighlight();
+ } catch (TreeManagerException e1) {
+ }
+ }
+
+ INVM3Entry[] entries = nvm3Mediator.getNVM3Entries();
+ if (next) {
+ if (entries.length == 0) {
+ speakWithFormat("Navigator.NO_OTHER_FENNEC", true);
+ return;
+ }
+ currentNVM3Idx++;
+ }
+ if (currentNVM3Idx > entries.length)
+ currentNVM3Idx = 0;
+ try {
+ restoreLocation(getLocation());
+ if (currentNVM3Idx == 0) {
+ initNVM3(null, flush, sayFlag);
+ } else {
+ initNVM3(entries[currentNVM3Idx - 1], flush, sayFlag);
+ }
+ speakActiveItem(false, false, JumpMode.NONE);
+ } catch (TreeManagerException e) {
+ }
+ }
+
+ protected void selectUserNVM3() {
+ if (lastHighlighted != null) {
+ try {
+ lastHighlighted.unhighlight();
+ } catch (TreeManagerException e1) {
+ }
+ }
+
+ INVM3Entry[] entries = nvm3Mediator.getNVM3Entries();
+ for (int i = 0; i < entries.length; i++) {
+ if (entries[i].isUserEntry()) {
+ try {
+ restoreLocation(getLocation());
+ initNVM3(entries[i], true, true);
+ speakActiveItem(false, false, JumpMode.NONE);
+ } catch (TreeManagerException e) {
+ }
+ return;
+ }
+ }
+ speakWithFormat("Navigator.NO_OTHER_FENNEC", true);
+ return;
+ }
+
+ public void selectNextNVM3() {
+ selectNVM3(true, true);
+ }
+
+ void setNVM3Mediator(INVM3Mediator nvm3Mediator) {
+ if (this.nvm3Mediator != null) {
+ this.nvm3Mediator.release();
+ }
+ this.nvm3Mediator = nvm3Mediator;
+ // TODO
+ this.treeManager = null;
+ this.lastHighlighted = null;
+ getNavigatorTreeView().clearItem();
+ }
+
+
+ private String getNVM3Name(INVM3Entry entry) {
+ if (entry == null)
+ return getMessageFormatter().mes("Navigator.NO_FENNEC_MESSAGE");
+ String text = entry.getDocumentation();
+ if ((text != null) && (text.length() > 0))
+ return text;
+ return getMessageFormatter().mes("Navigator.NO_FENNEC_NAME");
+ }
+
+ private void initNVM3(INVM3Entry entry, boolean flag, boolean sayFlag) throws TreeManagerException {
+ currentEntry = entry;
+ treeManager = nvm3Mediator.newTreeManager(entry);
+ String nvm3Name = getNVM3Name(entry);
+ if (sayFlag) {
+ if (entry == null) {
+ sayNoNVM3(flag);
+ } else {
+ sayNVM3Name(nvm3Name, flag);
+ }
+ }
+ getNavigatorTreeView().showNVM3Name(nvm3Name);
+ setMode(IManipulator.TREE_NAVIGATION_MODE);
+ try {
+ treeManager.initialize();
+ if (sayFlag)
+ speakPageInfo();
+ } catch (TreeManagerException e) {
+ if (sayFlag)
+ speakWithFormat(e.getMessage());
+ }
+
+ if (!skipToAnchor(webBrowser.getURL())) {
+ if (locationToBeRestored != null) {
+ try {
+ treeManager.moveToLocation(locationToBeRestored);
+ } catch (TreeManagerException e) {
+ }
+ locationToBeRestored = null;
+ }
+ }
+ }
+
+ public void startNavigation(IWebBrowserACTF webBrowser) {
+ startNavigation(webBrowser, true);
+ }
+
+ public void startNavigation(IWebBrowserACTF webBrowser, boolean sayFlag) {
+ endProgress();
+ if (ScreenReaderExtension.isAvailable() && isLeftViewsShown() && !isDemo) {
+ toggleLeftViewsShowing();
+ }
+
+ if (sayFlag)
+ speakWithFormat("Navigator.STARTNAVIGATION");
+
+ try {
+ initNVM3(nvm3Mediator.getDefaultNVM3Entry(), false, sayFlag);
+ currentNVM3Idx = 1;
+ if (sayFlag) {
+ speakActiveItem(false, false, JumpMode.NONE);
+ }
+ } catch (Exception e) {
+ // TODO Retry
+ e.printStackTrace();
+ }
+ ManipulatorExtension.setNavigator(this);
+ initializeMovieStartListener();
+ }
+
+ public void endNavigation() {
+ // TODO
+ ManipulatorExtension.disposeExtensions();
+ }
+
+ // --------------------------------------------------------------------------------
+ // Media Control
+ // --------------------------------------------------------------------------------
+
+ private ISoundControl prepareSoundControl() throws TreeManagerException {
+ ISoundControl sc = treeManager.getSoundControl();
+ if (sc.getCount() == 0) {
+ // say("Retry to control sound");
+ treeManager.analyze();
+ sc = treeManager.getSoundControl();
+ }
+ return sc;
+ }
+
+ private IVideoControl prepareVideoControl() throws TreeManagerException {
+ IVideoControl vc = treeManager.getVideoControl();
+ if (vc.getCount() == 0) {
+ // say("Retry to control video");
+ treeManager.analyze();
+ vc = treeManager.getVideoControl();
+ }
+ return vc;
+ }
+
+ public void muteMedia() {
+ ISoundControl sc;
+ try {
+ sc = prepareSoundControl();
+ } catch (TreeManagerException e) {
+ return;
+ }
+ if (sc == null)
+ return;
+ if (sc.getCount() == 0) {
+ speakWithFormat("Navigator.NOSOUND", true);
+ return;
+ }
+ sc.muteMedia();
+ if (sc.getVolumeState() == VolumeState.MUTE) {
+ speakWithFormat("Navigator.MUTEON", true);
+ } else {
+ speakWithFormat("Navigator.MUTEOFF", true);
+ }
+ }
+
+ public void volumeDownMedia() {
+ ISoundControl sc;
+ try {
+ sc = prepareSoundControl();
+ } catch (TreeManagerException e) {
+ return;
+ }
+ if (sc == null)
+ return;
+ if (sc.getCount() == 0) {
+ speakWithFormat("Navigator.NOSOUND", true);
+ return;
+ }
+ sc.volumeDownMedia();
+ if (sc.getVolumeState() == VolumeState.MIN || sc.getVolumeState() == VolumeState.MUTE) {
+ speakWithFormat("Navigator.VOLUMEMIN", true);
+ } else {
+ speakWithFormat("Navigator.VOLUMEDOWN", true);
+ }
+ }
+
+ public void minimalVolumeDownMedia() {
+ ISoundControl sc;
+ try {
+ sc = prepareSoundControl();
+ } catch (TreeManagerException e) {
+ return;
+ }
+ if (sc == null)
+ return;
+ if (sc.getCount() == 0) {
+ speakWithFormat("Navigator.NOSOUND", true);
+ return;
+ }
+ sc.minimalVolumeDownMedia();
+ if (sc.getVolumeState() == VolumeState.MIN || sc.getVolumeState() == VolumeState.MUTE) {
+ speakWithFormat("Navigator.VOLUMEMIN", true);
+ } else {
+ speakWithFormat("Navigator.VOLUMEDOWN", true);
+ }
+ }
+
+ public void volumeUpMedia() {
+ ISoundControl sc;
+ try {
+ sc = prepareSoundControl();
+ } catch (TreeManagerException e) {
+ return;
+ }
+ if (sc == null)
+ return;
+ if (sc.getCount() == 0) {
+ speakWithFormat("Navigator.NOSOUND", true);
+ return;
+ }
+ sc.volumeUpMedia();
+ if (sc.getVolumeState() == VolumeState.MAX) {
+ speakWithFormat("Navigator.VOLUMEMAX", true);
+ } else {
+ speakWithFormat("Navigator.VOLUMEUP", true);
+ }
+ }
+
+ public void minimalVolumeUpMedia() {
+ ISoundControl sc;
+ try {
+ sc = prepareSoundControl();
+ } catch (TreeManagerException e) {
+ return;
+ }
+ if (sc == null)
+ return;
+ if (sc.getCount() == 0) {
+ speakWithFormat("Navigator.NOSOUND", true);
+ return;
+ }
+ sc.minimalVolumeUpMedia();
+ if (sc.getVolumeState() == VolumeState.MAX) {
+ speakWithFormat("Navigator.VOLUMEMAX", true);
+ } else {
+ speakWithFormat("Navigator.VOLUMEUP", true);
+ }
+ }
+
+ private void sayVideoState(IVideoControl vc, boolean doPause, VideoState oldSt) {
+ VideoState st = vc.getVideoState();
+ switch (st) {
+ case STATE_PLAY:
+ if (doPause) {
+ if (oldSt == VideoState.STATE_PAUSE) {
+ speakWithFormat("Navigator.RESUMEMEDIA");
+ } else if (oldSt == VideoState.STATE_PLAY) {
+ speakWithFormat("Navigator.CANNOT_PAUSE");
+ }
+ } else {
+ speakWithFormat("Navigator.PLAYMEDIA");
+ }
+ break;
+ case STATE_STOP:
+ speakWithFormat("Navigator.STOPMEDIA");
+ break;
+ case STATE_PAUSE:
+ speakWithFormat("Navigator.PAUSEMEDIA");
+ break;
+ case STATE_WAITING:
+ speakWithFormat("Navigator.WAITINGMEDIA");
+ break;
+ case STATE_FASTFORWARD:
+ speakWithFormat("Navigator.FASTFORWARDMEDIA");
+ break;
+ case STATE_FASTREVERSE:
+ speakWithFormat("Navigator.FASTREVERSEMEDIA");
+ break;
+ case STATE_OTHER:
+ speakWithFormat("Navigator.NOT_AVAILABEL");
+ break;
+ }
+ }
+
+ public void previousTrack() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void nextTrack() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void stopMedia() {
+ try {
+ IVideoControl vc = prepareVideoControl();
+ VideoState st = vc.getVideoState();
+ vc.stopMedia();
+ sayVideoState(vc, false, st);
+ } catch (TreeManagerException e) {
+ }
+ }
+
+ public void playMedia() {
+ try {
+ IVideoControl vc = prepareVideoControl();
+ VideoState st = vc.getVideoState();
+ vc.playMedia();
+ sayVideoState(vc, false, st);
+ } catch (TreeManagerException e) {
+ }
+ }
+
+ public void pauseMedia() {
+ try {
+ IVideoControl vc = prepareVideoControl();
+ VideoState st = vc.getVideoState();
+ vc.pauseMedia();
+ sayVideoState(vc, true, st);
+ } catch (TreeManagerException e) {
+ }
+ }
+
+ public void fastReverse() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void fastForward() {
+ // TODO Auto-generated method stub
+
+ }
+
+ // --------------------------------------------------------------------------------
+ // Tree Navigation
+ // --------------------------------------------------------------------------------
+
+
+ interface Command {
+ int run(int retry) throws TreeManagerException;
+ void after(int st) throws TreeManagerException;
+ }
+
+ private void afterMove(int st, String notMoved) throws TreeManagerException {
+ afterMove(st, notMoved, null);
+ }
+
+ private void afterMove(int st, String notMoved, JumpMode jumpMode) throws TreeManagerException {
+ if ((st & ITreeManager.CLICKED) != 0) {
+ speakWithFormat("Navigator.CLICK");
+ }
+ else if ((st & ITreeManager.MOVED) != 0) {
+ speakActiveItem(true, false, jumpMode);
+ sayLevel();
+ } else {
+ sayLevel(notMoved);
+ }
+ speakAllMode = false;
+ }
+
+ private void moveCmd(Command cmd) {
+ if (treeManager == null)
+ return;
+ for (int i = 0; i < maxRetry; i++) {
+ try {
+ int st = cmd.run(i);
+ cmd.after(st);
+ return;
+ } catch (TreeManagerInterruptedException e) {
+ sayRetrial();
+ sleep(retryInterval);
+ } catch (TreeManagerException e) {
+ }
+ }
+ // navigationThread.sendCmd(cmd);
+ }
+
+ private boolean skipToAnchor(String url) throws TreeManagerException {
+ int hashIdx = url.lastIndexOf('#');
+ if (hashIdx < 0)
+ return false;
+ hashIdx++;
+ if (hashIdx >= url.length())
+ return false;
+ String target = url.substring(hashIdx);
+ treeManager.skipToAnchor(target);
+ return true;
+ }
+
+ public void treeLeft() {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ return treeManager.gotoParent();
+ }
+
+ public void after(int st) throws TreeManagerException {
+ afterMove(st, "Navigator.TOP");
+ }
+ });
+ }
+
+ public void treeRight() {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ return treeManager.gotoFirstChild();
+ }
+
+ public void after(int st) throws TreeManagerException {
+ afterMove(st, "Navigator.NO_SUBITEMS");
+ }
+ });
+ }
+
+ public void treeUp() {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ return treeManager.gotoPreviousSibling();
+ }
+
+ public void after(int st) throws TreeManagerException {
+ afterMove(st, "Navigator.TOP");
+ }
+ });
+ }
+
+ public void treeDown() {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ return treeManager.gotoNextSibling();
+ }
+
+ public void after(int st) throws TreeManagerException {
+ afterMove(st, "Navigator.BOTTOM");
+ }
+ });
+ }
+
+ public void treeTop() {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ return treeManager.gotoStartOfPage();
+ }
+
+ public void after(int st) throws TreeManagerException {
+ speakTab();
+ listJumping = false;
+ //afterMove(st, "Navigator.TOP");
+ }
+ });
+ }
+
+ public void treeBottom() {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ return treeManager.gotoEndOfPage();
+ }
+
+ public void after(int st) throws TreeManagerException {
+ afterMove(st, "Navigator.BOTTOM");
+ }
+ });
+ }
+
+ public void traverseNodeDown() {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ int moved;
+ int rFlag = 0;
+ do {
+ moved = treeManager.traverse(false);
+ rFlag |= moved;
+ } while (((moved & ITreeManager.LEVEL_CHANGED) == 0) && ((moved & ITreeManager.MOVED) != 0));
+ return moved | rFlag;
+ }
+
+ public void after(int st) throws TreeManagerException {
+ afterMove(st, "Navigator.BOTTOM");
+ }
+ });
+ }
+
+ public void traverseNodeUp() {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ int moved;
+ int rFlag = 0;
+ do {
+ moved = treeManager.traverse(true);
+ rFlag |= moved;
+ } while (((moved & ITreeManager.LEVEL_CHANGED) == 0) && ((moved & ITreeManager.MOVED) != 0));
+ return moved | rFlag;
+ }
+
+ public void after(int st) throws TreeManagerException {
+ afterMove(st, "Navigator.TOP");
+ }
+ });
+ }
+
+ public void traverseDown() {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ return treeManager.traverse(false);
+ }
+
+ public void after(int st) throws TreeManagerException {
+ if ((st & ITreeManager.MOVED) == 0) {
+ beep();
+ speak(getMessageFormatter().mes("Navigator.BOTTOM"), true, false);
+ speakActiveItem(false, false, JumpMode.NONE);
+ } else {
+ afterMove(st, "Navigator.BOTTOM");
+ }
+ }
+ });
+ }
+
+ public void traverseUp() {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ return treeManager.traverse(true);
+ }
+
+ public void after(int st) throws TreeManagerException {
+ if ((st & ITreeManager.MOVED) == 0) {
+ beep();
+ speak(getMessageFormatter().mes("Navigator.TOP"), true, false);
+ speakTab(false);
+ } else {
+ afterMove(st, "Navigator.TOP");
+ }
+ }
+ });
+ }
+
+ public void click() {
+ try {
+ ITreeItem item = treeManager.getActiveItem();
+ if (item == null)
+ return;
+
+ // for restoring the class name of the item
+ item.unhighlight();
+
+ if (Vocabulary.isFileEdit().eval(item) || //
+ Vocabulary.isCheckbox().eval(item) || //
+ Vocabulary.isRadio().eval(item) || //
+ !(Vocabulary.isInputable().eval(item) || Vocabulary.isSelectable().eval(item)) //
+ ) {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ if (r == 0) {
+ return treeManager.click(true);
+ } else {
+ return treeManager.click(false);
+ }
+ }
+
+ public void after(int st) throws TreeManagerException {
+ afterMove(st, "Navigator.CLICK");
+ }
+ });
+ return;
+ }
+
+ if (false) {
+ enterFormInputMode(item);
+ } else {
+ setMode(IManipulator.KEYHOOK_DISABLED_MODE);
+ //item.setFocus();
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ boolean combo = Vocabulary.isCombobox().eval(item);
+
+ if (combo) {
+ boolean multiple = Vocabulary.isMultiSelectable().eval(item);
+ FormSelectDialog dialog = new FormSelectDialog(shell, item, multiple);
+
+ if (dialog.open() == InputDialog.OK) {
+ int[] indices = dialog.getSelectedIndices();
+ int total = dialog.getLength();
+ if (indices != null) {
+ item.setSelectedIndices(indices);
+ if (indices.length > 0) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < indices.length; i++) {
+ String text = dialog.getTextAt(indices[i]);
+ sb.append(text + " " + getMessageFormatter().mes("Navigator.N_OF_M", indices[i] + 1, total)
+ + " ");
+ }
+ speak(sb.toString(), true);
+ } else {
+ speakWithFormat("Navigator.COMBO_BOX_NOSELECTION");
+ }
+ }
+ }
+ } else {
+ boolean multiline = Vocabulary.isMultilineEdit().eval(item);
+ boolean pass = Vocabulary.isPassword().eval(item);
+ FormInputDialog dialog = new FormInputDialog(shell, item.getText(), multiline, pass);
+
+ if (dialog.open() == InputDialog.OK) {
+ String result = dialog.getResult();
+ if (result != null) {
+ item.setText(dialog.getResult());
+ if (pass) {
+ if (item.getText().length() > 0) {
+ speakWithFormat(getMessageFormatter().mes("Navigator.PASSWORD_STAR3"));
+ }
+ } else {
+ speakWithFormat(item.getText());
+ }
+ }
+ }
+ }
+ //item.setFocus();
+ setMode(IManipulator.TREE_NAVIGATION_MODE);
+ }
+
+ // for restoring the class name of the item
+ item.highlight();
+ } catch (TreeManagerException e) {
+ e.printStackTrace();
+ }
+ }
+
+ // --------------------------------------------------------------------------------
+ // Skip Navigation
+ // --------------------------------------------------------------------------------
+
+ // Used by NavigatorImplExSub
+ protected void findNext(final IProposition p, final JumpMode jumpMode) {
+ moveCmd(new Command() {
+ ILocation current;
+ public int run(int r) throws TreeManagerException {
+ startProgress();
+ current = getLocation();
+ return treeManager.findNext(p);
+ }
+
+ public void after(int st) throws TreeManagerException {
+ if ((st & ITreeManager.MOVED) == 0) {
+ if (jumpMode != JumpMode.LISTITEM_TOP)
+ beep();
+ speak(getMessageFormatter().mes("Navigator.WRAPPING_TO_TOP"), true, false);
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ treeManager.gotoStartOfPage();
+ return treeManager.findNext(p);
+ }
+
+ public void after(int st) throws TreeManagerException {
+ if ((st & ITreeManager.MOVED) == 0)
+ treeManager.moveToLocation(current);
+ afterFind(st, jumpMode);
+ endProgress();
+ }
+ });
+ } else {
+ afterMove(st, "Navigator.BOTTOM", jumpMode);
+ endProgress();
+ }
+ }
+ });
+ }
+
+ private void afterFind(int st, JumpMode jumpMode) throws TreeManagerException {
+ afterFind(st, jumpMode, null);
+ }
+
+ private void afterFind(int st, JumpMode jumpMode, Object arg) throws TreeManagerException {
+ if ((st & ITreeManager.MOVED) != 0) {
+ speakActiveItem(false, false, jumpMode);
+ } else {
+ String buf = "";
+ if (jumpMode == JumpMode.HEADING)
+ buf = getMessageFormatter().mes("Navigator.NO_HEADING");
+ else if (jumpMode == JumpMode.BLOCK)
+ buf = getMessageFormatter().mes("Navigator.NO_BLOCK");
+ else if (jumpMode == JumpMode.INPUT)
+ buf = getMessageFormatter().mes("Navigator.NO_INPUT");
+ else if (jumpMode == JumpMode.LINK)
+ buf = getMessageFormatter().mes("Navigator.NO_LINK");
+ else if (jumpMode == JumpMode.LISTITEM_TOP || jumpMode == JumpMode.LISTITEM_BOTTOM)
+ buf = getMessageFormatter().mes("Navigator.NO_LISTITEM");
+ else if (jumpMode == JumpMode.OBJECT)
+ buf = getMessageFormatter().mes("Navigator.NO_OBJECT");
+ else if (jumpMode == JumpMode.MEDIA)
+ buf = getMessageFormatter().mes("Navigator.NO_MEDIA");
+ else if (jumpMode == JumpMode.ACCESSKEY)
+ buf = getMessageFormatter().mes("Navigator.NO_ACCESSKEY", arg);
+ else if (jumpMode == JumpMode.ALTALABLE)
+ buf = getMessageFormatter().mes("Navigator.NO_ALTALABLE");
+
+
+ speak(buf, true, false);
+ }
+ speakAllMode = false;
+ }
+
+ // Used by NavigatorImplExSub
+ protected void findPrevious(final IProposition p, final JumpMode jumpMode) {
+ moveCmd(new Command() {
+ private ILocation current;
+ public int run(int r) throws TreeManagerException {
+ startProgress();
+ current = getLocation();
+ return treeManager.findPrevious(p);
+ }
+
+ public void after(int st) throws TreeManagerException {
+ if ((st & ITreeManager.MOVED) == 0) {
+ if (jumpMode != JumpMode.LISTITEM_BOTTOM)
+ beep();
+ speak(getMessageFormatter().mes("Navigator.WRAPPING_TO_BOTTOM"), true, false);
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ treeManager.gotoEndOfPageForFind();
+ return treeManager.findPrevious(p);
+ }
+
+ public void after(int st) throws TreeManagerException {
+ if ((st & ITreeManager.MOVED) == 0)
+ treeManager.moveToLocation(current);
+ afterFind(st, jumpMode);
+ endProgress();
+ }
+ });
+ } else {
+ afterMove(st, "Navigator.TOP", jumpMode);
+ endProgress();
+ }
+ }
+ });
+ }
+
+ public void nextHeader() {
+ findNext(Vocabulary.isHeading(), JumpMode.HEADING);
+ }
+
+ public void previousHeader() {
+ findPrevious(Vocabulary.isHeading(), JumpMode.HEADING);
+ }
+
+ public void nextInputable() {
+ findNext(Vocabulary.or(Vocabulary.isInputable(), Vocabulary.isSelectable()), JumpMode.INPUT);
+ }
+
+ public void previousInputable() {
+ findPrevious(Vocabulary.or(Vocabulary.isInputable(), Vocabulary.isSelectable()), JumpMode.INPUT);
+ }
+
+ public void nextLink() {
+ findNext(Vocabulary.or(Vocabulary.isClickable(), Vocabulary.isInputable(), Vocabulary.isSelectable()),
+ JumpMode.LINK);
+ }
+
+ public void previousLink() {
+ findPrevious(Vocabulary.or(Vocabulary.isClickable(), Vocabulary.isInputable(), Vocabulary.isSelectable()),
+ JumpMode.LINK);
+ }
+
+ public void nextObject() {
+ findNext(Vocabulary.isEmbeddedObject(), JumpMode.OBJECT);
+ }
+
+ public void previousObject() {
+ findPrevious(Vocabulary.isEmbeddedObject(), JumpMode.OBJECT);
+ }
+
+ public void nextListItem() {
+ findNext(Vocabulary.isListItem(), JumpMode.LISTITEM_TOP);
+ }
+
+ public void previousListItem() {
+ findPrevious(Vocabulary.isListItem(), JumpMode.LISTITEM_BOTTOM);
+ }
+
+ public void nextBlock() {
+ findNext(Vocabulary.isBlockJumpPointF(), JumpMode.BLOCK);
+ }
+
+ public void previousBlock() {
+ findPrevious(Vocabulary.isBlockJumpPointB(), JumpMode.BLOCK);
+ }
+
+ public void nextMedia() {
+ findNext(Vocabulary.isMedia(), JumpMode.MEDIA);
+ }
+
+ public void previousMedia() {
+ findPrevious(Vocabulary.isMedia(), JumpMode.MEDIA);
+ }
+
+ public void nextHeader1() {
+ findNext(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading1()), JumpMode.HEADING);
+ }
+
+ public void nextHeader2() {
+ findNext(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading2()), JumpMode.HEADING);
+ }
+
+ public void nextHeader3() {
+ findNext(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading3()), JumpMode.HEADING);
+ }
+
+ public void nextHeader4() {
+ findNext(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading4()), JumpMode.HEADING);
+ }
+
+ public void nextHeader5() {
+ findNext(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading5()), JumpMode.HEADING);
+ }
+
+ public void nextHeader6() {
+ findNext(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading6()), JumpMode.HEADING);
+ }
+
+ public void previousHeader1() {
+ findPrevious(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading1()), JumpMode.HEADING);
+ }
+
+ public void previousHeader2() {
+ findPrevious(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading2()), JumpMode.HEADING);
+ }
+
+ public void previousHeader3() {
+ findPrevious(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading3()), JumpMode.HEADING);
+ }
+
+ public void previousHeader4() {
+ findPrevious(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading4()), JumpMode.HEADING);
+ }
+
+ public void previousHeader5() {
+ findPrevious(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading5()), JumpMode.HEADING);
+ }
+
+ public void previousHeader6() {
+ findPrevious(Vocabulary.and(Vocabulary.isHeading(), Vocabulary.isHeading6()), JumpMode.HEADING);
+ }
+
+ public void jumpToAccessKey(final char key) {
+ moveCmd(new Command() {
+ ILocation current;
+ public int run(int r) throws TreeManagerException {
+ startProgress();
+ current = getLocation();
+ return treeManager.findNext(Vocabulary.isAccessKey(key));
+ }
+
+ public void after(int st) throws TreeManagerException {
+ if ((st & ITreeManager.MOVED) == 0) {
+ moveCmd(new Command() {
+ public int run(int r) throws TreeManagerException {
+ treeManager.gotoStartOfPage();
+ return treeManager.findNext(Vocabulary.isAccessKey(key));
+ }
+
+ public void after(int st) throws TreeManagerException {
+ if ((st & ITreeManager.MOVED) == 0){
+ treeManager.moveToLocation(current);
+ afterFind(st, JumpMode.ACCESSKEY, key);
+ }
+ else
+ afterAccessKeyJump(st);
+ endProgress();
+ }
+ });
+ } else {
+ afterAccessKeyJump(st);
+ endProgress();
+ }
+ }
+ });
+ }
+
+ private void afterAccessKeyJump(int st) throws TreeManagerException {
+ ITreeItem item = treeManager.getActiveItem();
+
+ boolean isCheckbox = Vocabulary.isCheckbox().eval(item);
+ boolean isRadio = Vocabulary.isRadio().eval(item);
+
+ if (isRadio || isCheckbox) {
+ click();
+ speakActiveItem(true, false, JumpMode.NONE);
+ } else {
+ afterMove(st, "Navigator.BOTTOM", JumpMode.ACCESSKEY);
+ }
+ }
+
+ public void showAccessKeyList() {
+ try {
+ setMode(IManipulator.KEYHOOK_DISABLED_MODE);
+ IAccessKeyList list = treeManager.getAccessKeyList();
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+
+ AccessKeyListDialog dialog = new AccessKeyListDialog(shell, list);
+
+ if (dialog.open() == InputDialog.OK) {
+ char key = dialog.getSelectedKey();
+ if (key != 0)
+ jumpToAccessKey(key);
+ }
+ setMode(IManipulator.TREE_NAVIGATION_MODE);
+ } catch (TreeManagerException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void searchNext() {
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ SearchDialog dialog = new SearchDialog(shell);
+ dialog.setForward(true);
+ if (dialog.open() == Window.CANCEL || dialog.getString() == null || dialog.getString().length() == 0)
+ return;
+
+ moveCmd(new FindCommand(dialog.getString(), dialog.isForward(), dialog.isExact()));
+ }
+
+ public void searchPrevious() {
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ SearchDialog dialog = new SearchDialog(shell);
+ dialog.setForward(false);
+ if (dialog.open() == Window.CANCEL || dialog.getString() == null || dialog.getString().length() == 0)
+ return;
+
+ moveCmd(new FindCommand(dialog.getString(), dialog.isForward(), dialog.isExact()));
+ }
+
+ class FindCommand implements Command {
+ private String str;
+
+ private boolean direction;
+
+ private boolean exact;
+
+ FindCommand(String str, boolean direction, boolean exact) {
+ this.str = str;
+ this.direction = direction;
+ this.exact = exact;
+ }
+
+ public int run(int r) throws TreeManagerException {
+ if (direction)
+ return treeManager.findNext(Vocabulary.find(str, exact));
+ else
+ return treeManager.findPrevious(Vocabulary.find(str, exact));
+ }
+
+ public void after(int st) throws TreeManagerException {
+ if (direction)
+ afterMove(st, "Navigator.BOTTOM");
+ else
+ afterMove(st, "Navigator.TOP");
+ }
+ }
+
+ // --------------------------------------------------------------------------------
+ // Table Navigation
+ // --------------------------------------------------------------------------------
+
+ public void cellLeft() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void cellRight() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void cellUp() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void cellDown() {
+ // TODO Auto-generated method stub
+
+ }
+
+ // --------------------------------------------------------------------------------
+ // Speech Speed Control
+ // --------------------------------------------------------------------------------
+
+ private void saySpeechSpeed(int speed) {
+ String mes = getMessageFormatter().mes("Navigator.SPEECHSPEED",
+ new Object[] { new Integer(speed) });
+ speakWithFormat(mes, true);
+ }
+
+ public void speechSpeedUp() {
+ int nextSpeed = getVoiceManager().getSpeed() + 10;
+ if (IVoice.SPEED_MAX < nextSpeed) {
+ speakWithFormat("Navigator.SPEECHSPEEDMAX", true);
+ } else {
+ getVoiceManager().setSpeed(nextSpeed);
+ saySpeechSpeed(nextSpeed);
+ }
+ }
+
+ public void speechSpeedDown() {
+ int nextSpeed = getVoiceManager().getSpeed() - 10;
+ if (IVoice.SPEED_MIN > nextSpeed) {
+ speakWithFormat("Navigator.SPEECHSPEEDMIN", true);
+ } else {
+ getVoiceManager().setSpeed(nextSpeed);
+ saySpeechSpeed(nextSpeed);
+ }
+ }
+
+ // --------------------------------------------------------------------------------
+ // Form input mode.
+ // --------------------------------------------------------------------------------
+
+ public void exitFormMode() {
+ setMode(IManipulator.TREE_NAVIGATION_MODE);
+ }
+
+ public void submitForm() {
+ // TODO Auto-generated method stub
+ }
+
+
+ // --------------------------------------------------------------------------------
+ // Location Management
+ // --------------------------------------------------------------------------------
+
+ public ILocation getLocation() {
+ if (treeManager == null)
+ return null;
+ try {
+ return treeManager.getCurrentLocation();
+ } catch (TreeManagerException e) {
+ return null;
+ }
+ }
+
+ private ILocation locationToBeRestored;
+
+ public void restoreLocation(ILocation location) {
+ locationToBeRestored = location;
+ }
+
+ // --------------------------------------------------------------------------------
+ // IMediaControl.IHandle delegation class
+ // --------------------------------------------------------------------------------
+ private class MediaControlHandle implements IMediaControl.IHandle {
+ public ISoundControl getSoundControl() {
+ if (treeManager == null)
+ return null;
+ try {
+ return treeManager.getSoundControl();
+ } catch (TreeManagerException e) {
+ return null;
+ }
+ }
+
+ public IVideoControl getVideoControl() {
+ if (treeManager == null)
+ return null;
+ try {
+ return treeManager.getVideoControl();
+ } catch (TreeManagerException e) {
+ return null;
+ }
+ }
+
+ public IVoice getVoice() {
+ return NavigatorImpl.this.getVoiceManager();
+ }
+
+ public IWebBrowserACTF getWebBrowser() {
+ return webBrowser;
+ }
+ }
+
+ private MediaControlHandle handle = new MediaControlHandle();
+
+ IMediaControl.IHandle getMediaControlHandle() {
+ return handle;
+ }
+
+ public void toggleDescriptionEnable() {
+ int result = MediaControlExtension.toggleEnable();
+ switch (result) {
+ case IMediaControl.TOGGLE_FAIL:
+ speakWithFormat("AudioDescription.noExtension");
+ break;
+ case IMediaControl.STATUS_ON:
+ speakWithFormat("AudioDescription.on");
+ break;
+ case IMediaControl.STATUS_OFF:
+ speakWithFormat("AudioDescription.off");
+ break;
+ case IMediaControl.STATUS_NOT_AVAILABLE:
+ speakWithFormat("AudioDescription.notAvailable");
+ break;
+ }
+ }
+
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ MovieStartListener listener = null;
+
+ private void initializeMovieStartListener() {
+ IHandle mediaControlHandle = getMediaControlHandle();
+ final IVideoControl video = mediaControlHandle.getVideoControl();
+ if (listener != null) {
+ listener.stop();
+ }
+ listener = new MovieStartListener(video);
+ if (video != null) {
+ video.addEventListener(listener);
+ }
+ }
+
+ class MovieStartListener implements IMediaSyncEventListener {
+ IVideoControl video;
+
+ public MovieStartListener(IVideoControl video) {
+ this.video = video;
+ }
+
+ private boolean stopFlag = false;
+
+ public void stop() {
+ stopFlag = true;
+ }
+
+ public double getInterval() {
+ return 0.1;
+ }
+
+ private boolean topFlag = true;
+
+ public void run() {
+ if (stopFlag)
+ return;
+ double time = video.getCurrentPosition();
+ if (topFlag) {
+ // Heuristic solution.
+ // "stop" operation might locates nearly 0.001?. 0.1 avoids this situnation.
+ // 3.0 is a sentinel for waiting the completion of reloading and analyzing page content.
+ if (0.1 < time && time < 3.0) {
+ speakWithFormat("Navigator.MOVIE_START");
+ topFlag = false;
+ }
+ } else {
+ if (time < 0.1) {
+ topFlag = true;
+ }
+ }
+ }
+ }
+
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ public enum FocusTabResult {
+ STAY, CHANGED, NOTFOUND
+ }
+
+ public FocusTabResult focusTab() {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ IEditorReference[] erefs = page.getEditorReferences();
+ IEditorPart editor = page.getActiveEditor();
+
+ for (int i = 0; i < erefs.length; i++) {
+ IEditorPart part = erefs[i].getEditor(false);
+ IModelServiceHolder modelServiceHolder = (IModelServiceHolder) part;
+ IWebBrowserACTF wb = (IWebBrowserACTF) modelServiceHolder.getModelService();
+ if (wb == webBrowser) {
+ if (editor != part) {
+ page.activate(part);
+ return FocusTabResult.CHANGED;
+ }
+ return FocusTabResult.STAY;
+ }
+ }
+ return FocusTabResult.NOTFOUND;
+ }
+
+ public boolean isFocused() {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ IEditorReference[] erefs = page.getEditorReferences();
+ IEditorPart editor = page.getActiveEditor();
+
+ for (int i = 0; i < erefs.length; i++) {
+ IEditorPart part = erefs[i].getEditor(false);
+ IModelServiceHolder modelServiceHolder = (IModelServiceHolder) part;
+ IWebBrowserACTF wb = (IWebBrowserACTF) modelServiceHolder.getModelService();
+ if (wb == webBrowser) {
+ if (editor != part) {
+ return false;
+ }
+ return true;
+ }
+ }
+ // Should be regarded as an error.
+ System.err.println("Internal Error: WebBrowser:" + webBrowser + " is not managed in the editor");
+ return false;
+ }
+
+ public String getCurrentURL() {
+ return webBrowser.getURL();
+ }
+
+ // ----------------------------------------------------------------
+ // Browser Control
+ // ----------------------------------------------------------------
+
+ public void enterBrowserAddress() {
+ if (PlatformUIUtil.getActiveEditor() == null) {
+ speakWithFormat("Navigator.THERE_ARE_NO_TAB");
+ return;
+ }
+
+ webBrowser.setFocusAddressText(true);
+ speakWithFormat("Navigator.ENTERBROWSERADDRESS", false);
+ enterFormInputMode();
+ }
+
+ public void forceRestart(boolean flush) {
+ selectNVM3(false, flush);
+
+ // TODO
+ MediaControlExtension.doDispose(getMediaControlHandle());
+ MediaControlExtension.start(getMediaControlHandle());
+ initializeMovieStartListener();
+ }
+
+ public void forceRestart() {
+ forceRestart(true);
+ }
+
+ public void navigateRefresh() {
+ startProgress();
+ String buf = getMessageFormatter().mes("Navigator.REFRESH");
+ speak(buf, true, false);
+ webBrowser.navigateRefresh();
+ }
+
+ public void closeTab() {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ IEditorPart editor = page.getActiveEditor();
+
+ if (editor != null && editor instanceof IModelServiceHolder) {
+ ManipulatorExtension.setNavigator(null);
+ page.closeEditor(editor, false);
+ }
+ }
+
+ public void nextTab() {
+ gotoTab(1);
+ }
+
+ public void prevTab() {
+ gotoTab(-1);
+ }
+
+ private void gotoTab(int n) {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ IEditorReference[] erefs = page.getEditorReferences();
+ IEditorPart editor = page.getActiveEditor();
+
+ for (int i = 0; i < erefs.length; i++) {
+ if (erefs[i].getEditor(false).equals(editor)) {
+ n += i;
+
+ IEditorPart part;
+ if (n >= erefs.length) {
+ part = erefs[0].getEditor(false);
+ } else if (n < 0) {
+ part = erefs[erefs.length - 1].getEditor(false);
+ } else {
+ part = erefs[n].getEditor(false);
+ }
+ if (part != null) {
+ page.activate(part);
+ }
+ }
+ }
+ speakTab();
+ }
+
+
+ public void goBackward() {
+ webBrowser.goBackward();
+ }
+
+ public void goForward() {
+ webBrowser.goForward();
+ }
+
+ // It is used by the bridge.
+ public boolean gotoUrl(String url) {
+ webBrowser.navigate(url);
+ return true;
+ }
+
+ public void launchBrowser() {
+ BrowserLaunch.launch(webBrowser.getURL());
+ String buf = getMessageFormatter().mes("Navigator.LAUNCH_DEFAULT_BROWSER", webBrowser.getURL());
+ speak(buf, true, false);
+ }
+
+ public boolean isLeftViewsShown() {
+ return getNavigatorTreeView().isShown();
+ }
+
+ public void toggleLeftViewsShowing() {
+ boolean result = getNavigatorTreeView().toggleViewShowing();
+ boolean result2 = MediaControlExtension.toggleViewShowing();
+ while (result != result2)
+ result2 = MediaControlExtension.toggleViewShowing();
+
+ if (result)
+ speakWithFormat("Navigator.VIEWS_ARE_OPEND", true);
+ else
+ speakWithFormat("Navigator.VIEWS_ARE_CLOSED", true);
+ }
+
+ public void exportMetadata() {
+ if (getCurrentEntry() == null) {
+ speakWithFormat("Navigator.NO_ANNOTATION");
+ return;
+ }
+
+ String[] ext = { "*.fnc" };
+ speakWithFormat("Navigator.EXPORT_ANNOTATION");
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ FileDialog fileDialog = new FileDialog(shell, SWT.OPEN);
+ fileDialog.setFilterExtensions(ext);
+ String path = fileDialog.open();
+
+ if (path != null) {
+ if (!path.endsWith(".fnc")) {
+ path = path+".fnc";
+ }
+ File dest = new File(path);
+ if (dest.exists()) {
+ String title = getMessageFormatter().mes("Navigator.OVERWRITE_CONFIRM");
+ String message = getMessageFormatter().mes("Navigator.OVERWRITE_MESSAGE", dest.getName());
+ boolean ret = MessageDialog.openQuestion(shell, title, message);
+ if (!ret)
+ return;
+ }
+ if (getCurrentEntry().isUserEntry()) {
+ if (getCurrentEntry().export(dest)) {
+ speakWithFormat("Navigator.EXPORT_IS_SUCCEEDED");
+ } else {
+ speakWithFormat("Navigator.EXPORT_IS_FAILED");
+ }
+ }
+ }
+ }
+
+ public void repairFlash() {
+ startProgress(0);
+ try {
+ treeManager.repairFlash();
+ speakWithFormat("Navigator.REPAIR_FINISHED");
+ restoreLocation(getLocation());
+ selectNVM3(false, false, false);
+ } catch (TreeManagerException e) {
+ e.printStackTrace();
+ }
+ endProgress();
+ }
+
+ // ---------------------------------------------------------------
+ // Web Event
+ // ---------------------------------------------------------------
+
+ public void speakTitle(String title) {
+ try {
+ speak(title, true, true);
+ } catch (Exception e) {
+ }
+ }
+
+ public void speakTab() {
+ speakTab(true);
+ }
+
+ public void speakOpenTab() {
+ speakWithFormat(getMessageFormatter().mes("Navigator.NEW_TAB"));
+ }
+
+ public void navigateComplete() {
+ startProgress();
+ }
+
+ public void speakCloseTab(String title) {
+ speak(getMessageFormatter().mes("Navigator.CLOSE_TAB", title), true, true);
+ }
+
+ private long progressTimer = 0;
+
+ private static final int progressInterval = 2000;
+
+ private int prevPercent = -4;
+
+ void beforeNavigation(String uri) {
+ prevPercent = -4;
+ }
+
+ void progressChange(int progress, int progressMax) {
+ if (progressMax == 0)
+ return;
+ if (progress == -1) {
+ progressTimer = 0;
+ return;
+ }
+ long current = System.currentTimeMillis();
+
+ if (current - progressTimer > progressInterval * 5) {
+ prevPercent = -4;
+ }
+
+ if (progressMax < 10000) {
+ progressMax = 1000;
+ }
+ progressMax = (int) Math.pow(10, ((int) Math.log10(progressMax)) + 1);
+
+ int percent = (progress * 100) / progressMax;
+ if (progress * 10 == progressMax) {
+ percent = 100;
+ }
+
+ if ((progressTimer == 0) || ((current - progressTimer) >= progressInterval)) {
+ if (5 < percent && percent < 100) {
+ if (percent - prevPercent >= 5 || (prevPercent - percent > 10)) { // && prevPercent - percent < 50)) {
+ sayProgress(percent);
+
+ // System.out.println("Say " + percent);
+ prevPercent = percent;
+ progressTimer = current;
+ }
+ }
+ }
+ // System.out.println(progress + " / " + progressMax + ", " + percent + ", " + prevPercent);
+ }
+
+ private void sayProgress(int percent) {
+ if (percent < 0)
+ percent = 0;
+ else if (percent > 100)
+ percent = 100;
+ String mes = getMessageFormatter().mes("Navigator.PROGRESS", new Object[] { new Integer(percent) });
+ speak(mes, true, true);
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/NavigatorImplEx.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/NavigatorImplEx.java
new file mode 100644
index 0000000..6b81f4a
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/NavigatorImplEx.java
@@ -0,0 +1,292 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator.impl;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.fennec.treemanager.TreeManagerException;
+import org.eclipse.actf.ai.navigator.IManipulator;
+import org.eclipse.actf.ai.navigator.NavigatorPlugin;
+import org.eclipse.actf.ai.navigator.preferences.UserInfoPreferenceConstants;
+import org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier;
+import org.eclipse.actf.ai.navigator.userinfo.IUserInfoGenerator;
+import org.eclipse.actf.ai.navigator.userinfo.impl.AltInputDialog;
+import org.eclipse.actf.ai.navigator.userinfo.impl.AltTextEditor;
+import org.eclipse.actf.ai.navigator.userinfo.impl.AltTextGuesser;
+import org.eclipse.actf.ai.navigator.userinfo.impl.BrowserObserver;
+import org.eclipse.actf.ai.navigator.userinfo.impl.HeadingCanceller;
+import org.eclipse.actf.ai.navigator.userinfo.impl.LandmarkMaker;
+import org.eclipse.actf.ai.navigator.userinfo.impl.MetaDataModifier;
+import org.eclipse.actf.ai.navigator.util.ContentShortener;
+import org.eclipse.actf.ai.xmlstore.XMLStoreException;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.actf.util.ui.PlatformUIUtil;
+import org.eclipse.actf.util.vocab.Vocabulary;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+
+
+public class NavigatorImplEx extends NavigatorImpl {
+ private final IPreferenceStore preferenceStore;
+
+ private final ContentShortener contentShortener;
+
+ private final BrowserObserver observer;
+
+ private IWebBrowserACTF webBrowser;
+
+ public NavigatorImplEx(WebEventListener webEventListener,
+ IWebBrowserACTF webBrowser,
+ int maxRetry, int retryInterval) {
+ super(webEventListener, webBrowser, maxRetry, retryInterval);
+
+ this.webBrowser = webBrowser;
+ this.preferenceStore = NavigatorPlugin.getDefault().getPreferenceStore();
+ this.contentShortener = new ContentShortener(32, getMessageFormatter());
+ this.observer = new BrowserObserver(webBrowser);
+ }
+
+ public void saveUserInfo() {
+ if (getCurrentEntry() != null && !getCurrentEntry().isUserEntry()) {
+ speakUnavailableUserInfo();
+ return;
+ }
+ try {
+ IMetaDataModifier modifier = new MetaDataModifier();
+ // modifier.setGenerator(null);
+ modifier.setSite(observer.getTargetFilter());
+ modifier.setPageTitle(PlatformUIUtil.getActiveEditor().getTitle());
+ modifier.commit(true);
+ speakWithFormat("Navigator.ANNOTATION_IS_SAVED", true);
+ } catch (XMLStoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void guessAltText() {
+ if (getCurrentEntry() != null && !getCurrentEntry().isUserEntry()) {
+ speakUnavailableUserInfo();
+ return;
+ }
+ try {
+ ITreeItem item = getTreeManager().getCurrentRootItem();
+ setMode(IManipulator.KEYHOOK_DISABLED_MODE);
+ item.setFocus();
+ int k = guessAltTextIter(item);
+ if (k > 0) {
+ String mes = getMessageFormatter().mes("Navigator.ALT_TEXT_WERE_GUESSED", k);
+ speak(mes, true);
+ if (preferenceStore.getBoolean(UserInfoPreferenceConstants.AUTO_SAVE))
+ saveUserInfo();
+ if (preferenceStore.getBoolean(UserInfoPreferenceConstants.AUTO_REFRESH))
+ refresh();
+ }
+ else {
+ speakWithFormat("Navigator.THERE_IS_NO_MISSING_ALT_TEXT", true);
+ }
+ item.setFocus();
+ setMode(IManipulator.TREE_NAVIGATION_MODE);
+ } catch (TreeManagerException e) {
+ e.printStackTrace();
+ } catch (XMLStoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private int guessAltTextIter(ITreeItem item) throws XMLStoreException {
+ int k = 0;
+ ITreeItem[] v = item.getChildItems();
+
+ for (int i = 0; i < v.length; i++) {
+ ITreeItem c = v[i];
+ k += guessAltTextIter(c);
+ }
+
+ if (!Vocabulary.isAlterable().eval(item)) {
+ return k;
+ }
+
+ if (isGoodAltText(item.getUIString())) {
+ return k;
+ }
+
+ AltTextGuesser guesser = new AltTextGuesser(webBrowser, item);
+ String newText = guesser.guessByContext();
+
+ if (newText == null || newText.length() == 0) {
+ return k;
+ }
+
+ IMetaDataModifier modifier = new MetaDataModifier();
+ modifier.setGenerator(new AltTextEditor());
+ modifier.setSite(observer.getTargetFilter());
+ modifier.setPageTitle(PlatformUIUtil.getActiveEditor().getTitle());
+ modifier.setItem(item);
+
+ modifier.setText(getMessageFormatter().mes("Navigator.ANNOTATION_LINK_TO", newText));
+ IUserInfoGenerator.Result result = modifier.commit(false);
+
+ if (result != IUserInfoGenerator.Result.NOTHING)
+ ++k;
+
+ return k;
+ }
+
+ private boolean isGoodAltText(String s) {
+ return s.length() > 0;
+ }
+
+ public void nextAlterable() {
+ if (getCurrentEntry() != null && !getCurrentEntry().isUserEntry()) {
+ speakUnavailableUserInfo();
+ return;
+ }
+ findNext(Vocabulary.isAlterable(), JumpMode.ALTALABLE);
+ }
+
+ public void previousAlterable() {
+ if (getCurrentEntry() != null && !getCurrentEntry().isUserEntry()) {
+ speakUnavailableUserInfo();
+ return;
+ }
+ findPrevious(Vocabulary.isAlterable(), JumpMode.ALTALABLE);
+ }
+
+ public void editAltText() {
+ if (getCurrentEntry() != null && !getCurrentEntry().isUserEntry()) {
+ speakUnavailableUserInfo();
+ return;
+ }
+
+ try {
+// refresh();
+ ITreeItem item = getTreeManager().getActiveItem();
+ if (item == null)
+ return;
+ if (Vocabulary.isAlterable().eval(item)) {
+ setMode(IManipulator.KEYHOOK_DISABLED_MODE);
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ // String oldText = item.getUIString();
+ // AltInputDialog dialog = new AltInputDialog(shell, oldText.length() > 0 ? oldText : "(no ALT text)");
+ AltInputDialog dialog = new AltInputDialog(shell, item.getUIString());
+
+ if (dialog.open() == InputDialog.OK) {
+ String newText = dialog.getResult();
+ if (newText != null) {
+ IMetaDataModifier modifier = new MetaDataModifier();
+ modifier.setGenerator(new AltTextEditor());
+ modifier.setSite(observer.getTargetFilter());
+ modifier.setPageTitle(PlatformUIUtil.getActiveEditor().getTitle());
+ modifier.setItem(item);
+ modifier.setText(newText);
+ IUserInfoGenerator.Result result = modifier.commit(preferenceStore
+ .getBoolean(UserInfoPreferenceConstants.AUTO_SAVE));
+// if (result != IUserInfoGenerator.Result.NOTHING) {
+ if (preferenceStore.getBoolean(UserInfoPreferenceConstants.AUTO_REFRESH))
+ refresh();
+ speak(getMessageFormatter().mes(modifier.toString(result),
+ newText),
+ true, false);
+// }
+ }
+ }
+
+ setMode(IManipulator.TREE_NAVIGATION_MODE);
+ } else {
+ speakWithFormat("Navigator.ITEM_IS_NOT_AVAILABLE", true);
+ }
+ } catch (TreeManagerException e) {
+ e.printStackTrace();
+ } catch (XMLStoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void speakUnavailableUserInfo() {
+ speakWithFormat("Navigator.ANNOTATION_IS_NOT_AVAILABLE", true);
+ }
+
+ public void makeLandmark() {
+ if (getCurrentEntry() != null && !getCurrentEntry().isUserEntry()) {
+ speakUnavailableUserInfo();
+ return;
+ }
+ try {
+ ITreeItem item = getTreeManager().getActiveItem();
+ IMetaDataModifier modifier = new MetaDataModifier();
+ modifier.setGenerator(getHeadingLevelOf(item) > 0 ? new HeadingCanceller() : new LandmarkMaker());
+ // modifier.setGenerator(Vocabulary.isHeading().eval(item) ? new HeadingCanceller() : new LandmarkMaker());
+ modifier.setSite(observer.getTargetFilter());
+ modifier.setPageTitle(PlatformUIUtil.getActiveEditor().getTitle());
+ modifier.setItem(item);
+ IUserInfoGenerator.Result result = modifier.commit(preferenceStore
+ .getBoolean(UserInfoPreferenceConstants.AUTO_SAVE));
+ if (preferenceStore.getBoolean(UserInfoPreferenceConstants.AUTO_REFRESH))
+ refresh();
+
+ speak(getMessageFormatter().mes(modifier.toString(result),
+ contentShortener.getSummary(item, true)),
+ true, false);
+ } catch (TreeManagerException e) {
+ e.printStackTrace();
+ } catch (XMLStoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private short getHeadingLevelOf(ITreeItem item) {
+ short level = 0;
+ for (ITreeItem i = item; i != null; i = i.getParent()) {
+ short k = i.getHeadingLevel();
+ if (k < 0)
+ return k;
+ if (k > 0)
+ level = k;
+ }
+ return level;
+ }
+
+ private void refresh() throws TreeManagerException {
+ selectUserNVM3();
+ }
+
+ public void removeUserInfo() {
+ if (getCurrentEntry() == null) {
+ speakWithFormat("Navigator.NO_ANNOTATION");
+ return;
+ }
+
+ try {
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+
+ String title = getMessageFormatter().mes("Navigator.USER_INFO_REMOVE_CONFIRM");
+ String message = getMessageFormatter().mes("Navigator.USER_INFO_REMOVE_MESSAGE");
+ boolean ret = MessageDialog.openQuestion(shell, title, message);
+ if (!ret)
+ return;
+
+ IMetaDataModifier modifier = new MetaDataModifier();
+ modifier.setSite(observer.getTargetFilter());
+ modifier.setPageTitle(PlatformUIUtil.getActiveEditor().getTitle());
+ if (modifier.remove()) {
+ speakWithFormat("Navigator.ANNOTATION_IS_REMOVED", true);
+ forceRestart(false);
+ } else {
+ speakWithFormat("Navigator.NO_ANNOTATION", true);
+ }
+ } catch (XMLStoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/SearchDialog.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/SearchDialog.java
new file mode 100644
index 0000000..9c70d95
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/SearchDialog.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.impl;
+
+import org.eclipse.actf.ai.navigator.Messages;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+
+
+
+public class SearchDialog extends Dialog {
+ private static String formInputString = "";
+
+ private Text searchField;
+
+ private Button forwardRadio;
+
+ private Button backwardRadio;
+
+ private Button exactButton;
+
+ private static boolean isForward = true;
+
+ private static boolean exact = false;
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+
+ newShell.setText(Messages.getString("FormInputDialog.Search"));
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite container = (Composite) super.createDialogArea(parent);
+ GridData gd;
+ searchField = new Text(container, SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 400;
+ gd.horizontalSpan = ((GridLayout) parent.getLayout()).numColumns;
+ searchField.setLayoutData(gd);
+ searchField.setText(formInputString);
+ searchField.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ formInputString = searchField.getText();
+ }
+ });
+
+ backwardRadio = new Button(container, SWT.RADIO);
+ backwardRadio.setSelection(!isForward);
+ backwardRadio.setText(Messages.getString("FormInputDialog.Backward"));
+ backwardRadio.addSelectionListener(new SelectionListener(){
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent e) {
+ isForward = false;
+ }
+ });
+
+ forwardRadio = new Button(container, SWT.RADIO);
+ forwardRadio.setText(Messages.getString("FormInputDialog.Forward"));
+ forwardRadio.setSelection(isForward);
+ forwardRadio.addSelectionListener(new SelectionListener(){
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent e) {
+ isForward = true;
+ }
+ });
+
+ exactButton = new Button(container, SWT.CHECK);
+ exactButton.setSelection(exact);
+ exactButton.setText(Messages.getString("FormInputDialog.Exact"));
+ exactButton.addSelectionListener(new SelectionListener(){
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent e) {
+ exact = exactButton.getSelection();
+ }
+ });
+ searchField.setFocus();
+ searchField.setSelection(0, formInputString.length());
+
+ return container;
+ }
+
+ String getString() {
+ return formInputString;
+ }
+
+ boolean isForward(){
+ return isForward;
+ }
+
+ boolean isExact(){
+ return exact;
+ }
+
+ SearchDialog(Shell parent) {
+ super(parent);
+ }
+
+ public void setForward(boolean b) {
+ isForward = b;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/TripJournal.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/TripJournal.java
new file mode 100644
index 0000000..fa09c3f
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/TripJournal.java
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.impl;
+
+import org.eclipse.actf.ai.fennec.treemanager.ILocation;
+import org.eclipse.actf.ai.navigator.impl.NavigatorImpl.FocusTabResult;
+import org.eclipse.actf.ai.navigator.voice.VoiceManager;
+
+
+
+
+class TripJournal {
+ private static final boolean DEBUG = false;
+ private static final int JOURNAL_SIZE = 1024;
+
+ private static final VoiceManager voice = new VoiceManager(null);
+
+ private static class TripJournalItem {
+ final NavigatorImpl navigator;
+ final ILocation location;
+ final String url;
+
+ TripJournalItem(NavigatorImpl navigator,
+ ILocation location,
+ String url) {
+ this.navigator = navigator;
+ this.location = location;
+ this.url = url;
+ }
+ }
+
+ private int startIdx = 0;
+ private int endIdx = 0;
+ private int currentIdx = 0;
+ private int recordIdx = 0;
+ private TripJournalItem[] tripJournalItems = new TripJournalItem[JOURNAL_SIZE];
+
+ private boolean backwarding;
+ private boolean forwarding;
+
+
+ private int incrementIdx(int idx) {
+ idx++;
+ if (idx == tripJournalItems.length) {
+ idx = 0;
+ }
+ return idx;
+ }
+
+ private int decrementIdx(int idx) {
+ if (idx == 0) {
+ idx = tripJournalItems.length;
+ }
+ return --idx;
+ }
+
+ private void recordInPlay(NavigatorImpl navigator,
+ ILocation location,
+ String url) {
+ TripJournalItem tjiOld = tripJournalItems[recordIdx];
+ if ((location == null) && (tjiOld != null)) {
+ location = tjiOld.location;
+ }
+ TripJournalItem tji = new TripJournalItem(navigator, location, url);
+ tripJournalItems[recordIdx] = tji;
+ }
+
+ public void recordJournal(NavigatorImpl navigator,
+ ILocation location,
+ String url,
+ boolean init) {
+ if (init) {
+ if (DEBUG) System.err.println("Record-I");
+ currentIdx = incrementIdx(currentIdx);
+ endIdx = currentIdx;
+ tripJournalItems[currentIdx] = new TripJournalItem(navigator, location, url);
+ return;
+ }
+
+ if (!navigator.isFocused()) {
+ if (DEBUG) System.err.println("Not Recorded (out of focus)");
+ return;
+ }
+
+ if (backwarding) {
+ if (DEBUG) System.err.println("Record-B!");
+ recordInPlay(navigator, location, url);
+ backwarding = false;
+ } else if (forwarding) {
+ if (DEBUG) System.err.println("Record-F!");
+ recordInPlay(navigator, location, url);
+ forwarding = false;
+ } else {
+ if (DEBUG) System.err.println("Record!:" + url);
+ TripJournalItem tjiOld = tripJournalItems[currentIdx];
+ if (tjiOld != null) {
+ if (DEBUG) System.err.println("Old-URL:" + tjiOld.url);
+ if (url != null) {
+ if (url.equals(tjiOld.url)) return;
+ }
+ }
+ TripJournalItem tji = new TripJournalItem(navigator, location, url);
+ tripJournalItems[currentIdx] = tji;
+ currentIdx = incrementIdx(currentIdx);
+ endIdx = currentIdx;
+ if (startIdx == endIdx) {
+ startIdx = incrementIdx(startIdx);
+ }
+ }
+ }
+
+ TripJournal() {
+ }
+
+ // --------------------------------------------------------------------------------
+ // Browser Control
+ // --------------------------------------------------------------------------------
+
+ private void sayForward() {
+ voice.speakWithFormat("TripJournal.FORWARD", true, false);
+ }
+
+ private void sayForwardFailed() {
+ voice.speakWithFormat("TripJournal.FAILEDTOFORWARD", true, false);
+ }
+
+ public void forward(NavigatorImpl currentNavigartor) {
+ //if (backwarding || forwarding) return;
+ recordIdx = currentIdx;
+ int idxFwd = currentIdx;
+ for (;;) {
+ if (idxFwd == endIdx) {
+ sayForwardFailed();
+ return;
+ }
+ idxFwd = incrementIdx(idxFwd);
+ TripJournalItem tji = tripJournalItems[idxFwd];
+ if (tji == null) {
+ // This must not happen, but navigateComplete failed to record a trip log
+ // and the entry may be possibly missing. So try to emulate the forwarding.
+ forwarding = true;
+ currentIdx = idxFwd;
+ currentNavigartor.goForward();
+ currentNavigartor.restoreLocation(null);
+ return;
+ }
+ switch (tji.navigator.focusTab()) {
+ case STAY:
+ // Notice that it will invoke recordJournal method;
+ forwarding = true;
+ currentIdx = idxFwd;
+ tji.navigator.goForward();
+ tji.navigator.restoreLocation(tji.location);
+ sayForward();
+ return;
+ case CHANGED:
+ currentIdx = idxFwd;
+ sayForward();
+ return;
+ case NOTFOUND:
+ break;
+ }
+ }
+ }
+
+ private void sayBackward() {
+ voice.speakWithFormat("TripJournal.BACKWARD", true, false);
+ }
+
+ private void sayBackwardFailed() {
+ voice.speakWithFormat("TripJournal.FAILEDTOBACKWARD", true, false);
+ }
+
+ public void backward(NavigatorImpl currentNavigator) {
+ //if (backwarding || forwarding) return;
+ recordIdx = currentIdx;
+ int idxBack = currentIdx;
+ if (DEBUG) System.err.println("back:" + currentIdx);
+ for (;;) {
+ if (idxBack == startIdx) {
+ sayBackwardFailed();
+ return;
+ }
+ idxBack = decrementIdx(idxBack);
+ TripJournalItem tji = tripJournalItems[idxBack];
+ if (tji == null) {
+ // Since the item was not recorded, focus the previous item.
+ if (idxBack == startIdx) {
+ sayBackwardFailed();
+ return;
+ }
+ currentIdx = idxBack;
+ idxBack = decrementIdx(idxBack);
+ tji = tripJournalItems[idxBack];
+ if (tji != null) {
+ tji.navigator.focusTab();
+ }
+ sayBackward();
+ return;
+ }
+ switch (tji.navigator.focusTab()) {
+ case STAY:
+ // Notice that it will invoke recordJournal method;
+ backwarding = true;
+ currentIdx = idxBack;
+ tji.navigator.goBackward();
+ tji.navigator.restoreLocation(tji.location);
+ sayBackward();
+ return;
+ case CHANGED:
+ if (currentNavigator == null) {
+ endIdx = idxBack;
+ } else {
+ ILocation location = currentNavigator.getLocation();
+ int idx = incrementIdx(idxBack);
+ tripJournalItems[idx] = new TripJournalItem(currentNavigator,
+ location,
+ currentNavigator.getCurrentURL());
+ }
+ currentIdx = idxBack;
+ sayBackward();
+ return;
+ case NOTFOUND:
+ break;
+ }
+ }
+ }
+
+ public void tripEnd() {
+ forwarding = false;
+ backwarding = false;
+ }
+
+ public void refreshEnd() {
+ TripJournalItem tji = tripJournalItems[currentIdx];
+ if (tji == null) return;
+ if (tji.navigator.focusTab() == FocusTabResult.STAY) {
+ tji.navigator.restoreLocation(tji.location);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/WebEventListener.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/WebEventListener.java
new file mode 100644
index 0000000..889a943
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/impl/WebEventListener.java
@@ -0,0 +1,345 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator.impl;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.HashMap;
+
+import org.eclipse.actf.ai.fennec.INVM3Mediator;
+import org.eclipse.actf.ai.fennec.NVM3Plugin;
+import org.eclipse.actf.ai.fennec.treemanager.ILocation;
+import org.eclipse.actf.ai.navigator.NavigatorPlugin;
+import org.eclipse.actf.ai.navigator.broker.RequestBroker;
+import org.eclipse.actf.ai.navigator.extension.ManipulatorExtension;
+import org.eclipse.actf.ai.navigator.extension.MediaControlExtension;
+import org.eclipse.actf.ai.navigator.extension.ScreenReaderExtension;
+import org.eclipse.actf.model.IModelServiceHolder;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.actf.model.events.IWebBrowserACTFEventListener;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+
+public class WebEventListener implements IWebBrowserACTFEventListener {
+
+ private static final String ABOUT_BLANK_URL = "about:blank";
+
+ private NVM3Plugin getNVM3Plugin() {
+ return NVM3Plugin.getDefault();
+ }
+
+ // --------------------------------------------------------------------------------
+ // Browser State: It keeps the state of the browser by receiving Web Browser
+ // Events. In overall, we should encapsulate the stateful information around the browser
+ // into this class.
+ // --------------------------------------------------------------------------------
+ public class BrowserState {
+ public static final int STATE_NONE = -1;
+
+ public static final int STATE_UNINIT = 0;
+
+ public static final int STATE_PROGRESS = 1;
+
+ public static final int STATE_NAVIGATECOMPLETED = 3;
+
+ public static final int STATE_STARTED = 10;
+
+ boolean shouldRecord;
+ boolean initFlag;
+ ILocation savedLocation;
+ ILocation savedLocationForMyRefresh;
+
+ NavigatorImpl navigator;
+
+ public NavigatorImpl getNavigator() {
+ return navigator;
+ }
+
+ int state;
+
+
+ public int getState() {
+ return state;
+ }
+
+ void resetState() {
+ this.state = STATE_UNINIT;
+ }
+
+ void setNoState() {
+ this.state = STATE_NONE;
+ }
+
+ void forwardState(int newst) {
+ if (this.state < newst) this.state = newst;
+ }
+
+ BrowserState(IWebBrowserACTF webBrowser) {
+ this.navigator = new NavigatorImplEx(WebEventListener.this, webBrowser, 30, 1000);
+ NavigatorPlugin.getDefault().setNavigatorUI(this.navigator);
+ this.state = STATE_NONE;
+ }
+ }
+
+ private HashMap<IWebBrowserACTF, BrowserState> browserStateMap;
+
+ private RequestBroker requestBroker;
+
+ private final TripJournal tripJournal;
+
+ private final BrowserControlImpl browserControl;
+
+ public WebEventListener() {
+ this.browserStateMap = new HashMap<IWebBrowserACTF, BrowserState>();
+ this.tripJournal = new TripJournal();
+ this.browserControl = new BrowserControlImpl(this, this.tripJournal);
+ IWebBrowserACTF.WebBrowserNavigationEventListnerHolder.LISTENER = this.browserControl;
+ ManipulatorExtension.setBrowserControl(this.browserControl);
+
+ requestBroker = new RequestBroker(this);
+ }
+
+ public synchronized BrowserState getBrowserState(IWebBrowserACTF webBrowser) {
+ BrowserState bs = browserStateMap.get(webBrowser);
+ if (bs == null) {
+ bs = new BrowserState(webBrowser);
+ browserStateMap.put(webBrowser, bs);
+ }
+ return bs;
+ }
+
+ public void forceRestart(IWebBrowserACTF webBrowser) {
+ startNavigation(webBrowser, false);
+ }
+
+ public NavigatorImpl getFocused() {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ IEditorPart editor = page.getActiveEditor();
+
+ if (editor == null) return null;
+ IModelServiceHolder modelServiceHolder = (IModelServiceHolder) editor;
+ IWebBrowserACTF wb = (IWebBrowserACTF) modelServiceHolder.getModelService();
+ BrowserState bs = browserStateMap.get(wb);
+ if (bs == null) return null;
+
+ return bs.getNavigator();
+ }
+
+ // --------------------------------------------------------------------------------
+ // Event Handlers
+ // --------------------------------------------------------------------------------
+
+ private static final boolean EVENT_DEBUG = false;
+
+ private void startNavigation(IWebBrowserACTF webBrowser) {
+ startNavigation(webBrowser, false);
+ }
+
+ private void startNavigation(IWebBrowserACTF webBrowser, boolean isRefresh) {
+ tripJournal.tripEnd();
+ BrowserState bs = getBrowserState(webBrowser);
+ if (bs.state >= BrowserState.STATE_STARTED)
+ return;
+
+ if (EVENT_DEBUG) System.err.println(webBrowser.getURL() + ", isRefresh=" + isRefresh + ", " + webBrowser);
+
+ if (bs.state == BrowserState.STATE_STARTED) {
+ MediaControlExtension.doDispose(bs.navigator.getMediaControlHandle());
+ }
+ MediaControlExtension.start(bs.navigator.getMediaControlHandle());
+
+ INVM3Mediator mediator = getNVM3Plugin().newNVM3Mediator(webBrowser);
+ bs.navigator.setNVM3Mediator(mediator);
+ bs.navigator.startNavigation(webBrowser, !isRefresh);
+ requestBroker.setNavigator(bs.navigator, webBrowser);
+
+ bs.forwardState(BrowserState.STATE_STARTED);
+ requestBroker.newPageReady();
+ }
+
+ private static final String FILE_SCHEME_SUFFIX = "file:///";
+ private String unifyURLFileScheme(String url) {
+ if (url.startsWith(FILE_SCHEME_SUFFIX)) {
+ url = url.substring(FILE_SCHEME_SUFFIX.length());
+ try {
+ url = URLDecoder.decode(url, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ return url.replace('/', '\\');
+ }
+ return url;
+ }
+
+ private boolean urlEquals(String url1, String url2) {
+ if ((url1 == null) || (url2 == null)) return false;
+ return unifyURLFileScheme(url1).equals(unifyURLFileScheme(url2));
+ }
+
+ public void navigateComplete(IWebBrowserACTF webBrowser, String url) {
+ if (EVENT_DEBUG) System.out.println("navigateComplete " + url + ", "
+ + webBrowser.getURL() + " | " + webBrowser);
+
+ if (!urlEquals(url, webBrowser.getURL())) return;
+
+ BrowserState bs = getBrowserState(webBrowser);
+ if ((bs.shouldRecord)
+ && (bs.state < BrowserState.STATE_NAVIGATECOMPLETED)) {
+ tripJournal.recordJournal(bs.navigator,
+ bs.savedLocation,
+ webBrowser.getURL(),
+ bs.initFlag);
+ }
+ bs.forwardState(BrowserState.STATE_NAVIGATECOMPLETED);
+ bs.navigator.navigateComplete();
+ }
+
+ public void titleChange(IWebBrowserACTF webBrowser, String title) {
+ if (EVENT_DEBUG) System.out.println("titleChange " + title + ", "+ webBrowser);
+
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+
+ IEditorPart editor = page.getActiveEditor();
+ if (editor instanceof IModelServiceHolder) {
+ if (webBrowser != ((IModelServiceHolder) editor).getModelService()) {
+ return;
+ }
+ }
+
+ setWindowTitle(title);
+ }
+
+ public void dispose() {
+ }
+
+ public void progressChange(IWebBrowserACTF webBrowser, int progress, int progressMax) {
+ if (EVENT_DEBUG) System.out.println("progressChange progress=" + progress + ", progressMax=" + progressMax + ", " + webBrowser);
+ BrowserState bs = getBrowserState(webBrowser);
+ bs.forwardState(BrowserState.STATE_PROGRESS);
+ bs.navigator.progressChange(progress, progressMax);
+ }
+
+ public void myDocumentComplete(IWebBrowserACTF webBrowser) {
+ if (EVENT_DEBUG) System.out.println("myDocumentComplete " + webBrowser);
+ BrowserState bs = getBrowserState(webBrowser);
+
+ if (!(ABOUT_BLANK_URL.equals(webBrowser.getURL()))) {
+ bs.navigator.speakTab(false);
+ startNavigation(webBrowser);
+ } else {
+ bs.setNoState();
+ }
+ }
+
+ public void focusChange(IWebBrowserACTF webBrowser) {
+ if (EVENT_DEBUG) System.out.println("focusChange " + webBrowser);
+ BrowserState bs = getBrowserState(webBrowser);
+ ManipulatorExtension.setNavigator(bs.navigator);
+ requestBroker.setNavigator(bs.navigator, webBrowser);
+ MediaControlExtension.start(bs.navigator.getMediaControlHandle());
+ setWindowTitle();
+ }
+
+ private void setWindowTitle(String title) {
+ String productName = Platform.getProduct().getName();
+ PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().setText(title + " - " + productName);
+ }
+
+ private void setWindowTitle() {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ String title = page.getActiveEditor().getTitle();
+ setWindowTitle(title);
+ }
+
+ public void beforeNavigate(IWebBrowserACTF webBrowser,
+ String url,
+ String targetFrameName,
+ boolean isInNavigation) {
+ if (EVENT_DEBUG) System.out.println("beforeNavigate " + url + ", " + targetFrameName + ", isInNavigation=" + isInNavigation);
+ BrowserState bs = getBrowserState(webBrowser);
+ //if (isInNavigation) {
+ if (!url.startsWith("javascript")) {
+ if (!(ABOUT_BLANK_URL.equals(url))) {
+ if (bs.state == BrowserState.STATE_NONE) {
+ bs.initFlag = true;
+ } else {
+ bs.initFlag = false;
+ }
+ bs.shouldRecord = true;
+ bs.savedLocation = bs.navigator.getLocation();
+ } else {
+ bs.shouldRecord = false;
+ }
+ bs.resetState();
+ bs.navigator.beforeNavigation(webBrowser.getURL());
+ } else {
+ bs.shouldRecord = false;
+ }
+ ScreenReaderExtension.takeBackControl(webBrowser);
+ }
+
+ public void browserDisposed(IWebBrowserACTF webBrowser, String title) {
+ if (EVENT_DEBUG) System.out.println("browserDisposed " + title);
+ BrowserState bs = getBrowserState(webBrowser);
+ bs.navigator.speakCloseTab(title);
+
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+ if ((page == null) || (page.getActiveEditor() == null)) {
+ setWindowTitle("No Tab");
+ }
+ }
+
+ public void myRefresh(IWebBrowserACTF webBrowser) {
+ if (EVENT_DEBUG) System.out.println("myRefresh " + webBrowser);
+ BrowserState bs = getBrowserState(webBrowser);
+ bs.resetState();
+ bs.savedLocationForMyRefresh = bs.navigator.getLocation();
+ bs.navigator.beforeNavigation(webBrowser.getURL());
+ }
+
+ public void myRefreshComplete(IWebBrowserACTF webBrowser) {
+ if (EVENT_DEBUG) System.out.println("Refresh Complete " + webBrowser);
+ BrowserState bs = getBrowserState(webBrowser);
+ bs.navigator.restoreLocation(bs.savedLocationForMyRefresh);
+ startNavigation(webBrowser, true);
+ }
+
+ public void navigateStop(IWebBrowserACTF webBrowser) {
+ if (EVENT_DEBUG) System.out.println("navigateStop " + webBrowser);
+ }
+
+ public void focusGainedOfAddressText(IWebBrowserACTF webBrowser) {
+ if (EVENT_DEBUG) System.out.println("focusGainedOfAddressText " + webBrowser);
+ BrowserState bs = getBrowserState(webBrowser);
+ bs.navigator.enterBrowserAddress();
+ }
+
+ public void focusLostOfAddressText(IWebBrowserACTF webBrowser) {
+ if (EVENT_DEBUG) System.out.println("focusLostOfAddressText " + webBrowser);
+ BrowserState bs = getBrowserState(webBrowser);
+ bs.navigator.exitFormMode();
+ }
+
+ public void newWindow(IWebBrowserACTF webBrowser) {
+ if (EVENT_DEBUG) System.out.println("newWindow " + webBrowser);
+ BrowserState bs = getBrowserState(webBrowser);
+ bs.navigator.speakOpenTab();
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/message/Speech.properties b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/message/Speech.properties
new file mode 100644
index 0000000..1e5db03
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/message/Speech.properties
@@ -0,0 +1,179 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Hisashi MIYASHITA, Daisuke SATO - initial configuration.
+###############################################################################
+
+Navigator.LINK=Link
+Navigator.VISITED_LINK=Visited link
+Navigator.HEADING=Heading
+Navigator.LIST_TOP=List of {0} items
+Navigator.BUTTON=Button
+Navigator.TEXTBOX=Edit
+Navigator.TEXTAREA=Multiline edit contains text
+Navigator.TEXTAREA_EMPTY=Multiline edit
+Navigator.PASSWORD=password edit
+Navigator.FILE_UPLOAD=File upload edit
+Navigator.CHECKED=Checked
+Navigator.NOT_CHECKED=Not checked
+Navigator.CHECKBOX=Check box
+Navigator.RADIO=Radio button
+Navigator.COMBO_BOX=Combo box
+Navigator.COMBO_BOX_NOSELECTION=no selection
+
+Navigator.MEDIA=Multimedia
+
+Navigator.PASSWORD_STAR3=star star star
+Navigator.WRAPPING_TO_TOP=wrapping to top
+Navigator.WRAPPING_TO_BOTTOM=wrapping to top
+
+Navigator.NO_HEADING=No heading
+Navigator.NO_LISTITEM=No list item
+Navigator.NO_LINK=No link
+Navigator.NO_INPUT=No input
+Navigator.NO_BLOCK=No block
+Navigator.NO_OBJECT=No object
+Navigator.NO_SELECTION=No selection
+Navigator.NO_ACCESSKEY=No access key {0}
+Navigator.NO_ALTALABLE=No item needs alt text
+Navigator.NO_MEDIA=No multimedia object
+
+Navigator.MSAA_FLASH_CONTENT=Flash Content
+Navigator.FLASH_CONTENT=Windowless Flash Content
+Navigator.FLASH_END=Flash Content End
+
+Navigator.VIEWS_ARE_OPEND=Tree view is opend
+Navigator.VIEWS_ARE_CLOSED=Tree view is closed
+
+Navigator.LAUNCH_DEFAULT_BROWSER=Launch Default Browser. {0}
+Navigator.CLOSE_TAB={0} is closed.
+Navigator.NEW_TAB=New tab is opend.
+Navigator.MOVE_TAB={0} {1} of {2} tabs
+
+Navigator.ACCESSKEY_GUIDE=Access key is Alt Shift {0}
+
+Navigator.REFRESH=Refresh Page
+
+Navigator.PROGRESS=Loading {0} percent.
+Navigator.STARTNAVIGATION=Page is loaded.
+Navigator.FENNEC_NAME=Fennec {0} is used.
+Navigator.SUBITEMS={0} sub-items
+Navigator.N_OF_M={0} of {1}
+Navigator.NO_SUBITEMS=No sub-items
+Navigator.NO_CONTROLS=No controls
+Navigator.NOT_AVAILABLE={0} is not available
+Navigator.TOP=Top item
+Navigator.BOTTOM=Last item
+Navigator.INPUTABLE=Inputable
+Navigator.LEVEL=Level {0}
+Navigator.TOP_LEVEL=Level zero
+Navigator.CLICK=Click
+Navigator.PLAY_TIME=Play time {0}
+Navigator.HH_MM_SS={2} hour {1} minutes {0} seconds
+Navigator.MM_SS={1} minutes {0} seconds
+Navigator.SS={0} seconds
+Navigator.KEYBOARD_ON=Keyboard navigation start
+Navigator.KEYBOARD_OFF=Keyboard navigation end
+Navigator.NOT_TABLE=Not in the table
+Navigator.UNDONE=work in progress
+Navigator.SPEECHSPEED=speech speed is {0}
+Navigator.SPEECHSPEEDMAX=speech speed is max
+Navigator.SPEECHSPEEDMIN=speech speed is min
+Navigator.NO_OTHER_FENNEC=Fennec meta data is not available
+Navigator.NO_FENNEC=
+Navigator.ENTERBROWSERADDRESS=Enter URI
+
+Navigator.NO_FENNEC_MESSAGE=No Fennec
+Navigator.NO_FENNEC_NAME=Anonymous
+
+Navigator.STOPMEDIA=stop
+Navigator.PLAYMEDIA=play
+Navigator.PAUSEMEDIA=pause
+Navigator.RESUMEMEDIA=resume
+Navigator.WAITINGMEDIA=waiting for media
+Navigator.FASTFORWARDMEDIA=fast forward
+Navigator.FASTREVERSEMEDIA=fast reverse
+Navigator.VOLUMEUP=volume up
+Navigator.VOLUMEDOWN=volume down
+Navigator.VOLUMEMAX=maximum volume
+Navigator.VOLUMEMIN=minimum volume
+Navigator.MUTEON=mute
+Navigator.MUTEOFF=mute off
+Navigator.CANNOT_PAUSE=can not pause
+Navigator.MOVIE_START=movie start
+
+Navigator.NOT_AVAILABEL=not available
+
+Navigator.NOVIDEO=No video
+Navigator.SINGLEVIDEO=one video
+Navigator.VIDEOCOUNT={0} videos
+Navigator.NOSOUND=No sound
+Navigator.SINGLESOUND=one sound
+Navigator.SOUNDCOUNT={0} sound
+Navigator.VIDEOINDEX={0} of {1} videos
+
+Navigator.VIDEO_AT=at {0}
+Navigator.VIDEO_TOTAL=Total length is {0}
+
+NVM3.EMPTY_PAGE=The page is empty.
+
+ContentShortener.VerbalForm={0} bla bla bla
+ContentShortener.NonVerbalForm={0} ...
+
+LandmarkMaker.Result.CREATED=a landmark was added here : {0}
+LandmarkMaker.Result.REMOVED=the heading now gets effective : {0}
+LandmarkMaker.Result.ERROR=Failed to set a landmark here : {0}
+LandmarkMaker.Result.NOTHING=a landmark is already added here : {0}
+
+HeadingCanceller.Result.CREATED=the heading was turned off : {0}
+HeadingCanceller.Result.REMOVED=the landmark was removed : {0}
+HeadingCanceller.Result.ERROR=Failed to remove the heading : {0}
+HeadingCanceller.Result.NOTHING=the heading is already turned off : {0}
+
+AltTextEditor.Result.CREATED=an alt text was added here : {0}
+AltTextEditor.Result.REMOVED=the alt text was removed
+AltTextEditor.Result.CHANGED=the alt text was edited : {0}
+AltTextEditor.Result.ERROR=Failed to edit the alt text
+
+AudioDescription.on=Audio Description is on
+AudioDescription.off=Audio Description is off
+AudioDescription.available=Audio Description is available
+AudioDescription.notAvailable=No Audio Description
+AudioDescription.noExtension=No Audio Description Extension
+
+Navigator.ANNOTATION_IS_NOT_AVAILABLE=Annotation function is not available
+Navigator.ANNOTATION_IS_SAVED=Annotation is saved
+Navigator.ALT_TEXT_WERE_GUESSED={0} ALT text were guessed
+Navigator.THERE_IS_NO_MISSING_ALT_TEXT=There is no missing ALT text
+Navigator.ANNOTATION_LINK_TO=Link to {0}
+Navigator.ITEM_IS_NOT_AVAILABLE=This item is not alterable
+Navigator.ANNOTATION_IS_REMOVED=All annotations are removed
+Navigator.NO_ANNOTATION=There is no annotation
+
+Navigator.USER_INFO_REMOVE_CONFIRM=Remove All User Annotation
+Navigator.USER_INFO_REMOVE_MESSAGE=Will you remove all user annotation from this page?
+
+Navigator.THERE_ARE_NO_TAB=There are no tabs, please use Control O.
+
+TripJournal.FORWARD=Forward
+TripJournal.FAILEDTOFORWARD=Cannot forward the page.
+TripJournal.BACKWARD=Backward
+TripJournal.FAILEDTOBACKWARD=Cannot backward the page.
+
+Navigator.EXPORT_ANNOTATION=Export annotations of current page.
+Navigator.EXPORT_ALL_ANNOTATIONS=Export all your annotations.
+Navigator.IMPORT_FENNEC_FILE=Import annotation file.
+Navigator.EXPORT_IS_SUCCEEDED=Export is succeeded.
+Navigator.EXPORT_IS_FAILED=Export is failed.
+Navigator.IMPORT_IS_SUCCEEDED=Import is succeeded.
+Navigator.IMPORT_IS_FAILED=Import is failed.
+Navigator.OVERWRITE_CONFIRM=Exporting...
+Navigator.OVERWRITE_MESSAGE={0} already exists. Do you want to replace it?
+
+Navigator.REPAIR_START=Execute Flash repair.
+Navigator.REPAIR_FINISHED=Flash Repair is finished.
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/message/Speech_ja.properties b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/message/Speech_ja.properties
new file mode 100644
index 0000000..3af8e33
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/message/Speech_ja.properties
@@ -0,0 +1,179 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Hisashi MIYASHITA, Daisuke SATO - initial configuration.
+###############################################################################
+
+Navigator.LINK=\u30ea\u30f3\u30af
+Navigator.VISITED_LINK=\u65e2\u8aad\u30ea\u30f3\u30af
+Navigator.HEADING=\u898b\u51fa\u3057
+Navigator.LIST_TOP={0}\u9805\u76ee\u306e\u30ea\u30b9\u30c8
+Navigator.BUTTON=\u30dc\u30bf\u30f3
+Navigator.TEXTBOX=\u30c6\u30ad\u30b9\u30c8\u5165\u529b
+Navigator.TEXTAREA=\u30c6\u30ad\u30b9\u30c8\u30a8\u30ea\u30a2\u30c6\u30ad\u30b9\u30c8\u6709\u308a
+Navigator.TEXTAREA_EMPTY=\u30c6\u30ad\u30b9\u30c8\u30a8\u30ea\u30a2
+Navigator.PASSWORD=\u30d1\u30b9\u30ef\u30fc\u30c9\u5165\u529b\u30dc\u30c3\u30af\u30b9
+Navigator.FILE_UPLOAD=\u30d5\u30a1\u30a4\u30eb\u9078\u629e
+Navigator.CHECKED=\u30c1\u30a7\u30c3\u30af\u6709\u308a
+Navigator.NOT_CHECKED=\u30c1\u30a7\u30c3\u30af\u7121\u3057
+Navigator.CHECKBOX=\u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9
+Navigator.RADIO=\u30e9\u30b8\u30aa\u30dc\u30bf\u30f3
+Navigator.COMBO_BOX=\u30b3\u30f3\u30dc\u30dc\u30c3\u30af\u30b9
+Navigator.COMBO_BOX_NOSELECTION=\u9078\u629e\u3055\u308c\u3066\u3044\u308b\u9805\u76ee\u306f\u3042\u308a\u307e\u305b\u3093
+
+Navigator.MEDIA=\u30de\u30eb\u30c1\u30e1\u30c7\u30a3\u30a2
+
+Navigator.PASSWORD_STAR3=\u30b9\u30bf\u30fc\u30b9\u30bf\u30fc\u30b9\u30bf\u30fc
+Navigator.WRAPPING_TO_TOP=\u5148\u982d\u306b\u623b\u3063\u3066
+Navigator.WRAPPING_TO_BOTTOM=\u6700\u5f8c\u306b\u623b\u3063\u3066
+
+Navigator.NO_HEADING=\u898b\u51fa\u3057\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.NO_LISTITEM=\u30ea\u30b9\u30c8\u9805\u76ee\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.NO_LINK=\u30ea\u30f3\u30af\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.NO_INPUT=\u30d5\u30a9\u30fc\u30e0\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.NO_BLOCK=\u30d6\u30ed\u30c3\u30af\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.NO_OBJECT=\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.NO_SELECTION=\u9078\u629e\u9805\u76ee\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.NO_ACCESSKEY=\u30a2\u30af\u30bb\u30b9\u30ad\u30fc\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.NO_ALTALABLE=\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u304c\u5fc5\u8981\u306a\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.NO_MEDIA=\u30de\u30eb\u30c1\u30e1\u30c7\u30a3\u30a2\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u3042\u308a\u307e\u305b\u3093
+
+Navigator.MSAA_FLASH_CONTENT=\u30d5\u30e9\u30c3\u30b7\u30e5\u30b3\u30f3\u30c6\u30f3\u30c4
+Navigator.FLASH_CONTENT=\u30a6\u30a3\u30f3\u30c9\u30a6\u30ec\u30b9\u30d5\u30e9\u30c3\u30b7\u30e5\u30b3\u30f3\u30c6\u30f3\u30c4
+Navigator.FLASH_END=\u30d5\u30e9\u30c3\u30b7\u30e5\u30b3\u30f3\u30c6\u30f3\u30c4\u7d42\u308f\u308a
+
+Navigator.VIEWS_ARE_OPEND=\u30c4\u30ea\u30fc\u30d3\u30e5\u30fc\u304c\u958b\u3044\u3066\u3044\u307e\u3059
+Navigator.VIEWS_ARE_CLOSED=\u30c4\u30ea\u30fc\u30d3\u30e5\u30fc\u306f\u9589\u3058\u3066\u3044\u307e\u3059
+
+Navigator.LAUNCH_DEFAULT_BROWSER=\u901a\u5e38\u306e\u30d6\u30e9\u30a6\u30b6\u3067\u958b\u304d\u307e\u3059. {0}
+Navigator.CLOSE_TAB=\u30bf\u30d6\u3092\u9589\u3058\u307e\u3057\u305f {0}
+Navigator.NEW_TAB=\u65b0\u3057\u3044\u30bf\u30d6\u304c\u958b\u304d\u307e\u3057\u305f
+Navigator.MOVE_TAB={0} \u30bf\u30d6\u306e{1}\u500b\u4e2d{2}\u500b\u76ee
+
+Navigator.ACCESSKEY_GUIDE=\u30a2\u30af\u30bb\u30b9\u30ad\u30fc\u306f\u30aa\u30eb\u30c8 \u30b7\u30d5\u30c8 {0}
+
+Navigator.REFRESH=\u6700\u65b0\u306e\u60c5\u5831\u306b\u66f4\u65b0
+
+Navigator.PROGRESS=\u30ed\u30fc\u30c9\u4e2d
+Navigator.STARTNAVIGATION=\u30ed\u30fc\u30c9\u5b8c\u4e86
+Navigator.FENNEC_NAME=\u5916\u90e8\u60c5\u5831 {0} \u3092\u9069\u7528\u3057\u307e\u3059
+Navigator.SUBITEMS={0}\u500b\u306e\u30b5\u30d6\u30a2\u30a4\u30c6\u30e0\u304c\u3042\u308a\u307e\u3059
+Navigator.N_OF_M={1}\u500b\u4e2d{0}\u500b\u76ee
+Navigator.NO_SUBITEMS=\u30b5\u30d6\u30a2\u30a4\u30c6\u30e0\u304c\u3042\u308a\u307e\u305b\u3093
+Navigator.NO_CONTROLS=\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u304c\u3042\u308a\u307e\u305b\u3093
+Navigator.NOT_AVAILABLE={0}\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
+Navigator.TOP=\u5148\u982d\u3067\u3059
+Navigator.BOTTOM=\u6700\u5f8c\u3067\u3059
+Navigator.INPUTABLE=\u5165\u529b\u53ef\u80fd
+Navigator.LEVEL=\u30ec\u30d9\u30eb{0}
+Navigator.TOP_LEVEL=\u30ec\u30d9\u30eb0
+Navigator.CLICK=\u30af\u30ea\u30c3\u30af
+Navigator.PLAY_TIME=\u518d\u751f\u6642\u9593 {0}
+Navigator.HH_MM_SS={2}\u6642\u9593 {1}\u5206 {0}\u79d2
+Navigator.MM_SS={1}\u5206 {0}\u79d2
+Navigator.SS={0}\u79d2
+Navigator.KEYBOARD_ON=\u30ad\u30fc\u30dc\u30fc\u30c9\u4f7f\u7528\u958b\u59cb
+Navigator.KEYBOARD_OFF=\u30ad\u30fc\u30dc\u30fc\u30c9\u4f7f\u7528\u7d42\u4e86
+Navigator.NOT_TABLE=\u30c6\u30fc\u30d6\u30eb\u306e\u5916\u3067\u3059
+Navigator.UNDONE=\u51e6\u7406\u4e2d\u3067\u3059
+Navigator.SPEECHSPEED=\u30b9\u30d4\u30fc\u30c9{0}
+Navigator.SPEECHSPEEDMAX=\u6700\u9ad8\u30b9\u30d4\u30fc\u30c9\u3067\u3059
+Navigator.SPEECHSPEEDMIN=\u6700\u4f4e\u30b9\u30d4\u30fc\u30c9\u3067\u3059
+Navigator.NO_OTHER_FENNEC=\u5916\u90e8\u60c5\u5831\u3092\u5207\u308a\u66ff\u3048\u3089\u308c\u307e\u305b\u3093
+Navigator.NO_FENNEC=\u9069\u7528\u53ef\u80fd\u306a\u5916\u90e8\u60c5\u5831\u304c\u3042\u308a\u307e\u305b\u3093
+Navigator.ENTERBROWSERADDRESS=URI\u5165\u529b
+
+Navigator.NO_FENNEC_MESSAGE=Fennec\u7121\u52b9
+Navigator.NO_FENNEC_NAME=\u7121\u540d
+
+Navigator.STOPMEDIA=\u505c\u6b62
+Navigator.PLAYMEDIA=\u518d\u751f
+Navigator.PAUSEMEDIA=\u4e2d\u65ad
+Navigator.RESUMEMEDIA=\u518d\u958b
+Navigator.WAITINGMEDIA=\u5f85\u6a5f\u4e2d
+Navigator.FASTFORWARDMEDIA=\u65e9\u9001\u308a
+Navigator.FASTREVERSEMEDIA=\u5dfb\u304d\u623b\u3057
+Navigator.VOLUMEUP=\u97f3\u91cf\u5927
+Navigator.VOLUMEDOWN=\u97f3\u91cf\u5c0f
+Navigator.VOLUMEMAX=\u6700\u5927\u97f3\u91cf
+Navigator.VOLUMEMIN=\u97f3\u91cf\u7121\u3057
+Navigator.MUTEON=\u30df\u30e5\u30fc\u30c8
+Navigator.MUTEOFF=\u30df\u30e5\u30fc\u30c8\u30aa\u30d5
+Navigator.CANNOT_PAUSE=\u4e2d\u65ad\u3067\u304d\u307e\u305b\u3093
+Navigator.MOVIE_START=\u518d\u751f\u958b\u59cb
+
+Navigator.NOT_AVAILABEL=\u5229\u7528\u3067\u304d\u307e\u305b\u3093
+
+Navigator.NOVIDEO=\u52d5\u753b\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.SINGLEVIDEO=\u3072\u3068\u3064\u306e\u52d5\u753b
+Navigator.VIDEOCOUNT={0}\u500b\u306e\u52d5\u753b
+Navigator.NOSOUND=\u97f3\u6e90\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.SINGLESOUND=\u3072\u3068\u3064\u306e\u97f3\u6e90
+Navigator.SOUNDCOUNT={0}\u500b\u306e\u97f3\u6e90
+Navigator.VIDEOINDEX={1}\u500b\u4e2d{0}\u500b\u76ee\u306e\u30d3\u30c7\u30aa
+
+Navigator.VIDEO_AT={0}\u3092\u518d\u751f\u4e2d
+Navigator.VIDEO_TOTAL=\u5168\u4f53\u3067{0}
+
+NVM3.EMPTY_PAGE=\u304b\u3089\u306e\u30da\u30fc\u30b8\u3067\u3059\u3002
+
+ContentShortener.VerbalForm={0} \u4ee5\u4e0b\u7565
+ContentShortener.NonVerbalForm={0} ...
+
+LandmarkMaker.Result.CREATED=\u3057\u304a\u308a\u304c{0}\u306b\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f
+LandmarkMaker.Result.REMOVED=\u7121\u52b9\u306b\u306a\u3063\u3066\u3044\u305f\u898b\u51fa\u3057\u304c\u6709\u52b9\u306b\u306a\u308a\u307e\u3057\u305f : {0}
+LandmarkMaker.Result.ERROR=\u3057\u304a\u308a\u3092{0}\u306b\u8a2d\u5b9a\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f
+LandmarkMaker.Result.NOTHING=\u3057\u304a\u308a\u306f\u3059\u3067\u306b{0}\u306b\u3042\u308a\u307e\u3059
+
+HeadingCanceller.Result.CREATED=\u898b\u51fa\u3057\u3092\u7121\u52b9\u5316\u3057\u307e\u3057\u305f : {0}
+HeadingCanceller.Result.REMOVED=\u3057\u304a\u308a\u304c{0}\u304b\u3089\u53d6\u308a\u9664\u304b\u308c\u307e\u3057\u305f
+HeadingCanceller.Result.ERROR=\u898b\u51fa\u3057\u3092\u53d6\u308a\u9664\u3051\u307e\u305b\u3093\u3067\u3057\u305f : {0}
+HeadingCanceller.Result.NOTHING=\u898b\u51fa\u3057\u306f\u3059\u3067\u306b\u7121\u52b9\u5316\u3055\u308c\u3066\u3044\u307e\u3059 : {0}
+
+AltTextEditor.Result.CREATED=\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u3092{0}\u3068\u8a2d\u5b9a\u3057\u307e\u3057\u305f
+AltTextEditor.Result.REMOVED=\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u3092\u53d6\u308a\u9664\u304d\u307e\u3057\u305f
+AltTextEditor.Result.CHANGED=\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u3092{0}\u306b\u5909\u66f4\u3057\u307e\u3057\u305f
+AltTextEditor.Result.ERROR=\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u306e\u7de8\u96c6\u306b\u5931\u6557\u3057\u307e\u3057\u305f
+
+AudioDescription.on=\u97f3\u58f0\u89e3\u8aac\u30aa\u30f3
+AudioDescription.off=\u97f3\u58f0\u89e3\u8aac\u30aa\u30d5
+AudioDescription.available=\u97f3\u58f0\u89e3\u8aac\u6709\u308a
+AudioDescription.notAvailable=\u97f3\u58f0\u89e3\u8aac\u7121\u3057
+AudioDescription.noExtension=\u97f3\u58f0\u89e3\u8aac\u62e1\u5f35\u7121\u3057
+
+Navigator.ANNOTATION_IS_NOT_AVAILABLE=\u6ce8\u91c8\u6a5f\u80fd\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093
+Navigator.ANNOTATION_IS_SAVED=\u6ce8\u91c8\u304c\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f
+Navigator.ALT_TEXT_WERE_GUESSED={0} \u500b\u306e\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u304c\u63a8\u6e2c\u3055\u308c\u307e\u3057\u305f
+Navigator.THERE_IS_NO_MISSING_ALT_TEXT=\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u304c\u5fc5\u8981\u306a\u9805\u76ee\u306f\u3042\u308a\u307e\u305b\u3093
+Navigator.ANNOTATION_LINK_TO={0}\u3078\u306e\u30ea\u30f3\u30af
+Navigator.ITEM_IS_NOT_AVAILABLE=\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u3092\u4ed8\u3051\u3089\u308c\u306a\u3044\u9805\u76ee\u3067\u3059
+Navigator.ANNOTATION_IS_REMOVED=\u6ce8\u91c8\u3092\u5168\u3066\u524a\u9664\u3057\u307e\u3057\u305f
+Navigator.NO_ANNOTATION=\u6ce8\u91c8\u304c\u3042\u308a\u307e\u305b\u3093
+
+Navigator.USER_INFO_REMOVE_CONFIRM=\u6ce8\u91c8\u3092\u5168\u3066\u524a\u9664\u3057\u307e\u3059
+Navigator.USER_INFO_REMOVE_MESSAGE=\u3053\u306e\u30da\u30fc\u30b8\u306e\u5168\u3066\u306e\u6ce8\u91c8\u306e\u60c5\u5831\u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f
+
+Navigator.THERE_ARE_NO_TAB=\u30bf\u30d6\u304c\u3042\u308a\u307e\u305b\u3093\u3001\u30b3\u30f3\u30c8\u30ed\u30fc\u30ebO\u3092\u4f7f\u7528\u3057\u3066\u4e0b\u3055\u3044\u3002
+
+TripJournal.FORWARD=\u9032\u3080
+TripJournal.FAILEDTOFORWARD=\u6700\u5f8c\u3067\u3059
+TripJournal.BACKWARD=\u623b\u308b
+TripJournal.FAILEDTOBACKWARD=\u5148\u982d\u3067\u3059
+
+Navigator.EXPORT_ANNOTATION=\u73fe\u5728\u306e\u30da\u30fc\u30b8\u306e\u6ce8\u91c8\u3092\u66f8\u304d\u51fa\u3057\u307e\u3059
+Navigator.EXPORT_ALL_ANNOTATIONS=\u6ce8\u91c8\u30c7\u30fc\u30bf\u3092\u5168\u3066\u66f8\u304d\u51fa\u3057\u307e\u3059
+Navigator.IMPORT_FENNEC_FILE=\u6ce8\u91c8\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u307f\u307e\u3059
+Navigator.EXPORT_IS_SUCCEEDED=\u66f8\u304d\u51fa\u3057\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f
+Navigator.EXPORT_IS_FAILED=\u66f8\u304d\u51fa\u3057\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308a\u307e\u3057\u305f
+Navigator.IMPORT_IS_SUCCEEDED=\u8aad\u307f\u8fbc\u307f\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f
+Navigator.IMPORT_IS_FAILED=\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308a\u307e\u3057\u305f
+Navigator.OVERWRITE_CONFIRM=\u66f8\u304d\u51fa\u3057\u4e2d...
+Navigator.OVERWRITE_MESSAGE={0} \u306f\u65e2\u306b\u3042\u308a\u307e\u3059\u3002\u4e0a\u66f8\u304d\u3057\u3066\u7f6e\u304d\u63db\u3048\u307e\u3059\u304b\uff1f
+
+Navigator.REPAIR_START=Flash\u306e\u4fee\u5fa9\u3092\u958b\u59cb\u3057\u307e\u3059
+Navigator.REPAIR_FINISHED=Flash\u306e\u4fee\u5fa9\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/preferences/UserInfoPreferenceConstants.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/preferences/UserInfoPreferenceConstants.java
new file mode 100644
index 0000000..b29b3db
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/preferences/UserInfoPreferenceConstants.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator.preferences;
+
+/**
+ * Constant definitions for plug-in preferences
+ */
+public class UserInfoPreferenceConstants {
+
+ public static final String AUTO_SAVE = "autoSave";
+
+ public static final String AUTO_REFRESH = "autoRefresh";
+
+ public static final String NONVERBAL_OVERVIEW = "nonverbalOverview";
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/preferences/UserInfoPreferenceInitializer.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/preferences/UserInfoPreferenceInitializer.java
new file mode 100644
index 0000000..09f4713
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/preferences/UserInfoPreferenceInitializer.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator.preferences;
+
+import org.eclipse.actf.ai.navigator.NavigatorPlugin;
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+
+/**
+ * Class used to initialize default preference values.
+ */
+public class UserInfoPreferenceInitializer extends AbstractPreferenceInitializer {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+ */
+ @Override
+ public void initializeDefaultPreferences() {
+ IPreferenceStore store = NavigatorPlugin.getDefault().getPreferenceStore();
+ store.setDefault(UserInfoPreferenceConstants.AUTO_REFRESH, true);
+ store.setDefault(UserInfoPreferenceConstants.AUTO_SAVE, true);
+ store.setDefault(UserInfoPreferenceConstants.NONVERBAL_OVERVIEW, true);
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/preferences/UserInfoPreferencePage.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/preferences/UserInfoPreferencePage.java
new file mode 100644
index 0000000..4fdaa94
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/preferences/UserInfoPreferencePage.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator.preferences;
+
+import org.eclipse.actf.ai.navigator.Messages;
+import org.eclipse.actf.ai.navigator.NavigatorPlugin;
+import org.eclipse.jface.preference.*;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.IWorkbench;
+
+
+/**
+ * This class represents a preference page that
+ * is contributed to the Preferences dialog. By
+ * subclassing <samp>FieldEditorPreferencePage</samp>, we
+ * can use the field support built into JFace that allows
+ * us to create a page that is small and knows how to
+ * save, restore and apply itself.
+ * <p>
+ * This page is used to modify preferences only. They
+ * are stored in the preference store that belongs to
+ * the main plug-in class. That way, preferences can
+ * be accessed directly via the preference store.
+ */
+
+public class UserInfoPreferencePage
+ extends FieldEditorPreferencePage
+ implements IWorkbenchPreferencePage {
+
+ public UserInfoPreferencePage() {
+ super(GRID);
+ setPreferenceStore(NavigatorPlugin.getDefault().getPreferenceStore());
+ setDescription(Messages.getString("UserInfo.PREFERENCES_NAME"));
+ }
+
+ /**
+ * Creates the field editors. Field editors are abstractions of
+ * the common GUI blocks needed to manipulate various types
+ * of preferences. Each field editor knows how to save and
+ * restore itself.
+ */
+ @Override
+ public void createFieldEditors() {
+ addField(
+ new BooleanFieldEditor(
+ UserInfoPreferenceConstants.AUTO_SAVE,
+ Messages.getString("UserInfo.SAVE_ANNOTATION"),
+ getFieldEditorParent()));
+
+ /*
+ addField(
+ new BooleanFieldEditor(
+ UserInfoPreferenceConstants.AUTO_REFRESH,
+ Messages.getString("UserInfo.REFRESH_TREEVIEW"),
+
+ getFieldEditorParent()));
+ */
+
+ //addField(
+ // new BooleanFieldEditor(
+ // UserInfoPreferenceConstants.NONVERBAL_OVERVIEW,
+ // "&Nonverbal Overview",
+ // getFieldEditorParent()));
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/ui/ModeContribution.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/ui/ModeContribution.java
new file mode 100644
index 0000000..61a52de
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/ui/ModeContribution.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.ui;
+
+import org.eclipse.jface.action.ControlContribution;
+import org.eclipse.jface.action.StatusLineLayoutData;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+
+
+public class ModeContribution extends ControlContribution {
+
+ public ModeContribution(String id) {
+ super(id);
+ }
+
+ public static final String MODE_CONTRIBUTION_ID = "navigator.mode";
+
+ private Composite c;
+
+ private Label nvm3;
+
+ private String nvm3Text;
+
+ private Label mode;
+
+ private String modeText;
+
+ private StatusLineLayoutData data;
+
+ @Override
+ protected Control createControl(Composite parent) {
+ data = new StatusLineLayoutData();
+ data.heightHint = 18;
+ c = new Composite(parent, SWT.NULL);
+ c.setLayoutData(data);
+ RowLayout rl = new RowLayout();
+ rl.fill = true;
+ rl.justify = true;
+ rl.wrap = false;
+ c.setLayout(rl);
+
+ nvm3 = new Label(c, SWT.NONE);
+ if(nvm3Text != null)
+ nvm3.setText(nvm3Text);
+ mode = new Label(c, SWT.NONE);
+ if(modeText != null)
+ mode.setText(modeText);
+
+ return c;
+ }
+
+ public void setMode(String name) {
+ modeText = " [" + name + "]";
+ }
+
+ public void showNVM3Name(String name) {
+ nvm3Text = name;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/ui/URLOpenDialog.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/ui/URLOpenDialog.java
new file mode 100644
index 0000000..1a310e6
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/ui/URLOpenDialog.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator.ui;
+
+import org.eclipse.actf.ai.navigator.Messages;
+import org.eclipse.actf.util.ui.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+
+
+
+public class URLOpenDialog {
+
+ private Shell _shell;
+
+ private Text _urlText;
+
+ private String _url = "";
+
+ private int _returnCode = 0;
+
+ // Checked:030806
+ public URLOpenDialog(Shell shell) {
+ this._shell = new Shell(shell, SWT.DIALOG_TRIM | SWT.PRIMARY_MODAL);
+ this._shell.setLayout(new GridLayout());
+ }
+
+ // Checked:030806
+ private void createButtonControls() {
+ Composite composite = new Composite(this._shell, SWT.NULL);
+
+ GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_END);
+ gridData.heightHint = 50;
+ composite.setLayoutData(gridData);
+
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ layout.horizontalSpacing = 20;
+ layout.marginWidth = 20;
+ layout.marginHeight = 10;
+ composite.setLayout(layout);
+
+ Button okButton = new Button(composite, SWT.PUSH);
+ okButton.setText(IDialogConstants.OK); //$NON-NLS-1$
+ okButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ _returnCode = 1;
+ _url = _urlText.getText();
+// BrowserEventListenerManager.getInstance().fireSetAddressTextString(_url);
+ _shell.close();
+ }
+ });
+
+ Button cancelButton = new Button(composite, SWT.PUSH);
+ cancelButton.setText(IDialogConstants.CANCEL); //$NON-NLS-1$
+ cancelButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ _returnCode = 0;
+ _shell.close();
+ }
+ });
+
+
+// Button openButton = new Button(composite, SWT.PUSH);
+// openButton.setText(DialogConst.BROWSE); //$NON-NLS-1$
+// openButton.addSelectionListener(new SelectionAdapter() {
+// public void widgetSelected(SelectionEvent e) {
+// FileDialog openDialog = new FileDialog(_shell, SWT.OPEN);
+// String openFile = openDialog.open();
+//
+// if (openFile != null && !openFile.equals("")) { //$NON-NLS-1$
+// _urlText.setText(openFile);
+// }
+// }
+// });
+
+ this._shell.setDefaultButton(okButton);
+ }
+
+ // Checked:030806
+ private void createSettingControls() {
+ GridLayout gridLayout1;
+
+ Composite composite = new Composite(_shell, SWT.NULL);
+ composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ gridLayout1 = new GridLayout();
+ gridLayout1.numColumns = 2;
+ composite.setLayout(gridLayout1);
+
+ // information
+ Label infoLabel = new Label(composite, SWT.NONE);
+ infoLabel.setText(IDialogConstants.OPENFILE_INFO);
+ GridData gridData = new GridData();
+ gridData.horizontalSpan = 2;
+ infoLabel.setLayoutData(gridData);
+
+ // URL label
+ Label label1 = new Label(composite, SWT.NONE);
+ label1.setText("URL: ");
+
+ // Create the TextBox
+ _urlText = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ _urlText.setText("");
+
+ gridData = new GridData();
+ gridData.widthHint = 300;
+ _urlText.setLayoutData(gridData);
+ }
+
+ // Checked:030806
+ public int open() {
+ this._shell.setText(Messages.getString("DialogOpenURL.Open_URL_2"));
+
+ createSettingControls();
+
+ createButtonControls();
+ this._shell.setSize(375, 150);
+ this._shell.open();
+ this._shell.setLocation(100, 100);
+
+ Display display = _shell.getDisplay();
+ while (!_shell.isDisposed() || !display.readAndDispatch()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+
+ return this._returnCode;
+ }
+
+ public String getUrl(){
+ return this._url;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/IMetaDataModifier.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/IMetaDataModifier.java
new file mode 100644
index 0000000..db4eb90
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/IMetaDataModifier.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Masatomo KOBAYASHI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.userinfo;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.navigator.userinfo.IUserInfoGenerator.Result;
+import org.eclipse.actf.ai.xmlstore.XMLStoreException;
+
+
+
+
+public interface IMetaDataModifier {
+
+ String toString(Result result);
+
+ Result commit(boolean save) throws XMLStoreException;
+
+ String getSite();
+
+ void setSite(String targetSite);
+
+ ITreeItem getItem();
+
+ void setItem(ITreeItem item);
+
+ String getText();
+
+ void setText(String text);
+
+ IUserInfoGenerator getGenerator();
+
+ void setGenerator(IUserInfoGenerator generator);
+
+ boolean remove() throws XMLStoreException;
+
+ void setPageTitle(String title);
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/IUserInfoConstants.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/IUserInfoConstants.java
new file mode 100644
index 0000000..32ba92a
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/IUserInfoConstants.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Masatomo KOBAYASHI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.userinfo;
+
+
+
+public interface IUserInfoConstants {
+ public static final String DEFAULT_NAMESPACE = "http://www.ibm.com/xmlns/prod/aiBrowser/fennec";
+ public static final String LOC_NAMESPACE = "http://www.ibm.com/xmlns/prod/aiBrowser/fennec/xml-query";
+ public static final String FLQ_NAMESPACE = "http://www.ibm.com/xmlns/prod/aiBrowser/fennec/flash-query";
+ public static final String MSQ_NAMESPACE = "http://www.ibm.com/xmlns/prod/aiBrowser/fennec/msaa-query";
+}
+
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/IUserInfoGenerator.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/IUserInfoGenerator.java
new file mode 100644
index 0000000..50abf46
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/IUserInfoGenerator.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Masatomo KOBAYASHI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.userinfo;
+
+import org.w3c.dom.Node;
+
+
+public interface IUserInfoGenerator {
+ public static enum Result {
+ NOTHING,
+ CREATED,
+ REMOVED,
+ CHANGED,
+ ERROR,
+ }
+
+ String toString(Result result);
+// Status addUserInfo(Node container, TargetNodeQuery paths, String altText);
+ Result addUserInfo(Node node, String altText);
+}
+
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/AltInputDialog.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/AltInputDialog.java
new file mode 100644
index 0000000..22d9661
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/AltInputDialog.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Masatomo KOBAYASHI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.userinfo.impl;
+
+import org.eclipse.actf.ai.navigator.Messages;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+
+
+
+public class AltInputDialog extends Dialog {
+
+ private String formInputString = "";
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+
+ newShell.setText(Messages.getString("AltInputDialog.Text"));
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite container = (Composite) super.createDialogArea(parent);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 400;
+ gd.horizontalSpan = ((GridLayout) parent.getLayout()).numColumns;
+
+ final Text formInputField = new Text(container, SWT.BORDER);
+ formInputField.setLayoutData(gd);
+ formInputField.setText(formInputString);
+ formInputField.selectAll();
+
+ formInputField.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ formInputString = formInputField.getText();
+ }
+ });
+ return container;
+ }
+
+ public String getResult() {
+ return formInputString;
+ }
+
+ public AltInputDialog(Shell parent, String init) {
+ super(parent);
+ this.formInputString = init;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/AltTextEditor.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/AltTextEditor.java
new file mode 100644
index 0000000..fc55875
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/AltTextEditor.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Masatomo KOBAYASHI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.userinfo.impl;
+
+import org.eclipse.actf.ai.navigator.userinfo.IUserInfoConstants;
+import org.eclipse.actf.ai.navigator.userinfo.IUserInfoGenerator;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+
+
+
+public class AltTextEditor implements IUserInfoGenerator, IUserInfoConstants {
+
+// @Override
+// public String toString() {
+// return "ALT text";
+// }
+
+ public String toString(Result result) {
+ switch (result) {
+ case CREATED:
+ return "AltTextEditor.Result.CREATED";
+ case REMOVED:
+ return "AltTextEditor.Result.REMOVED";
+ case CHANGED:
+ return "AltTextEditor.Result.CHANGED";
+ case ERROR:
+ return "AltTextEditor.Result.ERROR";
+ }
+ return "";
+ }
+
+ private Node getExistingUserInfo(Node node) {
+ for (Node c = node.getFirstChild(); c != null; c = c.getNextSibling()) {
+ String ns = c.getNamespaceURI();
+ if ((ns == null) || (!ns.equals(DEFAULT_NAMESPACE))) continue;
+ String n = c.getLocalName();
+ if (n.equals("altText"))
+ return c;
+ }
+ return null;
+ }
+
+ public Result addUserInfo(Node node, String text) {
+ Document doc = node.getOwnerDocument();
+ Node info = getExistingUserInfo(node);
+ if (text.length() > 0) {
+ if (info == null) {
+ info = node.appendChild(doc.createElementNS(DEFAULT_NAMESPACE, "altText"));
+ info.setTextContent(text);
+ return Result.CREATED;
+ }
+ else {
+ info.setTextContent(text);
+ return Result.CHANGED;
+ }
+ }
+ // TODO ? which is better: "" -> remove the alt text added by the user or set an empty alt text
+ else if (info != null) {
+ node.removeChild(info);
+ return Result.REMOVED;
+ }
+ return Result.NOTHING;
+ }
+
+// public Status addUserInfo(Node parent, TargetNodeQuery paths, String text) {
+// Document doc = parent.getOwnerDocument();
+// Node node = paths.getNode(parent);
+// Node info = getExistingUserInfo(node);
+//
+// if (text.length() > 0) {
+// if (info == null) {
+// info = node.appendChild(doc.createElementNS(DEFAULT_NAMESPACE, "altText"));
+// info.setTextContent(text);
+// return Status.CREATED;
+// }
+// else {
+// info.setTextContent(text);
+// return Status.CHANGED;
+// }
+// }
+//
+// // TODO ? which is better: "" -> remove the alt text added by the user or set an empty alt text
+//
+// if (info != null) {
+// node.removeChild(info);
+// if (!node.hasChildNodes())
+// parent.removeChild(node);
+// return Status.REMOVED;
+// }
+//
+// return Status.NOTHING;
+// }
+
+// @Override
+// protected String buildXML(String attr, String base, String text) {
+// StringBuffer ret = new StringBuffer();
+// ret.append("<attach ");
+// ret.append(attr);
+// ret.append("=\"");
+// ret.append(base);
+// ret.append("\"");
+// ret.append("><altText>");
+// ret.append(text);
+// ret.append("</altText></attach>");
+// return ret.toString();
+// }
+
+// @Override
+// public String buildXML(Map<String, String> attr, String text) {
+// StringBuffer ret = new StringBuffer();
+// ret.append("<!--attach loc:path=\".\"--><group");
+// for (Map.Entry<String, String> e : attr.entrySet()) {
+// ret.append("\n ");
+// ret.append(e.getKey());
+// ret.append("=\"");
+// ret.append(e.getValue());
+// ret.append("\"");
+// }
+// ret.append(">\n <altText>");
+// ret.append(text);
+// ret.append("</altText>\n</group><!--/attach-->");
+// return ret.toString();
+// }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/AltTextGuesser.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/AltTextGuesser.java
new file mode 100644
index 0000000..a8c5a20
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/AltTextGuesser.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Masatomo KOBAYASHI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.userinfo.impl;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+
+
+public class AltTextGuesser {
+ private final IWebBrowserACTF browser;
+ private final ITreeItem item;
+
+ public AltTextGuesser(IWebBrowserACTF browser, ITreeItem item) {
+ this.browser = browser;
+ this.item = item;
+ }
+
+ public String getDefaultText() {
+ return item.getUIString();
+ }
+
+ public String guessByOCR() {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ public String guessByContext() {
+ return getContext(browser, getContext(item));
+ }
+
+ private String getContext(ITreeItem item) {
+ Object o = item.getBaseNode();
+ if (!(o instanceof Node))
+ return null;
+ for (Node n = (Node) o; n != null; n = n.getParentNode()) {
+// System.err.println(n.getClass());
+ if (n instanceof Document)
+ break;
+ String name = n.getLocalName();
+ // I'd like to use getLinkURI!!
+ if ("A".equals(name)) {
+// System.out.println(n.getClass());
+ NamedNodeMap v = n.getAttributes();
+ if (v == null)
+ continue;
+
+ Node a = v.getNamedItem("href");
+ if (a == null)
+ continue;
+ return a.getNodeValue();
+ }
+ }
+ return null;
+ }
+
+ private String getContext(IWebBrowserACTF browser, String path) {
+ try {
+ URL url = new URL(new URL(browser.getURL()), path);
+ String s = null;
+ String title = "", h1 = "";
+ Pattern pattern = Pattern.compile("<(?:(title)|(h1))[^>]*>([^<]*)</(?:title|h1)>" , Pattern.CASE_INSENSITIVE);
+ BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
+ while ((s = br.readLine()) != null) { // TODO ad-hoc
+ Matcher matcher = pattern.matcher(s);
+ if (!matcher.matches())
+ continue;
+ if (matcher.group(1) != null)
+ title = matcher.group(3);
+ if (matcher.group(2) != null)
+ h1 = matcher.group(3);
+ if (title.length() > 0 && h1.length() > 0)
+ break;
+ }
+ br.close();
+ System.out.println("URL\t" + url);
+ System.out.println("title\t" + title);
+ System.out.println("h1\t" + h1);
+ return title.length() > h1.length() ? title : h1;
+ } catch (MalformedURLException e) {
+// e.printStackTrace();
+ return null;
+ } catch (IOException e) {
+// e.printStackTrace();
+ return null;
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/BrowserObserver.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/BrowserObserver.java
new file mode 100644
index 0000000..a2ac38d
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/BrowserObserver.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Masatomo KOBAYASHI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.userinfo.impl;
+
+import org.eclipse.actf.model.IWebBrowserACTF;
+
+
+
+public class BrowserObserver {
+ private IWebBrowserACTF webBrowser;
+
+ public BrowserObserver(IWebBrowserACTF webBrowser) {
+ this.webBrowser = webBrowser;
+ }
+
+ public String getTargetFilter() { // TODO
+ String s = webBrowser.getURL();
+ int i = s.indexOf('?');
+ if (i >= 0)
+ s = s.substring(0, i).concat("*");
+ return s;
+ }
+
+ public IWebBrowserACTF getWebBrowser() {
+ return webBrowser;
+ }
+
+ public void setWebBrowser(IWebBrowserACTF webBrowser) {
+ this.webBrowser = webBrowser;
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/HeadingCanceller.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/HeadingCanceller.java
new file mode 100644
index 0000000..610ccad
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/HeadingCanceller.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Masatomo KOBAYASHI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.userinfo.impl;
+
+import org.eclipse.actf.ai.navigator.userinfo.IUserInfoConstants;
+import org.eclipse.actf.ai.navigator.userinfo.IUserInfoGenerator;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+
+
+
+public class HeadingCanceller implements IUserInfoGenerator, IUserInfoConstants {
+
+// @Override
+// public String toString() {
+// return "landmark";
+// }
+
+ public String toString(Result result) {
+ switch (result) {
+ case CREATED:
+ return "HeadingCanceller.Result.CREATED";
+ case REMOVED:
+ return "HeadingCanceller.Result.REMOVED";
+ case ERROR:
+ return "HeadingCanceller.Result.ERROR";
+ case NOTHING:
+ return "HeadingCanceller.Result.NOTHING";
+ }
+ return "";
+ }
+
+ private Node getExistingUserInfo(Node node) {
+ for (Node c = node.getFirstChild(); c != null; c = c.getNextSibling()) {
+ String ns = c.getNamespaceURI();
+ if ((ns == null) || (!ns.equals(DEFAULT_NAMESPACE))) continue;
+ String n = c.getLocalName();
+ if (n.equals("h1") || n.equals("h-"))
+ return c;
+ }
+ return null;
+ }
+
+ public Result addUserInfo(Node node, String text) {
+ Document doc = node.getOwnerDocument();
+ Node info = getExistingUserInfo(node);
+ if (info != null) {
+ if (info.getNodeName().equals("h-"))
+ return Result.NOTHING;
+ node.removeChild(info);
+// if (!node.hasChildNodes())
+// parent.removeChild(node);
+ return Result.REMOVED;
+ }
+ node.appendChild(doc.createElementNS(DEFAULT_NAMESPACE, "h-"));
+// node.appendChild(doc.createElementNS(DEFAULT_NAMESPACE, "altText")).appendChild(doc.createTextNode(text));
+ return Result.CREATED;
+ }
+
+// public Status addUserInfo(Node parent, TargetNodeQuery paths, String text) {
+// Document doc = parent.getOwnerDocument();
+// Node node = paths.getNode(parent);
+// Node info = getExistingUserInfo(node);
+// if (info != null) {
+// node.removeChild(info);
+// if (!node.hasChildNodes())
+// parent.removeChild(node);
+// return Status.REMOVED;
+// }
+// else {
+// node.appendChild(doc.createElementNS(DEFAULT_NAMESPACE, "h-"));
+//// node.appendChild(doc.createElementNS(DEFAULT_NAMESPACE, "altText")).appendChild(doc.createTextNode(text));
+// return Status.CREATED;
+// }
+// }
+
+// @Override
+// protected String buildXML(String attr, String base, String text) {
+// StringBuffer ret = new StringBuffer();
+// ret.append("<attach ");
+// ret.append(attr);
+// ret.append("=\"");
+// ret.append(base);
+// ret.append("\"");
+// ret.append("><h1/><altText>");
+// ret.append(text);
+// ret.append("</altText></attach>");
+// return ret.toString();
+// }
+
+// @Override
+// public String buildXML(Map<String, String> attr, String text) {
+// StringBuffer ret = new StringBuffer();
+// ret.append("<!--attach loc:path=\".\"--><group");
+// for (Map.Entry<String, String> e : attr.entrySet()) {
+// ret.append("\n ");
+// ret.append(e.getKey());
+// ret.append("=\"");
+// ret.append(e.getValue());
+// ret.append("\"");
+// }
+// ret.append(">\n <h1/>\n <altText>");
+// ret.append(text);
+// ret.append("</altText>\n</group><!--/attach-->");
+// return ret.toString();
+// }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/LandmarkMaker.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/LandmarkMaker.java
new file mode 100644
index 0000000..1877fd4
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/LandmarkMaker.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Masatomo KOBAYASHI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.userinfo.impl;
+
+import org.eclipse.actf.ai.navigator.userinfo.IUserInfoConstants;
+import org.eclipse.actf.ai.navigator.userinfo.IUserInfoGenerator;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+
+
+
+public class LandmarkMaker implements IUserInfoGenerator, IUserInfoConstants {
+
+// @Override
+// public String toString() {
+// return "landmark";
+// }
+
+ public String toString(Result result) {
+ switch (result) {
+ case CREATED:
+ return "LandmarkMaker.Result.CREATED";
+ case REMOVED:
+ return "LandmarkMaker.Result.REMOVED";
+ case ERROR:
+ return "LandmarkMaker.Result.ERROR";
+ case NOTHING:
+ return "LandmarkMaker.Result.NOTHING";
+ }
+ return "";
+ }
+
+ private Node getExistingUserInfo(Node node) {
+ for (Node c = node.getFirstChild(); c != null; c = c.getNextSibling()) {
+ String ns = c.getNamespaceURI();
+ if ((ns == null) || (!ns.equals(DEFAULT_NAMESPACE))) continue;
+ String n = c.getLocalName();
+ if (n.equals("h-") || n.equals("h1"))
+ return c;
+ }
+ return null;
+ }
+
+ public Result addUserInfo(Node node, String text) {
+ Document doc = node.getOwnerDocument();
+ Node info = getExistingUserInfo(node);
+ if (info != null) {
+ if (info.getNodeName().equals("h1"))
+ return Result.NOTHING;
+ node.removeChild(info);
+// if (!node.hasChildNodes())
+// parent.removeChild(node);
+ return Result.REMOVED;
+ }
+ node.appendChild(doc.createElementNS(DEFAULT_NAMESPACE, "h1"));
+// node.appendChild(doc.createElementNS(DEFAULT_NAMESPACE, "altText")).appendChild(doc.createTextNode(text));
+ return Result.CREATED;
+ }
+
+// public Status addUserInfo(Node parent, TargetNodeQuery paths, String text) {
+// Document doc = parent.getOwnerDocument();
+// Node node = paths.getNode(parent);
+// Node info = getExistingUserInfo(node);
+// if (info != null) {
+// node.removeChild(info);
+// if (!node.hasChildNodes())
+// parent.removeChild(node);
+// return Status.REMOVED;
+// }
+// else {
+// node.appendChild(doc.createElementNS(DEFAULT_NAMESPACE, "h1"));
+//// node.appendChild(doc.createElementNS(DEFAULT_NAMESPACE, "altText")).appendChild(doc.createTextNode(text));
+// return Status.CREATED;
+// }
+// }
+
+// @Override
+// protected String buildXML(String attr, String base, String text) {
+// StringBuffer ret = new StringBuffer();
+// ret.append("<attach ");
+// ret.append(attr);
+// ret.append("=\"");
+// ret.append(base);
+// ret.append("\"");
+// ret.append("><h1/><altText>");
+// ret.append(text);
+// ret.append("</altText></attach>");
+// return ret.toString();
+// }
+
+// @Override
+// public String buildXML(Map<String, String> attr, String text) {
+// StringBuffer ret = new StringBuffer();
+// ret.append("<!--attach loc:path=\".\"--><group");
+// for (Map.Entry<String, String> e : attr.entrySet()) {
+// ret.append("\n ");
+// ret.append(e.getKey());
+// ret.append("=\"");
+// ret.append(e.getValue());
+// ret.append("\"");
+// }
+// ret.append(">\n <h1/>\n <altText>");
+// ret.append(text);
+// ret.append("</altText>\n</group><!--/attach-->");
+// return ret.toString();
+// }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/MetaDataModifier.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/MetaDataModifier.java
new file mode 100644
index 0000000..9baafd7
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/userinfo/impl/MetaDataModifier.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Masatomo KOBAYASHI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.userinfo.impl;
+
+import java.util.Iterator;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier;
+import org.eclipse.actf.ai.navigator.userinfo.IUserInfoConstants;
+import org.eclipse.actf.ai.navigator.userinfo.IUserInfoGenerator;
+import org.eclipse.actf.ai.navigator.userinfo.IUserInfoGenerator.Result;
+import org.eclipse.actf.ai.xmlstore.IXMLEditableInfo;
+import org.eclipse.actf.ai.xmlstore.IXMLInfo;
+import org.eclipse.actf.ai.xmlstore.IXMLSelector;
+import org.eclipse.actf.ai.xmlstore.IXMLStore;
+import org.eclipse.actf.ai.xmlstore.IXMLStoreService;
+import org.eclipse.actf.ai.xmlstore.XMLStoreException;
+import org.eclipse.actf.ai.xmlstore.XMLStorePlugin;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+
+
+public class MetaDataModifier implements IUserInfoConstants, IMetaDataModifier {
+ private IUserInfoGenerator generator;
+ private ITreeItem item;
+ private String text;
+ private String site;
+ private String pageTitle;
+
+// @Override
+// public String toString() {
+// StringBuffer ret = new StringBuffer();
+// String s = item.getUIString();
+// ret.append(generator);
+// ret.append(" : ");
+// ret.append(s != null && s.length() > 0 ? s : "X");
+// ret.append(" is ");
+// ret.append(text);
+// return ret.toString();
+// }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier#toString(org.eclipse.actf.ai.navigator.userinfo.IUserInfoConstants.Result)
+ */
+ public String toString(Result result) {
+ return generator.toString(result);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier#commit(boolean)
+ */
+ public Result commit(boolean save) throws XMLStoreException {
+ IXMLEditableInfo info = getUserInfo();
+ info.setPageTitle(pageTitle);
+ Result result = Result.NOTHING;
+ if (generator != null) {
+ if (item == null) return Result.ERROR;
+ Document infoDocument = info.getRootNode().getOwnerDocument();
+ Node parent = infoDocument.getElementsByTagNameNS(DEFAULT_NAMESPACE, "attach").item(0);
+// TargetNodeQuery paths = getQueryPaths(parent.getOwnerDocument());
+// result = generator.addUserInfo(parent, paths, text);
+// Node node = getInfoNode(parent);
+ Node node = item.serializeQuery(parent);
+ if (node == null) return Result.ERROR;
+ result = generator.addUserInfo(node, text);
+ if (!node.hasChildNodes())
+ parent.removeChild(node);
+ }
+ if (save)
+ info.save();
+ return result;
+ }
+
+ private IXMLEditableInfo getUserInfo() throws XMLStoreException {
+ IXMLStoreService service = XMLStorePlugin.getDefault().getXMLStoreService();
+ IXMLEditableInfo info = getStoredUserInfo(service);
+ if (info != null) {
+ return info;
+ } else {
+ return createNewUserInfo(service);
+ }
+ }
+
+ private IXMLEditableInfo getStoredUserInfo(IXMLStoreService service) {
+ IXMLStore store0 = service.getRootStore();
+ IXMLSelector sel1 = service.getSelectorWithDocElem("fennec", DEFAULT_NAMESPACE);
+ IXMLStore store1 = store0.specify(sel1);
+ if (store1 == null)
+ return null;
+ IXMLSelector sel2 = service.getSelectorWithIRI(site);
+ IXMLStore store2 = store1.specify(sel2);
+ if (store2 == null)
+ return null;
+ for (Iterator<IXMLInfo> i = store2.getInfoIterator(); i.hasNext(); ) {
+ IXMLInfo info = i.next();
+ if (info.isUserEntry() && (info instanceof IXMLEditableInfo)) {
+ // System.out.println("open stored user info.");
+ return (IXMLEditableInfo) info;
+ }
+ }
+ return null;
+ }
+
+ private IXMLEditableInfo createNewUserInfo(IXMLStoreService service) throws XMLStoreException {
+ IXMLEditableInfo info = service.newUserXML(DEFAULT_NAMESPACE, "fennec", site);
+ info.setPageTitle(pageTitle);
+ Node root = info.getRootNode();
+ Document doc = root.getOwnerDocument();
+ Element node = doc.createElementNS(DEFAULT_NAMESPACE, "attach");
+ node.setAttributeNS(LOC_NAMESPACE, "loc:path", ".");
+ root.appendChild(node);
+ //System.out.println("create new user info.");
+ return info;
+ }
+
+ public boolean remove() throws XMLStoreException {
+ IXMLStoreService service = XMLStorePlugin.getDefault().getXMLStoreService();
+ IXMLEditableInfo info = getStoredUserInfo(service);
+
+ if (info == null) {
+ return false;
+ }
+ info.remove();
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier#getSite()
+ */
+ public String getSite() {
+ return site;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier#setSite(java.lang.String)
+ */
+ public void setSite(String targetSite) {
+ this.site = targetSite;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier#getItem()
+ */
+ public ITreeItem getItem() {
+ return item;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier#setItem(org.eclipse.actf.ai.fennec.treemanager.ITreeItem)
+ */
+ public void setItem(ITreeItem item) {
+ this.item = item;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier#getText()
+ */
+ public String getText() {
+ return text;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier#setText(java.lang.String)
+ */
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier#getGenerator()
+ */
+ public IUserInfoGenerator getGenerator() {
+ return generator;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.actf.ai.navigator.userinfo.IMetaDataModifier#setGenerator(org.eclipse.actf.ai.navigator.userinfo.IUserInfoGenerator)
+ */
+ public void setGenerator(IUserInfoGenerator generator) {
+ this.generator = generator;
+ }
+
+ public void setPageTitle(String pageTitle) {
+ this.pageTitle = pageTitle;
+ }
+}
+
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/util/ContentShortener.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/util/ContentShortener.java
new file mode 100644
index 0000000..28dbafe
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/util/ContentShortener.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Masatomo KOBAYASHI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.navigator.util;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+
+
+
+public class ContentShortener {
+ private int limit;
+
+ public int getLimit() {
+ return limit;
+ }
+
+ public void setLimit(int max) {
+ this.limit = max;
+ }
+
+ private final MessageFormatter messageFormatter;
+
+ public ContentShortener(int max,
+ MessageFormatter messageFormatter) {
+ this.limit = max;
+ this.messageFormatter = messageFormatter;
+ }
+
+ public String getSummary(ITreeItem item, boolean verbal) {
+ String s = item.getUIString();
+ if (s.length() <= limit) {
+ return s;
+ } else {
+ s = s.substring(0, limit);
+ if (verbal) {
+ return messageFormatter.mes("ContentShortener.VerbalForm", s);
+ } else {
+ return messageFormatter.mes("ContentShortener.NonVerbalForm", s);
+ }
+ }
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/util/MessageFormatter.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/util/MessageFormatter.java
new file mode 100644
index 0000000..dad8664
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/util/MessageFormatter.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator.util;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class MessageFormatter {
+ private ResourceBundle resourceBundle = null;
+
+ private void setResourceBundle(String pkgName) {
+ try {
+ resourceBundle = ResourceBundle.getBundle(pkgName);
+ } catch (MissingResourceException e) {
+ resourceBundle = null;
+ }
+ }
+
+ public MessageFormatter(String pkgName) {
+ setResourceBundle(pkgName);
+ }
+
+ private String getFormat(String propName) {
+ if (resourceBundle == null) {
+ return propName;
+ }
+ String format;
+ try {
+ format = resourceBundle.getString(propName);
+ } catch (MissingResourceException e) {
+ return propName;
+ }
+ if (format != null)
+ return format;
+ return propName;
+ }
+
+ public String mes(String propName, Object[] args) {
+ String format = getFormat(propName);
+ String message = MessageFormat.format(format, args);
+ return message;
+ }
+
+ public String mes(String propName, Object obj1) {
+ return mes(propName, new Object[] { obj1 });
+ }
+
+ public String mes(String propName, Object obj1, Object obj2) {
+ return mes(propName, new Object[] { obj1, obj2 });
+ }
+
+ public String mes(String propName, Object obj1, Object obj2, Object obj3) {
+ return mes(propName, new Object[] { obj1, obj2, obj3 });
+ }
+
+ public String mes(String propName, Object obj1, Object obj2, Object obj3, Object obj4) {
+ return mes(propName, new Object[] { obj1, obj2, obj3, obj4 });
+ }
+
+ public String mes(String propName) {
+ return getFormat(propName);
+ }
+
+ public String concat(String... args){
+ if (args.length == 0)
+ return "";
+ if (args.length == 1)
+ return args[0];
+
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < args.length-1; i++) {
+ buf.append(args[i]);
+ buf.append(" ");
+ }
+ buf.append(args[args.length-1]);
+ return buf.toString();
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/views/NavigatorTreeView.java b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/views/NavigatorTreeView.java
new file mode 100644
index 0000000..209f8c0
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.navigator/src/org/eclipse/actf/ai/navigator/views/NavigatorTreeView.java
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hisashi MIYASHITA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.navigator.views;
+
+import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
+import org.eclipse.actf.ai.navigator.IManipulator;
+import org.eclipse.actf.ai.navigator.Messages;
+import org.eclipse.actf.ai.navigator.NavigatorPlugin;
+import org.eclipse.actf.ai.navigator.ui.ModeContribution;
+import org.eclipse.actf.util.vocab.Vocabulary;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.ViewPart;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+public class NavigatorTreeView extends ViewPart {
+ public static final String ID = "org.eclipse.actf.ai.navigator.views.NavigatorTreeView"; //$NON-NLS-1$
+
+ private TreeViewer treeViewer;
+
+ private TableViewer tableViewer;
+
+ private boolean disposed;
+
+ static class ITreeItemLabelProvider extends LabelProvider {
+ @Override
+ public Image getImage(Object element) {
+ // TODO
+ return null;
+ }
+
+ @Override
+ public String getText(Object element) {
+ ITreeItem item = (ITreeItem) element;
+ String r = item.getUIString();
+ if (r.length() > 0)
+ return r;
+ r = item.getNodeString();
+ if (r == null)
+ return ""; //$NON-NLS-1$
+ return r;
+ }
+ }
+
+ static class ITreeItemContentProvider extends ArrayContentProvider implements ITreeContentProvider {
+
+ public Object[] getChildren(Object parentElement) {
+ ITreeItem item = (ITreeItem) parentElement;
+ return item.getChildItems();
+ }
+
+ public Object getParent(Object element) {
+ ITreeItem item = (ITreeItem) element;
+ return item.getParent();
+ }
+
+ public boolean hasChildren(Object element) {
+ ITreeItem item = (ITreeItem) element;
+ ITreeItem[] childItems = item.getChildItems();
+ if ((childItems != null) && (childItems.length > 0))
+ return true;
+ return false;
+ }
+
+ @Override
+ public Object[] getElements(Object input) {
+ return getChildren(input);
+ }
+ }
+
+ static class TreeItemDetailsContentProvider implements IStructuredContentProvider {
+ public void inputChanged(Viewer v, Object oldInput, Object newInput) {
+ }
+
+ public void dispose() {
+ }
+
+ private String calcPath(ITreeItem item) {
+ StringBuffer ret = new StringBuffer();
+ Object o = item.getBaseNode();
+ if (!(o instanceof Node))
+ return "#none"; //$NON-NLS-1$
+ for (Node n = (Node) o; n != null; n = n.getParentNode()) {
+ if (n instanceof Document)
+ break;
+ ret.insert(0, n.getNodeName());
+ ret.insert(0, "/"); //$NON-NLS-1$
+ }
+ return ret.toString();
+ }
+
+ private String calcID(ITreeItem item) {
+ Object o = item.getBaseNode();
+ if (!(o instanceof Element))
+ return ""; //$NON-NLS-1$
+ Element e = (Element) o;
+ return e.getAttribute("id"); //$NON-NLS-1$
+ }
+
+ private String formatStringInHex(String str) {
+ StringBuffer ret = new StringBuffer();
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ ret.append(Integer.toHexString(c));
+ ret.append(" "); //$NON-NLS-1$
+ }
+ return ret.toString();
+ }
+
+ public Object[] getElements(Object obj) {
+ ITreeItem item = (ITreeItem) obj;
+ String[] uiStrings = { "UIString", item.getUIString() }; //$NON-NLS-1$
+ String[] uiStringsInHex = { "UIString (HEX)", formatStringInHex(item.getUIString()) }; //$NON-NLS-1$
+ String[] nodeStrings = { "Node", item.getNodeString() }; //$NON-NLS-1$
+ String[] path = { "Path", calcPath(item) }; //$NON-NLS-1$
+ String[] id = { "ID", calcID(item) }; //$NON-NLS-1$
+ String[] hasContent = { "hasContent", "" + Vocabulary.hasContent().eval(item)}; //$NON-NLS-1$ //$NON-NLS-2$
+ String[] heading = { "Heading", "" + item.getHeadingLevel() }; //$NON-NLS-1$ //$NON-NLS-2$
+ String[] nodeObject = { "NodeObject", "" + item.getBaseNode() }; //$NON-NLS-1$ //$NON-NLS-2$
+ String[] isInputable = { "isInputable", "" + item.isInputable() }; //$NON-NLS-1$ //$NON-NLS-2$
+ String[] isConnectable = { "isConnectable", "" + Vocabulary.isConnectable().eval(item) }; //$NON-NLS-1$ //$NON-NLS-2$
+ return new Object[] { uiStrings, uiStringsInHex, nodeStrings, path, id, hasContent, heading, nodeObject,
+ isInputable, isConnectable };
+ }
+ }
+
+ static class TreeItemDetailsLabelProvider extends LabelProvider implements ITableLabelProvider {
+ public String getColumnText(Object obj, int index) {
+ String[] prop = (String[]) obj;
+ if (index >= prop.length)
+ return null;
+ return prop[index];
+ }
+
+ public Image getColumnImage(Object obj, int index) {
+ return getImage(obj);
+ }
+
+ @Override
+ public Image getImage(Object obj) {
+ // TODO
+ return null;
+ }
+ }
+
+ class TreeItemViewerDoubleClickListener implements IDoubleClickListener {
+ public void doubleClick(DoubleClickEvent event) {
+ IStructuredSelection sel = (IStructuredSelection) event.getSelection();
+ Object obj = sel.getFirstElement();
+ tableViewer.setInput(obj);
+ }
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ disposed = true;
+ }
+
+ void initView(Composite parent) {
+ Layout layout = new FillLayout(SWT.VERTICAL);
+ parent.setLayout(layout);
+
+ SashForm sash = new SashForm(parent, SWT.VERTICAL);
+
+ treeViewer = new TreeViewer(sash);
+ treeViewer.setLabelProvider(new ITreeItemLabelProvider());
+ treeViewer.setContentProvider(new ITreeItemContentProvider());
+ treeViewer.addDoubleClickListener(new TreeItemViewerDoubleClickListener());
+ // treeViewer.setAutoExpandLevel(0);
+
+ tableViewer = new TableViewer(sash, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+ Table table = tableViewer.getTable();
+ table.setHeaderVisible(true);
+ table.setLinesVisible(true);
+ TableColumn tableColumnProperty = new TableColumn(table, SWT.LEFT);
+ tableColumnProperty.setText(Messages.getString("NavigatorTreeView.property")); //$NON-NLS-1$
+ tableColumnProperty.setWidth(70);
+ TableColumn tableColumnValue = new TableColumn(table, SWT.LEFT);
+ tableColumnValue.setText(Messages.getString("NavigatorTreeView.value")); //$NON-NLS-1$
+ tableColumnValue.setWidth(100);
+
+ tableViewer.setLabelProvider(new TreeItemDetailsLabelProvider());
+ tableViewer.setContentProvider(new TreeItemDetailsContentProvider());
+
+ sash.setWeights(new int[]{90, 10});
+ }
+
+ public NavigatorTreeView() {
+ super();
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ initView(parent);
+ NavigatorPlugin.getDefault().setNavigatorTreeView(this);
+ }
+
+ @Override
+ public void setFocus() {
+ }
+
+ private ITreeItem getRoot(ITreeItem item) {
+ for (ITreeItem parent = item.getParent(); parent != null; parent = item.getParent()) {
+ item = parent;
+ }
+ return item;
+ }
+
+ public void showItem(ITreeItem item) {
+ if (disposed) return;
+ if (treeViewer.getControl().isDisposed()) return;
+ treeViewer.setInput(getRoot(item));
+ treeViewer.reveal(item);
+ ISelection is = new StructuredSelection(item);
+ treeViewer.setSelection(is, true);
+ }
+
+ public void clearItem() {
+ if (disposed) return;
+ treeViewer.setInput(null);
+ }
+
+ public boolean isShown() {
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IViewPart part = page.findView(ID);
+ return part != null;
+ }
+
+ public boolean toggleViewShowing() {
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IViewPart part = page.findView(ID);
+
+ if (part != null) {
+ page.hideView(part);
+ return false;
+ } else {
+ try {
+ page.showView(ID);
+ return true;
+ } catch (PartInitException e) {
+ e.printStackTrace();
+ }
+ }
+ return false;
+ }
+
+ private ModeContribution getModeContribution(String id) {
+ IViewSite viewSite = getViewSite();
+ IActionBars actionBars = viewSite.getActionBars();
+ IStatusLineManager manager = actionBars.getStatusLineManager();
+ return (ModeContribution) manager.find(id);
+ }
+ private void update(){
+ IViewSite viewSite = getViewSite();
+ IActionBars actionBars = viewSite.getActionBars();
+ IStatusLineManager manager = actionBars.getStatusLineManager();
+ manager.update(true);
+ }
+
+
+ public void setMode(IManipulator.Mode mode) {
+ ModeContribution mc = getModeContribution(ModeContribution.MODE_CONTRIBUTION_ID);
+ if (mc != null) {