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);
73 maLastWidgetSize
= new Dimension (0,0);
76 /** Tell the canvas which tree view to use to highlight accessible
79 public void setTree (JTree aTree
)
82 maTree
.removeTreeSelectionListener (this);
85 maTree
.addTreeSelectionListener (this);
91 public void addNode (AccTreeNode aNode
)
93 if (maNodes
.indexOf (aNode
) == -1)
97 CanvasShape aObject
= maObjects
.get (aNode
);
100 aObject
= new CanvasShape (aNode
);
101 // Update bounding box that includes all objects.
102 if (maObjects
.size() == 0)
103 maBoundingBox
= aObject
.getBBox();
105 maBoundingBox
= maBoundingBox
.union (aObject
.getBBox());
107 maObjects
.put (aNode
, aObject
);
108 maObjectList
.add (aObject
);
115 public void removeNode (AccTreeNode aNode
)
117 int i
= maNodes
.indexOf (aNode
);
120 Object aObject
= maObjects
.get(aNode
);
121 maObjectList
.remove (aObject
);
122 maObjects
.remove (aObject
);
123 maNodes
.remove (aNode
);
128 public void updateNode (AccTreeNode aNode
)
130 int i
= maNodes
.indexOf (aNode
);
133 CanvasShape aObject
= maObjects
.get(aNode
);
139 public void updateNodeGeometry (AccTreeNode aNode
)
141 CanvasShape aObject
= maObjects
.get(aNode
);
143 aObject
.updateGeometry();
148 while (maNodes
.size() > 0)
149 removeNode (maNodes
.get(0));
153 maObjectList
.clear();
156 public boolean getShowDescriptions ()
158 return Options
.GetBoolean ("ShowDescriptions");
161 public void setShowDescriptions (boolean bNewValue
)
163 Options
.SetBoolean ("ShowDescriptions", bNewValue
);
167 public boolean getShowNames ()
169 return Options
.GetBoolean ("ShowNames");
172 public void setShowNames (boolean bNewValue
)
174 Options
.SetBoolean ("ShowNames", bNewValue
);
178 public boolean getAntialiasing ()
180 return Options
.GetBoolean ("Antialiasing");
183 public void setAntialiasing (boolean bNewValue
)
185 Options
.SetBoolean ("Antialiasing", bNewValue
);
189 public boolean getShowText ()
191 return Options
.GetBoolean ("ShowText");
194 public void setShowText (boolean bNewValue
)
196 Options
.SetBoolean ("ShowText", bNewValue
);
200 public void setZoomMode (int nZoomMode
)
202 Options
.SetInteger ("ZoomMode", nZoomMode
);
206 public int getZoomMode ()
208 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 arround 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 (
262 mnHOffset
, mnVOffset
, mnScale
);
269 /** Set up the transformation so that the graphical display can show a
270 centered representation of the whole screen.
272 private void setupTransformation ()
274 // Turn off scrollbars when showing the whole screen. Otherwise show them when needed.
275 JViewport aViewport
= (JViewport
)getParent();
276 JScrollPane aScrollPane
= (JScrollPane
)aViewport
.getParent();
277 int nZoomMode
= getZoomMode();
278 if (nZoomMode
== WHOLE_SCREEN
)
280 if (aScrollPane
.getHorizontalScrollBarPolicy()
281 != JScrollPane
.HORIZONTAL_SCROLLBAR_NEVER
)
282 aScrollPane
.setHorizontalScrollBarPolicy (JScrollPane
.HORIZONTAL_SCROLLBAR_NEVER
);
283 if (aScrollPane
.getVerticalScrollBarPolicy()
284 != JScrollPane
.VERTICAL_SCROLLBAR_NEVER
)
285 aScrollPane
.setVerticalScrollBarPolicy (JScrollPane
.VERTICAL_SCROLLBAR_NEVER
);
289 if (aScrollPane
.getHorizontalScrollBarPolicy()
290 != JScrollPane
.HORIZONTAL_SCROLLBAR_AS_NEEDED
)
291 aScrollPane
.setHorizontalScrollBarPolicy (JScrollPane
.HORIZONTAL_SCROLLBAR_AS_NEEDED
);
292 if (aScrollPane
.getVerticalScrollBarPolicy()
293 != JScrollPane
.VERTICAL_SCROLLBAR_AS_NEEDED
)
294 aScrollPane
.setVerticalScrollBarPolicy (JScrollPane
.VERTICAL_SCROLLBAR_AS_NEEDED
);
297 Dimension aScreenSize
= Toolkit
.getDefaultToolkit().getScreenSize();
298 Dimension aWidgetSize
= aViewport
.getSize();
300 if ((aScreenSize
.getWidth() > 0) && (aScreenSize
.getHeight() > 0))
302 if (nZoomMode
== WHOLE_SCREEN
)
304 // Calculate the scales that would map the screen onto the
305 // widget in both of the coordinate axes and select the
307 // of the two: it maps the screen onto the widget in both
308 // axes at the same time.
309 double nHScale
= (aWidgetSize
.getWidth() - 10) / aScreenSize
.getWidth();
310 double nVScale
= (aWidgetSize
.getHeight() - 10) / aScreenSize
.getHeight();
311 if (nHScale
< nVScale
)
318 mnScale
= nZoomMode
/ 100.0;
321 // Calculate offsets that center the scaled screen inside the widget.
322 mnHOffset
= (aWidgetSize
.getWidth() - mnScale
*aScreenSize
.getWidth()) / 2.0;
323 mnVOffset
= (aWidgetSize
.getHeight() - mnScale
*aScreenSize
.getHeight()) / 2.0;
329 setPreferredSize (new Dimension (
330 (int)(2*mnHOffset
+ mnScale
* aScreenSize
.getWidth()),
331 (int)(2*mnVOffset
+ mnScale
* aScreenSize
.getHeight())));
336 // In case of a degenerate (not yet initialized?) screen size
337 // use some meaningless default values.
343 maLastWidgetSize
= aWidgetSize
;
348 /** Call getAccessibleAt to determine accessible object under mouse.
350 public void mouseClicked (MouseEvent e
)
354 public void mousePressed (MouseEvent e
)
356 CanvasShape aObjectUnderMouse
= FindCanvasShapeUnderMouse (e
);
357 highlightObject (aObjectUnderMouse
);
358 if ((e
.getModifiers() & InputEvent
.CTRL_MASK
) != 0)
360 maTree
.expandPath (aObjectUnderMouse
.getPath());
364 public void mouseReleased (MouseEvent e
)
368 public void mouseEntered (MouseEvent e
)
372 public void mouseExited (MouseEvent e
)
374 // Deselect currently active object.
375 if (maActiveObject
!= null)
377 maActiveObject
.unhighlight ();
378 maActiveObject
= null;
383 public void mouseDragged (MouseEvent e
)
387 public void mouseMoved (MouseEvent e
)
389 if ((e
.getModifiers() & InputEvent
.SHIFT_MASK
) != 0)
390 highlightObject (FindCanvasShapeUnderMouse (e
));
393 protected CanvasShape
FindCanvasShapeUnderMouse (MouseEvent e
)
395 int nObjects
= maObjects
.size();
396 CanvasShape aObjectUnderMouse
= null;
397 int nCount
= maObjectList
.size();
398 for (int i
=nCount
-1; i
>=0; --i
)
400 CanvasShape aObject
= maObjectList
.get(i
);
402 if (aObject
.contains (e
.getX(),e
.getY()))
404 aObjectUnderMouse
= aObject
;
408 return aObjectUnderMouse
;
411 protected boolean highlightObject (CanvasShape aNewActiveObject
)
413 if (aNewActiveObject
!= maActiveObject
)
415 if (maActiveObject
!= null)
416 maActiveObject
.unhighlight();
418 maActiveObject
= aNewActiveObject
;
419 if (maActiveObject
!= null)
423 maTree
.scrollPathToVisible (maActiveObject
.getPath());
424 maTree
.setSelectionPath (maActiveObject
.getPath());
427 maActiveObject
.highlight ();
436 /** Called when the selection of the tree changes. Highlight the
437 corresponding graphical representation of the first selected object.
439 public void valueChanged (javax
.swing
.event
.TreeSelectionEvent event
)
441 TreePath aPath
= event
.getPath();
442 Object aObject
= aPath
.getLastPathComponent();
443 if (aObject
instanceof AccTreeNode
)
445 CanvasShape aCanvasShape
= maObjects
.get (aObject
);
446 if (highlightObject (aCanvasShape
))
461 private java
.util
.HashMap
<AccTreeNode
, CanvasShape
>
463 private List
<CanvasShape
>
465 private List
<AccTreeNode
>
471 // The size of the widget at the last call of setupTransformation()