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 #include <vos/mutex.hxx>
29 #include <vcl/image.hxx>
30 #include <vcl/menu.hxx>
31 
32 #include <cppuhelper/compbase4.hxx>
33 #include <cppuhelper/compbase5.hxx>
34 #include <comphelper/broadcasthelper.hxx>
35 
36 #include <com/sun/star/frame/XFrame.hpp>
37 #include <com/sun/star/accessibility/XAccessible.hpp>
38 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
39 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
40 #include <com/sun/star/accessibility/XAccessibleSelection.hpp>
41 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
42 #include <com/sun/star/lang/DisposedException.hpp>
43 
44 #include <rtl/ref.hxx>
45 
46 #include <vector>
47 
48 #include "framestatuslistener.hxx"
49 
50 #include "svtools/valueset.hxx"
51 
52 namespace svtools {
53 
54 struct ToolbarMenu_Impl;
55 class ToolbarMenu;
56 class ToolbarMenuEntry;
57 
58 typedef ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener > > EventListenerVector;
59 typedef std::vector< ToolbarMenuEntry * > ToolbarMenuEntryVector;
60 
61 const int EXTRAITEMHEIGHT = 0; // 4;
62 const int SEPARATOR_HEIGHT = 4;
63 const int TITLE_ID = -1;
64 const int BORDER_X = 0;
65 const int BORDER_Y = 0;
66 
67 // --------------------
68 // - ToolbarMenuEntry -
69 // --------------------
70 
71 class ToolbarMenuEntry
72 {
73 public:
74 	ToolbarMenu& mrMenu;
75 
76 	int	mnEntryId;
77 	MenuItemBits mnBits;
78 	Size maSize;
79 
80 	bool mbHasText;
81 	bool mbHasImage;
82 	bool mbChecked;
83 	bool mbEnabled;
84 
85 	String maText;
86 	Image maImage;
87 	Control* mpControl;
88 	Rectangle maRect;
89 
90 	::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > mxAccContext;
91 
92 public:
93 	ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const String& rText, MenuItemBits nBits );
94 	ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, MenuItemBits nBits );
95 	ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, const String& rText, MenuItemBits nBits );
96 	ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, Control* pControl, MenuItemBits nBits );
97 	~ToolbarMenuEntry();
98 
99 	void init( int nEntryId, MenuItemBits nBits );
100 
101     const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& GetAccessible( bool bCreate = false );
102 
103     sal_Int32 getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException);
104     ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( sal_Int32 index ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
105 	void selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
106 
107 	bool HasCheck() const
108 	{
109 		return mbChecked || ( mnBits & ( MIB_RADIOCHECK | MIB_CHECKABLE | MIB_AUTOCHECK ) );
110 	}
111 };
112 
113 // ---------------
114 // - ToolbarMenuAcc -
115 // ---------------
116 
117 typedef ::cppu::WeakComponentImplHelper5<
118     ::com::sun::star::accessibility::XAccessible,
119     ::com::sun::star::accessibility::XAccessibleEventBroadcaster,
120     ::com::sun::star::accessibility::XAccessibleContext,
121     ::com::sun::star::accessibility::XAccessibleComponent,
122     ::com::sun::star::accessibility::XAccessibleSelection >
123     ToolbarMenuAccComponentBase;
124 
125 class ToolbarMenuAcc :
126     public ::comphelper::OBaseMutex,
127     public ToolbarMenuAccComponentBase
128 {
129 public:
130 
131     ToolbarMenuAcc( ToolbarMenu_Impl& rParent );
132     ~ToolbarMenuAcc();
133 
134     void                FireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue );
135     bool                HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); }
136 
137 public:
138     // XAccessible
139     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext(  ) throw (::com::sun::star::uno::RuntimeException);
140 
141     // XAccessibleEventBroadcaster
142     using cppu::WeakComponentImplHelper5<com::sun::star::accessibility::XAccessible, com::sun::star::accessibility::XAccessibleEventBroadcaster, com::sun::star::accessibility::XAccessibleContext, com::sun::star::accessibility::XAccessibleComponent, com::sun::star::accessibility::XAccessibleSelection>::addEventListener;
143     virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
144     using cppu::WeakComponentImplHelper5<com::sun::star::accessibility::XAccessible, com::sun::star::accessibility::XAccessibleEventBroadcaster, com::sun::star::accessibility::XAccessibleContext, com::sun::star::accessibility::XAccessibleComponent, com::sun::star::accessibility::XAccessibleSelection>::removeEventListener;
145     virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
146 
147     // XAccessibleContext
148     virtual sal_Int32 SAL_CALL getAccessibleChildCount(  ) throw (::com::sun::star::uno::RuntimeException);
149     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
150     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent(  ) throw (::com::sun::star::uno::RuntimeException);
151     virtual sal_Int32 SAL_CALL getAccessibleIndexInParent(  ) throw (::com::sun::star::uno::RuntimeException);
152     virtual sal_Int16 SAL_CALL getAccessibleRole(  ) throw (::com::sun::star::uno::RuntimeException);
153     virtual ::rtl::OUString SAL_CALL getAccessibleDescription(  ) throw (::com::sun::star::uno::RuntimeException);
154     virtual ::rtl::OUString SAL_CALL getAccessibleName(  ) throw (::com::sun::star::uno::RuntimeException);
155     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet(  ) throw (::com::sun::star::uno::RuntimeException);
156     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet(  ) throw (::com::sun::star::uno::RuntimeException);
157     virtual ::com::sun::star::lang::Locale SAL_CALL getLocale(  ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException);
158 
159     // XAccessibleComponent
160     virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
161     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
162     virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds(  ) throw (::com::sun::star::uno::RuntimeException);
163     virtual ::com::sun::star::awt::Point SAL_CALL getLocation(  ) throw (::com::sun::star::uno::RuntimeException);
164     virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen(  ) throw (::com::sun::star::uno::RuntimeException);
165     virtual ::com::sun::star::awt::Size SAL_CALL getSize(  ) throw (::com::sun::star::uno::RuntimeException);
166     virtual void SAL_CALL grabFocus(  ) throw (::com::sun::star::uno::RuntimeException);
167     virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding(  ) throw (::com::sun::star::uno::RuntimeException);
168     virtual sal_Int32 SAL_CALL getForeground(  ) throw (::com::sun::star::uno::RuntimeException);
169     virtual sal_Int32 SAL_CALL getBackground(  ) throw (::com::sun::star::uno::RuntimeException);
170 
171     // XAccessibleSelection
172     virtual void SAL_CALL selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
173     virtual sal_Bool SAL_CALL isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
174     virtual void SAL_CALL clearAccessibleSelection(  ) throw (::com::sun::star::uno::RuntimeException);
175     virtual void SAL_CALL selectAllAccessibleChildren(  ) throw (::com::sun::star::uno::RuntimeException);
176     virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount(  ) throw (::com::sun::star::uno::RuntimeException);
177     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
178     virtual void SAL_CALL deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
179 
180 	DECL_LINK( WindowEventListener, VclSimpleEvent* );
181 
182 private:
183     EventListenerVector mxEventListeners;
184     ToolbarMenu_Impl* mpParent;
185     /// The current FOCUSED state.
186     bool mbIsFocused;
187 
188 	void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent );
189 
190     /** Tell all listeners that the object is dying.  This callback is
191         usually called from the WeakComponentImplHelper class.
192     */
193     virtual void SAL_CALL disposing (void);
194 
195     /** Check whether or not the object has been disposed (or is in the
196         state of beeing disposed).  If that is the case then
197         DisposedException is thrown to inform the (indirect) caller of the
198         foul deed.
199     */
200     void ThrowIfDisposed (void) throw (::com::sun::star::lang::DisposedException);
201 };
202 
203 // -----------------------
204 // - ToolbarMenuEntryAcc -
205 // -----------------------
206 
207 typedef ::cppu::WeakComponentImplHelper4< ::com::sun::star::accessibility::XAccessible,
208                                                      ::com::sun::star::accessibility::XAccessibleEventBroadcaster,
209                                                      ::com::sun::star::accessibility::XAccessibleContext,
210                                                      ::com::sun::star::accessibility::XAccessibleComponent > ToolbarMenuEntryAccBase;
211 
212 class ToolbarMenuEntryAcc : public ::comphelper::OBaseMutex,
213 							public ToolbarMenuEntryAccBase
214 {
215 public:
216     ToolbarMenuEntryAcc( ToolbarMenuEntry* pParent );
217     ~ToolbarMenuEntryAcc();
218 
219     void    FireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue );
220     bool    HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); }
221 
222     // XAccessible
223     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext(  ) throw (::com::sun::star::uno::RuntimeException);
224 
225     // XAccessibleEventBroadcaster
226     using ToolbarMenuEntryAccBase::addEventListener;
227     virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
228     using ToolbarMenuEntryAccBase::removeEventListener;
229     virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
230 
231     // XAccessibleContext
232     virtual sal_Int32 SAL_CALL getAccessibleChildCount(  ) throw (::com::sun::star::uno::RuntimeException);
233     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
234     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent(  ) throw (::com::sun::star::uno::RuntimeException);
235     virtual sal_Int32 SAL_CALL getAccessibleIndexInParent(  ) throw (::com::sun::star::uno::RuntimeException);
236     virtual sal_Int16 SAL_CALL getAccessibleRole(  ) throw (::com::sun::star::uno::RuntimeException);
237     virtual ::rtl::OUString SAL_CALL getAccessibleDescription(  ) throw (::com::sun::star::uno::RuntimeException);
238     virtual ::rtl::OUString SAL_CALL getAccessibleName(  ) throw (::com::sun::star::uno::RuntimeException);
239     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet(  ) throw (::com::sun::star::uno::RuntimeException);
240     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet(  ) throw (::com::sun::star::uno::RuntimeException);
241     virtual ::com::sun::star::lang::Locale SAL_CALL getLocale(  ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException);
242 
243     // XAccessibleComponent
244     virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
245     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
246     virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds(  ) throw (::com::sun::star::uno::RuntimeException);
247     virtual ::com::sun::star::awt::Point SAL_CALL getLocation(  ) throw (::com::sun::star::uno::RuntimeException);
248     virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen(  ) throw (::com::sun::star::uno::RuntimeException);
249     virtual ::com::sun::star::awt::Size SAL_CALL getSize(  ) throw (::com::sun::star::uno::RuntimeException);
250     virtual void SAL_CALL grabFocus(  ) throw (::com::sun::star::uno::RuntimeException);
251     virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding(  ) throw (::com::sun::star::uno::RuntimeException);
252     virtual sal_Int32 SAL_CALL getForeground(  ) throw (::com::sun::star::uno::RuntimeException);
253     virtual sal_Int32 SAL_CALL getBackground(  ) throw (::com::sun::star::uno::RuntimeException);
254 
255 private:
256     EventListenerVector	   mxEventListeners;
257     ::vos::OMutex		   maMutex;
258     ToolbarMenuEntry*      mpParent;
259 
260 	/** Tell all listeners that the object is dying.  This callback is
261         usually called from the WeakComponentImplHelper class.
262     */
263     virtual void SAL_CALL disposing (void);
264 };
265 
266 // -----------------------------------------------------------------------------
267 
268 struct ToolbarMenu_Impl
269 {
270 	ToolbarMenu& mrMenu;
271 
272 	::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >              mxFrame;
273 	rtl::Reference< svt::FrameStatusListener >										 mxStatusListener;
274     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxServiceManager;
275 	rtl::Reference< ToolbarMenuAcc >												 mxAccessible;
276 	::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > mxOldSelection;
277 
278 	ToolbarMenuEntryVector	maEntryVector;
279 
280 	int mnCheckPos;
281     int mnImagePos;
282     int mnTextPos;
283 
284 	int mnHighlightedEntry;
285 	int mnSelectedEntry;
286 	int mnLastColumn;
287 
288 	Size maSize;
289 
290 	Link			maSelectHdl;
291 
292 	ToolbarMenu_Impl( ToolbarMenu& rMenu, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame );
293 	~ToolbarMenu_Impl();
294 
295 	void setAccessible( ToolbarMenuAcc* pAccessible );
296 
297 	void fireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue );
298 	bool hasAccessibleListeners();
299 
300 	sal_Int32 getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException);
301 	::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( sal_Int32 index ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
302 	::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( Control* pControl, sal_Int32 childIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
303 
304 	void selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
305 	sal_Bool isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
306 	void clearAccessibleSelection();
307 
308 	ToolbarMenuEntry* implGetEntry( int nEntry ) const;
309 	void notifyHighlightedEntry();
310 
311 	void implHighlightControl( sal_uInt16 nCode, Control* pControl );
312 };
313 
314 }
315