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