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 : #include <com/sun/star/embed/VerbDescriptor.hpp>
21 : #include <com/sun/star/embed/VerbAttributes.hpp>
22 : #include <basic/sbstar.hxx>
23 : #include <officecfg/Office/Common.hxx>
24 : #include <rtl/ustring.hxx>
25 : #include <sal/log.hxx>
26 : #include <svl/itempool.hxx>
27 : #include <svl/undo.hxx>
28 : #include <svtools/itemdel.hxx>
29 : #include <svtools/asynclink.hxx>
30 : #include <basic/sbx.hxx>
31 :
32 : #include <sfx2/app.hxx>
33 : #include <sfx2/shell.hxx>
34 : #include <sfx2/bindings.hxx>
35 : #include <sfx2/dispatch.hxx>
36 : #include <sfx2/viewfrm.hxx>
37 : #include <sfx2/objface.hxx>
38 : #include <sfx2/objsh.hxx>
39 : #include <sfx2/viewsh.hxx>
40 : #include "sfxtypes.hxx"
41 : #include <sfx2/request.hxx>
42 : #include <sfx2/mnumgr.hxx>
43 : #include "statcach.hxx"
44 : #include <sfx2/msgpool.hxx>
45 : #include <sfx2/sidebar/ContextChangeBroadcaster.hxx>
46 :
47 : #include <map>
48 :
49 :
50 : // Maps the Which() field to a pointer to a SfxPoolItem
51 0 : class SfxItemPtrMap : public std::map<sal_uInt16, SfxPoolItem*>
52 : {
53 : public:
54 0 : ~SfxItemPtrMap()
55 0 : {
56 0 : for(iterator it = begin(); it != end(); ++it)
57 0 : delete it->second;
58 0 : }
59 : };
60 :
61 0 : TYPEINIT0(SfxShell);
62 :
63 :
64 0 : class SfxVerbSlotArr_Impl : public std::vector<SfxSlot*>
65 : {
66 : public:
67 0 : ~SfxVerbSlotArr_Impl()
68 0 : {
69 0 : for(const_iterator it = begin(); it != end(); ++it)
70 0 : delete *it;
71 0 : }
72 : };
73 :
74 : using namespace com::sun::star;
75 :
76 :
77 : // SfxShell_Impl
78 :
79 : struct SfxShell_Impl: public SfxBroadcaster
80 : {
81 : OUString aObjectName; // Name of Sbx-Objects
82 : SfxItemPtrMap aItems; // Data exchange on Item level
83 : SfxViewShell* pViewSh; // SfxViewShell if Shell is
84 : // ViewFrame/ViewShell/SubShell list
85 : SfxViewFrame* pFrame; // Frame, if <UI-active>
86 : SfxRepeatTarget* pRepeatTarget; // SbxObjectRef xParent;
87 : bool bActive;
88 : sal_uIntPtr nDisableFlags;
89 : sal_uIntPtr nHelpId;
90 : svtools::AsynchronLink* pExecuter;
91 : svtools::AsynchronLink* pUpdater;
92 : SfxVerbSlotArr_Impl aSlotArr;
93 :
94 : com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > aVerbList;
95 : ::sfx2::sidebar::ContextChangeBroadcaster maContextChangeBroadcaster;
96 :
97 0 : SfxShell_Impl()
98 : : pViewSh(0)
99 : , pFrame(0)
100 : , pRepeatTarget(0)
101 : , bActive(false)
102 : , nDisableFlags(0)
103 : , nHelpId(0)
104 : , pExecuter(0)
105 0 : , pUpdater(0)
106 : {
107 0 : }
108 :
109 0 : virtual ~SfxShell_Impl() { delete pExecuter; delete pUpdater;}
110 : };
111 :
112 :
113 : // SfxShell
114 :
115 :
116 0 : void SfxShell::EmptyExecStub(SfxShell *, SfxRequest &)
117 : {
118 0 : }
119 :
120 0 : void SfxShell::EmptyStateStub(SfxShell *, SfxItemSet &)
121 : {
122 0 : }
123 :
124 0 : SfxShell::SfxShell()
125 :
126 : /* [Description]
127 :
128 : The constructor of the SfxShell class initializes only simple types,
129 : the corresponding SbxObject is only created on-demand. Therefore,
130 : the application of a SfxShell instance is very cheap.
131 : */
132 :
133 : : pImp(0),
134 : pPool(0),
135 0 : pUndoMgr(0)
136 : {
137 0 : pImp = new SfxShell_Impl;
138 0 : }
139 :
140 :
141 :
142 0 : SfxShell::SfxShell( SfxViewShell *pViewSh )
143 :
144 : /* [Description]
145 :
146 : The constructor of the SfxShell class initializes only simple types,
147 : the corresponding SbxObject is only created on-demand. Therefore,
148 : the application of a SfxShell instance is very cheap.
149 : */
150 :
151 : : pImp(0),
152 : pPool(0),
153 0 : pUndoMgr(0)
154 : {
155 0 : pImp = new SfxShell_Impl;
156 0 : pImp->pViewSh = pViewSh;
157 0 : }
158 :
159 :
160 :
161 0 : SfxShell::~SfxShell()
162 :
163 : /* [Description]
164 :
165 : The connection to a possible corresponding SbxObject is dissolved.
166 : The SbxObject may continoue to exist, but can not any longer perform
167 : any functions and can not provide any properties.
168 : */
169 :
170 : {
171 :
172 :
173 0 : delete pImp;
174 0 : }
175 :
176 :
177 :
178 0 : void SfxShell::SetName( const OUString &rName )
179 :
180 : /* [Description]
181 :
182 : Sets the name of the Shell object. With this name, the SfxShell instance
183 : of BASIC can be expressed.
184 : */
185 :
186 : {
187 0 : pImp->aObjectName = rName;
188 0 : }
189 :
190 :
191 :
192 0 : const OUString& SfxShell::GetName() const
193 :
194 : /* [Description]
195 :
196 : Returns the name of the Shell object. With this name, the SfxShell instance
197 : of BASIC can be expressed.
198 : */
199 :
200 : {
201 0 : return pImp->aObjectName;
202 : }
203 :
204 :
205 :
206 0 : SfxDispatcher* SfxShell::GetDispatcher() const
207 :
208 : /* [Description]
209 :
210 : This method returns a pointer to the <SfxDispatcher>, when the SfxShell
211 : is currently <UI-active> or a NULL-pointer if it is not UI-active.
212 :
213 : The returned pointer is only valid in the immediate context of the method
214 : call.
215 : */
216 :
217 : {
218 0 : return pImp->pFrame ? pImp->pFrame->GetDispatcher() : 0;
219 : }
220 :
221 :
222 :
223 0 : SfxViewShell* SfxShell::GetViewShell() const
224 :
225 : /* [Description]
226 :
227 : Returns the SfxViewShell in which they are located in the subshells.
228 : Otherwise, and if not specified by the App developer, this method
229 : returns NULL.
230 : */
231 :
232 : {
233 0 : return pImp->pViewSh;
234 : }
235 :
236 :
237 :
238 0 : SfxViewFrame* SfxShell::GetFrame() const
239 :
240 : /* [Description]
241 :
242 : This method returns a pointer to the <SfxViewFrame> to which this SfxShell
243 : instance is associated or in which they currently is <UI-active>.
244 : A NULL pointer is returned if this SfxShell instance is not UI-active at
245 : the moment and also no SfxViewFrame is permanently assigned.
246 :
247 : The returned pointer is only valid in the immediate context of the method
248 : call.
249 :
250 : [Note]
251 :
252 : Only instances of a subclass of SfxApplication and SfxObjectShell
253 : should here provide a NULL-pointer. Otherwise, there is an error in the
254 : application program (wrong constructor was called from SfxShell).
255 :
256 : [Cross-reference]
257 :
258 : <SfxViewShell::GetViewFrame()const>
259 : */
260 :
261 : {
262 0 : if ( pImp->pFrame )
263 0 : return pImp->pFrame;
264 0 : if ( pImp->pViewSh )
265 0 : return pImp->pViewSh->GetViewFrame();
266 0 : return 0;
267 : }
268 :
269 :
270 :
271 0 : const SfxPoolItem* SfxShell::GetItem
272 : (
273 : sal_uInt16 nSlotId // Slot-Id of the querying <SfxPoolItem>s
274 : ) const
275 :
276 : /* [Description]
277 :
278 : With this method any objects of <SfxPoolItemu> subclasses can be accessed.
279 : This exchange method is needed if, for example special <SfxToolBoxControl>
280 : subclasses need access to certain data such as the <SfxObjectShell>.
281 :
282 : The returned instance belongs to the particular SfxShell and may be
283 : used only in the immediate context of the method call.
284 :
285 : [Cross-reference]
286 :
287 : <SfxShell::PutItem(const SfxPoolItem&)>
288 : <SfxShell::RemoveItem(sal_uInt16)>
289 : */
290 :
291 : {
292 0 : SfxItemPtrMap::iterator it = pImp->aItems.find( nSlotId );
293 0 : if( it != pImp->aItems.end() )
294 0 : return it->second;
295 0 : return 0;
296 : }
297 :
298 :
299 :
300 0 : void SfxShell::PutItem
301 : (
302 : const SfxPoolItem& rItem /* Instance, of which a copy is created,
303 : which is stored in the SfxShell in a list. */
304 : )
305 :
306 : /* [Description]
307 :
308 : With this method, any objects of subclasses of <SfxPoolItem> can be made
309 : available. This exchange technology is needed if, for example, special
310 : <SfxToolBoxControl> Subclasses need access to certain data such as the
311 : <SfxObjectShell>
312 :
313 : If a SfxPoolItem exists with the same slot ID, it is deleted automatically.
314 :
315 : [Cross-reference]
316 :
317 : <SfxShell::RemoveItem(sal_uInt16)>
318 : <SfxShell::GetItem(sal_uInt16)>
319 : */
320 :
321 : {
322 : DBG_ASSERT( !rItem.ISA(SfxSetItem), "SetItems aren't allowed here" );
323 : DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ),
324 : "items with Which-Ids aren't allowed here" );
325 :
326 : // MSC made a mess here of WNT/W95, beware of changes
327 0 : SfxPoolItem *pItem = rItem.Clone();
328 0 : SfxPoolItemHint aItemHint( pItem );
329 0 : const sal_uInt16 nWhich = rItem.Which();
330 :
331 0 : SfxItemPtrMap::iterator it = pImp->aItems.find( nWhich );
332 0 : if( it != pImp->aItems.end() )
333 : {
334 0 : SfxPoolItem *pLoopItem = it->second;
335 : // Replace Item
336 0 : delete pLoopItem;
337 0 : it->second = pItem;
338 :
339 : // if active, notify Bindings
340 0 : SfxDispatcher *pDispat = GetDispatcher();
341 0 : if ( pDispat )
342 : {
343 0 : SfxBindings* pBindings = pDispat->GetBindings();
344 0 : pBindings->Broadcast( aItemHint );
345 0 : sal_uInt16 nSlotId = nWhich; //pItem->GetSlotId();
346 0 : SfxStateCache* pCache = pBindings->GetStateCache( nSlotId );
347 0 : if ( pCache )
348 : {
349 0 : pCache->SetState( SFX_ITEM_AVAILABLE, pItem->Clone(), true );
350 0 : pCache->SetCachedState( true );
351 : }
352 : }
353 0 : return;
354 : }
355 : else
356 : {
357 0 : Broadcast( aItemHint );
358 0 : pImp->aItems[ pItem->Which() ] = pItem;
359 0 : }
360 : }
361 :
362 :
363 :
364 0 : SfxInterface* SfxShell::GetInterface() const
365 :
366 : /* [Description]
367 :
368 : With this virtual method, which is automatically overloaded by each subclass
369 : with its own slots through the macro <SFX_DECL_INTERFACE>, one can access
370 : each of the <SfxInterface> instance beloning to the subclass.
371 :
372 : The class SfxShell itself has no own SfxInterface (no slots), therefore a
373 : NULL-pointer is returned.
374 : */
375 :
376 : {
377 0 : return GetStaticInterface();
378 : }
379 :
380 :
381 :
382 0 : ::svl::IUndoManager* SfxShell::GetUndoManager()
383 :
384 : /* [Description]
385 :
386 : Each Subclass of SfxShell can hava a <SfxUndoManager>. This can be set in
387 : the derived class with <SfxShell:SetUndoManager()>.
388 :
389 : The class SfxShell itself does not have a SfxUndoManager, a NULL-pointer
390 : is therefore returned.
391 : */
392 :
393 : {
394 0 : return pUndoMgr;
395 : }
396 :
397 :
398 :
399 0 : void SfxShell::SetUndoManager( ::svl::IUndoManager *pNewUndoMgr )
400 :
401 : /* [Description]
402 :
403 : Sets a <SfxUndoManager> for this <SfxShell> Instance. For the undo
404 : is only the undo-manager used for SfxShell at the top of the stack of each
405 : <SfxDispatcher>.
406 :
407 : On the given <SfxUndoManager> is automatically the current
408 : Max-Undo-Action-Count setting set form the options.
409 :
410 : 'pNewUndoMgr' must exist until the Destuctor of SfxShell instance is called
411 : or until the next 'SetUndoManager()'.
412 : */
413 :
414 : {
415 : OSL_ENSURE( ( pUndoMgr == NULL ) || ( pNewUndoMgr == NULL ) || ( pUndoMgr == pNewUndoMgr ),
416 : "SfxShell::SetUndoManager: exchanging one non-NULL manager with another non-NULL manager? Suspicious!" );
417 : // there's at least one client of our UndoManager - the DocumentUndoManager at the SfxBaseModel - which
418 : // caches the UndoManager, and registers itself as listener. If exchanging non-NULL UndoManagers is really
419 : // a supported scenario (/me thinks it is not), then we would need to notify all such clients instances.
420 :
421 0 : pUndoMgr = pNewUndoMgr;
422 0 : if ( pUndoMgr )
423 : pUndoMgr->SetMaxUndoActionCount(
424 0 : officecfg::Office::Common::Undo::Steps::get());
425 0 : }
426 :
427 :
428 :
429 0 : SfxRepeatTarget* SfxShell::GetRepeatTarget() const
430 :
431 : /* [Description]
432 :
433 : Returns a pointer to the <SfxRepeatTarget> instance that is used in
434 : SID_REPEAT as repeat target when it is addressed from the <SfxUndoManager>
435 : supplied by this SfxShell. The return value can be NULL.
436 :
437 : [Note]
438 :
439 : A derivation of <SfxShell> or one of its subclasses of <SfxRepeatTarget>
440 : is not recommended, as compiler errors are provoked.
441 : (due to Call-to-Pointer-to-Member-Function to the subclass).
442 : */
443 :
444 : {
445 0 : return pImp->pRepeatTarget;
446 : }
447 :
448 :
449 :
450 0 : void SfxShell::SetRepeatTarget( SfxRepeatTarget *pTarget )
451 :
452 : /* [Description]
453 :
454 : Sets the <SfxRepeatTarget> instance that is used in SID_REPEAT as
455 : RepeatTarget, when the current supplied by this <SfxUndoManager> is
456 : addressed. By 'pTarget==0' the SID_REPEAT is disabled for this SfxShell.
457 : The instance '*pTarget' must live as long as it is registered.
458 :
459 : [Note]
460 :
461 : A derivation of <SfxShell> or one of its subclasses of <SfxRepeatTarget>
462 : is not recommended, as compiler errors are provoked.
463 : (due to Call-to-Pointer-to-Member-Function to the subclass).
464 : */
465 :
466 : {
467 0 : pImp->pRepeatTarget = pTarget;
468 0 : }
469 :
470 :
471 :
472 0 : void SfxShell::Invalidate
473 : (
474 : sal_uInt16 nId /* Invalidated Slot-Id or Which-Id.
475 : If these are 0 (default), then all
476 : by this Shell currently handled Slot-Ids are
477 : invalidated. */
478 : )
479 :
480 : /* [Description]
481 :
482 : With this method can the slots of the subclasses be invalidated through the
483 : slot Id or alternatively through the Which ID. Slot IDs, which are
484 : inherited by the subclass are also invalidert.
485 :
486 : [Cross-reference]
487 :
488 : <SfxBindings::Invalidate(sal_uInt16)>
489 : <SfxBindings::InvalidateAll(sal_Bool)>
490 : */
491 :
492 : {
493 0 : if ( !GetViewShell() )
494 : {
495 : OSL_FAIL( "wrong Invalidate method called!" );
496 0 : return;
497 : }
498 :
499 0 : Invalidate_Impl( GetViewShell()->GetViewFrame()->GetBindings(), nId );
500 : }
501 :
502 0 : void SfxShell::Invalidate_Impl( SfxBindings& rBindings, sal_uInt16 nId )
503 : {
504 0 : if ( nId == 0 )
505 : {
506 0 : rBindings.InvalidateShell( *this, false );
507 : }
508 : else
509 : {
510 0 : const SfxInterface *pIF = GetInterface();
511 0 : do
512 : {
513 0 : const SfxSlot *pSlot = pIF->GetSlot(nId);
514 0 : if ( pSlot )
515 : {
516 : // At Enum-Slots invalidate the Master-Slot
517 0 : if ( SFX_KIND_ENUM == pSlot->GetKind() )
518 0 : pSlot = pSlot->GetLinkedSlot();
519 :
520 : // Invalidate the Slot itself and possible also all Slave-Slots
521 0 : rBindings.Invalidate( pSlot->GetSlotId() );
522 0 : for ( const SfxSlot *pSlave = pSlot->GetLinkedSlot();
523 0 : pSlave && pIF->ContainsSlot_Impl( pSlave ) &&
524 0 : pSlave->GetLinkedSlot() == pSlot;
525 : ++pSlave )
526 0 : rBindings.Invalidate( pSlave->GetSlotId() );
527 :
528 0 : return;
529 : }
530 :
531 0 : pIF = pIF->GetGenoType();
532 : }
533 :
534 : while ( pIF );
535 :
536 : DBG_WARNING( "W3: invalidating slot-id unknown in shell" );
537 : }
538 : }
539 :
540 :
541 :
542 0 : void SfxShell::DoActivate_Impl( SfxViewFrame *pFrame, bool bMDI )
543 :
544 : /* [Description]
545 :
546 : This method controls the activation of SfxShell instance. First, by calling
547 : the virtual method <SfxShell::Activate(sal_Bool)> which gives the subclass the
548 : opportunity to respond to the event.
549 :
550 : When bMDI == TRUE, the associated SbxObject is being 'armed', so that
551 : unqualified methods of the object (without the name of the object)
552 : from BASIC are found.
553 : */
554 :
555 : {
556 : #ifdef DBG_UTIL
557 : const SfxInterface *p_IF = GetInterface();
558 : if ( !p_IF )
559 : return;
560 : #endif
561 : SAL_INFO(
562 : "sfx.control",
563 : "SfxShell::DoActivate() " << this << " " << GetInterface()->GetName()
564 : << " bMDI " << (bMDI ? "MDI" : ""));
565 :
566 0 : if ( bMDI )
567 : {
568 : // Remember Frame, in which it was activated
569 0 : pImp->pFrame = pFrame;
570 0 : pImp->bActive = true;
571 : }
572 :
573 : // Notify Subclass
574 0 : Activate(bMDI);
575 0 : }
576 :
577 :
578 :
579 0 : void SfxShell::DoDeactivate_Impl( SfxViewFrame *pFrame, bool bMDI )
580 :
581 : /* [Description]
582 :
583 : This method controls the deactivation of the SfxShell instance. When
584 : bMDI == TRUE the SbxObject is first set to a status that only qualified
585 : BASIC methods can be called.
586 :
587 : Then the subclass gets the opportunity in every case to respond to the
588 : event by calling the virtual method <SfxShell::Deactivate(sal_Bool)>.
589 : */
590 :
591 : {
592 : #ifdef DBG_UTIL
593 : const SfxInterface *p_IF = GetInterface();
594 : if ( !p_IF )
595 : return;
596 : #endif
597 : SAL_INFO(
598 : "sfx.control",
599 : "SfxShell::DoDeactivate()" << this << " " << GetInterface()->GetName()
600 : << " bMDI " << (bMDI ? "MDI" : ""));
601 :
602 : // Only when it comes from a Frame
603 : // (not when for instance by poping BASIC-IDE from AppDisp)
604 0 : if ( bMDI && pImp->pFrame == pFrame )
605 : {
606 : // deliver
607 0 : pImp->pFrame = 0;
608 0 : pImp->bActive = false;
609 : }
610 :
611 : // Notify Subclass
612 0 : Deactivate(bMDI);
613 0 : }
614 :
615 :
616 :
617 0 : bool SfxShell::IsActive() const
618 : {
619 0 : return pImp->bActive;
620 : }
621 :
622 :
623 :
624 0 : void SfxShell::Activate
625 : (
626 : bool /*bMDI*/ /* TRUE
627 : the <SfxDispatcher>, on which the SfxShell is
628 : located, is activated or the SfxShell instance
629 : was pushed on an active SfxDispatcher.
630 : (compare with SystemWindow::IsMDIActivate())
631 :
632 : FALSE
633 : the <SfxViewFrame>, on which SfxDispatcher
634 : the SfxShell instance is located, was
635 : activated. (for example by a closing dialoge) */
636 : )
637 :
638 : /* [Description]
639 :
640 : Virtual method that is called when enabling the SfxShell instance,
641 : in order to give the Subclasses the opportunity to respond to the
642 : to the enabling.
643 :
644 : [Cross-reference]
645 :
646 : StarView SystemWindow::Activate(bool)
647 : */
648 :
649 : {
650 0 : BroadcastContextForActivation(true);
651 0 : }
652 :
653 :
654 :
655 0 : void SfxShell::Deactivate
656 : (
657 : bool /*bMDI*/ /* TRUE
658 : the <SfxDispatcher>, on which the SfxShell is
659 : located, is inactivated or the SfxShell instance
660 : was popped on an active SfxDispatcher.
661 : (compare with SystemWindow::IsMDIActivate())
662 :
663 : FALSE
664 : the <SfxViewFrame>, on which SfxDispatcher
665 : the SfxShell instance is located, was
666 : deactivated. (for example by a dialoge) */
667 :
668 : )
669 :
670 : /* [Description]
671 :
672 : Virtual method that is called when disabling the SfxShell instance,
673 : to give the Subclasses the opportunity to respond to the disabling.
674 :
675 : [Cross-reference]
676 :
677 : StarView SystemWindow::Dectivate(bool)
678 : */
679 :
680 : {
681 0 : BroadcastContextForActivation(false);
682 0 : }
683 :
684 :
685 0 : void SfxShell::ParentActivate
686 : (
687 : )
688 :
689 : /* [Description]
690 :
691 : A parent of the <SfxDispatcher> on which the SfxShell is located, has
692 : become active, or the SfxShell instance was pushed on a <SfxDispatcher>,
693 : which parent is active.
694 :
695 : The base implementation is empty and does not need to be called.
696 :
697 : [Cross-reference]
698 :
699 : SfxShell::Activate()
700 : */
701 : {
702 0 : }
703 :
704 :
705 :
706 0 : void SfxShell::ParentDeactivate
707 : (
708 : )
709 :
710 : /* [Description]
711 :
712 : The active parent of the <SfxDispatcher> on which the SfxShell is located,
713 : has been disabled.
714 :
715 : The base implementation is empty and does not need to be called.
716 :
717 : [Cross-reference]
718 :
719 : SfxShell::Deactivate()
720 : */
721 : {
722 0 : }
723 :
724 :
725 :
726 0 : ResMgr* SfxShell::GetResMgr() const
727 :
728 : /* [Description]
729 :
730 : This method provides the ResMgr of the <Resource-DLL> that are used by
731 : the SfxShell instance. If this is a NULL-pointer, then the current
732 : resource manager is to be used.
733 : */
734 :
735 : {
736 0 : return GetInterface()->GetResMgr();
737 : }
738 :
739 :
740 :
741 0 : bool SfxShell::CanExecuteSlot_Impl( const SfxSlot &rSlot )
742 :
743 : /* [Description]
744 :
745 : This method determines by calling the status function whether 'rSlot'
746 : can be executed currently.
747 : */
748 : {
749 : // Get Slot status
750 0 : SfxItemPool &rPool = GetPool();
751 0 : const sal_uInt16 nId = rSlot.GetWhich( rPool );
752 0 : SfxItemSet aSet(rPool, nId, nId);
753 0 : SfxStateFunc pFunc = rSlot.GetStateFnc();
754 0 : CallState( pFunc, aSet );
755 0 : return aSet.GetItemState(nId) != SFX_ITEM_DISABLED;
756 : }
757 :
758 :
759 :
760 0 : long ShellCall_Impl( void* pObj, void* pArg )
761 : {
762 0 : ((SfxShell* )pObj)->ExecuteSlot( *(SfxRequest*)pArg, (SfxInterface*)0L );
763 0 : return 0;
764 : }
765 :
766 : /* [Description]
767 :
768 : Asynchronous ExecuteSlot for the RELOAD
769 : */
770 :
771 :
772 0 : const SfxPoolItem* SfxShell::ExecuteSlot( SfxRequest& rReq, bool bAsync )
773 : {
774 0 : if( !bAsync )
775 0 : return ExecuteSlot( rReq, (SfxInterface*)0L );
776 : else
777 : {
778 0 : if( !pImp->pExecuter )
779 : pImp->pExecuter = new svtools::AsynchronLink(
780 0 : Link( this, ShellCall_Impl ) );
781 0 : pImp->pExecuter->Call( new SfxRequest( rReq ) );
782 0 : return 0;
783 : }
784 : }
785 :
786 0 : const SfxPoolItem* SfxShell::ExecuteSlot
787 : (
788 : SfxRequest &rReq, // the relayed <SfxRequest>
789 : const SfxInterface* pIF // default = 0 means get virtually
790 : )
791 :
792 : /* [Description]
793 :
794 : This method allows you to forward a <SfxRequest> to the specified
795 : base <SfxShell>.
796 :
797 : [Example]
798 :
799 : In a derived class of SfxViewShell the SID_PRINTDOCDIRECT will be
800 : intercepted. Under certain circumstances a query should appear before
801 : you print, and the request will be aborted if necessary.
802 :
803 : Also in the IDL of this subclass of the above slot is entered. The status
804 : method will contain in outline:
805 :
806 : void SubViewShell::Exec( SfxRequest &rReq )
807 : {
808 : if ( rReq.GetSlot() == SID_PRINTDOCDIRECT )
809 : {
810 : 'dialog'
811 : if ( 'condition' )
812 : ExecuteSlot( rReq, SfxViewShell::GetInterface() );
813 : }
814 : }
815 :
816 : It usually takes no rReq.Done() to be called as that is already completed
817 : in implementation of the SfxViewShell, for instance it has been canceled.
818 :
819 : [Cross-reference]
820 :
821 : <SfxShell::GetSlotState(sal_uInt16,const SfxInterface*,SfxItemSet*)>
822 : */
823 :
824 : {
825 0 : if ( !pIF )
826 0 : pIF = GetInterface();
827 :
828 0 : sal_uInt16 nSlot = rReq.GetSlot();
829 0 : const SfxSlot* pSlot = NULL;
830 0 : if ( nSlot >= SID_VERB_START && nSlot <= SID_VERB_END )
831 0 : pSlot = GetVerbSlot_Impl(nSlot);
832 0 : if ( !pSlot )
833 0 : pSlot = pIF->GetSlot(nSlot);
834 : DBG_ASSERT( pSlot, "slot not supported" );
835 :
836 0 : SfxExecFunc pFunc = pSlot->GetExecFnc();
837 0 : if ( pFunc )
838 0 : CallExec( pFunc, rReq );
839 :
840 0 : return rReq.GetReturnValue();
841 : }
842 :
843 :
844 :
845 0 : const SfxPoolItem* SfxShell::GetSlotState
846 : (
847 : sal_uInt16 nSlotId, // Slot-Id to the Slots in question
848 : const SfxInterface* pIF, // default = 0 means get virtually
849 : SfxItemSet* pStateSet // SfxItemSet of the Slot-State method
850 : )
851 :
852 : /* [Description]
853 :
854 : This method returns the status of the slot with the specified slot ID
855 : on the specified interface.
856 :
857 : If the slot is disabled or in this SfxShell (and their parent shells) are
858 : not known, a Null-pointer is returned.
859 :
860 : If the slot does not have a Status, a SfxVoidItem is returned.
861 :
862 : The status is set directly in this Set when pStateSet != 0 , so that
863 : overloaded Slots of the <SfxShell> Subclasses and also in the Status
864 : method of the base implementation can be called.
865 :
866 : [Example]
867 :
868 : In a derived class of SfxViewShell the SID_PRINTDOCDIRECT will be
869 : intercepted. Under certain circumstances a query should appear before
870 : you print, and the request will be aborted if necessary.
871 :
872 : Also in the IDL of this subclass of the above slot is entered. The status
873 : method will contain in outline:
874 :
875 : void SubViewShell::PrintState( SfxItemSet &rState )
876 : {
877 : if ( rState.GetItemState( SID_PRINTDOCDIRECT ) != SFX_ITEM_UNKNOWN )
878 : GetSlotState( SID_PRINTDOCDIRECT, SfxViewShell::GetInterface(),
879 : &rState );
880 : ...
881 : }
882 :
883 : [Cross-reference]
884 :
885 : <SfxShell::ExecuteSlot(SfxRequest&)>
886 : */
887 :
888 : {
889 : // Get Slot on the given Interface
890 0 : if ( !pIF )
891 0 : pIF = GetInterface();
892 : SfxItemState eState;
893 0 : SfxItemPool &rPool = GetPool();
894 :
895 0 : const SfxSlot* pSlot = NULL;
896 0 : if ( nSlotId >= SID_VERB_START && nSlotId <= SID_VERB_END )
897 0 : pSlot = GetVerbSlot_Impl(nSlotId);
898 0 : if ( !pSlot )
899 0 : pSlot = pIF->GetSlot(nSlotId);
900 0 : if ( pSlot )
901 : // Map on Which-Id if possible
902 0 : nSlotId = pSlot->GetWhich( rPool );
903 :
904 : // Get Item and Item status
905 0 : const SfxPoolItem *pItem = NULL;
906 0 : SfxItemSet aSet( rPool, nSlotId, nSlotId ); // else pItem dies too soon
907 0 : if ( pSlot )
908 : {
909 : // Call Status method
910 0 : SfxStateFunc pFunc = pSlot->GetStateFnc();
911 0 : if ( pFunc )
912 0 : CallState( pFunc, aSet );
913 0 : eState = aSet.GetItemState( nSlotId, true, &pItem );
914 :
915 : // get default Item if possible
916 0 : if ( eState == SFX_ITEM_DEFAULT )
917 : {
918 0 : if ( SfxItemPool::IsWhich(nSlotId) )
919 0 : pItem = &rPool.GetDefaultItem(nSlotId);
920 : else
921 0 : eState = SFX_ITEM_DONTCARE;
922 : }
923 : }
924 : else
925 0 : eState = SFX_ITEM_UNKNOWN;
926 :
927 : // Evaluate Item and item status and possibly maintain them in pStateSet
928 0 : SfxPoolItem *pRetItem = 0;
929 0 : if ( eState <= SFX_ITEM_DISABLED )
930 : {
931 0 : if ( pStateSet )
932 0 : pStateSet->DisableItem(nSlotId);
933 0 : return 0;
934 : }
935 0 : else if ( eState == SFX_ITEM_DONTCARE )
936 : {
937 0 : if ( pStateSet )
938 0 : pStateSet->ClearItem(nSlotId);
939 0 : pRetItem = new SfxVoidItem(0);
940 : }
941 : else
942 : {
943 0 : if ( pStateSet && pStateSet->Put( *pItem ) )
944 0 : return &pStateSet->Get( pItem->Which() );
945 0 : pRetItem = pItem->Clone();
946 : }
947 0 : DeleteItemOnIdle(pRetItem);
948 :
949 0 : return pRetItem;
950 : }
951 :
952 :
953 :
954 0 : SFX_EXEC_STUB(SfxShell, VerbExec)
955 0 : SFX_STATE_STUB(SfxShell, VerbState)
956 :
957 0 : void SfxShell::SetVerbs(const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& aVerbs)
958 : {
959 0 : SfxViewShell *pViewSh = PTR_CAST ( SfxViewShell, this);
960 :
961 : DBG_ASSERT(pViewSh, "Only call SetVerbs at the ViewShell!");
962 0 : if ( !pViewSh )
963 0 : return;
964 :
965 : // First make all Statecaches dirty, so that no-one no longer tries to use
966 : // the Slots
967 : {
968 : SfxBindings *pBindings =
969 0 : pViewSh->GetViewFrame()->GetDispatcher()->GetBindings();
970 0 : sal_uInt16 nCount = pImp->aSlotArr.size();
971 0 : for (sal_uInt16 n1=0; n1<nCount ; n1++)
972 : {
973 0 : sal_uInt16 nId = SID_VERB_START + n1;
974 0 : pBindings->Invalidate(nId, false, true);
975 : }
976 : }
977 :
978 0 : sal_uInt16 nr=0;
979 0 : for (sal_Int32 n=0; n<aVerbs.getLength(); n++)
980 : {
981 0 : sal_uInt16 nSlotId = SID_VERB_START + nr++;
982 : DBG_ASSERT(nSlotId <= SID_VERB_END, "To many Verbs!");
983 0 : if (nSlotId > SID_VERB_END)
984 0 : break;
985 :
986 0 : SfxSlot *pNewSlot = new SfxSlot;
987 0 : pNewSlot->nSlotId = nSlotId;
988 0 : pNewSlot->nGroupId = 0;
989 :
990 : // Verb slots must be executed asynchronously, so that they can be
991 : // destroyed while executing.
992 0 : pNewSlot->nFlags = SFX_SLOT_ASYNCHRON | SFX_SLOT_CONTAINER;
993 0 : pNewSlot->nMasterSlotId = 0;
994 0 : pNewSlot->nValue = 0;
995 0 : pNewSlot->fnExec = SFX_STUB_PTR(SfxShell,VerbExec);
996 0 : pNewSlot->fnState = SFX_STUB_PTR(SfxShell,VerbState);
997 0 : pNewSlot->pType = 0; // HACK(SFX_TYPE(SfxVoidItem)) ???
998 0 : pNewSlot->pName = OUStringToOString( aVerbs[n].VerbName, RTL_TEXTENCODING_UTF8 ).getStr();
999 0 : pNewSlot->pLinkedSlot = 0;
1000 0 : pNewSlot->nArgDefCount = 0;
1001 0 : pNewSlot->pFirstArgDef = 0;
1002 0 : pNewSlot->pUnoName = 0;
1003 :
1004 0 : if (!pImp->aSlotArr.empty())
1005 : {
1006 0 : SfxSlot *pSlot = pImp->aSlotArr[0];
1007 0 : pNewSlot->pNextSlot = pSlot->pNextSlot;
1008 0 : pSlot->pNextSlot = pNewSlot;
1009 : }
1010 : else
1011 0 : pNewSlot->pNextSlot = pNewSlot;
1012 :
1013 0 : pImp->aSlotArr.insert(pImp->aSlotArr.begin() + (sal_uInt16) n, pNewSlot);
1014 : }
1015 :
1016 0 : pImp->aVerbList = aVerbs;
1017 :
1018 0 : if (pViewSh)
1019 : {
1020 : // The status of SID_OBJECT is collected in the controller directly on
1021 : // the Shell, it is thus enough to encourage a new status update
1022 : SfxBindings *pBindings = pViewSh->GetViewFrame()->GetDispatcher()->
1023 0 : GetBindings();
1024 0 : pBindings->Invalidate( SID_OBJECT, true, true );
1025 : }
1026 : }
1027 :
1028 :
1029 :
1030 0 : const com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor >& SfxShell::GetVerbs() const
1031 : {
1032 0 : return pImp->aVerbList;
1033 : }
1034 :
1035 :
1036 :
1037 0 : void SfxShell::VerbExec(SfxRequest& rReq)
1038 : {
1039 0 : sal_uInt16 nId = rReq.GetSlot();
1040 0 : SfxViewShell *pViewShell = GetViewShell();
1041 0 : if ( pViewShell )
1042 : {
1043 0 : bool bReadOnly = pViewShell->GetObjectShell()->IsReadOnly();
1044 0 : com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > aList = pViewShell->GetVerbs();
1045 0 : for (sal_Int32 n=0, nVerb=0; n<aList.getLength(); n++)
1046 : {
1047 : // check for ReadOnly verbs
1048 0 : if ( bReadOnly && !(aList[n].VerbAttributes & embed::VerbAttributes::MS_VERBATTR_NEVERDIRTIES) )
1049 0 : continue;
1050 :
1051 : // check for verbs that shouldn't appear in the menu
1052 0 : if ( !(aList[n].VerbAttributes & embed::VerbAttributes::MS_VERBATTR_ONCONTAINERMENU) )
1053 0 : continue;
1054 :
1055 0 : if (nId == SID_VERB_START + nVerb++)
1056 : {
1057 0 : pViewShell->DoVerb(aList[n].VerbID);
1058 0 : rReq.Done();
1059 0 : return;
1060 : }
1061 0 : }
1062 : }
1063 : }
1064 :
1065 :
1066 :
1067 0 : void SfxShell::VerbState(SfxItemSet& )
1068 : {
1069 0 : }
1070 :
1071 :
1072 :
1073 0 : const SfxSlot* SfxShell::GetVerbSlot_Impl(sal_uInt16 nId) const
1074 : {
1075 0 : com::sun::star::uno::Sequence < com::sun::star::embed::VerbDescriptor > rList = pImp->aVerbList;
1076 :
1077 : DBG_ASSERT(nId >= SID_VERB_START && nId <= SID_VERB_END,"Wrong VerbId!");
1078 0 : sal_uInt16 nIndex = nId - SID_VERB_START;
1079 : DBG_ASSERT(nIndex < rList.getLength(),"Wrong VerbId!");
1080 :
1081 0 : if (nIndex < rList.getLength())
1082 0 : return pImp->aSlotArr[nIndex];
1083 : else
1084 0 : return 0;
1085 : }
1086 :
1087 :
1088 :
1089 0 : void SfxShell::SetHelpId(sal_uIntPtr nId)
1090 : {
1091 0 : pImp->nHelpId = nId;
1092 0 : }
1093 :
1094 :
1095 :
1096 0 : sal_uIntPtr SfxShell::GetHelpId() const
1097 : {
1098 0 : return pImp->nHelpId;
1099 : }
1100 :
1101 :
1102 :
1103 0 : SfxObjectShell* SfxShell::GetObjectShell()
1104 : {
1105 0 : if ( GetViewShell() )
1106 0 : return GetViewShell()->GetViewFrame()->GetObjectShell();
1107 : else
1108 0 : return NULL;
1109 : }
1110 :
1111 :
1112 :
1113 0 : bool SfxShell::HasUIFeature( sal_uInt32 )
1114 : {
1115 0 : return false;
1116 : }
1117 :
1118 0 : long DispatcherUpdate_Impl( void*, void* pArg )
1119 : {
1120 0 : ((SfxDispatcher*) pArg)->Update_Impl( true );
1121 0 : ((SfxDispatcher*) pArg)->GetBindings()->InvalidateAll(false);
1122 0 : return 0;
1123 : }
1124 :
1125 0 : void SfxShell::UIFeatureChanged()
1126 : {
1127 0 : SfxViewFrame *pFrame = GetFrame();
1128 0 : if ( pFrame && pFrame->IsVisible() )
1129 : {
1130 : // Also force an update, if dispatcher is already updated otherwise
1131 : // something my get stuck in the bunkered tools. Asynchronous call to
1132 : // prevent recursion.
1133 0 : if ( !pImp->pUpdater )
1134 0 : pImp->pUpdater = new svtools::AsynchronLink( Link( this, DispatcherUpdate_Impl ) );
1135 :
1136 : // Multiple views allowed
1137 0 : pImp->pUpdater->Call( pFrame->GetDispatcher(), true );
1138 : }
1139 0 : }
1140 :
1141 0 : void SfxShell::SetDisableFlags( sal_uIntPtr nFlags )
1142 : {
1143 0 : pImp->nDisableFlags = nFlags;
1144 0 : }
1145 :
1146 0 : sal_uIntPtr SfxShell::GetDisableFlags() const
1147 : {
1148 0 : return pImp->nDisableFlags;
1149 : }
1150 :
1151 0 : SfxItemSet* SfxShell::CreateItemSet( sal_uInt16 )
1152 : {
1153 0 : return NULL;
1154 : }
1155 :
1156 0 : void SfxShell::ApplyItemSet( sal_uInt16, const SfxItemSet& )
1157 : {
1158 0 : }
1159 :
1160 0 : void SfxShell::SetContextName (const ::rtl::OUString& rsContextName)
1161 : {
1162 0 : pImp->maContextChangeBroadcaster.Initialize(rsContextName);
1163 0 : }
1164 :
1165 0 : void SfxShell::SetViewShell_Impl( SfxViewShell* pView )
1166 : {
1167 0 : pImp->pViewSh = pView;
1168 0 : }
1169 :
1170 0 : void SfxShell::BroadcastContextForActivation (const bool bIsActivated)
1171 : {
1172 0 : SfxViewFrame* pViewFrame = GetFrame();
1173 0 : if (pViewFrame != NULL)
1174 : {
1175 0 : if (bIsActivated)
1176 0 : pImp->maContextChangeBroadcaster.Activate(pViewFrame->GetFrame().GetFrameInterface());
1177 : else
1178 0 : pImp->maContextChangeBroadcaster.Deactivate(pViewFrame->GetFrame().GetFrameInterface());
1179 : }
1180 0 : }
1181 :
1182 0 : bool SfxShell::SetContextBroadcasterEnabled (const bool bIsEnabled)
1183 : {
1184 0 : return pImp->maContextChangeBroadcaster.SetBroadcasterEnabled(bIsEnabled);
1185 : }
1186 :
1187 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|