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