bump product version to 5.0.4.1
[LibreOffice.git] / sfx2 / source / control / objface.cxx
blobac67cbb0c95473ed55bf8ab20440edcc3b532b65
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 .
20 #include <assert.h>
21 #include <stdlib.h>
23 #include <sal/log.hxx>
25 #include <tools/rcid.h>
26 #include <tools/stream.hxx>
27 #include "tools/resmgr.hxx"
29 #include <sfx2/module.hxx>
30 #include <sfx2/objface.hxx>
31 #include <sfx2/msg.hxx>
32 #include <sfx2/app.hxx>
33 #include <sfx2/msgpool.hxx>
34 #include <sfx2/sfxresid.hxx>
35 #include <sfx2/objsh.hxx>
36 #include <rtl/strbuf.hxx>
38 extern "C" {
40 static int SAL_CALL
41 SfxCompareSlots_qsort( const void* pSmaller, const void* pBigger )
43 return ( (int) static_cast<SfxSlot const *>(pSmaller)->GetSlotId() ) -
44 ( (int) static_cast<SfxSlot const *>(pBigger)->GetSlotId() );
47 static int SAL_CALL
48 SfxCompareSlots_bsearch( const void* pSmaller, const void* pBigger )
50 return ( (int) *static_cast<sal_uInt16 const *>(pSmaller) ) -
51 ( (int) static_cast<SfxSlot const *>(pBigger)->GetSlotId() );
56 struct SfxObjectUI_Impl
58 sal_uInt16 nPos;
59 sal_uInt32 nResId;
60 bool bVisible;
61 bool bContext;
62 sal_uInt32 nFeature;
64 SfxObjectUI_Impl(sal_uInt16 n, sal_uInt32 nId, bool bVis, sal_uInt32 nFeat) :
65 nPos(n),
66 nResId(nId),
67 bVisible(bVis),
68 bContext(false),
69 nFeature(nFeat)
74 typedef std::vector<SfxObjectUI_Impl*> SfxObjectUIArr_Impl;
76 struct SfxInterface_Impl
78 SfxObjectUIArr_Impl aObjectBars; // registered ObjectBars
79 SfxObjectUIArr_Impl aChildWindows; // registered ChildWindows
80 ResId aPopupRes; // registered PopupMenu
81 ResId aStatBarRes; // registered StatusBar
82 SfxModule* pModule;
83 bool bRegistered;
85 SfxInterface_Impl() :
86 aPopupRes(nullptr, *SfxApplication::GetSfxResManager()),
87 aStatBarRes(nullptr, *SfxApplication::GetSfxResManager())
88 , pModule(NULL)
89 , bRegistered(false)
93 ~SfxInterface_Impl()
95 for (SfxObjectUIArr_Impl::const_iterator it = aObjectBars.begin(); it != aObjectBars.end(); ++it)
96 delete *it;
98 for (SfxObjectUIArr_Impl::const_iterator it = aChildWindows.begin(); it != aChildWindows.end(); ++it)
99 delete *it;
103 static SfxObjectUI_Impl* CreateObjectBarUI_Impl(sal_uInt16 nPos, sal_uInt32 nResId, sal_uInt32 nFeature);
105 // constuctor, registeres a new unit
106 SfxInterface::SfxInterface( const char *pClassName,
107 bool bUsableSuperClass,
108 SfxInterfaceId nId,
109 const SfxInterface* pParent,
110 SfxSlot &rSlotMap, sal_uInt16 nSlotCount ):
111 pName(pClassName),
112 pGenoType(pParent),
113 nClassId(nId),
114 bSuperClass(bUsableSuperClass),
115 pImpData(0)
117 pImpData = new SfxInterface_Impl;
118 SetSlotMap( rSlotMap, nSlotCount );
121 void SfxInterface::Register( SfxModule* pMod )
123 pImpData->bRegistered = true;
124 pImpData->pModule = pMod;
125 if ( pMod )
126 pMod->GetSlotPool()->RegisterInterface(*this);
127 else
128 SfxGetpApp()->GetAppSlotPool_Impl().RegisterInterface(*this);
131 void SfxInterface::SetSlotMap( SfxSlot& rSlotMap, sal_uInt16 nSlotCount )
133 pSlots = &rSlotMap;
134 nCount = nSlotCount;
135 SfxSlot* pIter = pSlots;
136 if ( 1 == nCount && !pIter->pNextSlot )
137 pIter->pNextSlot = pIter;
139 if ( !pIter->pNextSlot )
141 // sort the SfxSlots by id
142 qsort( pSlots, nCount, sizeof(SfxSlot), SfxCompareSlots_qsort );
144 // link masters and slaves
145 sal_uInt16 nIter = 1;
146 for ( pIter = pSlots; nIter <= nCount; ++pIter, ++nIter )
149 assert( nIter == nCount ||
150 pIter->GetSlotId() != (pIter+1)->GetSlotId() );
152 // every master refers to his first slave (ENUM),
153 // all slaves refer to their master.
154 // Slaves refer in a circle to the other slaves with the same master
155 if ( pIter->GetKind() == SFX_KIND_ENUM )
157 pIter->pLinkedSlot = GetSlot( pIter->nMasterSlotId );
158 assert( pIter->pLinkedSlot );
159 if ( !pIter->pLinkedSlot->pLinkedSlot )
160 const_cast<SfxSlot*>(pIter->pLinkedSlot)->pLinkedSlot = pIter;
162 if ( 0 == pIter->GetNextSlot() )
164 SfxSlot *pLastSlot = pIter;
165 for ( sal_uInt16 n = nIter; n < Count(); ++n )
167 SfxSlot *pCurSlot = (pSlots+n);
168 if ( pCurSlot->nMasterSlotId == pIter->nMasterSlotId )
170 pLastSlot->pNextSlot = pCurSlot;
171 pLastSlot = pCurSlot;
174 pLastSlot->pNextSlot = pIter;
177 else if ( 0 == pIter->GetNextSlot() )
179 // Slots referring in circle to the next with the same
180 // Status method.
181 SfxSlot *pLastSlot = pIter;
182 for ( sal_uInt16 n = nIter; n < Count(); ++n )
184 SfxSlot *pCurSlot = (pSlots+n);
185 if ( pCurSlot->GetStateFnc() == pIter->GetStateFnc() )
187 pLastSlot->pNextSlot = pCurSlot;
188 pLastSlot = pCurSlot;
191 pLastSlot->pNextSlot = pIter;
195 #ifdef DBG_UTIL
196 else
198 sal_uInt16 nIter = 1;
199 for ( SfxSlot *pNext = pIter+1; nIter < nCount; ++pNext, ++nIter )
202 if ( pNext->GetSlotId() <= pIter->GetSlotId() )
203 SAL_WARN( "sfx.control", "Wrong order" );
205 if ( pIter->GetKind() == SFX_KIND_ENUM )
207 const SfxSlot *pMasterSlot = GetSlot(pIter->nMasterSlotId);
208 const SfxSlot *pFirstSlave = pMasterSlot->pLinkedSlot;
209 const SfxSlot *pSlave = pFirstSlave;
212 if ( pSlave->pLinkedSlot != pMasterSlot )
214 OStringBuffer aStr("Wrong Master/Slave- link: ");
215 aStr.append(static_cast<sal_Int32>(
216 pMasterSlot->GetSlotId()));
217 aStr.append(" , ");
218 aStr.append(static_cast<sal_Int32>(
219 pSlave->GetSlotId()));
220 SAL_WARN("sfx.control", aStr.getStr());
223 if ( pSlave->nMasterSlotId != pMasterSlot->GetSlotId() )
225 OStringBuffer aStr("Wrong Master/Slave-Ids: ");
226 aStr.append(static_cast<sal_Int32>(
227 pMasterSlot->GetSlotId()));
228 aStr.append(" , ");
229 aStr.append(static_cast<sal_Int32>(
230 pSlave->GetSlotId()));
231 SAL_WARN("sfx.control", aStr.getStr());
234 pSlave = pSlave->pNextSlot;
236 while ( pSlave != pFirstSlave );
238 else
240 if ( pIter->pLinkedSlot )
242 if ( pIter->pLinkedSlot->GetKind() != SFX_KIND_ENUM )
244 OStringBuffer aStr("Slave is no enum: ");
245 aStr.append(static_cast<sal_Int32>(pIter->GetSlotId()));
246 aStr.append(" , ");
247 aStr.append(static_cast<sal_Int32>(
248 pIter->pLinkedSlot->GetSlotId()));
249 SAL_WARN("sfx.control", aStr.getStr());
253 const SfxSlot *pCurSlot = pIter;
256 pCurSlot = pCurSlot->pNextSlot;
257 if ( pCurSlot->GetStateFnc() != pIter->GetStateFnc() )
259 OStringBuffer aStr("Linked Slots with different State Methods : ");
260 aStr.append(static_cast<sal_Int32>(
261 pCurSlot->GetSlotId()));
262 aStr.append(" , ");
263 aStr.append(static_cast<sal_Int32>(pIter->GetSlotId()));
264 SAL_WARN("sfx.control", aStr.getStr());
267 while ( pCurSlot != pIter );
270 pIter = pNext;
273 #endif
278 SfxInterface::~SfxInterface()
280 SfxModule *pMod = pImpData->pModule;
281 bool bRegistered = pImpData->bRegistered;
282 delete pImpData;
283 assert( bRegistered );
284 if ( bRegistered )
286 if ( pMod )
287 pMod->GetSlotPool()->ReleaseInterface(*this);
288 else
289 SfxGetpApp()->GetAppSlotPool_Impl().ReleaseInterface(*this);
295 // searches for the specified func
297 const SfxSlot* SfxInterface::GetSlot( sal_uInt16 nFuncId ) const
300 assert( pSlots );
301 assert( nCount );
303 // find the id using binary search
304 void* p = bsearch( &nFuncId, pSlots, nCount, sizeof(SfxSlot),
305 SfxCompareSlots_bsearch );
306 if ( !p && pGenoType )
307 return pGenoType->GetSlot( nFuncId );
309 return p ? static_cast<const SfxSlot*>(p) : 0;
312 const SfxSlot* SfxInterface::GetSlot( const OUString& rCommand ) const
314 static const char UNO_COMMAND[] = ".uno:";
316 OUString aCommand( rCommand );
317 if ( aCommand.startsWith( UNO_COMMAND ) )
318 aCommand = aCommand.copy( sizeof( UNO_COMMAND )-1 );
320 for ( sal_uInt16 n=0; n<nCount; n++ )
322 if ( (pSlots+n)->pUnoName &&
323 aCommand.compareToIgnoreAsciiCaseAscii( (pSlots+n)->GetUnoName() ) == 0 )
324 return pSlots+n;
327 return pGenoType ? pGenoType->GetSlot( aCommand ) : NULL;
332 const SfxSlot* SfxInterface::GetRealSlot( const SfxSlot *pSlot ) const
335 assert( pSlots );
336 assert( nCount );
338 if ( !ContainsSlot_Impl(pSlot) )
340 if(pGenoType)
341 return pGenoType->GetRealSlot(pSlot);
342 SAL_WARN( "sfx.control", "unknown Slot" );
343 return 0;
346 return pSlot->pLinkedSlot;
351 const SfxSlot* SfxInterface::GetRealSlot( sal_uInt16 nSlotId ) const
354 assert( pSlots );
355 assert( nCount );
357 const SfxSlot *pSlot = GetSlot(nSlotId);
358 if ( !pSlot )
360 if(pGenoType)
361 return pGenoType->GetRealSlot(nSlotId);
362 SAL_WARN( "sfx.control", "unknown Slot" );
363 return 0;
366 return pSlot->pLinkedSlot;
369 void SfxInterface::RegisterPopupMenu( const ResId& rResId )
372 pImpData->aPopupRes = rResId;
375 void SfxInterface::RegisterObjectBar(sal_uInt16 nPos, sal_uInt32 nResId)
377 RegisterObjectBar(nPos, nResId, 0UL);
380 void SfxInterface::RegisterObjectBar(sal_uInt16 nPos, sal_uInt32 nResId, sal_uInt32 nFeature)
382 SfxObjectUI_Impl* pUI = CreateObjectBarUI_Impl(nPos, nResId, nFeature);
383 if ( pUI )
384 pImpData->aObjectBars.push_back(pUI);
387 SfxObjectUI_Impl* CreateObjectBarUI_Impl(sal_uInt16 nPos, sal_uInt32 nResId, sal_uInt32 nFeature)
389 if ((nPos & SFX_VISIBILITY_MASK) == 0)
390 nPos |= SFX_VISIBILITY_STANDARD;
392 return new SfxObjectUI_Impl(nPos, nResId, true, nFeature);
395 sal_uInt32 SfxInterface::GetObjectBarId(sal_uInt16 nNo) const
397 bool bGenoType = (pGenoType != 0 && pGenoType->UseAsSuperClass());
398 if ( bGenoType )
400 // Are there toolbars in the super class?
401 sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
402 if ( nNo < nBaseCount )
403 // The Super class comes first
404 return pGenoType->GetObjectBarId(nNo);
405 else
406 nNo = nNo - nBaseCount;
409 assert( nNo<pImpData->aObjectBars.size() );
411 return pImpData->aObjectBars[nNo]->nResId;
414 sal_uInt16 SfxInterface::GetObjectBarPos( sal_uInt16 nNo ) const
416 bool bGenoType = (pGenoType != 0 && pGenoType->UseAsSuperClass());
417 if ( bGenoType )
419 // Are there toolbars in the super class?
420 sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
421 if ( nNo < nBaseCount )
422 // The Super class comes first
423 return pGenoType->GetObjectBarPos( nNo );
424 else
425 nNo = nNo - nBaseCount;
428 assert( nNo<pImpData->aObjectBars.size() );
430 return pImpData->aObjectBars[nNo]->nPos;
433 sal_uInt16 SfxInterface::GetObjectBarCount() const
435 if (pGenoType && pGenoType->UseAsSuperClass())
436 return pImpData->aObjectBars.size() + pGenoType->GetObjectBarCount();
437 else
438 return pImpData->aObjectBars.size();
441 void SfxInterface::RegisterChildWindow(sal_uInt16 nId, bool bContext)
443 RegisterChildWindow(nId, bContext, 0UL);
446 void SfxInterface::RegisterChildWindow(sal_uInt16 nId, bool bContext, sal_uInt32 nFeature)
448 SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(0, nId, true, nFeature);
449 pUI->bContext = bContext;
450 pImpData->aChildWindows.push_back(pUI);
453 void SfxInterface::RegisterStatusBar(const ResId& rResId)
455 pImpData->aStatBarRes = rResId;
458 sal_uInt32 SfxInterface::GetChildWindowId (sal_uInt16 nNo) const
460 if ( pGenoType )
462 // Are there ChildWindows in der Superklasse?
463 sal_uInt16 nBaseCount = pGenoType->GetChildWindowCount();
464 if ( nNo < nBaseCount )
465 // The Super class comes first
466 return pGenoType->GetChildWindowId( nNo );
467 else
468 nNo = nNo - nBaseCount;
471 assert( nNo<pImpData->aChildWindows.size() );
473 sal_uInt32 nRet = pImpData->aChildWindows[nNo]->nResId;
474 if ( pImpData->aChildWindows[nNo]->bContext )
475 nRet += sal_uInt32( nClassId ) << 16;
476 return nRet;
479 sal_uInt32 SfxInterface::GetChildWindowFeature (sal_uInt16 nNo) const
481 if ( pGenoType )
483 // Are there ChildWindows in der Superklasse?
484 sal_uInt16 nBaseCount = pGenoType->GetChildWindowCount();
485 if ( nNo < nBaseCount )
486 // The Super class comes first
487 return pGenoType->GetChildWindowFeature( nNo );
488 else
489 nNo = nNo - nBaseCount;
492 assert( nNo<pImpData->aChildWindows.size() );
494 return pImpData->aChildWindows[nNo]->nFeature;
500 sal_uInt16 SfxInterface::GetChildWindowCount() const
502 if (pGenoType)
503 return pImpData->aChildWindows.size() + pGenoType->GetChildWindowCount();
504 else
505 return pImpData->aChildWindows.size();
508 const ResId& SfxInterface::GetPopupMenuResId() const
510 return pImpData->aPopupRes;
513 const ResId& SfxInterface::GetStatusBarResId() const
515 if (pImpData->aStatBarRes.GetId() == 0 && pGenoType)
516 return pGenoType->GetStatusBarResId();
517 else
518 return pImpData->aStatBarRes;
521 sal_uInt32 SfxInterface::GetObjectBarFeature ( sal_uInt16 nNo ) const
523 bool bGenoType = (pGenoType != 0 && pGenoType->UseAsSuperClass());
524 if ( bGenoType )
526 // Are there toolbars in the super class?
527 sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
528 if ( nNo < nBaseCount )
529 // The Super class comes first
530 return pGenoType->GetObjectBarFeature( nNo );
531 else
532 nNo = nNo - nBaseCount;
535 assert( nNo<pImpData->aObjectBars.size() );
537 return pImpData->aObjectBars[nNo]->nFeature;
540 bool SfxInterface::IsObjectBarVisible(sal_uInt16 nNo) const
542 bool bGenoType = (pGenoType != 0 && pGenoType->UseAsSuperClass());
543 if ( bGenoType )
545 // Are there toolbars in the super class?
546 sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
547 if ( nNo < nBaseCount )
548 // The Super class comes first
549 return pGenoType->IsObjectBarVisible( nNo );
550 else
551 nNo = nNo - nBaseCount;
554 assert( nNo<pImpData->aObjectBars.size() );
556 return pImpData->aObjectBars[nNo]->bVisible;
559 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */