Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <classes/fwktabwindow.hxx>
21 : #include <services.h>
22 : #include <properties.h>
23 :
24 : #include <com/sun/star/awt/PosSize.hpp>
25 : #include <com/sun/star/awt/XSimpleTabController.hpp>
26 : #include <com/sun/star/awt/XWindow.hpp>
27 : #include <com/sun/star/beans/PropertyAttribute.hpp>
28 : #include <com/sun/star/beans/XPropertySet.hpp>
29 :
30 : #include <cppuhelper/basemutex.hxx>
31 : #include <cppuhelper/supportsservice.hxx>
32 : #include <cppuhelper/weak.hxx>
33 : #include <toolkit/helper/vclunohelper.hxx>
34 : #include <rtl/ref.hxx>
35 : #include <rtl/ustrbuf.hxx>
36 : #include <vcl/svapp.hxx>
37 : #include <vcl/window.hxx>
38 : #include <classes/propertysethelper.hxx>
39 : #include <macros/generic.hxx>
40 : #include <macros/xinterface.hxx>
41 : #include <macros/xtypeprovider.hxx>
42 : #include <macros/xserviceinfo.hxx>
43 : #include <general.h>
44 : #include <stdtypes.h>
45 :
46 : using namespace framework;
47 :
48 : namespace {
49 :
50 0 : struct TTabPageInfo
51 : {
52 : public:
53 :
54 0 : TTabPageInfo()
55 : : m_nIndex ( -1 )
56 : , m_bCreated (false)
57 : , m_pPage ( NULL )
58 0 : , m_lProperties ( )
59 0 : {}
60 :
61 0 : TTabPageInfo(::sal_Int32 nID)
62 : : m_nIndex ( nID )
63 : , m_bCreated (false)
64 : , m_pPage ( NULL )
65 0 : , m_lProperties ( )
66 0 : {}
67 :
68 : public:
69 :
70 : ::sal_Int32 m_nIndex;
71 : bool m_bCreated;
72 : FwkTabPage* m_pPage;
73 : css::uno::Sequence< css::beans::NamedValue > m_lProperties;
74 : };
75 :
76 : typedef ::boost::unordered_map< ::sal_Int32 ,
77 : TTabPageInfo ,
78 : Int32HashCode ,
79 : ::std::equal_to< ::sal_Int32 > > TTabPageInfoHash;
80 :
81 : /*-************************************************************************************************************
82 : @short implements a helper service providing a dockable tab control window
83 : *//*-*************************************************************************************************************/
84 :
85 : class TabWindowService : public css::lang::XTypeProvider
86 : , public css::lang::XServiceInfo
87 : , public css::awt::XSimpleTabController
88 : , public css::lang::XComponent
89 : , public TransactionBase
90 : , private cppu::BaseMutex
91 : , public PropertySetHelper
92 : , public ::cppu::OWeakObject
93 : {
94 : public:
95 : TabWindowService();
96 : virtual ~TabWindowService();
97 :
98 : /// Initialization function after having acquire()'d.
99 : void initProperties();
100 :
101 : FWK_DECLARE_XINTERFACE
102 : FWK_DECLARE_XTYPEPROVIDER
103 :
104 0 : virtual OUString SAL_CALL getImplementationName()
105 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
106 : {
107 0 : return OUString("com.sun.star.comp.framework.TabWindowService");
108 : }
109 :
110 0 : virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
111 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
112 : {
113 0 : return cppu::supportsService(this, ServiceName);
114 : }
115 :
116 0 : virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
117 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
118 : {
119 0 : css::uno::Sequence< OUString > aSeq(1);
120 0 : aSeq[0] = OUString("com.sun.star.ui.dialogs.TabContainerWindow");
121 0 : return aSeq;
122 : }
123 :
124 : // XSimpleTabController
125 :
126 : virtual sal_Int32 SAL_CALL insertTab() throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
127 : virtual void SAL_CALL removeTab( sal_Int32 nID ) throw ( css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
128 : virtual void SAL_CALL setTabProps( sal_Int32 nID, const css::uno::Sequence< css::beans::NamedValue >& aProperties ) throw ( css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
129 : virtual css::uno::Sequence< css::beans::NamedValue > SAL_CALL getTabProps( sal_Int32 nID ) throw ( css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
130 : virtual void SAL_CALL activateTab( sal_Int32 nID ) throw ( css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
131 : virtual sal_Int32 SAL_CALL getActiveTabID() throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
132 : virtual void SAL_CALL addTabListener( const css::uno::Reference< css::awt::XTabListener >& Listener ) throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
133 : virtual void SAL_CALL removeTabListener( const css::uno::Reference< css::awt::XTabListener >& Listener ) throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
134 :
135 : // XComponent
136 :
137 : virtual void SAL_CALL dispose() throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
138 : virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
139 : virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw ( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
140 :
141 : private:
142 :
143 : void impl_initializePropInfo();
144 : virtual void SAL_CALL impl_setPropertyValue(const OUString& sProperty,
145 : sal_Int32 nHandle ,
146 : const css::uno::Any& aValue ) SAL_OVERRIDE;
147 : virtual css::uno::Any SAL_CALL impl_getPropertyValue(const OUString& sProperty,
148 : sal_Int32 nHandle ) SAL_OVERRIDE;
149 :
150 : DECL_DLLPRIVATE_LINK( EventListener, VclSimpleEvent * );
151 :
152 : void impl_checkTabIndex (::sal_Int32 nID) throw (css::lang::IndexOutOfBoundsException);
153 : TTabPageInfoHash::iterator impl_getTabPageInfo(::sal_Int32 nID) throw (css::lang::IndexOutOfBoundsException);
154 : FwkTabWindow* mem_TabWin ();
155 :
156 : private:
157 :
158 : /// the tab window as XWindow ( to hold window* alive !)
159 : css::uno::Reference< css::awt::XWindow > m_xTabWin;
160 :
161 : /// the VCL tab window
162 : FwkTabWindow* m_pTabWin;
163 :
164 : /// container of inserted tab pages
165 : TTabPageInfoHash m_lTabPageInfos;
166 :
167 : /// container of the added TabListener
168 : ::cppu::OMultiTypeInterfaceContainerHelper m_lListener;
169 :
170 : /// counter of the tabpage indexes
171 : ::sal_Int32 m_nPageIndexCounter;
172 :
173 : /// index of the current active page
174 : ::sal_Int32 m_nCurrentPageIndex;
175 :
176 : /// title of the tabcontrolled window
177 : OUString m_sTitle;
178 : };
179 :
180 0 : DEFINE_XINTERFACE_6 ( TabWindowService ,
181 : OWeakObject ,
182 : DIRECT_INTERFACE(css::lang::XTypeProvider ),
183 : DIRECT_INTERFACE(css::lang::XServiceInfo ),
184 : DIRECT_INTERFACE(css::lang::XComponent),
185 : DIRECT_INTERFACE(css::awt::XSimpleTabController),
186 : DIRECT_INTERFACE(css::beans::XPropertySet ),
187 : DIRECT_INTERFACE(css::beans::XPropertySetInfo )
188 : )
189 :
190 0 : DEFINE_XTYPEPROVIDER_6 ( TabWindowService ,
191 : css::lang::XTypeProvider ,
192 : css::lang::XServiceInfo ,
193 : css::lang::XComponent ,
194 : css::awt::XSimpleTabController ,
195 : css::beans::XPropertySet ,
196 : css::beans::XPropertySetInfo
197 : )
198 :
199 : // constructor
200 :
201 0 : TabWindowService::TabWindowService()
202 : : TransactionBase ( )
203 : , PropertySetHelper ( m_aMutex,
204 : &m_aTransactionManager ,
205 : false ) // sal_False => dont release shared mutex on calling us!
206 : , OWeakObject ( )
207 :
208 : // Init member
209 : , m_xTabWin ( )
210 : , m_pTabWin ( NULL )
211 : , m_lTabPageInfos ( )
212 : , m_lListener ( m_aMutex )
213 : , m_nPageIndexCounter ( 1 )
214 0 : , m_nCurrentPageIndex ( 0 )
215 : {
216 0 : }
217 :
218 0 : void TabWindowService::initProperties()
219 : {
220 0 : impl_initializePropInfo();
221 0 : m_aTransactionManager.setWorkingMode( E_WORK );
222 0 : }
223 :
224 : // destructor
225 :
226 0 : TabWindowService::~TabWindowService()
227 : {
228 0 : SolarMutexGuard g;
229 0 : if (m_pTabWin)
230 0 : m_pTabWin->RemoveEventListener( LINK( this, TabWindowService, EventListener ) );
231 0 : }
232 :
233 : // XSimpleTabController
234 :
235 0 : ::sal_Int32 SAL_CALL TabWindowService::insertTab()
236 : throw ( css::uno::RuntimeException, std::exception )
237 : {
238 0 : SolarMutexGuard g;
239 :
240 0 : ::sal_Int32 nID = m_nPageIndexCounter++;
241 0 : TTabPageInfo aInfo(nID);
242 :
243 0 : m_lTabPageInfos[nID] = aInfo;
244 :
245 0 : return nID;
246 : }
247 :
248 : // XSimpleTabController
249 :
250 0 : void SAL_CALL TabWindowService::removeTab(::sal_Int32 nID)
251 : throw (css::lang::IndexOutOfBoundsException,
252 : css::uno::RuntimeException, std::exception )
253 : {
254 0 : SolarMutexGuard g;
255 :
256 : // throws suitable IndexOutOfBoundsException .-)
257 0 : TTabPageInfoHash::iterator pIt = impl_getTabPageInfo (nID);
258 0 : m_lTabPageInfos.erase(pIt);
259 :
260 0 : FwkTabWindow* pTabWin = mem_TabWin ();
261 0 : if (pTabWin)
262 0 : pTabWin->RemovePage(nID);
263 0 : }
264 :
265 : // XSimpleTabController
266 :
267 0 : void SAL_CALL TabWindowService::setTabProps( ::sal_Int32 nID ,
268 : const css::uno::Sequence< css::beans::NamedValue >& lProperties)
269 : throw (css::lang::IndexOutOfBoundsException,
270 : css::uno::RuntimeException, std::exception )
271 : {
272 0 : SolarMutexGuard g;
273 :
274 : // throws suitable IndexOutOfBoundsException .-)
275 0 : TTabPageInfoHash::iterator pIt = impl_getTabPageInfo (nID);
276 0 : TTabPageInfo& rInfo = pIt->second;
277 0 : rInfo.m_lProperties = lProperties;
278 :
279 0 : if ( ! rInfo.m_bCreated)
280 : {
281 0 : FwkTabWindow* pTabWin = mem_TabWin ();
282 0 : if (pTabWin)
283 : {
284 0 : pTabWin->AddTabPage(rInfo.m_nIndex, rInfo.m_lProperties);
285 0 : rInfo.m_bCreated = true;
286 : }
287 0 : }
288 0 : }
289 :
290 : // XSimpleTabController
291 :
292 0 : css::uno::Sequence< css::beans::NamedValue > SAL_CALL TabWindowService::getTabProps(::sal_Int32 nID)
293 : throw (css::lang::IndexOutOfBoundsException,
294 : css::uno::RuntimeException, std::exception )
295 : {
296 0 : SolarMutexGuard g;
297 :
298 : // throws suitable IndexOutOfBoundsException .-)
299 0 : TTabPageInfoHash::const_iterator pIt = impl_getTabPageInfo (nID);
300 0 : const TTabPageInfo& rInfo = pIt->second;
301 :
302 0 : return rInfo.m_lProperties;
303 : }
304 :
305 : // XSimpleTabController
306 :
307 0 : void SAL_CALL TabWindowService::activateTab(::sal_Int32 nID)
308 : throw (css::lang::IndexOutOfBoundsException,
309 : css::uno::RuntimeException, std::exception )
310 : {
311 0 : SolarMutexGuard g;
312 :
313 : // throws suitable IndexOutOfBoundsException .-)
314 0 : impl_checkTabIndex (nID);
315 0 : m_nCurrentPageIndex = nID;
316 :
317 0 : FwkTabWindow* pTabWin = mem_TabWin ();
318 0 : if (pTabWin)
319 0 : pTabWin->ActivatePage(nID);
320 0 : }
321 :
322 : // XSimpleTabController
323 :
324 0 : ::sal_Int32 SAL_CALL TabWindowService::getActiveTabID()
325 : throw (css::uno::RuntimeException, std::exception)
326 : {
327 0 : SolarMutexGuard g;
328 0 : return m_nCurrentPageIndex;
329 : }
330 :
331 : // XSimpleTabController
332 :
333 0 : void SAL_CALL TabWindowService::addTabListener(const css::uno::Reference< css::awt::XTabListener >& xListener)
334 : throw (css::uno::RuntimeException, std::exception)
335 : {
336 0 : m_lListener.addInterface(::getCppuType((const css::uno::Reference< css::awt::XTabListener >*)NULL), xListener);
337 0 : }
338 :
339 : // XSimpleTabController
340 :
341 0 : void SAL_CALL TabWindowService::removeTabListener(const css::uno::Reference< css::awt::XTabListener >& xListener)
342 : throw (css::uno::RuntimeException, std::exception)
343 : {
344 0 : m_lListener.removeInterface(::getCppuType((const css::uno::Reference< css::awt::XTabListener >*)NULL), xListener);
345 0 : }
346 :
347 : // XComponent
348 :
349 0 : void SAL_CALL TabWindowService::dispose()
350 : throw (css::uno::RuntimeException, std::exception)
351 : {
352 0 : SolarMutexGuard g;
353 :
354 0 : css::uno::Reference< css::uno::XInterface > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
355 0 : css::lang::EventObject aEvent(xThis);
356 :
357 0 : m_lListener.disposeAndClear (aEvent);
358 :
359 0 : if (m_pTabWin)
360 0 : m_pTabWin->RemoveEventListener( LINK( this, TabWindowService, EventListener ) );
361 :
362 0 : m_pTabWin = NULL;
363 0 : m_xTabWin.clear();
364 0 : }
365 :
366 : // XComponent
367 :
368 0 : void SAL_CALL TabWindowService::addEventListener(const css::uno::Reference< css::lang::XEventListener >& xListener)
369 : throw (css::uno::RuntimeException, std::exception)
370 : {
371 0 : m_lListener.addInterface(::getCppuType((const css::uno::Reference< css::lang::XEventListener >*)NULL), xListener);
372 0 : }
373 :
374 : // XComponent
375 :
376 0 : void SAL_CALL TabWindowService::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener)
377 : throw (css::uno::RuntimeException, std::exception)
378 : {
379 0 : m_lListener.removeInterface(::getCppuType((const css::uno::Reference< css::lang::XEventListener >*)NULL), xListener);
380 0 : }
381 :
382 0 : void TabWindowService::impl_initializePropInfo()
383 : {
384 0 : impl_setPropertyChangeBroadcaster(static_cast< css::awt::XSimpleTabController* >(this));
385 :
386 : impl_addPropertyInfo(
387 : css::beans::Property(
388 : OUString("Window"),
389 : TABWINDOWSERVICE_PROPHANDLE_WINDOW,
390 0 : ::getCppuType((const css::uno::Reference< css::awt::XWindow >*)NULL),
391 0 : css::beans::PropertyAttribute::TRANSIENT));
392 0 : }
393 :
394 0 : void SAL_CALL TabWindowService::impl_setPropertyValue(const OUString& /*sProperty*/,
395 : sal_Int32 /*nHandle */,
396 : const css::uno::Any& /*aValue */)
397 :
398 : {
399 0 : }
400 :
401 0 : css::uno::Any SAL_CALL TabWindowService::impl_getPropertyValue(const OUString& /*sProperty*/,
402 : sal_Int32 nHandle )
403 : {
404 : /* There is no need to lock any mutex here. Because we share the
405 : solar mutex with our base class. And we said to our base class: "dont release it on calling us" .-)
406 : see ctor of PropertySetHelper for further information.
407 : */
408 0 : css::uno::Any aValue;
409 :
410 0 : switch (nHandle)
411 : {
412 : case TABWINDOWSERVICE_PROPHANDLE_WINDOW:
413 : {
414 0 : mem_TabWin (); // force "creation on demand" of m_xTabWin :-)
415 0 : aValue <<= m_xTabWin;
416 : }
417 0 : break;
418 : }
419 :
420 0 : return aValue;
421 : }
422 :
423 : // TabWindowService
424 :
425 0 : IMPL_LINK( TabWindowService, EventListener, VclSimpleEvent*, pEvent )
426 : {
427 :
428 0 : if ( !pEvent && !pEvent->ISA(VclWindowEvent))
429 0 : return 0;
430 :
431 0 : sal_uLong nEventId = pEvent->GetId();
432 0 : VclWindowEvent* pWinEvt = static_cast< VclWindowEvent* >(pEvent);
433 :
434 0 : css::uno::Reference< css::uno::XInterface > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
435 0 : css::lang::EventObject aEvent( xThis );
436 :
437 0 : if (nEventId == VCLEVENT_OBJECT_DYING)
438 : {
439 0 : m_lListener.disposeAndClear (aEvent);
440 :
441 0 : m_pTabWin->RemoveEventListener( LINK( this, TabWindowService, EventListener ) );
442 0 : m_pTabWin = NULL;
443 0 : m_xTabWin.clear();
444 :
445 0 : return 0;
446 : }
447 :
448 0 : ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer(::getCppuType((const css::uno::Reference< css::awt::XTabListener >*) NULL));
449 0 : if ( ! pContainer)
450 0 : return 0;
451 :
452 0 : ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
453 0 : while (pIterator.hasMoreElements())
454 : {
455 : try
456 : {
457 0 : css::awt::XTabListener* pListener = (css::awt::XTabListener*)pIterator.next();
458 :
459 0 : switch (nEventId)
460 : {
461 : case VCLEVENT_TABPAGE_ACTIVATE :
462 0 : pListener->activated( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
463 0 : break;
464 :
465 : case VCLEVENT_TABPAGE_DEACTIVATE :
466 0 : pListener->deactivated( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
467 0 : break;
468 :
469 : case VCLEVENT_TABPAGE_INSERTED :
470 0 : pListener->inserted( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
471 0 : break;
472 :
473 : case VCLEVENT_TABPAGE_REMOVED :
474 0 : pListener->removed( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
475 0 : break;
476 :
477 : case VCLEVENT_TABPAGE_PAGETEXTCHANGED :
478 : case VCLEVENT_TABPAGE_REMOVEDALL :
479 0 : break;
480 : }
481 : }
482 0 : catch(const css::uno::RuntimeException&)
483 : {
484 0 : pIterator.remove();
485 : }
486 : }
487 :
488 0 : return 0;
489 : }
490 :
491 : // TabWindowService
492 :
493 0 : void TabWindowService::impl_checkTabIndex (::sal_Int32 nID)
494 : throw (css::lang::IndexOutOfBoundsException)
495 : {
496 0 : if (
497 0 : (nID <= 0 ) ||
498 0 : (nID > m_nPageIndexCounter)
499 : )
500 : {
501 : throw css::lang::IndexOutOfBoundsException(
502 : OUString("Tab index out of bounds."),
503 0 : css::uno::Reference< css::uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ));
504 : }
505 0 : }
506 :
507 : // TabWindowService
508 :
509 0 : TTabPageInfoHash::iterator TabWindowService::impl_getTabPageInfo(::sal_Int32 nID)
510 : throw (css::lang::IndexOutOfBoundsException)
511 : {
512 0 : TTabPageInfoHash::iterator pIt = m_lTabPageInfos.find(nID);
513 0 : if (pIt == m_lTabPageInfos.end ())
514 : throw css::lang::IndexOutOfBoundsException(
515 : OUString("Tab index out of bounds."),
516 0 : css::uno::Reference< css::uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ));
517 0 : return pIt;
518 : }
519 :
520 : // TabWindowService
521 0 : FwkTabWindow* TabWindowService::mem_TabWin ()
522 : {
523 0 : FwkTabWindow* pWin = NULL;
524 :
525 0 : if ( ! m_xTabWin.is ())
526 : {
527 0 : Window* pFakeParent = dynamic_cast< Window* >(Application::GetDefaultDevice ());
528 :
529 0 : m_pTabWin = new FwkTabWindow (pFakeParent);
530 0 : m_xTabWin = VCLUnoHelper::GetInterface (m_pTabWin);
531 :
532 0 : m_pTabWin->AddEventListener( LINK( this, TabWindowService, EventListener ) );
533 : }
534 :
535 0 : if (m_xTabWin.is ())
536 0 : pWin = m_pTabWin;
537 :
538 0 : return pWin;
539 : }
540 :
541 : }
542 :
543 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
544 0 : com_sun_star_comp_framework_TabWindowService_get_implementation(
545 : css::uno::XComponentContext *,
546 : css::uno::Sequence<css::uno::Any> const &)
547 : {
548 0 : TabWindowService *inst = new TabWindowService;
549 0 : css::uno::XInterface *acquired_inst = cppu::acquire(inst);
550 :
551 0 : inst->initProperties();
552 :
553 0 : return acquired_inst;
554 : }
555 :
556 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|