xref: /trunk/main/sfx2/source/control/request.cxx (revision d119d52d)
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 
25 // MARKER(update_precomp.py): autogen include statement, do not remove
26 #include "precompiled_sfx2.hxx"
27 
28 #include <com/sun/star/frame/DispatchStatement.hpp>
29 #include <com/sun/star/container/XIndexReplace.hpp>
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/uno/Sequence.hxx>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/util/XURLTransformer.hpp>
34 #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
35 #include <svl/itemiter.hxx>
36 
37 #ifndef _ARGS_HXX //autogen
38 #include <svl/itempool.hxx>
39 #endif
40 #include <svtools/itemdel.hxx>
41 
42 #include <comphelper/processfactory.hxx>
43 
44 #ifndef GCC
45 #endif
46 
47 #include <svl/smplhint.hxx>
48 
49 #include <sfx2/request.hxx>
50 #include <sfx2/dispatch.hxx>
51 #include <sfx2/msg.hxx>
52 #include <sfx2/viewfrm.hxx>
53 #include "macro.hxx"
54 #include <sfx2/objface.hxx>
55 #include <sfx2/appuno.hxx>
56 
57 //===================================================================
58 
59 using namespace ::com::sun::star;
60 
61 struct SfxRequest_Impl: public SfxListener
62 
63 /* 	[Beschreibung]
64 
65 	Implementations-Struktur der Klasse <SfxRequest>.
66 */
67 
68 {
69 	SfxRequest*			pAnti;		 // Owner wegen sterbendem Pool
70 	String				aTarget;	 // ggf. von App gesetztes Zielobjekt
71 	SfxItemPool*        pPool;		 // ItemSet mit diesem Pool bauen
72 	SfxPoolItem*		pRetVal;	 // R"uckgabewert geh"ort sich selbst
73     SfxShell*           pShell;      // ausgef"uhrt an dieser Shell
74 	const SfxSlot*		pSlot;		 // ausgef"uhrter Slot
75 	sal_uInt16              nModifier;   // welche Modifier waren gedrueckt?
76 	sal_Bool				bDone;		 // "uberhaupt ausgef"uhrt
77 	sal_Bool				bIgnored;	 // vom User abgebrochen
78 	sal_Bool				bCancelled;	 // nicht mehr zustellen
79 	sal_Bool				bUseTarget;	 // aTarget wurde von Applikation gesetzt
80 	sal_uInt16  			nCallMode;   // Synch/Asynch/API/Record
81     sal_Bool                bAllowRecording;
82 	SfxAllItemSet*      pInternalArgs;
83     SfxViewFrame*       pViewFrame;
84 
85     com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;
86 
SfxRequest_ImplSfxRequest_Impl87 						SfxRequest_Impl( SfxRequest *pOwner )
88 						: pAnti( pOwner)
89 						, pPool(0)
90 						, nModifier(0)
91 						, bCancelled(sal_False)
92 						, nCallMode( SFX_CALLMODE_SYNCHRON )
93 						, bAllowRecording( sal_False )
94 						, pInternalArgs( 0 )
95 						, pViewFrame(0)
96 						{}
~SfxRequest_ImplSfxRequest_Impl97 	~SfxRequest_Impl() { delete pInternalArgs; }
98 
99 
100 	void				SetPool( SfxItemPool *pNewPool );
101 	virtual void		Notify( SfxBroadcaster &rBC, const SfxHint &rHint );
102     void                Record( const uno::Sequence < beans::PropertyValue >& rArgs );
103 };
104 
105 
106 //====================================================================
107 
Notify(SfxBroadcaster &,const SfxHint & rHint)108 void SfxRequest_Impl::Notify( SfxBroadcaster&, const SfxHint &rHint )
109 {
110 	SfxSimpleHint *pSimpleHint = PTR_CAST(SfxSimpleHint, &rHint);
111 	if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DYING )
112 		pAnti->Cancel();
113 }
114 
115 //====================================================================
116 
SetPool(SfxItemPool * pNewPool)117 void SfxRequest_Impl::SetPool( SfxItemPool *pNewPool )
118 {
119 	if ( pNewPool != pPool )
120 	{
121 		if ( pPool )
122 			EndListening( pPool->BC() );
123 		pPool = pNewPool;
124 		if ( pNewPool )
125 			StartListening( pNewPool->BC() );
126 	}
127 }
128 
129 //====================================================================
130 
131 
~SfxRequest()132 SfxRequest::~SfxRequest()
133 {
134 	DBG_MEMTEST();
135 
136 	// nicht mit Done() marktierte Requests mit 'rem' rausschreiben
137 	if ( pImp->xRecorder.is() && !pImp->bDone && !pImp->bIgnored )
138         pImp->Record( uno::Sequence < beans::PropertyValue >() );
139 
140 	// Objekt abr"aumen
141 	delete pArgs;
142 	if ( pImp->pRetVal )
143 		DeleteItemOnIdle(pImp->pRetVal);
144 	delete pImp;
145 }
146 //--------------------------------------------------------------------
147 
148 
SfxRequest(const SfxRequest & rOrig)149 SfxRequest::SfxRequest
150 (
151 	const SfxRequest& rOrig
152 )
153 :	SfxHint( rOrig ),
154     nSlot(rOrig.nSlot),
155 	pArgs(rOrig.pArgs? new SfxAllItemSet(*rOrig.pArgs): 0),
156 	pImp( new SfxRequest_Impl(this) )
157 {
158 	DBG_MEMTEST();
159 
160     pImp->bAllowRecording = rOrig.pImp->bAllowRecording;
161     pImp->bDone = sal_False;
162 	pImp->bIgnored = sal_False;
163 	pImp->pRetVal = 0;
164 	pImp->pShell = 0;
165 	pImp->pSlot = 0;
166 	pImp->nCallMode = rOrig.pImp->nCallMode;
167 	pImp->bUseTarget = rOrig.pImp->bUseTarget;
168 	pImp->aTarget = rOrig.pImp->aTarget;
169 	pImp->nModifier = rOrig.pImp->nModifier;
170 
171     // deep copy needed !
172     pImp->pInternalArgs = (rOrig.pImp->pInternalArgs ? new SfxAllItemSet(*rOrig.pImp->pInternalArgs) : 0);
173 
174 	if ( pArgs )
175 		pImp->SetPool( pArgs->GetPool() );
176 	else
177 		pImp->SetPool( rOrig.pImp->pPool );
178 }
179 //--------------------------------------------------------------------
180 
181 
SfxRequest(SfxViewFrame * pViewFrame,sal_uInt16 nSlotId)182 SfxRequest::SfxRequest
183 (
184     SfxViewFrame*   pViewFrame,
185     sal_uInt16          nSlotId
186 
187 )
188 
189 /*	[Beschreibung]
190 
191 	Mit diesem Konstruktor k"onnen Events, die nicht "uber den SfxDispatcher
192 	gelaufen sind (z.B aus KeyInput() oder Mouse-Events) nachtr"aglich
193 	recorded werden. Dazu wird eine SfxRequest-Instanz mit diesem Konstruktor
194 	erzeugt und dann genauso verfahren, wie mit einem SfxRequest, der in
195 	eine <Slot-Execute-Methode> als Parameter gegeben wird.
196 */
197 
198 :	nSlot(nSlotId),
199 	pArgs(0),
200 	pImp( new SfxRequest_Impl(this) )
201 {
202 	DBG_MEMTEST();
203 
204 	pImp->bDone = sal_False;
205 	pImp->bIgnored = sal_False;
206     pImp->SetPool( &pViewFrame->GetPool() );
207 	pImp->pRetVal = 0;
208 	pImp->pShell = 0;
209     pImp->pSlot = 0;
210 	pImp->nCallMode = SFX_CALLMODE_SYNCHRON;
211 	pImp->bUseTarget = sal_False;
212     pImp->pViewFrame = pViewFrame;
213     if( pImp->pViewFrame->GetDispatcher()->GetShellAndSlot_Impl( nSlotId, &pImp->pShell, &pImp->pSlot, sal_True, sal_True ) )
214     {
215         pImp->SetPool( &pImp->pShell->GetPool() );
216         pImp->xRecorder = SfxRequest::GetMacroRecorder( pViewFrame );
217         pImp->aTarget = pImp->pShell->GetName();
218     }
219 #ifdef DBG_UTIL
220     else
221     {
222         ByteString aStr( "Recording unsupported slot: ");
223         aStr += ByteString::CreateFromInt32( pImp->pPool->GetSlotId(nSlotId) );
224         DBG_ERROR( aStr.GetBuffer() );
225     }
226 #endif
227 }
228 
229 //--------------------------------------------------------------------
230 
231 
SfxRequest(sal_uInt16 nSlotId,SfxCallMode nMode,SfxItemPool & rPool)232 SfxRequest::SfxRequest
233 (
234 	sal_uInt16 			nSlotId, 	// auszuf"uhrende <Slot-Id>
235 	SfxCallMode 	nMode,		// Synch/API/...
236 	SfxItemPool&	rPool 		// ggf. f"ur das SfxItemSet f"ur Parameter
237 )
238 
239 // creates a SfxRequest without arguments
240 
241 :	nSlot(nSlotId),
242 	pArgs(0),
243 	pImp( new SfxRequest_Impl(this) )
244 {
245 	DBG_MEMTEST();
246 
247 	pImp->bDone = sal_False;
248 	pImp->bIgnored = sal_False;
249 	pImp->SetPool( &rPool );
250 	pImp->pRetVal = 0;
251 	pImp->pShell = 0;
252 	pImp->pSlot = 0;
253 	pImp->nCallMode = nMode;
254 	pImp->bUseTarget = sal_False;
255 }
256 
SfxRequest(const SfxSlot * pSlot,const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> & rArgs,SfxCallMode nMode,SfxItemPool & rPool)257 SfxRequest::SfxRequest
258 (
259 	const SfxSlot* pSlot, 	// auszuf"uhrende <Slot-Id>
260 	const com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue >& rArgs,
261 	SfxCallMode 	nMode,		// Synch/API/...
262 	SfxItemPool&	rPool 		// ggf. f"ur das SfxItemSet f"ur Parameter
263 )
264 :	nSlot(pSlot->GetSlotId()),
265 	pArgs(new SfxAllItemSet(rPool)),
266 	pImp( new SfxRequest_Impl(this) )
267 {
268 	DBG_MEMTEST();
269 
270 	pImp->bDone = sal_False;
271 	pImp->bIgnored = sal_False;
272 	pImp->SetPool( &rPool );
273 	pImp->pRetVal = 0;
274 	pImp->pShell = 0;
275 	pImp->pSlot = 0;
276 	pImp->nCallMode = nMode;
277 	pImp->bUseTarget = sal_False;
278 	TransformParameters( nSlot, rArgs, *pArgs, pSlot );
279 }
280 
281 //-----------------------------------------------------------------------
282 
SfxRequest(sal_uInt16 nSlotId,sal_uInt16 nMode,const SfxAllItemSet & rSfxArgs)283 SfxRequest::SfxRequest
284 (
285 	sal_uInt16 					nSlotId,
286 	sal_uInt16					nMode,
287 	const SfxAllItemSet&	rSfxArgs
288 )
289 
290 // creates a SfxRequest with arguments
291 
292 :	nSlot(nSlotId),
293 	pArgs(new SfxAllItemSet(rSfxArgs)),
294 	pImp( new SfxRequest_Impl(this) )
295 {
296 	DBG_MEMTEST();
297 
298 	pImp->bDone = sal_False;
299 	pImp->bIgnored = sal_False;
300 	pImp->SetPool( rSfxArgs.GetPool() );
301 	pImp->pRetVal = 0;
302 	pImp->pShell = 0;
303 	pImp->pSlot = 0;
304 	pImp->nCallMode = nMode;
305 	pImp->bUseTarget = sal_False;
306 }
307 //--------------------------------------------------------------------
308 
GetCallMode() const309 sal_uInt16 SfxRequest::GetCallMode() const
310 {
311 	return pImp->nCallMode;
312 }
313 
314 //--------------------------------------------------------------------
315 
IsSynchronCall() const316 sal_Bool SfxRequest::IsSynchronCall() const
317 {
318 	return SFX_CALLMODE_SYNCHRON == ( SFX_CALLMODE_SYNCHRON & pImp->nCallMode );
319 }
320 
321 //--------------------------------------------------------------------
322 
SetSynchronCall(sal_Bool bSynchron)323 void SfxRequest::SetSynchronCall( sal_Bool bSynchron )
324 {
325 	if ( bSynchron )
326 		pImp->nCallMode |= SFX_CALLMODE_SYNCHRON;
327 	else
328 		pImp->nCallMode &= ~(sal_uInt16) SFX_CALLMODE_SYNCHRON;
329 }
330 
SetInternalArgs_Impl(const SfxAllItemSet & rArgs)331 void SfxRequest::SetInternalArgs_Impl( const SfxAllItemSet& rArgs )
332 {
333 	delete pImp->pInternalArgs;
334 	pImp->pInternalArgs = new SfxAllItemSet( rArgs );
335 }
336 
GetInternalArgs_Impl() const337 const SfxItemSet* SfxRequest::GetInternalArgs_Impl() const
338 {
339 	return pImp->pInternalArgs;
340 }
341 
342 //--------------------------------------------------------------------
343 
344 
Record(const uno::Sequence<beans::PropertyValue> & rArgs)345 void SfxRequest_Impl::Record
346 (
347     const uno::Sequence < beans::PropertyValue >& rArgs    // aktuelle Parameter
348 )
349 
350 /*	[Beschreibung]
351 
352 	Interne Hilfsmethode zum erzeugen einer <SfxMacroStatement>-Instanz,
353 	welche den bereits ausgef"uhrten SfxRequest wiederholbar beschreibt.
354 
355 	Die erzeugte Instanz, auf die ein Pointer zur"uckgeliefert wird
356 	geht in das Eigentum des Aufrufers "uber.
357 */
358 
359 {
360     String aCommand = String::CreateFromAscii(".uno:");
361     aCommand.AppendAscii( pSlot->GetUnoName() );
362 	::rtl::OUString aCmd( aCommand );
363     if(xRecorder.is())
364     {
365 		uno::Reference< container::XIndexReplace > xReplace( xRecorder, uno::UNO_QUERY );
366 		if ( xReplace.is() && aCmd.compareToAscii(".uno:InsertText") == COMPARE_EQUAL )
367 		{
368 			sal_Int32 nCount = xReplace->getCount();
369 			if ( nCount )
370 			{
371 				frame::DispatchStatement aStatement;
372 				uno::Any aElement = xReplace->getByIndex(nCount-1);
373 				if ( (aElement >>= aStatement) && aStatement.aCommand == aCmd )
374 				{
375 					::rtl::OUString aStr;
376 					::rtl::OUString aNew;
377 		            aStatement.aArgs[0].Value >>= aStr;
378 					rArgs[0].Value >>= aNew;
379 					aStr += aNew;
380 		            aStatement.aArgs[0].Value <<= aStr;
381 					aElement <<= aStatement;
382 					xReplace->replaceByIndex( nCount-1, aElement );
383 					return;
384 				}
385 			}
386 		}
387 
388         com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xFactory(
389                 ::comphelper::getProcessServiceFactory(),
390                 com::sun::star::uno::UNO_QUERY);
391 
392         com::sun::star::uno::Reference< com::sun::star::util::XURLTransformer > xTransform(
393                 xFactory->createInstance(rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")),
394                 com::sun::star::uno::UNO_QUERY);
395 
396         com::sun::star::util::URL aURL;
397         aURL.Complete = aCmd;
398         xTransform->parseStrict(aURL);
399 
400         if (bDone)
401             xRecorder->recordDispatch(aURL,rArgs);
402         else
403             xRecorder->recordDispatchAsComment(aURL,rArgs);
404     }
405 }
406 
407 //--------------------------------------------------------------------
408 
Record_Impl(SfxShell & rSh,const SfxSlot & rSlot,com::sun::star::uno::Reference<com::sun::star::frame::XDispatchRecorder> xRecorder,SfxViewFrame * pViewFrame)409 void SfxRequest::Record_Impl
410 (
411     SfxShell& rSh,    // die <SfxShell>, die den Request ausgef"uhrt hat
412 	const SfxSlot&	rSlot, 	// der <SfxSlot>, der den Request ausgef"uhrt hat
413     com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder,  // der Recorder, mit dem aufgezeichnet wird
414     SfxViewFrame* pViewFrame
415 )
416 
417 /*	[Beschreibung]
418 
419 	Diese interne Methode markiert den SfxRequest als in dem angegebenen
420 	SfxMakro aufzuzeichnen.
421 
422 	Pointer auf die Parameter werden in Done() wieder verwendet, m"usseb
423 	dann also noch leben.
424 */
425 
426 {
427 	DBG_MEMTEST();
428 	pImp->pShell = &rSh;
429 	pImp->pSlot = &rSlot;
430     pImp->xRecorder = xRecorder;
431 	pImp->aTarget = rSh.GetName();
432     pImp->pViewFrame = pViewFrame;
433 }
434 
435 //--------------------------------------------------------------------
436 
SetArgs(const SfxAllItemSet & rArgs)437 void SfxRequest::SetArgs( const SfxAllItemSet& rArgs )
438 {
439 	delete pArgs;
440 	pArgs = new SfxAllItemSet(rArgs);
441 	pImp->SetPool( pArgs->GetPool() );
442 }
443 
444 //--------------------------------------------------------------------
445 
AppendItem(const SfxPoolItem & rItem)446 void SfxRequest::AppendItem(const SfxPoolItem &rItem)
447 {
448 	if(!pArgs)
449 		pArgs = new SfxAllItemSet(*pImp->pPool);
450 	pArgs->Put(rItem, rItem.Which());
451 }
452 
453 //--------------------------------------------------------------------
454 
RemoveItem(sal_uInt16 nID)455 void SfxRequest::RemoveItem( sal_uInt16 nID )
456 {
457 	if (pArgs)
458 	{
459 		pArgs->ClearItem(nID);
460 		if ( !pArgs->Count() )
461 			DELETEZ(pArgs);
462 	}
463 }
464 
465 //--------------------------------------------------------------------
466 
GetArg(sal_uInt16 nSlotId,bool bDeep,TypeId aType) const467 const SfxPoolItem* SfxRequest::GetArg
468 (
469 	sal_uInt16 			nSlotId, 	// Slot-Id oder Which-Id des Parameters
470 	bool 		bDeep,	 	// false: nicht in Parent-ItemSets suchen
471 	TypeId			aType		// != 0:  RTTI Pruefung mit Assertion
472 ) 	const
473 {
474 	return GetItem( pArgs, nSlotId, bDeep, aType );
475 }
476 
477 
478 //--------------------------------------------------------------------
GetItem(const SfxItemSet * pArgs,sal_uInt16 nSlotId,bool bDeep,TypeId aType)479 const SfxPoolItem* SfxRequest::GetItem
480 (
481 	const SfxItemSet* pArgs,
482 	sal_uInt16 			nSlotId, 	// Slot-Id oder Which-Id des Parameters
483 	bool    		bDeep,	 	// false: nicht in Parent-ItemSets suchen
484 	TypeId			aType		// != 0:  RTTI Pruefung mit Assertion
485 )
486 
487 /*	[Beschreibung]
488 
489 	Mit dieser Methode wird der Zugriff auf einzelne Parameter im
490 	SfxRequest wesentlich vereinfacht. Insbesondere wird die Typpr"ufung
491 	(per Assertion) durchgef"uhrt, wodurch die Applikations-Sourcen
492 	wesentlich "ubersichtlicher werden. In der PRODUCT-Version wird
493 	eine 0 zur"uckgegeben, wenn das gefundene Item nicht von der
494 	angegebenen Klasse ist.
495 
496 
497 	[Beispiel]
498 
499 	void MyShell::Execute( SfxRequest &rReq )
500 	{
501 		switch ( rReq.GetSlot() )
502 		{
503 			case SID_MY:
504 			{
505 				...
506 				// ein Beispiel ohne Verwendung des Makros
507 				const SfxInt32Item *pPosItem = (const SfxUInt32Item*)
508 					rReq.GetArg( SID_POS, sal_False, TYPE(SfxInt32Item) );
509 				sal_uInt16 nPos = pPosItem ? pPosItem->GetValue() : 0;
510 
511 				// ein Beispiel mit Verwendung des Makros
512 				SFX_REQUEST_ARG(rReq, pSizeItem, SfxInt32Item, SID_SIZE, sal_False);
513 				sal_uInt16 nSize = pSizeItem ? pPosItem->GetValue() : 0;
514 
515 				...
516 			}
517 
518 			...
519 		}
520 	}
521 */
522 
523 {
524 	if ( pArgs )
525 	{
526 		// ggf. in Which-Id umrechnen
527 		sal_uInt16 nWhich = pArgs->GetPool()->GetWhich(nSlotId);
528 
529 		// ist das Item gesetzt oder bei bDeep==TRUE verf"ugbar?
530 		const SfxPoolItem *pItem = 0;
531 		if ( ( bDeep ? SFX_ITEM_AVAILABLE : SFX_ITEM_SET )
532 			 <= pArgs->GetItemState( nWhich, bDeep, &pItem ) )
533 		{
534 			// stimmt der Typ "uberein?
535 			if ( !pItem || pItem->IsA(aType) )
536 				return pItem;
537 
538 			// Item da aber falsch => Programmierfehler
539 			DBG_ERROR(  "invalid argument type" );
540 		}
541 	}
542 
543 	// keine Parameter, nicht gefunden oder falschen Typ gefunden
544 	return 0;
545 }
546 
547 //--------------------------------------------------------------------
548 
SetReturnValue(const SfxPoolItem & rItem)549 void SfxRequest::SetReturnValue(const SfxPoolItem &rItem)
550 {
551 	DBG_ASSERT(!pImp->pRetVal, "Returnwert mehrfach setzen?");
552 	if(pImp->pRetVal)
553 		delete pImp->pRetVal;
554 	pImp->pRetVal = rItem.Clone();
555 }
556 
557 //--------------------------------------------------------------------
558 
GetReturnValue() const559 const SfxPoolItem* SfxRequest::GetReturnValue() const
560 {
561 	return pImp->pRetVal;
562 }
563 
564 //--------------------------------------------------------------------
565 
Done(const SfxItemSet & rSet,bool bKeep)566 void SfxRequest::Done
567 (
568 	const SfxItemSet&	rSet,   /* 	von der Applikation mitgeteilte Parameter,
569 									die z.B. in einem Dialog vom Benuter
570 									erfragt wurden, ggf. 0 falls keine
571 									Parameter gesetzt wurden */
572 
573 	bool 			bKeep	/*  true (default)
574 									'rSet' wird gepeichert und ist "uber
575 									GetArgs() abfragbar
576 
577 									false
578 									'rSet' wird nicht kopiert (schneller) */
579 )
580 
581 /*	[Beschreibung]
582 
583 	Diese Methode mu\s in der <Execute-Methode> des <SfxSlot>s gerufen
584 	werden, der den SfxRequest ausgef"uhrt hat, wenn die Ausf"uhrung
585 	tats"achlich stattgefunden hat. Wird 'Done()' nicht gerufen, gilt
586 	der SfxRequest als abgebrochen.
587 
588 	Etwaige Returnwerte werden nur durchgereicht, wenn 'Done()' gerufen
589 	wurde. Ebenso werden beim Aufzeichnen von Makros nur echte
590 	Statements erzeugt, wenn 'Done()' gerufen wurde; f"ur SfxRequests,
591 	die nicht derart gekennzeichnet wurden, wird anstelle dessen eine
592 	auf die abgebrochene Funktion hinweisende Bemerkung ('rem') eingf"ugt.
593 
594 
595 	[Anmerkung]
596 
597 	'Done()' wird z.B. nicht gerufen, wenn ein durch die Funktion gestarteter
598 	Dialog vom Benutzer	abgebrochen wurde oder das Ausf"uhren aufgrund
599 	eines falschen Kontextes (ohne Verwendung separater <SfxShell>s)
600 	nicht durchgef"uhrt werden konnte. 'Done()' mu\s sehr wohl gerufen
601 	werden, wenn das Ausf"uhren der Funktion zu einem regul"aren Fehler
602 	f"uhrte (z.B. Datei konnte nicht ge"offnet werden).
603 */
604 
605 {
606 	Done_Impl( &rSet );
607 
608 	// ggf. Items merken, damit StarDraw sie abfragen kann
609 	if ( bKeep )
610 	{
611 		if ( !pArgs )
612 		{
613 			pArgs = new SfxAllItemSet( rSet );
614 			pImp->SetPool( pArgs->GetPool() );
615 		}
616 		else
617 		{
618 			SfxItemIter aIter(rSet);
619 			const SfxPoolItem* pItem = aIter.FirstItem();
620 			while(pItem)
621 			{
622 				if(!IsInvalidItem(pItem))
623 					pArgs->Put(*pItem,pItem->Which());
624 				pItem = aIter.NextItem();
625 			}
626 		}
627 	}
628 }
629 
630 //--------------------------------------------------------------------
631 
632 
Done(sal_Bool bRelease)633 void SfxRequest::Done( sal_Bool bRelease )
634 //	[<SfxRequest::Done(SfxItemSet&)>]
635 {
636 	Done_Impl( pArgs );
637 	if( bRelease )
638 		DELETEZ( pArgs );
639 }
640 
641 //--------------------------------------------------------------------
642 
ForgetAllArgs()643 void SfxRequest::ForgetAllArgs()
644 {
645     DELETEZ( pArgs );
646     DELETEZ( pImp->pInternalArgs );
647 }
648 
649 //--------------------------------------------------------------------
650 
IsCancelled() const651 sal_Bool SfxRequest::IsCancelled() const
652 {
653 	return pImp->bCancelled;
654 }
655 
656 //--------------------------------------------------------------------
657 
Cancel()658 void SfxRequest::Cancel()
659 
660 /*	[Beschreibung]
661 
662 	Markiert diesen Request als nicht mehr auszufuehren. Wird z.B. gerufen,
663 	wenn das Ziel (genauer dessen Pool) stirbt.
664 */
665 
666 {
667 	pImp->bCancelled = sal_True;
668 	pImp->SetPool( 0 );
669 	DELETEZ( pArgs );
670 }
671 
672 //--------------------------------------------------------------------
673 
674 
Ignore()675 void SfxRequest::Ignore()
676 
677 /*	[Beschreibung]
678 
679 	Wird diese Methode anstelle von <SfxRequest::Done()> gerufen, dann
680 	wird dieser Request nicht recorded.
681 
682 
683 	[Bespiel]
684 
685 	Das Selektieren von Tools im StarDraw soll nicht aufgezeichnet werden,
686 	dieselben Slots sollen aber zum erzeugen der von den Tools zu
687 	erzeugenden Objekte verwendet werde. Also kann nicht NoRecord
688 	angegeben werden, dennoch soll u.U. nicht aufgezeichnet werden.
689 */
690 
691 {
692 	// als tats"achlich ausgef"uhrt markieren
693 	pImp->bIgnored = sal_True;
694 }
695 
696 //--------------------------------------------------------------------
697 
Done_Impl(const SfxItemSet * pSet)698 void SfxRequest::Done_Impl
699 (
700 	const SfxItemSet*	pSet	/* 	von der Applikation mitgeteilte Parameter,
701 									die z.B. in einem Dialog vom Benuter
702 									erfragt wurden, ggf. 0 falls keine
703 									Parameter gesetzt wurden */
704 )
705 
706 /*	[Beschreibung]
707 
708 	Interne Methode zum als 'done' markieren des SfxRequest und zum Auswerten
709     der Parameter in 'pSet' falls aufgezeichnet wird.
710 */
711 
712 {
713 	// als tats"achlich ausgef"uhrt markieren
714 	pImp->bDone = sal_True;
715 
716 	// nicht Recorden
717 	if ( !pImp->xRecorder.is() )
718 		return;
719 
720 	// wurde ein anderer Slot ausgef"uhrt als angefordert (Delegation)
721 	if ( nSlot != pImp->pSlot->GetSlotId() )
722 	{
723 		// Slot neu suchen
724 		pImp->pSlot = pImp->pShell->GetInterface()->GetSlot(nSlot);
725 		DBG_ASSERT( pImp->pSlot, "delegated SlotId not found" );
726 		if ( !pImp->pSlot ) // Hosentr"ger und G"urtel
727 			return;
728 	}
729 
730 	// record-f"ahig?
731     // neues Recorden verwendet UnoName!
732     if ( !pImp->pSlot->pUnoName )
733     {
734         ByteString aStr( "Recording not exported slot: ");
735         aStr += ByteString::CreateFromInt32( pImp->pSlot->GetSlotId() );
736         DBG_ERROR( aStr.GetBuffer() );
737     }
738 
739     if ( !pImp->pSlot->pUnoName ) // Hosentr"ger und G"urtel
740         return;
741 
742 	// "ofters ben"otigte Werte
743 	SfxItemPool &rPool = pImp->pShell->GetPool();
744 
745 	// Property-Slot?
746 	if ( !pImp->pSlot->IsMode(SFX_SLOT_METHOD) )
747 	{
748 		// des Property als SfxPoolItem besorgen
749 		const SfxPoolItem *pItem;
750 		sal_uInt16 nWhich = rPool.GetWhich(pImp->pSlot->GetSlotId());
751         SfxItemState eState = pSet ? pSet->GetItemState( nWhich, sal_False, &pItem ) : SFX_ITEM_UNKNOWN;
752 #ifdef DBG_UTIL
753         if ( SFX_ITEM_SET != eState )
754         {
755             ByteString aStr( "Recording property not available: ");
756             aStr += ByteString::CreateFromInt32( pImp->pSlot->GetSlotId() );
757             DBG_ERROR( aStr.GetBuffer() );
758         }
759 #endif
760         uno::Sequence < beans::PropertyValue > aSeq;
761 		if ( eState == SFX_ITEM_SET )
762             TransformItems( pImp->pSlot->GetSlotId(), *pSet, aSeq, pImp->pSlot );
763         pImp->Record( aSeq );
764 	}
765 
766 	// alles in ein einziges Statement aufzeichnen?
767 	else if ( pImp->pSlot->IsMode(SFX_SLOT_RECORDPERSET) )
768 	{
769         uno::Sequence < beans::PropertyValue > aSeq;
770         if ( pSet )
771             TransformItems( pImp->pSlot->GetSlotId(), *pSet, aSeq, pImp->pSlot );
772         pImp->Record( aSeq );
773 	}
774 
775 	// jedes Item als einzelnes Statement recorden
776 	else if ( pImp->pSlot->IsMode(SFX_SLOT_RECORDPERITEM) )
777 	{
778 		if ( pSet )
779 		{
780 			// "uber die Items iterieren
781 			SfxItemIter aIter(*pSet);
782             for ( const SfxPoolItem* pItem = aIter.FirstItem(); pItem; pItem = aIter.NextItem() )
783 			{
784 				// die Slot-Id f"ur das einzelne Item ermitteln
785 				sal_uInt16 nSlotId = rPool.GetSlotId( pItem->Which() );
786 				if ( nSlotId == nSlot )
787 				{
788 					// mit Hosentr"ager und G"urtel reparieren des falschen Flags
789 					DBG_ERROR( "recursion RecordPerItem - use RecordPerSet!" );
790 					SfxSlot *pSlot = (SfxSlot*) pImp->pSlot;
791 					pSlot->nFlags &= ~((sal_uIntPtr)SFX_SLOT_RECORDPERITEM);
792 					pSlot->nFlags &=  SFX_SLOT_RECORDPERSET;
793 				}
794 
795 				// einen Sub-Request recorden
796                 SfxRequest aReq( pImp->pViewFrame, nSlotId );
797                 if ( aReq.pImp->pSlot )
798                     aReq.AppendItem( *pItem );
799                 aReq.Done();
800 			}
801 		}
802 		else
803 		{
804 			HACK(hierueber nochmal nachdenken)
805             pImp->Record( uno::Sequence < beans::PropertyValue >() );
806 		}
807 	}
808 }
809 
810 //--------------------------------------------------------------------
811 
IsDone() const812 sal_Bool SfxRequest::IsDone() const
813 
814 /*	[Beschreibung]
815 
816 	Mit dieser Methode kann abgefragt werden, ob der SfxRequest tats"achlich
817 	ausgef"uhrt wurde oder nicht. Wurde ein SfxRequest nicht ausgef"uhrt,
818 	liegt dies z.B. daran, da\s der Benutzer abgebrochen hat oder
819 	der Kontext f"ur diesen Request falsch war, dieses aber nicht "uber
820 	eine separate <SfxShell> realisiert wurde.
821 
822 	SfxRequest-Instanzen, die hier sal_False liefern, werden nicht recorded.
823 
824 
825 	[Querverweise]
826 
827 	<SfxRequest::Done(const SfxItemSet&)>
828 	<SfxRequest::Done()>
829 */
830 
831 {
832 	return pImp->bDone;
833 }
834 
835 //--------------------------------------------------------------------
836 
GetRecordingMacro()837 SfxMacro* SfxRequest::GetRecordingMacro()
838 
839 /*	[Beschreibung]
840 
841 	Mit dieser Methode kann abgefragt werden, ob und in welchem <SfxMacro>
842 	die SfxRequests gerade aufgezeichnet werden.
843 */
844 
845 {
846     return NULL;
847 }
848 
849 //--------------------------------------------------------------------
850 
GetMacroRecorder(SfxViewFrame * pView)851 com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > SfxRequest::GetMacroRecorder( SfxViewFrame* pView )
852 
853 /*  [Beschreibung]
854 
855     Hier wird versucht einen Recorder fuer dispatch() Aufrufe vom Frame zu bekommen.
856     Dieser ist dort per Property an einem Supplier verfuegbar - aber nur dann, wenn
857     recording angeschaltet wurde.
858     (Siehe auch SfxViewFrame::MiscExec_Impl() und SID_RECORDING)
859 */
860 
861 {
862     com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;
863 
864     com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet(
865         (pView ? pView : SfxViewFrame::Current())->GetFrame().GetFrameInterface(),
866         com::sun::star::uno::UNO_QUERY);
867 
868     if(xSet.is())
869     {
870         com::sun::star::uno::Any aProp = xSet->getPropertyValue(rtl::OUString::createFromAscii("DispatchRecorderSupplier"));
871         com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier;
872         aProp >>= xSupplier;
873         if(xSupplier.is())
874             xRecorder = xSupplier->getDispatchRecorder();
875     }
876 
877     return xRecorder;
878 }
879 
HasMacroRecorder(SfxViewFrame * pView)880 sal_Bool SfxRequest::HasMacroRecorder( SfxViewFrame* pView )
881 {
882     return GetMacroRecorder( pView ).is();
883 }
884 
885 
886 //--------------------------------------------------------------------
887 
IsAPI() const888 sal_Bool SfxRequest::IsAPI() const
889 
890 /*	[Beschreibung]
891 
892 	Liefert sal_True, wenn dieser SfxRequest von einer API (z.B. BASIC)
893 	erzeugt wurde, sonst sal_False.
894 */
895 
896 {
897 	return SFX_CALLMODE_API == ( SFX_CALLMODE_API & pImp->nCallMode );
898 }
899 
900 //--------------------------------------------------------------------
901 
902 
IsRecording() const903 bool SfxRequest::IsRecording() const
904 
905 /*	[Beschreibung]
906 
907 	Liefert sal_True, wenn dieser SfxRequest recorded werden soll, d.h.
908 	1. zu Zeit ein Makro aufgezeichnet wird
909 	2. dieser Request "uberhaupt aufgezeichnet wird
910 	3. der Request nicht von reiner API (z.B. BASIC) ausgeht,
911 	sonst sal_False.
912 */
913 
914 {
915     return ( AllowsRecording() && GetMacroRecorder().is() );
916 }
917 
918 //--------------------------------------------------------------------
SetModifier(sal_uInt16 nModi)919 void SfxRequest::SetModifier( sal_uInt16 nModi )
920 {
921 	pImp->nModifier = nModi;
922 }
923 
924 //--------------------------------------------------------------------
GetModifier() const925 sal_uInt16 SfxRequest::GetModifier() const
926 {
927 	return pImp->nModifier;
928 }
929 
930 //--------------------------------------------------------------------
931 
SetTarget(const String & rTarget)932 void SfxRequest::SetTarget( const String &rTarget )
933 
934 /*	[Beschreibung]
935 
936 	Mit dieser Methode kann das zu recordende Zielobjekt umgesetzt werden.
937 
938 
939 	[Beispiel]
940 
941 	Die BASIC-Methode 'Open' wird zwar von der Shell 'Application' ausgef"uhrt,
942 	aber am Objekt 'Documents' (global) recorded:
943 
944 		rReq.SetTarget( "Documents" );
945 
946 	Dies f"uhrt dann zu:
947 
948 		Documents.Open( ... )
949 */
950 
951 {
952 	pImp->aTarget = rTarget;
953 	pImp->bUseTarget = sal_True;
954 }
955 
AllowRecording(sal_Bool bSet)956 void SfxRequest::AllowRecording( sal_Bool bSet )
957 {
958     pImp->bAllowRecording = bSet;
959 }
960 
AllowsRecording() const961 sal_Bool SfxRequest::AllowsRecording() const
962 {
963     sal_Bool bAllow = pImp->bAllowRecording;
964     if( !bAllow )
965         bAllow = ( SFX_CALLMODE_API != ( SFX_CALLMODE_API & pImp->nCallMode ) ) &&
966                  ( SFX_CALLMODE_RECORD == ( SFX_CALLMODE_RECORD & pImp->nCallMode ) );
967     return bAllow;
968 }
969 
ReleaseArgs()970 void SfxRequest::ReleaseArgs()
971 {
972     DELETEZ( pArgs );
973     DELETEZ( pImp->pInternalArgs );
974 }
975