2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 import com
.sun
.star
.frame
.XFrame
;
20 import com
.sun
.star
.frame
.XModel
;
21 import com
.sun
.star
.frame
.XTerminateListener
;
22 import com
.sun
.star
.uno
.UnoRuntime
;
24 import com
.sun
.star
.accessibility
.XAccessibleContext
;
25 import com
.sun
.star
.awt
.XExtendedToolkit
;
28 import java
.awt
.event
.*;
30 import javax
.swing
.tree
.*;
31 import javax
.swing
.event
.TreeSelectionListener
;
32 import javax
.swing
.event
.TreeSelectionEvent
;
33 import ov
.ObjectViewContainer
;
35 /** This class manages the GUI of the work bench.
36 @see AccessibilityTreeModel
37 for the implementation of the tree view on the left side which also
38 manages the registration of accessibility listeners.
40 for the graphical view of the accessible objects.
42 public class AccessibilityWorkBench
44 implements ActionListener
, XTerminateListener
, TreeSelectionListener
47 public static final String msVersion
= "v1.7.2";
48 public String msOptionsFileName
= ".AWBrc";
50 public static void main (String args
[])
52 int nPortNumber
= 5678;
54 for (int i
=0; i
<args
.length
; i
++)
56 if (args
[i
].equals ("-h") || args
[i
].equals ("--help") || args
[i
].equals ("-?"))
58 System
.out
.println ("usage: AccessibilityWorkBench <option>*");
59 System
.out
.println ("options:");
60 System
.out
.println (" -p <port-number> Port on which to connect to StarOffice.");
61 System
.out
.println (" Defaults to 5678.");
64 else if (args
[i
].equals ("-p"))
66 nPortNumber
= Integer
.parseInt (args
[++i
]);
70 saWorkBench
= new AccessibilityWorkBench (nPortNumber
);
76 /** Return the one instance of the AccessibilityWorkBench
78 Returns null when the AccessibilityWorkBench could not be
81 public static AccessibilityWorkBench
Instance ()
88 /** Create an accessibility work bench that listens at the specified
89 port to Office applications.
91 private AccessibilityWorkBench (int nPortNumber
)
93 mbInitialized
= false;
97 MessageArea
.println (System
.getProperty ("os.name") + " / "
98 + System
.getProperty ("os.arch") + " / "
99 + System
.getProperty ("os.version"));
100 MessageArea
.println ("Using port " + nPortNumber
);
101 office
= new SimpleOffice (nPortNumber
);
102 info
= new InformationWriter ();
104 maAccessibilityTree
.getComponent().addTreeSelectionListener (this);
106 addWindowListener (new WindowAdapter ()
107 { public void windowClosing (WindowEvent e
)
117 /** Create and arrange the widgets of the GUI.
119 public void Layout ()
121 setSize (new Dimension (8000,600));
123 JScrollPane aScrollPane
;
124 GridBagConstraints constraints
;
126 // Create new layout.
127 GridBagLayout aLayout
= new GridBagLayout ();
128 getContentPane().setLayout (aLayout
);
131 maAccessibilityTree
= new AccessibilityTree ();
132 // maAccessibilityTree.getComponent().setMinimumSize (new Dimension (250,300));
133 JScrollPane aTreeScrollPane
= new JScrollPane(
134 maAccessibilityTree
.getComponent(),
135 JScrollPane
.VERTICAL_SCROLLBAR_ALWAYS
,
136 JScrollPane
.HORIZONTAL_SCROLLBAR_ALWAYS
);
137 aTreeScrollPane
.setPreferredSize (new Dimension (400,300));
139 // Object view shows details about the currently selected accessible
141 maObjectViewContainer
= new ObjectViewContainer ();
142 // maObjectViewContainer.setPreferredSize (new Dimension (300,100));
143 JScrollPane aObjectViewContainerScrollPane
= new JScrollPane(
144 maObjectViewContainer
,
145 JScrollPane
.VERTICAL_SCROLLBAR_AS_NEEDED
,
146 JScrollPane
.HORIZONTAL_SCROLLBAR_AS_NEEDED
);
147 aObjectViewContainerScrollPane
.setPreferredSize (new Dimension (400,300));
149 // Split pane for tree view and object view.
150 JSplitPane aLeftViewSplitPane
= new JSplitPane (
151 JSplitPane
.VERTICAL_SPLIT
,
153 aObjectViewContainerScrollPane
155 aLeftViewSplitPane
.setDividerLocation (300);
158 maCanvas
= new Canvas ();
159 maCanvas
.setTree (maAccessibilityTree
.getComponent());
160 maAccessibilityTree
.SetCanvas (maCanvas
);
161 JScrollPane aScrolledCanvas
= new JScrollPane(maCanvas
,
162 JScrollPane
.VERTICAL_SCROLLBAR_AS_NEEDED
,
163 JScrollPane
.HORIZONTAL_SCROLLBAR_AS_NEEDED
);
164 aScrolledCanvas
.getViewport().setBackground (Color
.RED
);
165 aScrolledCanvas
.setPreferredSize (new Dimension(600,400));
167 // Split pane for tree view and canvas.
168 JSplitPane aViewSplitPane
= new JSplitPane (
169 JSplitPane
.HORIZONTAL_SPLIT
,
173 aViewSplitPane
.setOneTouchExpandable(true);
174 aViewSplitPane
.setDividerLocation (400);
177 maMessageArea
= MessageArea
.Instance ();
178 // maMessageArea.setPreferredSize (new Dimension (300,50));
180 // Split pane for the two views and the message area.
181 JSplitPane aSplitPane
= new JSplitPane (JSplitPane
.VERTICAL_SPLIT
,
182 aViewSplitPane
, maMessageArea
);
183 aSplitPane
.setOneTouchExpandable(true);
184 addGridElement (aViewSplitPane
, 0,0, 2,1, 3,3,
185 GridBagConstraints
.CENTER
, GridBagConstraints
.BOTH
);
188 maButtonBar
= new JPanel();
189 GridBagLayout aButtonLayout
= new GridBagLayout ();
190 maButtonBar
.setLayout (new FlowLayout());
191 addGridElement (maButtonBar
, 0,3, 2,1, 1,0,
192 GridBagConstraints
.WEST
, GridBagConstraints
.HORIZONTAL
);
195 aConnectButton
= createButton ("Connect", "connect");
196 aUpdateButton
= createButton ("Update", "update");
197 aShapesButton
= createButton ("Expand Shapes", "shapes");
198 aExpandButton
= createButton ("Expand All", "expand");
199 aQuitButton
= createButton ("Quit", "quit");
200 UpdateButtonStates ();
202 Options
.Instance().Load (msOptionsFileName
);
204 setJMenuBar (CreateMenuBar ());
206 setTitle("Accessibility Workbench " + msVersion
);
217 /** Shortcut method for adding an object to a GridBagLayout.
219 void addGridElement (JComponent object
,
220 int x
, int y
, int width
, int height
, int weightx
, int weighty
,
221 int anchor
, int fill
)
223 GridBagConstraints constraints
= new GridBagConstraints ();
224 constraints
.gridx
= x
;
225 constraints
.gridy
= y
;
226 constraints
.gridwidth
= width
;
227 constraints
.gridheight
= height
;
228 constraints
.weightx
= weightx
;
229 constraints
.weighty
= weighty
;
230 constraints
.anchor
= anchor
;
231 constraints
.fill
= fill
;
232 getContentPane().add (object
, constraints
);
238 /** Create a new button and place at the right most position into the
241 public JButton
createButton (String title
, String command
)
243 JButton aButton
= new JButton (title
);
244 aButton
.setEnabled (false);
245 aButton
.setActionCommand (command
);
246 aButton
.addActionListener (this);
248 maButtonBar
.add (aButton
);
255 /** Create a menu bar for the application.
257 Returns the new menu bar. The returned reference is also
258 remembered in the data member <member>maMenuBar</member>.
260 JMenuBar
CreateMenuBar ()
263 maMenuBar
= new JMenuBar ();
266 JMenu aFileMenu
= new JMenu ("File");
267 maMenuBar
.add (aFileMenu
);
269 aItem
= new JMenuItem ("Quit");
270 aFileMenu
.add (aItem
);
271 aItem
.addActionListener (this);
274 JMenu aViewMenu
= new JMenu ("View");
275 maMenuBar
.add (aViewMenu
);
276 ButtonGroup aGroup
= new ButtonGroup ();
277 JRadioButtonMenuItem aRadioButton
= new JRadioButtonMenuItem ("Whole Screen");
278 aGroup
.add (aRadioButton
);
279 aViewMenu
.add (aRadioButton
);
280 aRadioButton
.addActionListener (this);
281 aRadioButton
= new JRadioButtonMenuItem ("200%");
282 aGroup
.add (aRadioButton
);
283 aViewMenu
.add (aRadioButton
);
284 aRadioButton
.addActionListener (this);
285 aRadioButton
= new JRadioButtonMenuItem ("100%");
286 aGroup
.add (aRadioButton
);
287 aViewMenu
.add (aRadioButton
);
288 aRadioButton
.addActionListener (this);
289 aRadioButton
= new JRadioButtonMenuItem ("50%");
290 aGroup
.add (aRadioButton
);
291 aViewMenu
.add (aRadioButton
);
292 aRadioButton
.addActionListener (this);
293 aRadioButton
= new JRadioButtonMenuItem ("25%");
294 aGroup
.add (aRadioButton
);
295 aViewMenu
.add (aRadioButton
);
296 aRadioButton
.addActionListener (this);
297 aRadioButton
= new JRadioButtonMenuItem ("10%");
298 aGroup
.add (aRadioButton
);
299 aViewMenu
.add (aRadioButton
);
300 aRadioButton
.addActionListener (this);
303 JMenu aOptionsMenu
= new JMenu ("Options");
304 maMenuBar
.add (aOptionsMenu
);
305 JCheckBoxMenuItem aCBItem
;
306 aCBItem
= new JCheckBoxMenuItem ("Show Descriptions", maCanvas
.getShowDescriptions());
307 aOptionsMenu
.add (aCBItem
);
308 aCBItem
.addActionListener (this);
310 aCBItem
= new JCheckBoxMenuItem ("Show Names", maCanvas
.getShowNames());
311 aOptionsMenu
.add (aCBItem
);
312 aCBItem
.addActionListener (this);
314 aCBItem
= new JCheckBoxMenuItem ("Show Text", maCanvas
.getShowText());
315 aOptionsMenu
.add (aCBItem
);
316 aCBItem
.addActionListener (this);
318 aCBItem
= new JCheckBoxMenuItem ("Antialiased Rendering", maCanvas
.getAntialiasing());
319 aOptionsMenu
.add (aCBItem
);
320 aCBItem
.addActionListener (this);
323 JMenu aHelpMenu
= new JMenu ("Help");
324 maMenuBar
.add (aHelpMenu
);
326 aItem
= new JMenuItem ("Help");
327 aHelpMenu
.add (aItem
);
328 aItem
.addActionListener (this);
330 aItem
= new JMenuItem ("News");
331 aHelpMenu
.add (aItem
);
332 aItem
.addActionListener (this);
334 aItem
= new JMenuItem ("About");
335 aHelpMenu
.add (aItem
);
336 aItem
.addActionListener (this);
344 /** Initialize the AWB. This includes clearing the canvas, add
345 listeners, creation of a new tree model for the tree list box and
346 the update of the button states.
348 This method may be called any number of times. Note that all
349 actions will be carried out every time. The main purpose of a
350 second call is that of a re-initialization after a reconnect.
352 protected void initialize ()
356 AccessibilityTreeModel aModel
= null;
357 aModel
= new AccessibilityTreeModel (createTreeModelRoot());
359 aModel
.setCanvas (maCanvas
);
360 maAccessibilityTree
.getComponent().setModel (aModel
);
364 // Add terminate listener.
365 if (office
.getDesktop() != null)
366 office
.getDesktop().addTerminateListener (this);
368 XExtendedToolkit xToolkit
= office
.getExtendedToolkit();
369 // Remove old top window listener.
370 if (maTopWindowListener
!= null)
371 xToolkit
.removeTopWindowListener (maQueuedTopWindowListener
);
372 // Add top window listener.
373 if (xToolkit
!= null)
375 MessageArea
.println ("registering at extended toolkit");
376 maTopWindowListener
= new TopWindowListener (aModel
, office
);
377 maQueuedTopWindowListener
= new QueuedTopWindowListener (maTopWindowListener
);
378 xToolkit
.addTopWindowListener (maQueuedTopWindowListener
);
379 maTopWindowListener
.Initialize ();
382 maTopWindowListener
= null;
385 mbInitialized
= true;
386 UpdateButtonStates ();
392 /** Update the states of the buttons according to the internal state of
395 protected void UpdateButtonStates ()
397 aConnectButton
.setEnabled (mbInitialized
);
398 aQuitButton
.setEnabled (mbInitialized
);
399 aUpdateButton
.setEnabled (mbInitialized
);
400 aExpandButton
.setEnabled (mbInitialized
);
401 aShapesButton
.setEnabled (mbInitialized
);
406 /** Callback for GUI actions from the buttons.
408 public void actionPerformed (java
.awt
.event
.ActionEvent e
)
410 if (e
.getActionCommand().equals("connect"))
415 else if (e
.getActionCommand().equals("quit"))
417 AccessibilityTreeModel aModel
= (AccessibilityTreeModel
)maAccessibilityTree
.getComponent().getModel();
421 else if (e
.getActionCommand().equals("update"))
425 else if (e
.getActionCommand().equals("shapes"))
427 Cursor aCursor
= getCursor();
428 setCursor (new Cursor (Cursor
.WAIT_CURSOR
));
429 maAccessibilityTree
.expandShapes();
432 else if (e
.getActionCommand().equals("expand"))
434 Cursor aCursor
= getCursor();
435 setCursor (new Cursor (Cursor
.WAIT_CURSOR
));
436 maAccessibilityTree
.expandAll();
439 else if (e
.getActionCommand().equals ("Quit"))
441 System
.out
.println ("exiting");
444 else if (e
.getActionCommand().equals ("Show Descriptions"))
446 maCanvas
.setShowDescriptions ( ! maCanvas
.getShowDescriptions());
447 Options
.Instance().Save (msOptionsFileName
);
449 else if (e
.getActionCommand().equals ("Show Names"))
451 maCanvas
.setShowNames ( ! maCanvas
.getShowNames());
452 Options
.Instance().Save (msOptionsFileName
);
454 else if (e
.getActionCommand().equals ("Antialiased Rendering"))
456 maCanvas
.setAntialiasing ( ! maCanvas
.getAntialiasing());
457 Options
.Instance().Save (msOptionsFileName
);
459 else if (e
.getActionCommand().equals ("Help"))
461 HelpWindow
.Instance().loadFile ("help.html");
463 else if (e
.getActionCommand().equals ("News"))
466 HelpWindow
.Instance().loadFile ("news.html");
467 } catch (Exception ex
) {}
469 else if (e
.getActionCommand().equals ("About"))
471 HelpWindow
.Instance().loadFile ("about.html");
473 else if (e
.getActionCommand().equals ("Whole Screen"))
475 maCanvas
.setZoomMode (Canvas
.WHOLE_SCREEN
);
476 Options
.Instance().Save (msOptionsFileName
);
478 else if (e
.getActionCommand().equals ("200%"))
480 maCanvas
.setZoomMode (200);
481 Options
.Instance().Save (msOptionsFileName
);
483 else if (e
.getActionCommand().equals ("100%"))
485 maCanvas
.setZoomMode (100);
486 Options
.Instance().Save (msOptionsFileName
);
488 else if (e
.getActionCommand().equals ("50%"))
490 maCanvas
.setZoomMode (50);
491 Options
.Instance().Save (msOptionsFileName
);
493 else if (e
.getActionCommand().equals ("25%"))
495 maCanvas
.setZoomMode (25);
496 Options
.Instance().Save (msOptionsFileName
);
498 else if (e
.getActionCommand().equals ("10%"))
500 maCanvas
.setZoomMode (10);
501 Options
.Instance().Save (msOptionsFileName
);
505 System
.err
.println("unknown command " + e
.getActionCommand());
512 /** Create an AccessibilityTreeModel root which contains the documents
513 (top windows) that are present at the moment.
515 private AccessibleTreeNode
createTreeModelRoot()
518 VectorNode aRoot
= new VectorNode ("Accessibility Tree", null);
519 if (maTopWindowListener
!= null)
520 maTopWindowListener
.Initialize ();
525 // TreeSelectionListener
526 public void valueChanged (TreeSelectionEvent aEvent
)
528 TreePath aPath
= aEvent
.getPath();
529 Object aObject
= aPath
.getLastPathComponent();
530 if (aObject
instanceof AccTreeNode
)
532 AccTreeNode aNode
= (AccTreeNode
) aObject
;
533 XAccessibleContext xContext
= aNode
.getContext();
534 maObjectViewContainer
.SetObject (xContext
);
542 public void disposing( com
.sun
.star
.lang
.EventObject aSourceObj
)
544 XFrame xFrame
= UnoRuntime
.queryInterface(XFrame
.class, aSourceObj
.Source
);
547 System
.out
.println("frame disposed");
549 System
.out
.println("controller disposed");
555 // XTerminateListener
556 public void queryTermination (final com
.sun
.star
.lang
.EventObject aEvent
) throws RuntimeException
558 System
.out
.println ("Terminate Event : " + aEvent
);
564 // XTerminateListener
565 public void notifyTermination (final com
.sun
.star
.lang
.EventObject aEvent
) throws RuntimeException
567 System
.out
.println ("Notifiy Termination Event : " + aEvent
);
572 /// The Singleton Workbench object.
573 private static AccessibilityWorkBench
576 protected SimpleOffice
578 protected InformationWriter
588 private AccessibilityTree
590 private ObjectViewContainer
591 maObjectViewContainer
;
608 private TopWindowListener
610 private QueuedTopWindowListener
611 maQueuedTopWindowListener
;