xref: /trunk/main/sfx2/source/control/ctrlitem.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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