Bump version to 4.1-6
[LibreOffice.git] / sfx2 / source / control / objface.cxx
blob09870eafb1d484ce5d288a7f1c073e9ff24f9152
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <stdlib.h>
22 #include <tools/rcid.h>
23 #include <tools/stream.hxx>
25 #include <sfx2/module.hxx>
26 #include <sfx2/objface.hxx>
27 #include <sfx2/msg.hxx>
28 #include <sfx2/app.hxx>
29 #include <sfx2/msgpool.hxx>
30 #include "sfx2/sfxresid.hxx"
31 #include <sfx2/objsh.hxx>
32 #include <rtl/strbuf.hxx>
34 DBG_NAME(SfxInterface)
36 //====================================================================
38 extern "C"
39 #ifdef WNT
40 int _cdecl
41 #else
42 int
43 #endif
45 SfxCompareSlots_Impl( const void* pSmaller, const void* pBigger )
47 return ( (int) ((SfxSlot*)pSmaller)->GetSlotId() ) -
48 ( (int) ((SfxSlot*)pBigger)->GetSlotId() );
51 //=========================================================================
53 struct SfxObjectUI_Impl
55 sal_uInt16 nPos;
56 ResId aResId;
57 sal_Bool bVisible;
58 sal_Bool bContext;
59 String* pName;
60 sal_uInt32 nFeature;
62 SfxObjectUI_Impl(sal_uInt16 n, const ResId& rResId, sal_Bool bVis, sal_uInt32 nFeat) :
63 nPos(n),
64 aResId(rResId.GetId(), *rResId.GetResMgr()),
65 bVisible(bVis),
66 bContext(sal_False),
67 pName(0),
68 nFeature(nFeat)
70 aResId.SetRT(rResId.GetRT());
73 ~SfxObjectUI_Impl()
75 delete pName;
79 typedef std::vector<SfxObjectUI_Impl*> SfxObjectUIArr_Impl;
81 struct SfxInterface_Impl
83 SfxObjectUIArr_Impl aObjectBars; // registered ObjectBars
84 SfxObjectUIArr_Impl aChildWindows; // registered ChildWindows
85 ResId aPopupRes; // registered PopupMenu
86 ResId aStatBarRes; // registered StatusBar
87 SfxModule* pModule;
88 sal_Bool bRegistered;
90 SfxInterface_Impl() :
91 aPopupRes(0,*SfxApplication::GetOrCreate()->GetSfxResManager()),
92 aStatBarRes(0,*SfxApplication::GetOrCreate()->GetSfxResManager())
93 , pModule(NULL)
94 , bRegistered(sal_False)
98 ~SfxInterface_Impl()
100 for (SfxObjectUIArr_Impl::const_iterator it = aObjectBars.begin(); it != aObjectBars.end(); ++it)
101 delete *it;
103 for (SfxObjectUIArr_Impl::const_iterator it = aChildWindows.begin(); it != aChildWindows.end(); ++it)
104 delete *it;
108 static SfxObjectUI_Impl* CreateObjectBarUI_Impl( sal_uInt16 nPos, const ResId& rResId, sal_uInt32 nFeature, const String *pStr );
110 //====================================================================
112 //====================================================================
113 // constuctor, registeres a new unit
115 SfxInterface::SfxInterface( const char *pClassName,
116 const ResId& rNameResId,
117 SfxInterfaceId nId,
118 const SfxInterface* pParent,
119 SfxSlot &rSlotMap, sal_uInt16 nSlotCount ):
120 pName(pClassName),
121 pGenoType(pParent),
122 nClassId(nId),
123 aNameResId(rNameResId.GetId(),*rNameResId.GetResMgr()),
124 pImpData(0)
126 pImpData = new SfxInterface_Impl;
127 SetSlotMap( rSlotMap, nSlotCount );
130 void SfxInterface::Register( SfxModule* pMod )
132 pImpData->bRegistered = sal_True;
133 pImpData->pModule = pMod;
134 if ( pMod )
135 pMod->GetSlotPool()->RegisterInterface(*this);
136 else
137 SFX_APP()->GetAppSlotPool_Impl().RegisterInterface(*this);
140 void SfxInterface::SetSlotMap( SfxSlot& rSlotMap, sal_uInt16 nSlotCount )
142 pSlots = &rSlotMap;
143 nCount = nSlotCount;
144 SfxSlot* pIter = pSlots;
145 if ( 1 == nCount && !pIter->pNextSlot )
146 pIter->pNextSlot = pIter;
148 if ( !pIter->pNextSlot )
150 // sort the SfxSlots by id
151 qsort( pSlots, nCount, sizeof(SfxSlot), SfxCompareSlots_Impl );
153 // link masters and slaves
154 sal_uInt16 nIter = 1;
155 for ( pIter = pSlots; nIter <= nCount; ++pIter, ++nIter )
158 DBG_ASSERT( nIter == nCount ||
159 pIter->GetSlotId() != (pIter+1)->GetSlotId(),
160 "doppelte SID" );
162 // every master refers to his first slave (ENUM),
163 // all slaves refer to their master.
164 // Slaves refer in a circle to the other slaves with the same master
165 if ( pIter->GetKind() == SFX_KIND_ENUM )
167 pIter->pLinkedSlot = GetSlot( pIter->nMasterSlotId );
168 DBG_ASSERT( pIter->pLinkedSlot, "slave without master" );
169 if ( !pIter->pLinkedSlot->pLinkedSlot )
170 ( (SfxSlot*) pIter->pLinkedSlot)->pLinkedSlot = pIter;
172 if ( 0 == pIter->GetNextSlot() )
174 SfxSlot *pLastSlot = pIter;
175 for ( sal_uInt16 n = nIter; n < Count(); ++n )
177 SfxSlot *pCurSlot = (pSlots+n);
178 if ( pCurSlot->nMasterSlotId == pIter->nMasterSlotId )
180 pLastSlot->pNextSlot = pCurSlot;
181 pLastSlot = pCurSlot;
184 pLastSlot->pNextSlot = pIter;
187 else if ( 0 == pIter->GetNextSlot() )
189 // Slots refering in circle to the next with the same
190 // Status method.
191 SfxSlot *pLastSlot = pIter;
192 for ( sal_uInt16 n = nIter; n < Count(); ++n )
194 SfxSlot *pCurSlot = (pSlots+n);
195 if ( pCurSlot->GetStateFnc() == pIter->GetStateFnc() )
197 pLastSlot->pNextSlot = pCurSlot;
198 pLastSlot = pCurSlot;
201 pLastSlot->pNextSlot = pIter;
205 #ifdef DBG_UTIL
206 else
208 sal_uInt16 nIter = 1;
209 for ( SfxSlot *pNext = pIter+1; nIter < nCount; ++pNext, ++nIter )
212 if ( pNext->GetSlotId() <= pIter->GetSlotId() )
213 OSL_FAIL("Wrong order!");
215 if ( pIter->GetKind() == SFX_KIND_ENUM )
217 const SfxSlot *pMasterSlot = GetSlot(pIter->nMasterSlotId);
218 const SfxSlot *pFirstSlave = pMasterSlot->pLinkedSlot;
219 const SfxSlot *pSlave = pFirstSlave;
222 if ( pSlave->pLinkedSlot != pMasterSlot )
224 OStringBuffer aStr(RTL_CONSTASCII_STRINGPARAM(
225 "Wrong Master/Slave- link: "));
226 aStr.append(static_cast<sal_Int32>(
227 pMasterSlot->GetSlotId()));
228 aStr.append(RTL_CONSTASCII_STRINGPARAM(" , "));
229 aStr.append(static_cast<sal_Int32>(
230 pSlave->GetSlotId()));
231 OSL_FAIL(aStr.getStr());
234 if ( pSlave->nMasterSlotId != pMasterSlot->GetSlotId() )
236 OStringBuffer aStr(RTL_CONSTASCII_STRINGPARAM(
237 "Wrong Master/Slave-Ids: "));
238 aStr.append(static_cast<sal_Int32>(
239 pMasterSlot->GetSlotId()));
240 aStr.append(RTL_CONSTASCII_STRINGPARAM(" , "));
241 aStr.append(static_cast<sal_Int32>(
242 pSlave->GetSlotId()));
243 OSL_FAIL(aStr.getStr());
246 pSlave = pSlave->pNextSlot;
248 while ( pSlave != pFirstSlave );
250 else
252 if ( pIter->pLinkedSlot )
254 if ( pIter->pLinkedSlot->GetKind() != SFX_KIND_ENUM )
256 OStringBuffer aStr(RTL_CONSTASCII_STRINGPARAM(
257 "Slave is no enum: "));
258 aStr.append(static_cast<sal_Int32>(pIter->GetSlotId()));
259 aStr.append(RTL_CONSTASCII_STRINGPARAM(" , "));
260 aStr.append(static_cast<sal_Int32>(
261 pIter->pLinkedSlot->GetSlotId()));
262 OSL_FAIL(aStr.getStr());
266 const SfxSlot *pCurSlot = pIter;
269 pCurSlot = pCurSlot->pNextSlot;
270 if ( pCurSlot->GetStateFnc() != pIter->GetStateFnc() )
272 OStringBuffer aStr(RTL_CONSTASCII_STRINGPARAM(
273 "Linked Slots with different State Methods : "));
274 aStr.append(static_cast<sal_Int32>(
275 pCurSlot->GetSlotId()));
276 aStr.append(RTL_CONSTASCII_STRINGPARAM(" , "));
277 aStr.append(static_cast<sal_Int32>(pIter->GetSlotId()));
278 OSL_FAIL(aStr.getStr());
281 while ( pCurSlot != pIter );
284 pIter = pNext;
287 #endif
290 //--------------------------------------------------------------------
292 SfxInterface::~SfxInterface()
294 SfxModule *pMod = pImpData->pModule;
295 sal_Bool bRegistered = pImpData->bRegistered;
296 delete pImpData;
297 DBG_ASSERT( bRegistered, "Interface not registered!" );
298 if ( bRegistered )
300 if ( pMod )
301 pMod->GetSlotPool()->ReleaseInterface(*this);
302 else
303 SFX_APP()->GetAppSlotPool_Impl().ReleaseInterface(*this);
307 //--------------------------------------------------------------------
309 // searches for the specified func
311 const SfxSlot* SfxInterface::GetSlot( sal_uInt16 nFuncId ) const
313 DBG_CHKTHIS(SfxInterface, 0);
314 DBG_ASSERT( this && pSlots && nCount, "" );
316 // find the id using binary search
317 void* p = bsearch( &nFuncId, pSlots, nCount, sizeof(SfxSlot),
318 SfxCompareSlots_Impl );
319 if ( !p && pGenoType )
320 return pGenoType->GetSlot( nFuncId );
322 return p ? (const SfxSlot*)p : 0;
325 const SfxSlot* SfxInterface::GetSlot( const String& rCommand ) const
327 static const char UNO_COMMAND[] = ".uno:";
329 String aCommand( rCommand );
330 if ( aCommand.SearchAscii( UNO_COMMAND ) == 0 )
331 aCommand.Erase( 0, sizeof( UNO_COMMAND )-1 );
333 for ( sal_uInt16 n=0; n<nCount; n++ )
335 if ( (pSlots+n)->pUnoName &&
336 aCommand.CompareIgnoreCaseToAscii( (pSlots+n)->GetUnoName() ) == COMPARE_EQUAL )
337 return pSlots+n;
340 return pGenoType ? pGenoType->GetSlot( aCommand ) : NULL;
343 //--------------------------------------------------------------------
345 const SfxSlot* SfxInterface::GetRealSlot( const SfxSlot *pSlot ) const
347 DBG_CHKTHIS(SfxInterface, 0);
348 DBG_ASSERT( this && pSlots && nCount, "" );
350 if ( !ContainsSlot_Impl(pSlot) )
352 if(pGenoType)
353 return pGenoType->GetRealSlot(pSlot);
354 OSL_FAIL("unknown Slot");
355 return 0;
358 return pSlot->pLinkedSlot;
361 //--------------------------------------------------------------------
363 const SfxSlot* SfxInterface::GetRealSlot( sal_uInt16 nSlotId ) const
365 DBG_CHKTHIS(SfxInterface, 0);
366 DBG_ASSERT( this && pSlots && nCount, "" );
368 const SfxSlot *pSlot = GetSlot(nSlotId);
369 if ( !pSlot )
371 if(pGenoType)
372 return pGenoType->GetRealSlot(nSlotId);
373 OSL_FAIL("unkonown Slot");
374 return 0;
377 return pSlot->pLinkedSlot;
380 //--------------------------------------------------------------------
382 void SfxInterface::RegisterPopupMenu( const ResId& rResId )
384 DBG_CHKTHIS(SfxInterface, 0);
385 pImpData->aPopupRes = rResId;
388 //--------------------------------------------------------------------
390 void SfxInterface::RegisterObjectBar( sal_uInt16 nPos, const ResId& rResId,
391 const String *pStr )
393 RegisterObjectBar( nPos, rResId, 0UL, pStr );
397 void SfxInterface::RegisterObjectBar( sal_uInt16 nPos, const ResId& rResId, sal_uInt32 nFeature, const String *pStr )
399 SfxObjectUI_Impl* pUI = CreateObjectBarUI_Impl( nPos, rResId, nFeature, pStr );
400 if ( pUI )
401 pImpData->aObjectBars.push_back(pUI);
404 SfxObjectUI_Impl* CreateObjectBarUI_Impl( sal_uInt16 nPos, const ResId& rResId, sal_uInt32 nFeature, const String *pStr )
406 if ((nPos & SFX_VISIBILITY_MASK) == 0)
407 nPos |= SFX_VISIBILITY_STANDARD;
409 SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(nPos, rResId, sal_True, nFeature);
411 if (pStr == 0)
413 ResId aResId(rResId);
414 aResId.SetRT(RSC_STRING);
415 aResId.SetResMgr(rResId.GetResMgr());
416 if( ! aResId.GetResMgr() )
417 aResId.SetResMgr( SfxApplication::GetOrCreate()->GetOffResManager_Impl() );
418 if ( !aResId.GetResMgr() || !aResId.GetResMgr()->IsAvailable(aResId) )
419 pUI->pName = new String ("NoName");
420 else
421 pUI->pName = new String(aResId.toString());
423 else
424 pUI->pName = new String(*pStr);
426 return pUI;
429 const ResId& SfxInterface::GetObjectBarResId( sal_uInt16 nNo ) const
431 sal_Bool bGenoType = (pGenoType != 0 && !pGenoType->HasName());
432 if ( bGenoType )
434 // Are there toolbars in the super class?
435 sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
436 if ( nNo < nBaseCount )
437 // The Super class comes first
438 return pGenoType->GetObjectBarResId( nNo );
439 else
440 nNo = nNo - nBaseCount;
443 #ifdef DBG_UTIL
444 sal_uInt16 nObjBarCount = pImpData->aObjectBars.size();
445 DBG_ASSERT( nNo<nObjBarCount,"Objectbar is unknown!" );
446 #endif
447 return pImpData->aObjectBars[nNo]->aResId;
450 //--------------------------------------------------------------------
453 sal_uInt16 SfxInterface::GetObjectBarPos( sal_uInt16 nNo ) const
455 sal_Bool bGenoType = (pGenoType != 0 && !pGenoType->HasName());
456 if ( bGenoType )
458 // Are there toolbars in the super class?
459 sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
460 if ( nNo < nBaseCount )
461 // The Super class comes first
462 return pGenoType->GetObjectBarPos( nNo );
463 else
464 nNo = nNo - nBaseCount;
467 #ifdef DBG_UTIL
468 sal_uInt16 nObjBarCount = pImpData->aObjectBars.size();
469 DBG_ASSERT( nNo<nObjBarCount,"Objectbar is unknown!" );
470 #endif
471 return pImpData->aObjectBars[nNo]->nPos;
474 //--------------------------------------------------------------------
477 sal_uInt16 SfxInterface::GetObjectBarCount() const
479 if (pGenoType && ! pGenoType->HasName())
480 return pImpData->aObjectBars.size() + pGenoType->GetObjectBarCount();
481 else
482 return pImpData->aObjectBars.size();
485 //--------------------------------------------------------------------
486 void SfxInterface::RegisterChildWindow(sal_uInt16 nId, sal_Bool bContext, const String* pChildWinName)
488 RegisterChildWindow( nId, bContext, 0UL, pChildWinName );
491 void SfxInterface::RegisterChildWindow(sal_uInt16 nId, sal_Bool bContext, sal_uInt32 nFeature, const String*)
493 SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(0, ResId(nId, *SfxApplication::GetOrCreate()->GetOffResManager_Impl()), sal_True, nFeature);
494 pUI->bContext = bContext;
495 pImpData->aChildWindows.push_back(pUI);
498 void SfxInterface::RegisterStatusBar(const ResId& rResId)
500 pImpData->aStatBarRes = rResId;
504 sal_uInt32 SfxInterface::GetChildWindowId (sal_uInt16 nNo) const
506 if ( pGenoType )
508 // Are there ChildWindows in der Superklasse?
509 sal_uInt16 nBaseCount = pGenoType->GetChildWindowCount();
510 if ( nNo < nBaseCount )
511 // The Super class comes first
512 return pGenoType->GetChildWindowId( nNo );
513 else
514 nNo = nNo - nBaseCount;
517 #ifdef DBG_UTIL
518 sal_uInt16 nCWCount = pImpData->aChildWindows.size();
519 DBG_ASSERT( nNo<nCWCount,"ChildWindow is unknown!" );
520 #endif
521 sal_uInt32 nRet = pImpData->aChildWindows[nNo]->aResId.GetId();
522 if ( pImpData->aChildWindows[nNo]->bContext )
523 nRet += sal_uInt32( nClassId ) << 16;
524 return nRet;
527 sal_uInt32 SfxInterface::GetChildWindowFeature (sal_uInt16 nNo) const
529 if ( pGenoType )
531 // Are there ChildWindows in der Superklasse?
532 sal_uInt16 nBaseCount = pGenoType->GetChildWindowCount();
533 if ( nNo < nBaseCount )
534 // The Super class comes first
535 return pGenoType->GetChildWindowFeature( nNo );
536 else
537 nNo = nNo - nBaseCount;
540 #ifdef DBG_UTIL
541 sal_uInt16 nCWCount = pImpData->aChildWindows.size();
542 DBG_ASSERT( nNo<nCWCount,"ChildWindow is unknown!" );
543 #endif
544 return pImpData->aChildWindows[nNo]->nFeature;
547 //--------------------------------------------------------------------
550 sal_uInt16 SfxInterface::GetChildWindowCount() const
552 if (pGenoType)
553 return pImpData->aChildWindows.size() + pGenoType->GetChildWindowCount();
554 else
555 return pImpData->aChildWindows.size();
559 const ResId& SfxInterface::GetPopupMenuResId() const
561 return pImpData->aPopupRes;
565 const ResId& SfxInterface::GetStatusBarResId() const
567 if (pImpData->aStatBarRes.GetId() == 0 && pGenoType)
568 return pGenoType->GetStatusBarResId();
569 else
570 return pImpData->aStatBarRes;
575 const String* SfxInterface::GetObjectBarName ( sal_uInt16 nNo ) const
577 sal_Bool bGenoType = (pGenoType != 0 && !pGenoType->HasName());
578 if ( bGenoType )
580 // Are there toolbars in the super class?
581 sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
582 if ( nNo < nBaseCount )
583 // The Super class comes first
584 return pGenoType->GetObjectBarName( nNo );
585 else
586 nNo = nNo - nBaseCount;
589 #ifdef DBG_UTIL
590 sal_uInt16 nObjBarCount = pImpData->aObjectBars.size();
591 DBG_ASSERT( nNo<nObjBarCount,"Objectbar is unknown!" );
592 #endif
593 return pImpData->aObjectBars[nNo]->pName;
596 sal_uInt32 SfxInterface::GetObjectBarFeature ( sal_uInt16 nNo ) const
598 sal_Bool bGenoType = (pGenoType != 0 && !pGenoType->HasName());
599 if ( bGenoType )
601 // Are there toolbars in the super class?
602 sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
603 if ( nNo < nBaseCount )
604 // The Super class comes first
605 return pGenoType->GetObjectBarFeature( nNo );
606 else
607 nNo = nNo - nBaseCount;
610 #ifdef DBG_UTIL
611 sal_uInt16 nObjBarCount = pImpData->aObjectBars.size();
612 DBG_ASSERT( nNo<nObjBarCount,"Objectbar is unknown!" );
613 #endif
614 return pImpData->aObjectBars[nNo]->nFeature;
617 sal_Bool SfxInterface::IsObjectBarVisible(sal_uInt16 nNo) const
619 sal_Bool bGenoType = (pGenoType != 0 && !pGenoType->HasName());
620 if ( bGenoType )
622 // Are there toolbars in the super class?
623 sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
624 if ( nNo < nBaseCount )
625 // The Super class comes first
626 return pGenoType->IsObjectBarVisible( nNo );
627 else
628 nNo = nNo - nBaseCount;
631 #ifdef DBG_UTIL
632 sal_uInt16 nObjBarCount = pImpData->aObjectBars.size();
633 DBG_ASSERT( nNo<nObjBarCount,"Objectbar is unknown!" );
634 #endif
635 return pImpData->aObjectBars[nNo]->bVisible;
638 const SfxInterface* SfxInterface::GetRealInterfaceForSlot( const SfxSlot *pRealSlot ) const
640 DBG_ASSERT( pImpData->bRegistered, "Interface not registered!" );
641 const SfxInterface* pInterface = this;
643 // The slot could also originate from the interface of a shell base class.
646 const SfxSlot *pLastSlot = (*pInterface)[pInterface->Count()-1];
647 const SfxSlot *pFirstSlot = (*pInterface)[0];
649 // Is pInterface the Owner of pRealSlot ?
650 if ( pFirstSlot <= pRealSlot && pRealSlot <= pLastSlot )
651 break;
653 // Otherwise try the Interface of Super class
654 pInterface = pInterface->pGenoType;
656 while ( pInterface );
658 return pInterface;
661 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */