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_basctl.hxx"
30 #include <accessibledialogcontrolshape.hxx>
31 #include <baside3.hxx>
32 #include <dlgeddef.hxx>
33 #include <dlgedview.hxx>
34 #include <dlgedobj.hxx>
35 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
36 #include <com/sun/star/accessibility/AccessibleRole.hpp>
37 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
38 #include <unotools/accessiblestatesethelper.hxx>
39 #include <unotools/accessiblerelationsethelper.hxx>
40 #include <toolkit/awt/vclxfont.hxx>
41 #include <toolkit/helper/externallock.hxx>
42 #include <toolkit/helper/convert.hxx>
43 #include <toolkit/helper/vclunohelper.hxx>
44 #include <vcl/svapp.hxx>
45 
46 using namespace ::com::sun::star;
47 using namespace ::com::sun::star::uno;
48 using namespace ::com::sun::star::lang;
49 using namespace ::com::sun::star::beans;
50 using namespace ::com::sun::star::accessibility;
51 using namespace ::comphelper;
52 
53 
54 // -----------------------------------------------------------------------------
55 // class AccessibleDialogControlShape
56 // -----------------------------------------------------------------------------
57 
58 AccessibleDialogControlShape::AccessibleDialogControlShape( DialogWindow* pDialogWindow, DlgEdObj* pDlgEdObj )
59 	:AccessibleExtendedComponentHelper_BASE( new VCLExternalSolarLock() )
60 	,m_pDialogWindow( pDialogWindow )
61 	,m_pDlgEdObj( pDlgEdObj )
62 {
63 	m_pExternalLock = static_cast< VCLExternalSolarLock* >( getExternalLock() );
64 
65 	if ( m_pDlgEdObj )
66 		m_xControlModel = Reference< XPropertySet >( m_pDlgEdObj->GetUnoControlModel(), UNO_QUERY );
67 
68 	if ( m_xControlModel.is() )
69 		m_xControlModel->addPropertyChangeListener( ::rtl::OUString(), static_cast< beans::XPropertyChangeListener* >( this ) );
70 
71 	m_bFocused = IsFocused();
72 	m_bSelected = IsSelected();
73 	m_aBounds = GetBounds();
74 }
75 
76 // -----------------------------------------------------------------------------
77 
78 AccessibleDialogControlShape::~AccessibleDialogControlShape()
79 {
80 	if ( m_xControlModel.is() )
81 		m_xControlModel->removePropertyChangeListener( ::rtl::OUString(), static_cast< beans::XPropertyChangeListener* >( this ) );
82 
83 	delete m_pExternalLock;
84 	m_pExternalLock = NULL;
85 }
86 
87 // -----------------------------------------------------------------------------
88 
89 sal_Bool AccessibleDialogControlShape::IsFocused()
90 {
91 	sal_Bool bFocused = sal_False;
92 	if ( m_pDialogWindow )
93 	{
94 		SdrView* pSdrView = m_pDialogWindow->GetView();
95 		if ( pSdrView && pSdrView->IsObjMarked( m_pDlgEdObj ) && pSdrView->GetMarkedObjectList().GetMarkCount() == 1 )
96 			bFocused = sal_True;
97 	}
98 
99 	return bFocused;
100 }
101 
102 // -----------------------------------------------------------------------------
103 
104 sal_Bool AccessibleDialogControlShape::IsSelected()
105 {
106 	sal_Bool bSelected = sal_False;
107 	if ( m_pDialogWindow )
108 	{
109 		SdrView* pSdrView = m_pDialogWindow->GetView();
110 		if ( pSdrView )
111 			bSelected = pSdrView->IsObjMarked( m_pDlgEdObj );
112 	}
113 
114 	return bSelected;
115 }
116 
117 // -----------------------------------------------------------------------------
118 
119 void AccessibleDialogControlShape::SetFocused( sal_Bool bFocused )
120 {
121 	if ( m_bFocused != bFocused )
122 	{
123 		Any aOldValue, aNewValue;
124 		if ( m_bFocused )
125 			aOldValue <<= AccessibleStateType::FOCUSED;
126 		else
127 			aNewValue <<= AccessibleStateType::FOCUSED;
128 		m_bFocused = bFocused;
129 		NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
130 	}
131 }
132 
133 // -----------------------------------------------------------------------------
134 
135 void AccessibleDialogControlShape::SetSelected( sal_Bool bSelected )
136 {
137 	if ( m_bSelected != bSelected )
138 	{
139 		Any aOldValue, aNewValue;
140 		if ( m_bSelected )
141 			aOldValue <<= AccessibleStateType::SELECTED;
142 		else
143 			aNewValue <<= AccessibleStateType::SELECTED;
144 		m_bSelected = bSelected;
145 		NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
146 	}
147 }
148 
149 // -----------------------------------------------------------------------------
150 
151 awt::Rectangle AccessibleDialogControlShape::GetBounds()
152 {
153 	awt::Rectangle aBounds( 0, 0, 0, 0 );
154 	if ( m_pDlgEdObj )
155 	{
156 		// get the bounding box of the shape in logic units
157 		Rectangle aRect = m_pDlgEdObj->GetSnapRect();
158 
159 		if ( m_pDialogWindow )
160 		{
161 			// transform coordinates relative to the parent
162 			MapMode aMap = m_pDialogWindow->GetMapMode();
163 			Point aOrg = aMap.GetOrigin();
164 			aRect.Move( aOrg.X(), aOrg.Y() );
165 
166 			// convert logic units to pixel
167 			aRect = m_pDialogWindow->LogicToPixel( aRect, MapMode(MAP_100TH_MM) );
168 
169 			// clip the shape's bounding box with the bounding box of its parent
170 			Rectangle aParentRect( Point( 0, 0 ), m_pDialogWindow->GetSizePixel() );
171 			aRect = aRect.GetIntersection( aParentRect );
172 			aBounds = AWTRectangle( aRect );
173 		}
174 	}
175 
176 	return aBounds;
177 }
178 
179 // -----------------------------------------------------------------------------
180 
181 void AccessibleDialogControlShape::SetBounds( const awt::Rectangle& aBounds )
182 {
183 	if ( m_aBounds.X != aBounds.X || m_aBounds.Y != aBounds.Y || m_aBounds.Width != aBounds.Width || m_aBounds.Height != aBounds.Height )
184 	{
185 		m_aBounds = aBounds;
186 		NotifyAccessibleEvent( AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any() );
187 	}
188 }
189 
190 // -----------------------------------------------------------------------------
191 
192 Window*	AccessibleDialogControlShape::GetWindow() const
193 {
194 	Window* pWindow = NULL;
195 	if ( m_pDlgEdObj )
196 	{
197 		Reference< awt::XControl > xControl( m_pDlgEdObj->GetControl(), UNO_QUERY );
198 		if ( xControl.is() )
199 			pWindow = VCLUnoHelper::GetWindow( xControl->getPeer() );
200 	}
201 
202 	return pWindow;
203 }
204 
205 // -----------------------------------------------------------------------------
206 
207 ::rtl::OUString	AccessibleDialogControlShape::GetModelStringProperty( const sal_Char* pPropertyName )
208 {
209 	::rtl::OUString sReturn;
210 
211 	try
212 	{
213 		if ( m_xControlModel.is() )
214 		{
215 			::rtl::OUString sPropertyName( ::rtl::OUString::createFromAscii( pPropertyName ) );
216 			Reference< XPropertySetInfo > xInfo = m_xControlModel->getPropertySetInfo();
217 			if ( xInfo.is() && xInfo->hasPropertyByName( sPropertyName ) )
218 				m_xControlModel->getPropertyValue( sPropertyName ) >>= sReturn;
219 		}
220 	}
221 	catch ( const Exception& )
222 	{
223 		OSL_ENSURE( sal_False, "AccessibleDialogControlShape::GetModelStringProperty: caught an exception!" );
224 	}
225 
226 	return sReturn;
227 }
228 
229 // -----------------------------------------------------------------------------
230 
231 void AccessibleDialogControlShape::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
232 {
233 	rStateSet.AddState( AccessibleStateType::ENABLED );
234 
235 	rStateSet.AddState( AccessibleStateType::VISIBLE );
236 
237 	rStateSet.AddState( AccessibleStateType::SHOWING );
238 
239 	rStateSet.AddState( AccessibleStateType::FOCUSABLE );
240 
241 	if ( IsFocused() )
242 		rStateSet.AddState( AccessibleStateType::FOCUSED );
243 
244 	rStateSet.AddState( AccessibleStateType::SELECTABLE );
245 
246 	if ( IsSelected() )
247 		rStateSet.AddState( AccessibleStateType::SELECTED );
248 
249 	rStateSet.AddState( AccessibleStateType::RESIZABLE );
250 }
251 
252 // -----------------------------------------------------------------------------
253 // OCommonAccessibleComponent
254 // -----------------------------------------------------------------------------
255 
256 awt::Rectangle AccessibleDialogControlShape::implGetBounds() throw (RuntimeException)
257 {
258 	return GetBounds();
259 }
260 
261 // -----------------------------------------------------------------------------
262 // XInterface
263 // -----------------------------------------------------------------------------
264 
265 IMPLEMENT_FORWARD_XINTERFACE2( AccessibleDialogControlShape, AccessibleExtendedComponentHelper_BASE, AccessibleDialogControlShape_BASE )
266 
267 // -----------------------------------------------------------------------------
268 // XTypeProvider
269 // -----------------------------------------------------------------------------
270 
271 IMPLEMENT_FORWARD_XTYPEPROVIDER2( AccessibleDialogControlShape, AccessibleExtendedComponentHelper_BASE, AccessibleDialogControlShape_BASE )
272 
273 // -----------------------------------------------------------------------------
274 // XComponent
275 // -----------------------------------------------------------------------------
276 
277 void AccessibleDialogControlShape::disposing()
278 {
279 	AccessibleExtendedComponentHelper_BASE::disposing();
280 
281 	m_pDialogWindow = NULL;
282 	m_pDlgEdObj = NULL;
283 
284 	if ( m_xControlModel.is() )
285 		m_xControlModel->removePropertyChangeListener( ::rtl::OUString(), static_cast< beans::XPropertyChangeListener* >( this ) );
286 	m_xControlModel.clear();
287 }
288 
289 // -----------------------------------------------------------------------------
290 // XEventListener
291 // -----------------------------------------------------------------------------
292 
293 void AccessibleDialogControlShape::disposing( const lang::EventObject& ) throw (RuntimeException)
294 {
295 	if ( m_xControlModel.is() )
296 		m_xControlModel->removePropertyChangeListener( ::rtl::OUString(), static_cast< beans::XPropertyChangeListener* >( this ) );
297 	m_xControlModel.clear();
298 }
299 
300 // -----------------------------------------------------------------------------
301 // XPropertyChangeListener
302 // -----------------------------------------------------------------------------
303 
304 void AccessibleDialogControlShape::propertyChange( const beans::PropertyChangeEvent& rEvent ) throw (RuntimeException)
305 {
306 	if ( rEvent.PropertyName == DLGED_PROP_NAME )
307 	{
308         NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, rEvent.OldValue, rEvent.NewValue );
309 	}
310 	else if ( rEvent.PropertyName == DLGED_PROP_POSITIONX ||
311 			  rEvent.PropertyName == DLGED_PROP_POSITIONY ||
312 			  rEvent.PropertyName == DLGED_PROP_WIDTH ||
313 			  rEvent.PropertyName == DLGED_PROP_HEIGHT )
314 	{
315 		SetBounds( GetBounds() );
316 	}
317 	else if ( rEvent.PropertyName == DLGED_PROP_BACKGROUNDCOLOR ||
318 			  rEvent.PropertyName == DLGED_PROP_TEXTCOLOR ||
319 			  rEvent.PropertyName == DLGED_PROP_TEXTLINECOLOR )
320 	{
321 		NotifyAccessibleEvent( AccessibleEventId::VISIBLE_DATA_CHANGED, Any(), Any() );
322 	}
323 }
324 
325 // -----------------------------------------------------------------------------
326 // XServiceInfo
327 // -----------------------------------------------------------------------------
328 
329 ::rtl::OUString AccessibleDialogControlShape::getImplementationName() throw (RuntimeException)
330 {
331 	return ::rtl::OUString::createFromAscii( "com.sun.star.comp.basctl.AccessibleShape" );
332 }
333 
334 // -----------------------------------------------------------------------------
335 
336 sal_Bool AccessibleDialogControlShape::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException)
337 {
338 	Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
339 	const ::rtl::OUString* pNames = aNames.getConstArray();
340 	const ::rtl::OUString* pEnd = pNames + aNames.getLength();
341 	for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
342 		;
343 
344 	return pNames != pEnd;
345 }
346 
347 // -----------------------------------------------------------------------------
348 
349 Sequence< ::rtl::OUString > AccessibleDialogControlShape::getSupportedServiceNames() throw (RuntimeException)
350 {
351 	Sequence< ::rtl::OUString > aNames(1);
352 	aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.drawing.AccessibleShape" );
353 	return aNames;
354 }
355 
356 // -----------------------------------------------------------------------------
357 // XAccessible
358 // -----------------------------------------------------------------------------
359 
360 Reference< XAccessibleContext > AccessibleDialogControlShape::getAccessibleContext(  ) throw (RuntimeException)
361 {
362 	OExternalLockGuard aGuard( this );
363 
364 	return this;
365 }
366 
367 // -----------------------------------------------------------------------------
368 // XAccessibleContext
369 // -----------------------------------------------------------------------------
370 
371 sal_Int32 AccessibleDialogControlShape::getAccessibleChildCount() throw (RuntimeException)
372 {
373 	OExternalLockGuard aGuard( this );
374 
375 	return 0;
376 }
377 
378 // -----------------------------------------------------------------------------
379 
380 Reference< XAccessible > AccessibleDialogControlShape::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
381 {
382 	OExternalLockGuard aGuard( this );
383 
384 	if ( i < 0 || i >= getAccessibleChildCount() )
385 		throw IndexOutOfBoundsException();
386 
387 	return Reference< XAccessible >();
388 }
389 
390 // -----------------------------------------------------------------------------
391 
392 Reference< XAccessible > AccessibleDialogControlShape::getAccessibleParent(  ) throw (RuntimeException)
393 {
394 	OExternalLockGuard aGuard( this );
395 
396 	Reference< XAccessible > xParent;
397 	if ( m_pDialogWindow )
398 		xParent = m_pDialogWindow->GetAccessible();
399 
400 	return xParent;
401 }
402 
403 // -----------------------------------------------------------------------------
404 
405 sal_Int32 AccessibleDialogControlShape::getAccessibleIndexInParent(  ) throw (RuntimeException)
406 {
407 	OExternalLockGuard aGuard( this );
408 
409 	sal_Int32 nIndexInParent = -1;
410     Reference< XAccessible > xParent( getAccessibleParent() );
411     if ( xParent.is() )
412     {
413         Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
414         if ( xParentContext.is() )
415         {
416 			for ( sal_Int32 i = 0, nCount = xParentContext->getAccessibleChildCount(); i < nCount; ++i )
417             {
418                 Reference< XAccessible > xChild( xParentContext->getAccessibleChild( i ) );
419                 if ( xChild.is() )
420                 {
421                     Reference< XAccessibleContext > xChildContext = xChild->getAccessibleContext();
422 	                if ( xChildContext == (XAccessibleContext*)this )
423                     {
424                         nIndexInParent = i;
425                         break;
426                     }
427                 }
428             }
429         }
430     }
431 
432 	return nIndexInParent;
433 }
434 
435 // -----------------------------------------------------------------------------
436 
437 sal_Int16 AccessibleDialogControlShape::getAccessibleRole(  ) throw (RuntimeException)
438 {
439 	OExternalLockGuard aGuard( this );
440 
441 	return AccessibleRole::SHAPE;
442 }
443 
444 // -----------------------------------------------------------------------------
445 
446 ::rtl::OUString AccessibleDialogControlShape::getAccessibleDescription(	) throw (RuntimeException)
447 {
448 	OExternalLockGuard aGuard( this );
449 
450 	return GetModelStringProperty( "HelpText" );
451 }
452 
453 // -----------------------------------------------------------------------------
454 
455 ::rtl::OUString AccessibleDialogControlShape::getAccessibleName(  ) throw (RuntimeException)
456 {
457 	OExternalLockGuard aGuard( this );
458 
459 	return GetModelStringProperty( "Name" );
460 }
461 
462 // -----------------------------------------------------------------------------
463 
464 Reference< XAccessibleRelationSet > AccessibleDialogControlShape::getAccessibleRelationSet(  ) throw (RuntimeException)
465 {
466 	OExternalLockGuard aGuard( this );
467 
468 	utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
469 	Reference< XAccessibleRelationSet > xSet = pRelationSetHelper;
470 	return xSet;
471 }
472 
473 // -----------------------------------------------------------------------------
474 
475 Reference< XAccessibleStateSet > AccessibleDialogControlShape::getAccessibleStateSet(  ) throw (RuntimeException)
476 {
477 	OExternalLockGuard aGuard( this );
478 
479 	utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
480 	Reference< XAccessibleStateSet > xSet = pStateSetHelper;
481 
482 	if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
483 	{
484 		FillAccessibleStateSet( *pStateSetHelper );
485 	}
486 	else
487 	{
488 		pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
489 	}
490 
491 	return xSet;
492 }
493 
494 // -----------------------------------------------------------------------------
495 
496 Locale AccessibleDialogControlShape::getLocale(  ) throw (IllegalAccessibleComponentStateException, RuntimeException)
497 {
498 	OExternalLockGuard aGuard( this );
499 
500 	return Application::GetSettings().GetLocale();
501 }
502 
503 // -----------------------------------------------------------------------------
504 // XAccessibleComponent
505 // -----------------------------------------------------------------------------
506 
507 Reference< XAccessible > AccessibleDialogControlShape::getAccessibleAtPoint( const awt::Point& ) throw (RuntimeException)
508 {
509 	OExternalLockGuard aGuard( this );
510 
511 	return Reference< XAccessible >();
512 }
513 
514 // -----------------------------------------------------------------------------
515 
516 void AccessibleDialogControlShape::grabFocus(  ) throw (RuntimeException)
517 {
518 	// no focus for shapes
519 }
520 
521 // -----------------------------------------------------------------------------
522 
523 sal_Int32 AccessibleDialogControlShape::getForeground(	) throw (RuntimeException)
524 {
525 	OExternalLockGuard aGuard( this );
526 
527 	sal_Int32 nColor = 0;
528 	Window* pWindow = GetWindow();
529 	if ( pWindow )
530 	{
531 		if ( pWindow->IsControlForeground() )
532 			nColor = pWindow->GetControlForeground().GetColor();
533 		else
534 		{
535 			Font aFont;
536 			if ( pWindow->IsControlFont() )
537 				aFont = pWindow->GetControlFont();
538 			else
539 				aFont = pWindow->GetFont();
540 			nColor = aFont.GetColor().GetColor();
541 		}
542 	}
543 
544 	return nColor;
545 }
546 
547 // -----------------------------------------------------------------------------
548 
549 sal_Int32 AccessibleDialogControlShape::getBackground(  ) throw (RuntimeException)
550 {
551 	OExternalLockGuard aGuard( this );
552 
553 	sal_Int32 nColor = 0;
554 	Window* pWindow = GetWindow();
555 	if ( pWindow )
556 	{
557 		if ( pWindow->IsControlBackground() )
558 			nColor = pWindow->GetControlBackground().GetColor();
559 		else
560 			nColor = pWindow->GetBackground().GetColor().GetColor();
561 	}
562 
563 	return nColor;
564 }
565 
566 // -----------------------------------------------------------------------------
567 // XAccessibleExtendedComponent
568 // -----------------------------------------------------------------------------
569 
570 Reference< awt::XFont > AccessibleDialogControlShape::getFont(  ) throw (RuntimeException)
571 {
572 	OExternalLockGuard aGuard( this );
573 
574 	Reference< awt::XFont > xFont;
575 	Window* pWindow = GetWindow();
576 	if ( pWindow )
577 	{
578 		Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), UNO_QUERY );
579 		if ( xDev.is() )
580 		{
581 			Font aFont;
582 			if ( pWindow->IsControlFont() )
583 				aFont = pWindow->GetControlFont();
584 			else
585 				aFont = pWindow->GetFont();
586 			VCLXFont* pVCLXFont = new VCLXFont;
587 			pVCLXFont->Init( *xDev.get(), aFont );
588 			xFont = pVCLXFont;
589 		}
590 	}
591 
592 	return xFont;
593 }
594 
595 // -----------------------------------------------------------------------------
596 
597 ::rtl::OUString AccessibleDialogControlShape::getTitledBorderText(  ) throw (RuntimeException)
598 {
599 	OExternalLockGuard aGuard( this );
600 
601 	return ::rtl::OUString();
602 }
603 
604 // -----------------------------------------------------------------------------
605 
606 ::rtl::OUString AccessibleDialogControlShape::getToolTipText(  ) throw (RuntimeException)
607 {
608 	OExternalLockGuard aGuard( this );
609 
610 	::rtl::OUString sText;
611 	Window* pWindow = GetWindow();
612 	if ( pWindow )
613 		sText = pWindow->GetQuickHelpText();
614 
615 	return sText;
616 }
617 
618 // -----------------------------------------------------------------------------
619 
620