Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #ifdef SOLARIS
22 : #include <ctime>
23 : #endif
24 :
25 : #include <string>
26 : #include <com/sun/star/uno/Reference.h>
27 : #include <com/sun/star/beans/PropertyValue.hpp>
28 : #include <com/sun/star/frame/Desktop.hpp>
29 : #include <com/sun/star/frame/XDispatch.hpp>
30 : #include <com/sun/star/frame/XDispatchProvider.hpp>
31 : #include <com/sun/star/frame/XFrame.hpp>
32 : #include <com/sun/star/util/URL.hpp>
33 : #include <com/sun/star/util/URLTransformer.hpp>
34 : #include <com/sun/star/util/XURLTransformer.hpp>
35 : #include <comphelper/processfactory.hxx>
36 : #include <tools/urlobj.hxx>
37 : #include <svl/eitem.hxx>
38 : #include <svl/stritem.hxx>
39 : #include <svtools/imagemgr.hxx>
40 : #include <svtools/menuoptions.hxx>
41 : #include <framework/menuconfiguration.hxx>
42 :
43 : #include <sfx2/app.hxx>
44 : #include <sfx2/sfx.hrc>
45 : #include <sfx2/msgpool.hxx>
46 : #include <sfx2/msg.hxx>
47 : #include <sfx2/bindings.hxx>
48 : #include <sfx2/dispatch.hxx>
49 : #include "idpool.hxx"
50 : #include "sfxtypes.hxx"
51 : #include "virtmenu.hxx"
52 : #include <sfx2/mnuitem.hxx>
53 : #include <sfx2/tbxctrl.hxx>
54 : #include "arrdecl.hxx"
55 : #include <sfx2/module.hxx>
56 : #include <sfx2/unoctitm.hxx>
57 : #include <sfx2/viewfrm.hxx>
58 : #include <sfx2/imgmgr.hxx>
59 : #include <sfx2/imagemgr.hxx>
60 : #include <sfx2/sfxresid.hxx>
61 : #include "../doc/doc.hrc"
62 : #include <vcl/settings.hxx>
63 :
64 : using namespace ::com::sun::star::uno;
65 : using namespace ::com::sun::star::frame;
66 : using namespace ::com::sun::star::beans;
67 : using namespace ::com::sun::star::util;
68 :
69 :
70 :
71 : // binds the instance to the specified id and assignes the title
72 :
73 0 : void SfxMenuControl::Bind(
74 : SfxVirtualMenu* pOwn,
75 : sal_uInt16 nSlotId,
76 : const OUString& rTitle,
77 : SfxBindings &rBindings )
78 : {
79 0 : aTitle = rTitle;
80 0 : pOwnMenu = pOwn;
81 0 : pSubMenu = 0;
82 0 : if ( pOwn )
83 0 : SfxControllerItem::Bind(nSlotId, &rBindings);
84 : else
85 0 : SetId( nSlotId );
86 :
87 : DBG( CheckConfigure_Impl(SFX_SLOT_MENUCONFIG) );
88 0 : }
89 :
90 :
91 :
92 :
93 : // binds the item to the specified menu and assignes the title
94 :
95 0 : void SfxMenuControl::Bind(
96 : SfxVirtualMenu* pOwn,
97 : sal_uInt16 nSlotId,
98 : SfxVirtualMenu& rMenu,
99 : const OUString& rTitle,
100 : SfxBindings &rBindings )
101 : {
102 0 : SetId( nSlotId );
103 0 : SetBindings(rBindings);
104 0 : pOwnMenu = pOwn;
105 0 : pSubMenu = &rMenu;
106 0 : aTitle = rTitle;
107 0 : }
108 :
109 :
110 :
111 : // Constructor for explicit registration
112 :
113 0 : SfxMenuControl::SfxMenuControl( bool bShowStrings )
114 : : pOwnMenu(0),
115 : pSubMenu(0),
116 0 : b_ShowStrings(bShowStrings)
117 : {
118 0 : }
119 :
120 :
121 :
122 : // Constructor for array
123 0 : SfxMenuControl::SfxMenuControl():
124 : pOwnMenu(0),
125 : pSubMenu(0),
126 0 : b_ShowStrings(false)
127 : {
128 0 : }
129 :
130 :
131 :
132 0 : SfxMenuControl::SfxMenuControl(sal_uInt16 nSlotId, SfxBindings& rBindings):
133 : SfxControllerItem(nSlotId, rBindings),
134 : pOwnMenu(0),
135 : pSubMenu(0),
136 0 : b_ShowStrings(false)
137 : {
138 : // This constructor should make it possible already during the design
139 : // to fall back to the bindings, but can as always be bound later.
140 : // The usefulness of this is for example if a StatusForwarder should
141 : // be created in the constructor of a derived class.
142 0 : UnBind();
143 0 : }
144 :
145 :
146 :
147 :
148 0 : SfxMenuControl::~SfxMenuControl()
149 : {
150 0 : delete pSubMenu;
151 0 : }
152 :
153 :
154 :
155 : // changes the state in the virtual menu
156 :
157 0 : void SfxMenuControl::StateChanged
158 : (
159 : sal_uInt16 nSID,
160 : SfxItemState eState,
161 : const SfxPoolItem* pState
162 : )
163 : {
164 : (void)nSID;
165 : DBG_ASSERT( nSID == GetId(), "strange SID" );
166 : DBG_ASSERT( pOwnMenu != 0, "setting state to dangling SfxMenuControl" );
167 :
168 : bool bIsObjMenu =
169 0 : GetId() >= SID_OBJECTMENU0 && GetId() < SID_OBJECTMENU_LAST;
170 :
171 : // Fix inclusion of enabled/disabled-Flag
172 :
173 : #ifdef UNIX
174 0 : if (nSID == SID_PASTE)
175 0 : pOwnMenu->EnableItem( GetId(), true );
176 : else
177 : #endif
178 0 : pOwnMenu->EnableItem( GetId(), bIsObjMenu
179 0 : ? 0 != pOwnMenu->GetSVMenu()->GetPopupMenu( GetId() )
180 0 : : eState != SFX_ITEM_DISABLED );
181 :
182 0 : if ( eState != SFX_ITEM_AVAILABLE )
183 : {
184 : // check only for non-Object Menus
185 0 : if ( !bIsObjMenu )
186 0 : pOwnMenu->CheckItem( GetId(), false );
187 :
188 0 : if ( pOwnMenu->GetSVMenu()->GetItemText( GetId() ) != GetTitle() )
189 : {
190 : DBG_WARNING("Title of menu item changed - please check if this needs correction!");
191 : }
192 0 : return;
193 : }
194 :
195 0 : bool bCheck = false;
196 0 : if ( pState->ISA(SfxBoolItem) )
197 : {
198 : // BoolItem for check
199 : DBG_ASSERT( GetId() < SID_OBJECTMENU0 || GetId() > SID_OBJECTMENU_LAST,
200 : "SfxBoolItem not allowed for SID_OBJECTMENUx" );
201 0 : bCheck = ((const SfxBoolItem*)pState)->GetValue();
202 0 : Menu* pMenu = pOwnMenu->GetSVMenu();
203 0 : pMenu->SetItemBits( GetId() , pMenu->GetItemBits( GetId() ) | MIB_CHECKABLE);
204 : }
205 0 : else if ( pState->ISA(SfxEnumItemInterface) &&
206 0 : ((SfxEnumItemInterface *)pState)->HasBoolValue() )
207 : {
208 : // Treat EnumItem as Bool
209 : DBG_ASSERT( GetId() < SID_OBJECTMENU0 || GetId() > SID_OBJECTMENU_LAST,
210 : "SfxEnumItem not allowed for SID_OBJECTMENUx" );
211 0 : bCheck = ((SfxEnumItemInterface *)pState)->GetBoolValue();
212 0 : Menu* pMenu = pOwnMenu->GetSVMenu();
213 0 : pMenu->SetItemBits( GetId() , pMenu->GetItemBits( GetId() ) | MIB_CHECKABLE);
214 : }
215 0 : else if ( ( b_ShowStrings || bIsObjMenu ) && pState->ISA(SfxStringItem) )
216 : {
217 : // Get MenuText from SfxStringItem
218 0 : OUString aStr( ((const SfxStringItem*)pState)->GetValue() );
219 0 : if ( aStr.startsWith("($1)") )
220 : {
221 0 : OUString aEntry(SfxResId(STR_UPDATEDOC).toString());
222 0 : aEntry += " ";
223 0 : aEntry += aStr.copy(4);
224 0 : aStr = aEntry;
225 : }
226 0 : else if ( aStr.startsWith("($2)") )
227 : {
228 0 : OUString aEntry(SfxResId(STR_CLOSEDOC_ANDRETURN).toString());
229 0 : aEntry += aStr.copy(4);
230 0 : aStr = aEntry;
231 : }
232 :
233 0 : pOwnMenu->SetItemText( GetId(), aStr );
234 : }
235 :
236 0 : pOwnMenu->CheckItem( GetId(), bCheck );
237 : }
238 :
239 :
240 :
241 0 : SfxMenuControl* SfxMenuControl::CreateImpl( sal_uInt16 /*nId*/, Menu& /*rMenu*/, SfxBindings& /*rBindings*/ )
242 : {
243 0 : return new SfxMenuControl( true );
244 : }
245 :
246 0 : void SfxMenuControl::RegisterControl( sal_uInt16 nSlotId, SfxModule *pMod )
247 : {
248 : RegisterMenuControl( pMod, new SfxMenuCtrlFactory(
249 0 : SfxMenuControl::CreateImpl, TYPE(SfxStringItem), nSlotId ) );
250 0 : }
251 :
252 :
253 0 : void SfxMenuControl::RegisterMenuControl(SfxModule* pMod, SfxMenuCtrlFactory* pFact)
254 : {
255 0 : SFX_APP()->RegisterMenuControl_Impl( pMod, pFact );
256 0 : }
257 :
258 0 : SfxMenuControl* SfxMenuControl::CreateControl( sal_uInt16 nId, Menu &rMenu, SfxBindings &rBindings )
259 : {
260 0 : TypeId aSlotType = SFX_SLOTPOOL().GetSlotType(nId);
261 0 : if ( aSlotType )
262 : {
263 0 : SfxApplication *pApp = SFX_APP();
264 0 : SfxDispatcher *pDisp = rBindings.GetDispatcher_Impl();
265 0 : SfxModule *pMod = pDisp ? SfxModule::GetActiveModule( pDisp->GetFrame() ) :0;
266 0 : if ( pMod )
267 : {
268 0 : SfxMenuCtrlFactArr_Impl *pFactories = pMod->GetMenuCtrlFactories_Impl();
269 0 : if ( pFactories )
270 : {
271 0 : SfxMenuCtrlFactArr_Impl &rFactories = *pFactories;
272 0 : for ( sal_uInt16 nFactory = 0; nFactory < rFactories.size(); ++nFactory )
273 0 : if ( rFactories[nFactory]->nTypeId == aSlotType &&
274 0 : ( ( rFactories[nFactory]->nSlotId == 0 ) ||
275 0 : ( rFactories[nFactory]->nSlotId == nId) ) )
276 0 : return rFactories[nFactory]->pCtor( nId, rMenu, rBindings );
277 : }
278 : }
279 :
280 0 : SfxMenuCtrlFactArr_Impl &rFactories = pApp->GetMenuCtrlFactories_Impl();
281 :
282 0 : for ( sal_uInt16 nFactory = 0; nFactory < rFactories.size(); ++nFactory )
283 0 : if ( rFactories[nFactory]->nTypeId == aSlotType &&
284 0 : ( ( rFactories[nFactory]->nSlotId == 0 ) ||
285 0 : ( rFactories[nFactory]->nSlotId == nId) ) )
286 0 : return rFactories[nFactory]->pCtor( nId, rMenu, rBindings );
287 : }
288 0 : return 0;
289 : }
290 :
291 :
292 :
293 0 : PopupMenu* SfxMenuControl::GetPopup () const
294 : {
295 0 : if (GetPopupMenu())
296 0 : return (PopupMenu*)GetPopupMenu()->GetSVMenu();
297 : else
298 0 : return 0;
299 : }
300 :
301 : long Select_Impl( void* pHdl, void* pVoid );
302 :
303 0 : SFX_IMPL_MENU_CONTROL( SfxAppMenuControl_Impl, SfxStringItem );
304 :
305 0 : SfxAppMenuControl_Impl::SfxAppMenuControl_Impl(
306 : sal_uInt16 nPos, Menu& rMenu, SfxBindings& rBindings )
307 0 : : SfxMenuControl( nPos, rBindings ), pMenu(0)
308 : {
309 : // Determine the current background color setting for menus
310 0 : const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
311 0 : m_sIconTheme = rSettings.DetermineIconTheme();
312 0 : m_bShowMenuImages = rSettings.GetUseImagesInMenus();
313 :
314 0 : ::framework::MenuConfiguration aConf( ::comphelper::getProcessComponentContext() );
315 0 : Reference<com::sun::star::frame::XFrame> aXFrame( GetBindings().GetDispatcher_Impl()->GetFrame()->GetFrame().GetFrameInterface() );
316 0 : pMenu = aConf.CreateBookmarkMenu( aXFrame, GetId() == SID_NEWDOCDIRECT ? BOOKMARK_NEWMENU : BOOKMARK_WIZARDMENU );
317 0 : if( pMenu )
318 : {
319 0 : pMenu->SetSelectHdl( Link( &(this->GetBindings()), Select_Impl ) );
320 0 : pMenu->SetActivateHdl( LINK(this, SfxAppMenuControl_Impl, Activate) );
321 0 : rMenu.SetPopupMenu( nPos, pMenu );
322 0 : }
323 0 : }
324 :
325 0 : SfxAppMenuControl_Impl::~SfxAppMenuControl_Impl()
326 : {
327 0 : delete pMenu;
328 0 : }
329 :
330 0 : IMPL_LINK( SfxAppMenuControl_Impl, Activate, Menu *, pActMenu )
331 : {
332 0 : if ( pActMenu )
333 : {
334 0 : const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
335 0 : OUString sIconTheme = rSettings.DetermineIconTheme();
336 0 : bool bShowMenuImages = rSettings.GetUseImagesInMenus();
337 :
338 0 : if (( sIconTheme != m_sIconTheme ) ||
339 0 : ( bShowMenuImages != m_bShowMenuImages ))
340 : {
341 0 : m_sIconTheme = sIconTheme;
342 0 : m_bShowMenuImages = bShowMenuImages;
343 :
344 0 : sal_uInt16 nCount = pActMenu->GetItemCount();
345 0 : for ( sal_uInt16 nSVPos = 0; nSVPos < nCount; nSVPos++ )
346 : {
347 0 : sal_uInt16 nItemId = pActMenu->GetItemId( nSVPos );
348 0 : if ( pActMenu->GetItemType( nSVPos ) != MENUITEM_SEPARATOR )
349 : {
350 0 : if ( bShowMenuImages )
351 : {
352 0 : bool bImageSet = false;
353 0 : OUString aImageId;
354 : ::framework::MenuConfiguration::Attributes* pMenuAttributes =
355 0 : (::framework::MenuConfiguration::Attributes*)pMenu->GetUserValue( nItemId );
356 :
357 0 : if ( pMenuAttributes )
358 0 : aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
359 :
360 0 : if ( aImageId.getLength() > 0 )
361 : {
362 0 : Reference< ::com::sun::star::frame::XFrame > xFrame;
363 0 : Image aImage = GetImage( xFrame, aImageId, false );
364 0 : if ( !!aImage )
365 : {
366 0 : bImageSet = true;
367 0 : pActMenu->SetItemImage( nItemId, aImage );
368 0 : }
369 : }
370 :
371 0 : OUString aCmd( pActMenu->GetItemCommand( nItemId ) );
372 0 : if ( !bImageSet && !aCmd.isEmpty() )
373 : {
374 : Image aImage = SvFileInformationManager::GetImage(
375 0 : INetURLObject(aCmd), false );
376 0 : if ( !!aImage )
377 0 : pActMenu->SetItemImage( nItemId, aImage );
378 0 : }
379 : }
380 : else
381 0 : pActMenu->SetItemImage( nItemId, Image() );
382 : }
383 : }
384 : }
385 :
386 0 : return sal_True;
387 : }
388 :
389 0 : return sal_False;
390 : }
391 :
392 0 : SfxUnoMenuControl* SfxMenuControl::CreateControl( const OUString& rCmd,
393 : sal_uInt16 nId, Menu& rMenu, const OUString& sItemText,
394 : SfxBindings& rBindings, SfxVirtualMenu* pVirt)
395 : {
396 0 : return new SfxUnoMenuControl( rCmd, nId, rMenu, sItemText, rBindings, pVirt);
397 : }
398 :
399 0 : SfxUnoMenuControl::SfxUnoMenuControl(
400 : const OUString& rCmd, sal_uInt16 nSlotId, Menu& /*rMenu*/,
401 : const OUString& rItemText,
402 : SfxBindings& rBindings, SfxVirtualMenu* pVirt)
403 0 : : SfxMenuControl( nSlotId, rBindings )
404 : {
405 0 : Bind( pVirt, nSlotId, rItemText, rBindings);
406 0 : UnBind();
407 0 : pUnoCtrl = new SfxUnoControllerItem( this, rBindings, rCmd );
408 0 : pUnoCtrl->acquire();
409 0 : pUnoCtrl->GetNewDispatch();
410 0 : }
411 :
412 0 : SfxUnoMenuControl::~SfxUnoMenuControl()
413 : {
414 0 : pUnoCtrl->UnBind();
415 0 : pUnoCtrl->release();
416 0 : }
417 :
418 0 : long Select_Impl( void* /*pHdl*/, void* pVoid )
419 : {
420 0 : Menu* pMenu = (Menu*)pVoid;
421 0 : OUString aURL( pMenu->GetItemCommand( pMenu->GetCurItemId() ) );
422 :
423 0 : if( aURL.isEmpty() )
424 0 : return 0;
425 :
426 : Reference < ::com::sun::star::frame::XDesktop2 > xDesktop =
427 0 : ::com::sun::star::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
428 :
429 0 : URL aTargetURL;
430 0 : aTargetURL.Complete = aURL;
431 0 : Reference < XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
432 0 : xTrans->parseStrict( aTargetURL );
433 :
434 0 : Reference < XDispatch > xDisp;
435 0 : if (aTargetURL.Protocol == "slot:")
436 0 : xDisp = xDesktop->queryDispatch( aTargetURL, OUString(), 0 );
437 : else
438 : {
439 0 : OUString aTargetFrame( "_blank" );
440 : ::framework::MenuConfiguration::Attributes* pMenuAttributes =
441 0 : (::framework::MenuConfiguration::Attributes*)pMenu->GetUserValue( pMenu->GetCurItemId() );
442 :
443 0 : if ( pMenuAttributes )
444 0 : aTargetFrame = pMenuAttributes->aTargetFrame;
445 :
446 0 : xDisp = xDesktop->queryDispatch( aTargetURL, aTargetFrame , 0 );
447 : }
448 :
449 0 : if ( xDisp.is() )
450 : {
451 0 : SfxAppMenuControl_Impl::ExecuteInfo* pExecuteInfo = new SfxAppMenuControl_Impl::ExecuteInfo;
452 0 : pExecuteInfo->xDispatch = xDisp;
453 0 : pExecuteInfo->aTargetURL = aTargetURL;
454 0 : pExecuteInfo->aArgs = Sequence< PropertyValue >();
455 0 : Application::PostUserEvent( STATIC_LINK( 0, SfxAppMenuControl_Impl, ExecuteHdl_Impl), pExecuteInfo );
456 : }
457 :
458 0 : return sal_True;
459 : }
460 :
461 0 : IMPL_STATIC_LINK_NOINSTANCE( SfxAppMenuControl_Impl, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
462 : {
463 0 : pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
464 0 : delete pExecuteInfo;
465 0 : return 0;
466 : }
467 :
468 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|