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 java
.awt
.Color
;
20 import java
.awt
.Dimension
;
21 import java
.awt
.Graphics
;
22 import java
.awt
.Graphics2D
;
23 import java
.awt
.Rectangle
;
24 import java
.awt
.RenderingHints
;
25 import java
.awt
.Toolkit
;
26 import java
.awt
.event
.InputEvent
;
27 import java
.awt
.event
.MouseEvent
;
28 import java
.awt
.event
.MouseListener
;
29 import java
.awt
.event
.MouseMotionListener
;
30 import java
.awt
.geom
.Rectangle2D
;
31 import java
.util
.ArrayList
;
32 import java
.util
.List
;
34 import javax
.swing
.JPanel
;
35 import javax
.swing
.JScrollPane
;
36 import javax
.swing
.JTree
;
37 import javax
.swing
.JViewport
;
38 import javax
.swing
.event
.TreeSelectionListener
;
39 import javax
.swing
.tree
.TreePath
;
41 /** This canvas displays accessible objects graphically. Each accessible
42 object with graphical representation is represented by an
43 CanvasShape object and has to be added by the
44 <member>addAccessible</member> member function.
46 <p>The canvas listens to selection events of the associated JTree and
47 highlights the first selected node of that tree.</p>
51 implements MouseListener
, MouseMotionListener
, TreeSelectionListener
//, Scrollable
53 // This constant can be passed to SetZoomMode to always show the whole screen.
54 public static final int WHOLE_SCREEN
= -1;
59 maObjects
= new java
.util
.HashMap
<AccTreeNode
, CanvasShape
> ();
60 maNodes
= new ArrayList
<AccTreeNode
> ();
61 maObjectList
= new ArrayList
<CanvasShape
> ();
62 addMouseListener (this);
63 addMouseMotionListener (this);
64 maBoundingBox
= new Rectangle (0,0,100,100);
70 setShowDescriptions (true);
72 setAntialiasing (true);
75 /** Tell the canvas which tree view to use to highlight accessible
78 public void setTree (JTree aTree
)
81 maTree
.removeTreeSelectionListener (this);
84 maTree
.addTreeSelectionListener (this);
90 public void addNode (AccTreeNode aNode
)
92 if (maNodes
.indexOf (aNode
) == -1)
96 CanvasShape aObject
= maObjects
.get (aNode
);
99 aObject
= new CanvasShape (aNode
);
100 // Update bounding box that includes all objects.
101 if (maObjects
.isEmpty())
102 maBoundingBox
= aObject
.getBBox();
104 maBoundingBox
= maBoundingBox
.union (aObject
.getBBox());
106 maObjects
.put (aNode
, aObject
);
107 maObjectList
.add (aObject
);
114 public void removeNode (AccTreeNode aNode
)
116 int i
= maNodes
.indexOf (aNode
);
119 CanvasShape aObject
= maObjects
.get(aNode
);
120 maObjectList
.remove (aObject
);
121 maObjects
.remove (aNode
);
122 maNodes
.remove (aNode
);
127 public void updateNode (AccTreeNode aNode
)
129 int i
= maNodes
.indexOf (aNode
);
132 CanvasShape aObject
= maObjects
.get(aNode
);
138 public void updateNodeGeometry (AccTreeNode aNode
)
140 CanvasShape aObject
= maObjects
.get(aNode
);
142 aObject
.updateGeometry();
147 while (maNodes
.size() > 0) {
148 removeNode (maNodes
.get(0));
152 maObjectList
.clear();
155 public boolean getShowDescriptions ()
157 return Options
.GetBoolean ("ShowDescriptions");
160 public void setShowDescriptions (boolean bNewValue
)
162 Options
.SetBoolean ("ShowDescriptions", bNewValue
);
166 public boolean getShowNames ()
168 return Options
.GetBoolean ("ShowNames");
171 public void setShowNames (boolean bNewValue
)
173 Options
.SetBoolean ("ShowNames", bNewValue
);
177 public boolean getAntialiasing ()
179 return Options
.GetBoolean ("Antialiasing");
182 public void setAntialiasing (boolean bNewValue
)
184 Options
.SetBoolean ("Antialiasing", bNewValue
);
188 public boolean getShowText ()
190 return Options
.GetBoolean ("ShowText");
193 private void setShowText (boolean bNewValue
)
195 Options
.SetBoolean ("ShowText", bNewValue
);
199 public void setZoomMode (int nZoomMode
)
201 Options
.SetInteger ("ZoomMode", nZoomMode
);
205 private int getZoomMode ()
207 return Options
.GetInteger ("ZoomMode", WHOLE_SCREEN
);
212 public void paintComponent (Graphics g
)
216 super.paintComponent (g
);
218 Graphics2D g2
= (Graphics2D
)g
;
219 if (getAntialiasing())
220 g2
.setRenderingHint (RenderingHints
.KEY_ANTIALIASING
,
221 RenderingHints
.VALUE_ANTIALIAS_ON
);
223 g2
.setRenderingHint (RenderingHints
.KEY_ANTIALIASING
,
224 RenderingHints
.VALUE_ANTIALIAS_OFF
);
226 setupTransformation ();
228 // Draw the screen representation to give a hint of the location of the
229 // accessible object on the screen.
230 Dimension aScreenSize
= Toolkit
.getDefaultToolkit().getScreenSize();
231 Rectangle2D
.Double aScreen
= new Rectangle2D
.Double (
234 mnScale
*aScreenSize
.getWidth(),
235 mnScale
*aScreenSize
.getHeight());
236 // Fill the screen rectangle and draw a frame around it to increase its visibility.
237 g2
.setColor (new Color (250,240,230));
239 g2
.setColor (Color
.BLACK
);
242 synchronized (maObjectList
)
244 int nCount
= maObjectList
.size();
245 boolean bShowDescriptions
= getShowDescriptions();
246 boolean bShowNames
= getShowNames();
247 boolean bShowText
= getShowText();
248 for (int i
=0; i
<nCount
; i
++)
250 CanvasShape aCanvasShape
= maObjectList
.get(i
);
253 mnHOffset
, mnVOffset
, mnScale
,
254 bShowDescriptions
, bShowNames
, bShowText
);
258 // Paint highlighted frame around active object as the last thing.
259 if (maActiveObject
!= null)
260 maActiveObject
.paint_highlight (
268 /** Set up the transformation so that the graphical display can show a
269 centered representation of the whole screen.
271 private void setupTransformation ()
273 // Turn off scrollbars when showing the whole screen. Otherwise show them when needed.
274 JViewport aViewport
= (JViewport
)getParent();
275 JScrollPane aScrollPane
= (JScrollPane
)aViewport
.getParent();
276 int nZoomMode
= getZoomMode();
277 if (nZoomMode
== WHOLE_SCREEN
)
279 if (aScrollPane
.getHorizontalScrollBarPolicy()
280 != JScrollPane
.HORIZONTAL_SCROLLBAR_NEVER
)
281 aScrollPane
.setHorizontalScrollBarPolicy (JScrollPane
.HORIZONTAL_SCROLLBAR_NEVER
);
282 if (aScrollPane
.getVerticalScrollBarPolicy()
283 != JScrollPane
.VERTICAL_SCROLLBAR_NEVER
)
284 aScrollPane
.setVerticalScrollBarPolicy (JScrollPane
.VERTICAL_SCROLLBAR_NEVER
);
288 if (aScrollPane
.getHorizontalScrollBarPolicy()
289 != JScrollPane
.HORIZONTAL_SCROLLBAR_AS_NEEDED
)
290 aScrollPane
.setHorizontalScrollBarPolicy (JScrollPane
.HORIZONTAL_SCROLLBAR_AS_NEEDED
);
291 if (aScrollPane
.getVerticalScrollBarPolicy()
292 != JScrollPane
.VERTICAL_SCROLLBAR_AS_NEEDED
)
293 aScrollPane
.setVerticalScrollBarPolicy (JScrollPane
.VERTICAL_SCROLLBAR_AS_NEEDED
);
296 Dimension aScreenSize
= Toolkit
.getDefaultToolkit().getScreenSize();
297 Dimension aWidgetSize
= aViewport
.getSize();
299 if ((aScreenSize
.getWidth() > 0) && (aScreenSize
.getHeight() > 0))
301 if (nZoomMode
== WHOLE_SCREEN
)
303 // Calculate the scales that would map the screen onto the
304 // widget in both of the coordinate axes and select the
306 // of the two: it maps the screen onto the widget in both
307 // axes at the same time.
308 double nHScale
= (aWidgetSize
.getWidth() - 10) / aScreenSize
.getWidth();
309 double nVScale
= (aWidgetSize
.getHeight() - 10) / aScreenSize
.getHeight();
310 if (nHScale
< nVScale
)
317 mnScale
= nZoomMode
/ 100.0;
320 // Calculate offsets that center the scaled screen inside the widget.
321 mnHOffset
= (aWidgetSize
.getWidth() - mnScale
*aScreenSize
.getWidth()) / 2.0;
322 mnVOffset
= (aWidgetSize
.getHeight() - mnScale
*aScreenSize
.getHeight()) / 2.0;
328 setPreferredSize (new Dimension (
329 (int)(2*mnHOffset
+ mnScale
* aScreenSize
.getWidth()),
330 (int)(2*mnVOffset
+ mnScale
* aScreenSize
.getHeight())));
335 // In case of a degenerate (not yet initialized?) screen size
336 // use some meaningless default values.
346 /** Call getAccessibleAt to determine accessible object under mouse.
348 public void mouseClicked (MouseEvent e
)
352 public void mousePressed (MouseEvent e
)
354 CanvasShape aObjectUnderMouse
= FindCanvasShapeUnderMouse (e
);
355 highlightObject (aObjectUnderMouse
);
356 if ((e
.getModifiers() & InputEvent
.CTRL_MASK
) != 0)
358 maTree
.expandPath (aObjectUnderMouse
.getPath());
362 public void mouseReleased (MouseEvent e
)
366 public void mouseEntered (MouseEvent e
)
370 public void mouseExited (MouseEvent e
)
372 // Deselect currently active object.
373 if (maActiveObject
!= null)
375 maActiveObject
.unhighlight ();
376 maActiveObject
= null;
381 public void mouseDragged (MouseEvent e
)
385 public void mouseMoved (MouseEvent e
)
387 if ((e
.getModifiers() & InputEvent
.SHIFT_MASK
) != 0)
388 highlightObject (FindCanvasShapeUnderMouse (e
));
391 private CanvasShape
FindCanvasShapeUnderMouse (MouseEvent e
)
393 CanvasShape aObjectUnderMouse
= null;
394 int nCount
= maObjectList
.size();
395 for (int i
=nCount
-1; i
>=0; --i
)
397 CanvasShape aObject
= maObjectList
.get(i
);
399 if (aObject
.contains (e
.getX(),e
.getY()))
401 aObjectUnderMouse
= aObject
;
405 return aObjectUnderMouse
;
408 private boolean highlightObject (CanvasShape aNewActiveObject
)
410 if (aNewActiveObject
!= maActiveObject
)
412 if (maActiveObject
!= null)
413 maActiveObject
.unhighlight();
415 maActiveObject
= aNewActiveObject
;
416 if (maActiveObject
!= null)
420 maTree
.scrollPathToVisible (maActiveObject
.getPath());
421 maTree
.setSelectionPath (maActiveObject
.getPath());
424 maActiveObject
.highlight ();
433 /** Called when the selection of the tree changes. Highlight the
434 corresponding graphical representation of the first selected object.
436 public void valueChanged (javax
.swing
.event
.TreeSelectionEvent event
)
438 TreePath aPath
= event
.getPath();
439 Object aObject
= aPath
.getLastPathComponent();
440 if (aObject
instanceof AccTreeNode
)
442 CanvasShape aCanvasShape
= maObjects
.get (aObject
);
443 if (highlightObject (aCanvasShape
))
454 private final java
.util
.HashMap
<AccTreeNode
, CanvasShape
>
456 private final List
<CanvasShape
>
458 private final List
<AccTreeNode
>