xref: /AOO41X/main/sfx2/source/control/ctrlitem.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 #include <svl/itempool.hxx>
31 #ifndef GCC
32 #endif
33 
34 #include <sfx2/ctrlitem.hxx>
35 #include <sfx2/bindings.hxx>
36 #include <sfx2/dispatch.hxx>
37 #include <sfx2/msgpool.hxx>
38 #include "statcach.hxx"
39 #include <sfx2/viewfrm.hxx>
40 
41 //====================================================================
42 
43 DBG_NAME(SfxControllerItem);
44 
45 //--------------------------------------------------------------------
46 #ifdef DBG_UTIL
47 
48 void SfxControllerItem::CheckConfigure_Impl( sal_uIntPtr nType )
49 {
50 	// echter Slot? (also kein Separator etc.)
51 	if ( !nId )
52 		return;
53 
54 	// ist die Id "uberhaupt in 'nType' konfigurierbar?
55 	const SfxSlot *pSlot = SFX_SLOTPOOL().GetSlot(nId);
56 	DBG_ASSERTWARNING( pSlot, "SfxControllerItem: binding not existing slot" );
57 	if ( pSlot && !pSlot->IsMode(nType) )
58 	{
59 		DBG_WARNING( "SfxControllerItem: slot without ...Config-flag" );
60 		DbgOutf( "SfxControllerItem: Config-flag missing at SID %5d",
61 				 pSlot->GetSlotId() );
62 	}
63 }
64 
65 #endif
66 
67 //--------------------------------------------------------------------
68 
69 // returns the next registered SfxControllerItem with the same id
70 
71 SfxControllerItem* SfxControllerItem::GetItemLink()
72 {
73 	DBG_MEMTEST();
74 	DBG_CHKTHIS(SfxControllerItem, 0);
75 	return pNext == this ? 0 : pNext;
76 }
77 
78 //--------------------------------------------------------------------
79 
80 // returns sal_True if this binding is really bound to a function
81 
82 sal_Bool SfxControllerItem::IsBound() const
83 {
84 	DBG_MEMTEST();
85 	DBG_CHKTHIS(SfxControllerItem, 0);
86 	return pNext != this;
87 }
88 
89 //--------------------------------------------------------------------
90 
91 // returns the associated function-id or 0 if none
92 
93 // sal_uInt16 SfxControllerItem::GetId() const;
94 
95 //====================================================================
96 
97 // registeres with the id at the bindings
98 
99 void SfxControllerItem::Bind( sal_uInt16 nNewId, SfxBindings *pBindinx )
100 {
101 	DBG_MEMTEST();
102 	DBG_CHKTHIS(SfxControllerItem, 0);
103 	DBG_ASSERT(pBindings || pBindinx, "Keine Bindings");
104 
105 	if ( IsBound() ) {
106 		DBG_ASSERT(pBindings, "Keine Bindings");
107 		pBindings->Release(*this);
108 	}
109 
110 	nId = nNewId;
111 	pNext = 0;
112 
113 	if (pBindinx)
114 		pBindings = pBindinx;
115 	pBindings->Register(*this);
116 }
117 
118 void SfxControllerItem::BindInternal_Impl( sal_uInt16 nNewId, SfxBindings *pBindinx )
119 {
120 	DBG_MEMTEST();
121 	DBG_CHKTHIS(SfxControllerItem, 0);
122 	DBG_ASSERT(pBindings || pBindinx, "Keine Bindings");
123 
124 	if ( IsBound() ) {
125 		DBG_ASSERT(pBindings, "Keine Bindings");
126 		pBindings->Release(*this);
127 	}
128 
129 	nId = nNewId;
130 	pNext = 0;
131 
132 	if (pBindinx)
133 		pBindings = pBindinx;
134     pBindings->RegisterInternal_Impl(*this);
135 }
136 
137 
138 //====================================================================
139 
140 void SfxControllerItem::UnBind()
141 
142 /*	[Beschreibung]
143 
144 	"ost die Verbindung dieses SfxControllerItems mit der SfxBindings-Instanz,
145 	an der es zur Zeit gebunden ist. Ab diesem Zeitpunkt erh"alt es keine
146 	Statusbenachrichtigungen (<SfxControllerItem::StateChented()>) mehr.
147 
148 
149 	[Querverweise]
150 
151 	<SfxControllerItem::ReBind()>
152 	<SfxControllerItem::ClearCache()>
153 */
154 {
155 	DBG_MEMTEST();
156 	DBG_CHKTHIS(SfxControllerItem, 0);
157 	DBG_ASSERT(pBindings, "Keine Bindings");
158 	DBG_ASSERT( IsBound(), "unbindings unbound SfxControllerItem" );
159 
160 	pBindings->Release(*this);
161 	pNext = this;
162 }
163 
164 //====================================================================
165 
166 void SfxControllerItem::ReBind()
167 
168 /*	[Beschreibung]
169 
170 	Binded dieses SfxControllerItem wieder an die SfxBindings-Instanz,
171 	an der es zuletzt gebunden war. Ab diesem Zeitpunkt erh"alt es wieder
172 	Statusbenachrichtigungen (<SfxControllerItem::StateChented()>).
173 
174 
175 	[Querverweise]
176 
177 	<SfxControllerItem::UnBind()>
178 	<SfxControllerItem::ClearCache()>
179 */
180 
181 {
182 	DBG_MEMTEST();
183 DBG_CHKTHIS(SfxControllerItem, 0);
184 	DBG_ASSERT(pBindings, "Keine Bindings");
185 	DBG_ASSERT( !IsBound(), "bindings rebound SfxControllerItem" );
186 
187 	pBindings->Register(*this);
188 }
189 
190 //====================================================================
191 
192 void SfxControllerItem::UpdateSlot()
193 
194 /*	[Beschreibung]
195 
196 	Holt den Status 'hart' neu.
197 
198 	[Querverweise]
199 
200 	<SfxControllerItem::ClearCache()>
201 */
202 
203 {
204 	DBG_MEMTEST();
205 	DBG_CHKTHIS(SfxControllerItem, 0);
206 	DBG_ASSERT(pBindings, "Keine Bindings");
207 
208 	pBindings->Update( GetId() );
209 }
210 
211 //--------------------------------------------------------------------
212 
213 void SfxControllerItem::ClearCache()
214 
215 /*	[Beschreibung]
216 
217 	"oscht den Status-Cache f"ur dieses SfxControllerItem. D.h. beim
218 	n"achsten Status-Update wird das <SfxPoolItem> auf jeden Fall geschickt,
219 	auch wenn zuvor dasselbe geschickt wurde. Dies wird ben"otigt, wenn
220 	ein Controller umgeschaltet werden kann und sich diesen Status
221 	selbst merkt.
222 
223 
224 	[Beispiel]
225 
226 	Der Kombi-Controller f"ur das Einstellen des Fl"achentyps und der
227 	konkreten Auspr"agung (Farbe blau oder Schraffur X) kann im Typ
228 	umgestellt werden, wird jedoch dann bei der n"achsten Selektion
229 	wieder benachrichtigt, auch wenn es dieselben Daten sind.
230 
231 
232 	[Querverweise]
233 
234 	<SfxControllerItem::UnBind()>
235 	<SfxControllerItem::ReBind()>
236 */
237 
238 
239 {
240 	DBG_MEMTEST();
241 	DBG_CHKTHIS(SfxControllerItem, 0);
242 	DBG_ASSERT(pBindings, "Keine Bindings");
243 
244 	pBindings->ClearCache_Impl( GetId() );
245 }
246 
247 //--------------------------------------------------------------------
248 
249 // replaces the successor in the list of bindings of the same id
250 
251 SfxControllerItem* SfxControllerItem::ChangeItemLink( SfxControllerItem* pNewLink )
252 {
253 	DBG_MEMTEST();
254 	DBG_CHKTHIS(SfxControllerItem, 0);
255 	SfxControllerItem* pOldLink = pNext;
256 	pNext = pNewLink;
257 	return pOldLink == this ? 0 : pOldLink;
258 }
259 
260 //--------------------------------------------------------------------
261 
262 // changes the id of unbound functions (e.g. for sub-menu-ids)
263 
264 void SfxControllerItem::SetId( sal_uInt16 nItemId )
265 {
266 	DBG_MEMTEST();
267 	DBG_CHKTHIS(SfxControllerItem, 0);
268 	DBG_ASSERT( !IsBound(), "changing id of bound binding" );
269 	nId = nItemId;
270 }
271 
272 //--------------------------------------------------------------------
273 
274 // creates a atomic item for a controller  without registration
275 
276 SfxControllerItem::SfxControllerItem():
277 	nId(0),
278 	pNext(this),
279 	pBindings(0)
280 {
281 	DBG_MEMTEST();
282 	DBG_CTOR(SfxControllerItem, 0);
283 }
284 
285 //--------------------------------------------------------------------
286 
287 // creates a representation of the function nId and registeres it
288 
289 SfxControllerItem::SfxControllerItem( sal_uInt16 nID, SfxBindings &rBindings ):
290 	nId(nID),
291 	pNext(this),
292 	pBindings(&rBindings)
293 {
294 	DBG_MEMTEST();
295 	DBG_CTOR(SfxControllerItem, 0);
296 	Bind(nId, &rBindings);
297 }
298 
299 //--------------------------------------------------------------------
300 
301 // unregisteres the item in the bindings
302 
303 SfxControllerItem::~SfxControllerItem()
304 {
305 	DBG_MEMTEST();
306 	if ( IsBound() )
307 		pBindings->Release(*this);
308 	DBG_DTOR(SfxControllerItem, 0);
309 }
310 
311 //--------------------------------------------------------------------
312 
313 void SfxControllerItem::StateChanged
314 (
315 	sal_uInt16				,	// <SID> des ausl"osenden Slot
316 	SfxItemState		, 	// <SfxItemState> von 'pState'
317 	const SfxPoolItem*		// Slot-Status, ggf. 0 oder IsInvalidItem()
318 )
319 
320 /*	[Beschreibung]
321 
322 	Diese virtuelle Methode wird vom SFx gerufen, um <SfxControllerItem>s
323 	dar"uber zu benachrichtigen, da\s sich der Status des Slots 'nSID'
324 	ge"andert hat. Der neue Wert sowie der von diesem Wert ermittelte
325 	Status wird als 'pState' bzw. 'eState' mitgegeben.
326 
327 	Der Status eines Slots kann sich "andern, wenn z.B. das MDI-Fenster
328 	gewechselt wird oder der Slot explizit mit <SfxBindings::Invalidate()>
329 	invalidiert wurde.
330 
331 	Achtung! Die Methode wird nicht gerufen, wenn der Slot ung"ultig wurde,
332 	danach jedoch wieder denselben Wert angenommen hat.
333 
334 	Diese Basisklasse braucht nicht gerufen zu werden, weitere Zwischenstufen
335 	jedoch (z.B. <SfxToolboxControl>) sollten gerufen werden.
336 */
337 
338 {
339 	DBG_MEMTEST();
340 	DBG_CHKTHIS(SfxControllerItem, 0);
341 }
342 
343 //--------------------------------------------------------------------
344 
345 void SfxControllerItem::DeleteFloatingWindow()
346 {
347 	DBG_MEMTEST();
348 	DBG_CHKTHIS(SfxControllerItem, 0);
349 }
350 
351 //--------------------------------------------------------------------
352 
353 void SfxStatusForwarder::StateChanged
354 (
355 	sal_uInt16				nSID,		// <SID> des ausl"osenden Slot
356 	SfxItemState		eState, 	// <SfxItemState> von 'pState'
357 	const SfxPoolItem*	pState		// Slot-Status, ggf. 0 oder IsInvalidItem()
358 )
359 
360 {
361 	pMaster->StateChanged( nSID, eState, pState );
362 }
363 
364 //--------------------------------------------------------------------
365 
366 SfxStatusForwarder::SfxStatusForwarder(
367 			sal_uInt16              nSlotId,
368 			SfxControllerItem&  rMaster ):
369 	SfxControllerItem( nSlotId, rMaster.GetBindings() ),
370 	pMaster( &rMaster )
371 {
372 }
373 
374 //--------------------------------------------------------------------
375 
376 SfxItemState SfxControllerItem::GetItemState
377 (
378 	const SfxPoolItem* pState 	/* 	Pointer auf das <SfxPoolItem>, dessen
379 									Status erfragt werden soll. */
380 )
381 
382 /*	[Beschreibung]
383 
384 	Statische Methode zum Ermitteln des Status des SfxPoolItem-Pointers,
385 	in der Methode <SfxControllerItem::StateChanged(const SfxPoolItem*)>
386 	zu verwenden.
387 
388 	[R"uckgabewert]
389 
390 	SfxItemState		SFX_ITEM_UNKNOWN
391 						Enabled, aber keine weitere Statusinformation
392 						verf"ugbar. Typisch f"ur <Slot>s, die allenfalls
393 						zeitweise disabled sind, aber ihre Darstellung sonst
394 						nicht "andern.
395 
396 						SFX_ITEM_DISABLED
397 						Disabled und keine weiter Statusinformation
398 						verf"ugbar. Alle anderen ggf. angezeigten Werte sollten
399 						auf den Default zur"uckgesetzt werden.
400 
401 						SFX_ITEM_DONTCARE
402 						Enabled aber es waren nur uneindeutige Werte
403 						verf"ugbar (also keine, die abgefragt werden k"onnen).
404 
405 						SFX_ITEM_AVAILABLE
406 						Enabled und mit verf"ugbarem Wert, der von 'pState'
407 						erfragbar ist. Der Typ ist dabei im gesamten
408 						Programm eindeutig und durch den Slot festgelegt.
409 */
410 
411 {
412 	return !pState
413 				? SFX_ITEM_DISABLED
414 				: IsInvalidItem(pState)
415 					? SFX_ITEM_DONTCARE
416 					: pState->ISA(SfxVoidItem) && !pState->Which()
417 						? SFX_ITEM_UNKNOWN
418 						: SFX_ITEM_AVAILABLE;
419 }
420 
421 //--------------------------------------------------------------------
422 
423 SfxMapUnit SfxControllerItem::GetCoreMetric() const
424 
425 /*	[Beschreibung]
426 
427 	Holt vom zust"andigen Pool die Ma\seinheit ab, in der das Status-Item
428 	vorliegt.
429 */
430 
431 {
432 	SfxStateCache *pCache = pBindings->GetStateCache( nId );
433 	SfxDispatcher *pDispat = pBindings->GetDispatcher_Impl();
434 
435     if ( !pDispat )
436     {
437         SfxViewFrame* pViewFrame = SfxViewFrame::Current();
438         if ( !pViewFrame )
439             SfxViewFrame::GetFirst();
440         if ( pViewFrame )
441             pDispat = pViewFrame->GetDispatcher();
442     }
443 
444     if ( pDispat && pCache )
445     {
446         const SfxSlotServer *pServer = pCache->GetSlotServer( *pDispat );
447         if ( pServer )
448         {
449             SfxShell *pSh = pDispat->GetShell( pServer->GetShellLevel() );
450             SfxItemPool &rPool = pSh->GetPool();
451             sal_uInt16 nWhich = rPool.GetWhich( nId );
452             return rPool.GetMetric( nWhich );
453         }
454     }
455 
456     DBG_WARNING( "W1: Can not find ItemPool!" );
457     return SFX_MAPUNIT_100TH_MM;
458 }
459 
460 //------------------------------------------------------------------------
461 
462 #ifdef _MSC_VER
463 #pragma optimize("g",off)
464 #endif
465 
466 
467