1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_accessibility.hxx"
30 #include <accessibility/standard/vclxaccessiblestatusbar.hxx>
31 #include <accessibility/standard/vclxaccessiblestatusbaritem.hxx>
32 #include <toolkit/helper/convert.hxx>
33 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
34 #include <vcl/status.hxx>
35 
36 
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::lang;
40 using namespace ::com::sun::star::accessibility;
41 using namespace ::comphelper;
42 
43 
44 //	----------------------------------------------------
45 //	class VCLXAccessibleStatusBar
46 //	----------------------------------------------------
47 
48 VCLXAccessibleStatusBar::VCLXAccessibleStatusBar( VCLXWindow* pVCLXWindow )
49 	:VCLXAccessibleComponent( pVCLXWindow )
50 {
51 	m_pStatusBar = static_cast< StatusBar* >( GetWindow() );
52 
53 	if ( m_pStatusBar )
54 		m_aAccessibleChildren.assign( m_pStatusBar->GetItemCount(), Reference< XAccessible >() );
55 }
56 
57 // -----------------------------------------------------------------------------
58 
59 VCLXAccessibleStatusBar::~VCLXAccessibleStatusBar()
60 {
61 }
62 
63 // -----------------------------------------------------------------------------
64 
65 void VCLXAccessibleStatusBar::UpdateShowing( sal_Int32 i, sal_Bool bShowing )
66 {
67 	if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
68 	{
69 		Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
70 		if ( xChild.is() )
71 		{
72 			VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
73 			if ( pVCLXAccessibleStatusBarItem )
74 				pVCLXAccessibleStatusBarItem->SetShowing( bShowing );
75 		}
76 	}
77 }
78 
79 // -----------------------------------------------------------------------------
80 
81 void VCLXAccessibleStatusBar::UpdateItemName( sal_Int32 i )
82 {
83 	if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
84 	{
85 		Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
86 		if ( xChild.is() )
87 		{
88 			VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
89 			if ( pVCLXAccessibleStatusBarItem )
90 			{
91 				::rtl::OUString sItemName = pVCLXAccessibleStatusBarItem->GetItemName();
92 				pVCLXAccessibleStatusBarItem->SetItemName( sItemName );
93 			}
94 		}
95 	}
96 }
97 
98 // -----------------------------------------------------------------------------
99 
100 void VCLXAccessibleStatusBar::UpdateItemText( sal_Int32 i )
101 {
102 	if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
103 	{
104 		Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
105 		if ( xChild.is() )
106 		{
107 			VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
108 			if ( pVCLXAccessibleStatusBarItem )
109 			{
110 				::rtl::OUString sItemText = pVCLXAccessibleStatusBarItem->GetItemText();
111 				pVCLXAccessibleStatusBarItem->SetItemText( sItemText );
112 			}
113 		}
114 	}
115 }
116 
117 // -----------------------------------------------------------------------------
118 
119 void VCLXAccessibleStatusBar::InsertChild( sal_Int32 i )
120 {
121 	if ( i >= 0 && i <= (sal_Int32)m_aAccessibleChildren.size() )
122 	{
123 		// insert entry in child list
124 		m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
125 
126 		// send accessible child event
127 		Reference< XAccessible > xChild( getAccessibleChild( i ) );
128 		if ( xChild.is() )
129 		{
130 			Any aOldValue, aNewValue;
131 			aNewValue <<= xChild;
132 			NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
133 		}
134 	}
135 }
136 
137 // -----------------------------------------------------------------------------
138 
139 void VCLXAccessibleStatusBar::RemoveChild( sal_Int32 i )
140 {
141 	if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
142 	{
143 		// get the accessible of the removed page
144 		Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
145 
146 		// remove entry in child list
147 		m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
148 
149 		// send accessible child event
150 		if ( xChild.is() )
151 		{
152 			Any aOldValue, aNewValue;
153 			aOldValue <<= xChild;
154 			NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
155 
156 			Reference< XComponent > xComponent( xChild, UNO_QUERY );
157 			if ( xComponent.is() )
158 				xComponent->dispose();
159 		}
160 	}
161 }
162 
163 // -----------------------------------------------------------------------------
164 
165 void VCLXAccessibleStatusBar::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
166 {
167     switch ( rVclWindowEvent.GetId() )
168     {
169 		case VCLEVENT_STATUSBAR_ITEMADDED:
170         {
171 			if ( m_pStatusBar )
172 			{
173                 sal_uInt16 nItemId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData();
174 				sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
175 				InsertChild( nItemPos );
176 			}
177         }
178         break;
179 		case VCLEVENT_STATUSBAR_ITEMREMOVED:
180         {
181 			if ( m_pStatusBar )
182 			{
183                 sal_uInt16 nItemId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData();
184 				for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
185 				{
186 					Reference< XAccessible > xChild( getAccessibleChild( i ) );
187 					if ( xChild.is() )
188 					{
189 						VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
190 						if ( pVCLXAccessibleStatusBarItem && pVCLXAccessibleStatusBarItem->GetItemId() == nItemId )
191 						{
192 							RemoveChild( i );
193 							break;
194 						}
195 					}
196 				}
197 			}
198         }
199         break;
200 		case VCLEVENT_STATUSBAR_ALLITEMSREMOVED:
201         {
202 			for ( sal_Int32 i = m_aAccessibleChildren.size() - 1; i >= 0; --i )
203 				RemoveChild( i );
204         }
205         break;
206 		case VCLEVENT_STATUSBAR_SHOWITEM:
207 		case VCLEVENT_STATUSBAR_HIDEITEM:
208 		{
209 			if ( m_pStatusBar )
210 			{
211                 sal_uInt16 nItemId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData();
212 				sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
213 				UpdateShowing( nItemPos, rVclWindowEvent.GetId() == VCLEVENT_STATUSBAR_SHOWITEM );
214 			}
215         }
216         break;
217 		case VCLEVENT_STATUSBAR_SHOWALLITEMS:
218 		case VCLEVENT_STATUSBAR_HIDEALLITEMS:
219 		{
220 			for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
221 				UpdateShowing( i, rVclWindowEvent.GetId() == VCLEVENT_STATUSBAR_SHOWALLITEMS );
222         }
223         break;
224 		case VCLEVENT_STATUSBAR_NAMECHANGED:
225 		{
226 			if ( m_pStatusBar )
227 			{
228                 sal_uInt16 nItemId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData();
229 				sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
230 				UpdateItemName( nItemPos );
231 			}
232         }
233         break;
234 		case VCLEVENT_STATUSBAR_DRAWITEM:
235 		{
236 			if ( m_pStatusBar )
237 			{
238                 sal_uInt16 nItemId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData();
239 				sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
240 				UpdateItemText( nItemPos );
241 			}
242         }
243         break;
244 		case VCLEVENT_OBJECT_DYING:
245         {
246 			if ( m_pStatusBar )
247 			{
248 				m_pStatusBar = NULL;
249 
250 				// dispose all children
251 				for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
252 				{
253 					Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY );
254 					if ( xComponent.is() )
255 						xComponent->dispose();
256 				}
257 				m_aAccessibleChildren.clear();
258 			}
259 
260 			VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
261         }
262         break;
263 		default:
264 			VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
265    }
266 }
267 
268 // -----------------------------------------------------------------------------
269 // XComponent
270 // -----------------------------------------------------------------------------
271 
272 void VCLXAccessibleStatusBar::disposing()
273 {
274 	VCLXAccessibleComponent::disposing();
275 
276 	if ( m_pStatusBar )
277 	{
278 		m_pStatusBar = NULL;
279 
280 		// dispose all children
281 		for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
282 		{
283 			Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY );
284 			if ( xComponent.is() )
285 				xComponent->dispose();
286 		}
287 		m_aAccessibleChildren.clear();
288 	}
289 }
290 
291 // -----------------------------------------------------------------------------
292 // XServiceInfo
293 // -----------------------------------------------------------------------------
294 
295 ::rtl::OUString VCLXAccessibleStatusBar::getImplementationName() throw (RuntimeException)
296 {
297 	return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleStatusBar" );
298 }
299 
300 // -----------------------------------------------------------------------------
301 
302 Sequence< ::rtl::OUString > VCLXAccessibleStatusBar::getSupportedServiceNames() throw (RuntimeException)
303 {
304 	Sequence< ::rtl::OUString > aNames(1);
305 	aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleStatusBar" );
306 	return aNames;
307 }
308 
309 // -----------------------------------------------------------------------------
310 // XAccessibleContext
311 // -----------------------------------------------------------------------------
312 
313 sal_Int32 VCLXAccessibleStatusBar::getAccessibleChildCount() throw (RuntimeException)
314 {
315 	OExternalLockGuard aGuard( this );
316 
317 	return m_aAccessibleChildren.size();
318 }
319 
320 // -----------------------------------------------------------------------------
321 
322 Reference< XAccessible > VCLXAccessibleStatusBar::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
323 {
324 	OExternalLockGuard aGuard( this );
325 
326 	if ( i < 0 || i >= getAccessibleChildCount() )
327 		throw IndexOutOfBoundsException();
328 
329 	Reference< XAccessible > xChild = m_aAccessibleChildren[i];
330 	if ( !xChild.is() )
331 	{
332 		if ( m_pStatusBar )
333 		{
334 			sal_uInt16 nItemId = m_pStatusBar->GetItemId( (sal_uInt16)i );
335 
336 			xChild = new VCLXAccessibleStatusBarItem( m_pStatusBar, nItemId );
337 
338 			// insert into status bar item list
339 			m_aAccessibleChildren[i] = xChild;
340 		}
341 	}
342 
343     return xChild;
344 }
345 
346 // -----------------------------------------------------------------------------
347 // XAccessibleComponent
348 // -----------------------------------------------------------------------------
349 
350 Reference< XAccessible > VCLXAccessibleStatusBar::getAccessibleAtPoint( const awt::Point& rPoint ) throw (RuntimeException)
351 {
352 	OExternalLockGuard aGuard( this );
353 
354 	Reference< XAccessible > xChild;
355 	if ( m_pStatusBar )
356 	{
357 		sal_uInt16 nItemId = m_pStatusBar->GetItemId( VCLPoint( rPoint ) );
358 		sal_Int32 nItemPos = m_pStatusBar->GetItemPos( nItemId );
359 		if ( nItemPos >= 0 && nItemPos < (sal_Int32)m_aAccessibleChildren.size() )
360 			xChild = getAccessibleChild( nItemPos );
361 	}
362 
363 	return xChild;
364 }
365 
366 // -----------------------------------------------------------------------------
367