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
.XTerminateListener
;
21 import com
.sun
.star
.uno
.UnoRuntime
;
23 import com
.sun
.star
.accessibility
.XAccessibleContext
;
24 import com
.sun
.star
.awt
.XExtendedToolkit
;
27 import java
.awt
.event
.*;
29 import javax
.swing
.tree
.*;
30 import javax
.swing
.event
.TreeSelectionListener
;
31 import javax
.swing
.event
.TreeSelectionEvent
;
32 import ov
.ObjectViewContainer
;
34 /** This class manages the GUI of the work bench.
35 @see AccessibilityTreeModel
36 for the implementation of the tree view on the left side which also
37 manages the registration of accessibility listeners.
39 for the graphical view of the accessible objects.
41 public class AccessibilityWorkBench
43 implements ActionListener
, XTerminateListener
, TreeSelectionListener
46 private static final String msVersion
= "v1.7.2";
47 private String msOptionsFileName
= ".AWBrc";
49 public static void main (String args
[])
51 int nPortNumber
= 5678;
53 for (int i
=0; i
<args
.length
; i
++)
55 if (args
[i
].equals ("-h") || args
[i
].equals ("--help") || args
[i
].equals ("-?"))
57 System
.out
.println ("usage: AccessibilityWorkBench <option>*");
58 System
.out
.println ("options:");
59 System
.out
.println (" -p <port-number> Port on which to connect to StarOffice.");
60 System
.out
.println (" Defaults to 5678.");
63 else if (args
[i
].equals ("-p"))
65 nPortNumber
= Integer
.parseInt (args
[++i
]);
69 saWorkBench
= new AccessibilityWorkBench (nPortNumber
);
75 /** Return the one instance of the AccessibilityWorkBench
77 Returns null when the AccessibilityWorkBench could not be
80 public static AccessibilityWorkBench
Instance ()
87 /** Create an accessibility work bench that listens at the specified
88 port to Office applications.
90 private AccessibilityWorkBench (int nPortNumber
)
92 mbInitialized
= false;
96 MessageArea
.println (System
.getProperty ("os.name") + " / "
97 + System
.getProperty ("os.arch") + " / "
98 + System
.getProperty ("os.version"));
99 MessageArea
.println ("Using port " + nPortNumber
);
100 office
= new SimpleOffice (nPortNumber
);
102 maAccessibilityTree
.getComponent().addTreeSelectionListener (this);
104 addWindowListener (new WindowAdapter ()
106 public void windowClosing (WindowEvent e
)
116 /** Create and arrange the widgets of the GUI.
118 private void Layout ()
120 setSize (new Dimension (8000,600));
122 // Create new layout.
123 GridBagLayout aLayout
= new GridBagLayout ();
124 getContentPane().setLayout (aLayout
);
127 maAccessibilityTree
= new AccessibilityTree ();
128 JScrollPane aTreeScrollPane
= new JScrollPane(
129 maAccessibilityTree
.getComponent(),
130 JScrollPane
.VERTICAL_SCROLLBAR_ALWAYS
,
131 JScrollPane
.HORIZONTAL_SCROLLBAR_ALWAYS
);
132 aTreeScrollPane
.setPreferredSize (new Dimension (400,300));
134 // Object view shows details about the currently selected accessible
136 maObjectViewContainer
= new ObjectViewContainer ();
137 JScrollPane aObjectViewContainerScrollPane
= new JScrollPane(
138 maObjectViewContainer
,
139 JScrollPane
.VERTICAL_SCROLLBAR_AS_NEEDED
,
140 JScrollPane
.HORIZONTAL_SCROLLBAR_AS_NEEDED
);
141 aObjectViewContainerScrollPane
.setPreferredSize (new Dimension (400,300));
143 // Split pane for tree view and object view.
144 JSplitPane aLeftViewSplitPane
= new JSplitPane (
145 JSplitPane
.VERTICAL_SPLIT
,
147 aObjectViewContainerScrollPane
149 aLeftViewSplitPane
.setDividerLocation (300);
152 maCanvas
= new Canvas ();
153 maCanvas
.setTree (maAccessibilityTree
.getComponent());
154 maAccessibilityTree
.SetCanvas (maCanvas
);
155 JScrollPane aScrolledCanvas
= new JScrollPane(maCanvas
,
156 JScrollPane
.VERTICAL_SCROLLBAR_AS_NEEDED
,
157 JScrollPane
.HORIZONTAL_SCROLLBAR_AS_NEEDED
);
158 aScrolledCanvas
.getViewport().setBackground (Color
.RED
);
159 aScrolledCanvas
.setPreferredSize (new Dimension(600,400));
161 // Split pane for tree view and canvas.
162 JSplitPane aViewSplitPane
= new JSplitPane (
163 JSplitPane
.HORIZONTAL_SPLIT
,
167 aViewSplitPane
.setOneTouchExpandable(true);
168 aViewSplitPane
.setDividerLocation (400);
171 MessageArea aMessageArea
= MessageArea
.Instance ();
173 // Split pane for the two views and the message area.
174 JSplitPane aSplitPane
= new JSplitPane (JSplitPane
.VERTICAL_SPLIT
,
175 aViewSplitPane
, aMessageArea
);
176 aSplitPane
.setOneTouchExpandable(true);
177 addGridElement (aViewSplitPane
, 0,0, 2,1, 3,3,
178 GridBagConstraints
.CENTER
, GridBagConstraints
.BOTH
);
181 maButtonBar
= new JPanel();
182 maButtonBar
.setLayout (new FlowLayout());
183 addGridElement (maButtonBar
, 0,3, 2,1, 1,0,
184 GridBagConstraints
.WEST
, GridBagConstraints
.HORIZONTAL
);
187 aConnectButton
= createButton ("Connect", "connect");
188 aUpdateButton
= createButton ("Update", "update");
189 aShapesButton
= createButton ("Expand Shapes", "shapes");
190 aExpandButton
= createButton ("Expand All", "expand");
191 aQuitButton
= createButton ("Quit", "quit");
192 UpdateButtonStates ();
194 Options
.Instance().Load (msOptionsFileName
);
196 setJMenuBar (CreateMenuBar ());
198 setTitle("Accessibility Workbench " + msVersion
);
209 /** Shortcut method for adding an object to a GridBagLayout.
211 private void addGridElement (JComponent object
,
212 int x
, int y
, int width
, int height
, int weightx
, int weighty
,
213 int anchor
, int fill
)
215 GridBagConstraints constraints
= new GridBagConstraints ();
216 constraints
.gridx
= x
;
217 constraints
.gridy
= y
;
218 constraints
.gridwidth
= width
;
219 constraints
.gridheight
= height
;
220 constraints
.weightx
= weightx
;
221 constraints
.weighty
= weighty
;
222 constraints
.anchor
= anchor
;
223 constraints
.fill
= fill
;
224 getContentPane().add (object
, constraints
);
230 /** Create a new button and place at the right most position into the
233 private JButton
createButton (String title
, String command
)
235 JButton aButton
= new JButton (title
);
236 aButton
.setEnabled (false);
237 aButton
.setActionCommand (command
);
238 aButton
.addActionListener (this);
240 maButtonBar
.add (aButton
);
247 /** Create a menu bar for the application.
249 Returns the new menu bar. The returned reference is also
250 remembered in the data member <member>maMenuBar</member>.
252 private JMenuBar
CreateMenuBar ()
255 JMenuBar aMenuBar
= new JMenuBar ();
258 JMenu aFileMenu
= new JMenu ("File");
259 aMenuBar
.add (aFileMenu
);
261 aItem
= new JMenuItem ("Quit");
262 aFileMenu
.add (aItem
);
263 aItem
.addActionListener (this);
266 JMenu aViewMenu
= new JMenu ("View");
267 aMenuBar
.add (aViewMenu
);
268 ButtonGroup aGroup
= new ButtonGroup ();
269 JRadioButtonMenuItem aRadioButton
= new JRadioButtonMenuItem ("Whole Screen");
270 aGroup
.add (aRadioButton
);
271 aViewMenu
.add (aRadioButton
);
272 aRadioButton
.addActionListener (this);
273 aRadioButton
= new JRadioButtonMenuItem ("200%");
274 aGroup
.add (aRadioButton
);
275 aViewMenu
.add (aRadioButton
);
276 aRadioButton
.addActionListener (this);
277 aRadioButton
= new JRadioButtonMenuItem ("100%");
278 aGroup
.add (aRadioButton
);
279 aViewMenu
.add (aRadioButton
);
280 aRadioButton
.addActionListener (this);
281 aRadioButton
= new JRadioButtonMenuItem ("50%");
282 aGroup
.add (aRadioButton
);
283 aViewMenu
.add (aRadioButton
);
284 aRadioButton
.addActionListener (this);
285 aRadioButton
= new JRadioButtonMenuItem ("25%");
286 aGroup
.add (aRadioButton
);
287 aViewMenu
.add (aRadioButton
);
288 aRadioButton
.addActionListener (this);
289 aRadioButton
= new JRadioButtonMenuItem ("10%");
290 aGroup
.add (aRadioButton
);
291 aViewMenu
.add (aRadioButton
);
292 aRadioButton
.addActionListener (this);
295 JMenu aOptionsMenu
= new JMenu ("Options");
296 aMenuBar
.add (aOptionsMenu
);
297 JCheckBoxMenuItem aCBItem
;
298 aCBItem
= new JCheckBoxMenuItem ("Show Descriptions", maCanvas
.getShowDescriptions());
299 aOptionsMenu
.add (aCBItem
);
300 aCBItem
.addActionListener (this);
302 aCBItem
= new JCheckBoxMenuItem ("Show Names", maCanvas
.getShowNames());
303 aOptionsMenu
.add (aCBItem
);
304 aCBItem
.addActionListener (this);
306 aCBItem
= new JCheckBoxMenuItem ("Show Text", maCanvas
.getShowText());
307 aOptionsMenu
.add (aCBItem
);
308 aCBItem
.addActionListener (this);
310 aCBItem
= new JCheckBoxMenuItem ("Antialiased Rendering", maCanvas
.getAntialiasing());
311 aOptionsMenu
.add (aCBItem
);
312 aCBItem
.addActionListener (this);
315 JMenu aHelpMenu
= new JMenu ("Help");
316 aMenuBar
.add (aHelpMenu
);
318 aItem
= new JMenuItem ("Help");
319 aHelpMenu
.add (aItem
);
320 aItem
.addActionListener (this);
322 aItem
= new JMenuItem ("News");
323 aHelpMenu
.add (aItem
);
324 aItem
.addActionListener (this);
326 aItem
= new JMenuItem ("About");
327 aHelpMenu
.add (aItem
);
328 aItem
.addActionListener (this);
336 /** Initialize the AWB. This includes clearing the canvas, add
337 listeners, creation of a new tree model for the tree list box and
338 the update of the button states.
340 This method may be called any number of times. Note that all
341 actions will be carried out every time. The main purpose of a
342 second call is that of a re-initialization after a reconnect.
344 private void initialize ()
348 AccessibilityTreeModel aModel
= null;
349 aModel
= new AccessibilityTreeModel (createTreeModelRoot());
351 aModel
.setCanvas (maCanvas
);
352 maAccessibilityTree
.getComponent().setModel (aModel
);
356 // Add terminate listener.
357 if (office
.getDesktop() != null)
358 office
.getDesktop().addTerminateListener (this);
360 XExtendedToolkit xToolkit
= office
.getExtendedToolkit();
361 // Remove old top window listener.
362 if (maTopWindowListener
!= null)
363 xToolkit
.removeTopWindowListener (maQueuedTopWindowListener
);
364 // Add top window listener.
365 if (xToolkit
!= null)
367 MessageArea
.println ("registering at extended toolkit");
368 maTopWindowListener
= new TopWindowListener (aModel
, office
);
369 maQueuedTopWindowListener
= new QueuedTopWindowListener (maTopWindowListener
);
370 xToolkit
.addTopWindowListener (maQueuedTopWindowListener
);
371 maTopWindowListener
.Initialize ();
374 maTopWindowListener
= null;
377 mbInitialized
= true;
378 UpdateButtonStates ();
384 /** Update the states of the buttons according to the internal state of
387 private void UpdateButtonStates ()
389 aConnectButton
.setEnabled (mbInitialized
);
390 aQuitButton
.setEnabled (mbInitialized
);
391 aUpdateButton
.setEnabled (mbInitialized
);
392 aExpandButton
.setEnabled (mbInitialized
);
393 aShapesButton
.setEnabled (mbInitialized
);
398 /** Callback for GUI actions from the buttons.
400 public void actionPerformed (java
.awt
.event
.ActionEvent e
)
402 if (e
.getActionCommand().equals("connect"))
407 else if (e
.getActionCommand().equals("quit"))
409 AccessibilityTreeModel aModel
= (AccessibilityTreeModel
)maAccessibilityTree
.getComponent().getModel();
413 else if (e
.getActionCommand().equals("update"))
417 else if (e
.getActionCommand().equals("shapes"))
419 Cursor aCursor
= getCursor();
420 setCursor (new Cursor (Cursor
.WAIT_CURSOR
));
421 maAccessibilityTree
.expandShapes();
424 else if (e
.getActionCommand().equals("expand"))
426 Cursor aCursor
= getCursor();
427 setCursor (new Cursor (Cursor
.WAIT_CURSOR
));
428 maAccessibilityTree
.expandAll();
431 else if (e
.getActionCommand().equals ("Quit"))
433 System
.out
.println ("exiting");
436 else if (e
.getActionCommand().equals ("Show Descriptions"))
438 maCanvas
.setShowDescriptions ( ! maCanvas
.getShowDescriptions());
439 Options
.Instance().Save (msOptionsFileName
);
441 else if (e
.getActionCommand().equals ("Show Names"))
443 maCanvas
.setShowNames ( ! maCanvas
.getShowNames());
444 Options
.Instance().Save (msOptionsFileName
);
446 else if (e
.getActionCommand().equals ("Antialiased Rendering"))
448 maCanvas
.setAntialiasing ( ! maCanvas
.getAntialiasing());
449 Options
.Instance().Save (msOptionsFileName
);
451 else if (e
.getActionCommand().equals ("Help"))
453 HelpWindow
.Instance().loadFile ("help.html");
455 else if (e
.getActionCommand().equals ("News"))
458 HelpWindow
.Instance().loadFile ("news.html");
459 } catch (Exception ex
) {}
461 else if (e
.getActionCommand().equals ("About"))
463 HelpWindow
.Instance().loadFile ("about.html");
465 else if (e
.getActionCommand().equals ("Whole Screen"))
467 maCanvas
.setZoomMode (Canvas
.WHOLE_SCREEN
);
468 Options
.Instance().Save (msOptionsFileName
);
470 else if (e
.getActionCommand().equals ("200%"))
472 maCanvas
.setZoomMode (200);
473 Options
.Instance().Save (msOptionsFileName
);
475 else if (e
.getActionCommand().equals ("100%"))
477 maCanvas
.setZoomMode (100);
478 Options
.Instance().Save (msOptionsFileName
);
480 else if (e
.getActionCommand().equals ("50%"))
482 maCanvas
.setZoomMode (50);
483 Options
.Instance().Save (msOptionsFileName
);
485 else if (e
.getActionCommand().equals ("25%"))
487 maCanvas
.setZoomMode (25);
488 Options
.Instance().Save (msOptionsFileName
);
490 else if (e
.getActionCommand().equals ("10%"))
492 maCanvas
.setZoomMode (10);
493 Options
.Instance().Save (msOptionsFileName
);
497 System
.err
.println("unknown command " + e
.getActionCommand());
504 /** Create an AccessibilityTreeModel root which contains the documents
505 (top windows) that are present at the moment.
507 private AccessibleTreeNode
createTreeModelRoot()
510 VectorNode aRoot
= new VectorNode ("Accessibility Tree", null);
511 if (maTopWindowListener
!= null)
512 maTopWindowListener
.Initialize ();
517 // TreeSelectionListener
518 public void valueChanged (TreeSelectionEvent aEvent
)
520 TreePath aPath
= aEvent
.getPath();
521 Object aObject
= aPath
.getLastPathComponent();
522 if (aObject
instanceof AccTreeNode
)
524 AccTreeNode aNode
= (AccTreeNode
) aObject
;
525 XAccessibleContext xContext
= aNode
.getContext();
526 maObjectViewContainer
.SetObject (xContext
);
534 public void disposing( com
.sun
.star
.lang
.EventObject aSourceObj
)
536 XFrame xFrame
= UnoRuntime
.queryInterface(XFrame
.class, aSourceObj
.Source
);
539 System
.out
.println("frame disposed");
541 System
.out
.println("controller disposed");
547 // XTerminateListener
548 public void queryTermination (final com
.sun
.star
.lang
.EventObject aEvent
) throws RuntimeException
550 System
.out
.println ("Terminate Event : " + aEvent
);
556 // XTerminateListener
557 public void notifyTermination (final com
.sun
.star
.lang
.EventObject aEvent
) throws RuntimeException
559 System
.out
.println ("Notify Termination Event : " + aEvent
);
564 /// The Singleton Workbench object.
565 private static AccessibilityWorkBench
575 private AccessibilityTree
577 private ObjectViewContainer
578 maObjectViewContainer
;
587 private TopWindowListener
589 private QueuedTopWindowListener
590 maQueuedTopWindowListener
;