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_framework.hxx"
30 
31 //_________________________________________________________________________________________________________________
32 //	my own includes
33 //_________________________________________________________________________________________________________________
34 
35 #include <services/tabwindowservice.hxx>
36 #include <classes/fwktabwindow.hxx>
37 #include <threadhelp/resetableguard.hxx>
38 #include <services.h>
39 #include <properties.h>
40 
41 //_________________________________________________________________________________________________________________
42 //	interface includes
43 //_________________________________________________________________________________________________________________
44 
45 #include <com/sun/star/awt/PosSize.hpp>
46 #include <com/sun/star/beans/PropertyAttribute.hpp>
47 
48 //_________________________________________________________________________________________________________________
49 //	includes of other projects
50 //_________________________________________________________________________________________________________________
51 
52 #include <toolkit/helper/vclunohelper.hxx>
53 #include <tools/urlobj.hxx>
54 #include <rtl/ustrbuf.hxx>
55 #include <vcl/svapp.hxx>
56 
57 //_________________________________________________________________________________________________________________
58 //	namespace
59 //_________________________________________________________________________________________________________________
60 
61 namespace framework{
62 
63 //_________________________________________________________________________________________________________________
64 //	non exported definitions
65 //_________________________________________________________________________________________________________________
66 
67 //_________________________________________________________________________________________________________________
68 //	declarations
69 //_________________________________________________________________________________________________________________
70 
71 //*****************************************************************************************************************
72 //	css::uno::XInterface, XTypeProvider, XServiceInfo
73 //*****************************************************************************************************************
74 
75 DEFINE_XINTERFACE_6                 (   TabWindowService                                ,
76                                         OWeakObject                                     ,
77                                         DIRECT_INTERFACE(css::lang::XTypeProvider      ),
78                                         DIRECT_INTERFACE(css::lang::XServiceInfo       ),
79                                         DIRECT_INTERFACE(css::lang::XComponent),
80                                         DIRECT_INTERFACE(css::awt::XSimpleTabController),
81                                         DIRECT_INTERFACE(css::beans::XPropertySet      ),
82                                         DIRECT_INTERFACE(css::beans::XPropertySetInfo  )
83 									)
84 
85 DEFINE_XTYPEPROVIDER_6              (   TabWindowService               ,
86                                         css::lang::XTypeProvider       ,
87                                         css::lang::XServiceInfo        ,
88                                         css::lang::XComponent          ,
89                                         css::awt::XSimpleTabController ,
90                                         css::beans::XPropertySet       ,
91                                         css::beans::XPropertySetInfo
92 									)
93 
94 DEFINE_XSERVICEINFO_MULTISERVICE    (   TabWindowService                   ,
95                                         OWeakObject                        ,
96                                         SERVICENAME_TABWINDOWSERVICE       ,
97                                         IMPLEMENTATIONNAME_TABWINDOWSERVICE
98 									)
99 
100 DEFINE_INIT_SERVICE                 (   TabWindowService,
101                                         {
102                                             impl_initializePropInfo();
103                                             m_aTransactionManager.setWorkingMode( E_WORK );
104                                         }
105                                     )
106 
107 //*****************************************************************************************************************
108 //	constructor
109 //*****************************************************************************************************************
110 TabWindowService::TabWindowService( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
111 		//	Init baseclasses first
112 		//	Attention:
113 		//		Don't change order of initialization!
114 		//      ThreadHelpBase is a struct with a mutex as member. We can't use a mutex as member, while
115 		//		we must garant right initialization and a valid value of this! First initialize
116 		//		baseclasses and then members. And we need the mutex for other baseclasses !!!
117         :   ThreadHelpBase          ( &Application::GetSolarMutex() )
118         ,   TransactionBase         (                               )
119         ,   PropertySetHelper       ( xFactory                      ,
120                                       &m_aLock                      ,
121                                       &m_aTransactionManager        ,
122                                       sal_False                     ) // sal_False => dont release shared mutex on calling us!
123         ,   OWeakObject             (                               )
124 
125 		// Init member
126         ,   m_xFactory              ( xFactory                      )
127         ,   m_xTabWin               (                               )
128         ,   m_pTabWin               ( NULL                          )
129         ,   m_lTabPageInfos         (                               )
130         ,   m_lListener             ( m_aLock.getShareableOslMutex())
131         ,   m_nPageIndexCounter     ( 1                             )
132         ,   m_nCurrentPageIndex     ( 0                             )
133 {
134 	// Safe impossible cases.
135 	// Method not defined for all incoming parameter.
136     LOG_ASSERT( xFactory.is(), "TabWindowService::TabWindowService()\nInvalid parameter detected!\n" )
137 }
138 
139 //*****************************************************************************************************************
140 //	destructor
141 //*****************************************************************************************************************
142 TabWindowService::~TabWindowService()
143 {
144     // SAFE->
145     ResetableGuard aGuard(m_aLock);
146 
147     if (m_pTabWin)
148         m_pTabWin->RemoveEventListener( LINK( this, TabWindowService, EventListener ) );
149 }
150 
151 //*****************************************************************************************************************
152 //  XSimpleTabController
153 //*****************************************************************************************************************
154 ::sal_Int32 SAL_CALL TabWindowService::insertTab()
155     throw ( css::uno::RuntimeException )
156 {
157     // SAFE ->
158     ResetableGuard aGuard( m_aLock );
159 
160     ::sal_Int32  nID  = m_nPageIndexCounter++;
161     TTabPageInfo aInfo(nID);
162 
163     m_lTabPageInfos[nID] = aInfo;
164 
165     return nID;
166 }
167 
168 //*****************************************************************************************************************
169 //  XSimpleTabController
170 //*****************************************************************************************************************
171 void SAL_CALL TabWindowService::removeTab(::sal_Int32 nID)
172     throw (css::lang::IndexOutOfBoundsException,
173            css::uno::RuntimeException          )
174 {
175     // SAFE ->
176     ResetableGuard aGuard(m_aLock);
177 
178     // throws suitable IndexOutOfBoundsException .-)
179     TTabPageInfoHash::iterator pIt = impl_getTabPageInfo (nID);
180     m_lTabPageInfos.erase(pIt);
181 
182     FwkTabWindow* pTabWin = mem_TabWin ();
183     if (pTabWin)
184         pTabWin->RemovePage(nID);
185 }
186 
187 //*****************************************************************************************************************
188 //  XSimpleTabController
189 //*****************************************************************************************************************
190 void SAL_CALL TabWindowService::setTabProps(      ::sal_Int32                                   nID        ,
191                                               const css::uno::Sequence< css::beans::NamedValue >& lProperties)
192     throw (css::lang::IndexOutOfBoundsException,
193            css::uno::RuntimeException          )
194 {
195     // SAFE ->
196     ResetableGuard aGuard(m_aLock);
197 
198     // throws suitable IndexOutOfBoundsException .-)
199     TTabPageInfoHash::iterator pIt   = impl_getTabPageInfo (nID);
200     TTabPageInfo&              rInfo = pIt->second;
201     rInfo.m_lProperties = lProperties;
202 
203     if ( ! rInfo.m_bCreated)
204     {
205         FwkTabWindow* pTabWin = mem_TabWin ();
206         if (pTabWin)
207         {
208             pTabWin->AddTabPage(rInfo.m_nIndex, rInfo.m_lProperties);
209 			rInfo.m_bCreated = sal_True;
210         }
211     }
212 }
213 
214 //*****************************************************************************************************************
215 //  XSimpleTabController
216 //*****************************************************************************************************************
217 css::uno::Sequence< css::beans::NamedValue > SAL_CALL TabWindowService::getTabProps(::sal_Int32 nID)
218     throw (css::lang::IndexOutOfBoundsException,
219            css::uno::RuntimeException          )
220 {
221     // SAFE ->
222     ResetableGuard aGuard(m_aLock);
223 
224     // throws suitable IndexOutOfBoundsException .-)
225     TTabPageInfoHash::const_iterator pIt   = impl_getTabPageInfo (nID);
226     const TTabPageInfo&              rInfo = pIt->second;
227 
228     return rInfo.m_lProperties;
229 }
230 
231 //*****************************************************************************************************************
232 //  XSimpleTabController
233 //*****************************************************************************************************************
234 void SAL_CALL TabWindowService::activateTab(::sal_Int32 nID)
235     throw (css::lang::IndexOutOfBoundsException,
236            css::uno::RuntimeException          )
237 {
238     // SAFE ->
239     ResetableGuard aGuard(m_aLock);
240 
241     // throws suitable IndexOutOfBoundsException .-)
242     impl_checkTabIndex (nID);
243     m_nCurrentPageIndex = nID;
244 
245     FwkTabWindow* pTabWin = mem_TabWin ();
246     if (pTabWin)
247         pTabWin->ActivatePage(nID);
248 }
249 
250 //*****************************************************************************************************************
251 //  XSimpleTabController
252 //*****************************************************************************************************************
253 ::sal_Int32 SAL_CALL TabWindowService::getActiveTabID()
254     throw (css::uno::RuntimeException)
255 {
256     // SAFE->
257     ResetableGuard aGuard( m_aLock );
258     return m_nCurrentPageIndex;
259 }
260 
261 //*****************************************************************************************************************
262 //  XSimpleTabController
263 //*****************************************************************************************************************
264 void SAL_CALL TabWindowService::addTabListener(const css::uno::Reference< css::awt::XTabListener >& xListener)
265     throw (css::uno::RuntimeException)
266 {
267     m_lListener.addInterface(::getCppuType((const css::uno::Reference< css::awt::XTabListener >*)NULL), xListener);
268 }
269 
270 //*****************************************************************************************************************
271 //  XSimpleTabController
272 //*****************************************************************************************************************
273 void SAL_CALL TabWindowService::removeTabListener(const css::uno::Reference< css::awt::XTabListener >& xListener)
274     throw (css::uno::RuntimeException)
275 {
276     m_lListener.removeInterface(::getCppuType((const css::uno::Reference< css::awt::XTabListener >*)NULL), xListener);
277 }
278 
279 //*****************************************************************************************************************
280 //  XComponent
281 //*****************************************************************************************************************
282 void SAL_CALL TabWindowService::dispose()
283     throw (css::uno::RuntimeException)
284 {
285     // SAFE->
286     ResetableGuard aGuard(m_aLock);
287 
288     css::uno::Reference< css::uno::XInterface > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
289     css::lang::EventObject aEvent(xThis);
290 
291     m_lListener.disposeAndClear (aEvent);
292 
293 	if (m_pTabWin)
294 	    m_pTabWin->RemoveEventListener( LINK( this, TabWindowService, EventListener ) );
295 
296     m_pTabWin = NULL;
297     m_xTabWin.clear();
298 }
299 
300 //*****************************************************************************************************************
301 //  XComponent
302 //*****************************************************************************************************************
303 void SAL_CALL TabWindowService::addEventListener(const css::uno::Reference< css::lang::XEventListener >& xListener)
304     throw (css::uno::RuntimeException)
305 {
306     m_lListener.addInterface(::getCppuType((const css::uno::Reference< css::lang::XEventListener >*)NULL), xListener);
307 }
308 
309 //*****************************************************************************************************************
310 //  XComponent
311 //*****************************************************************************************************************
312 void SAL_CALL TabWindowService::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener)
313     throw (css::uno::RuntimeException)
314 {
315     m_lListener.removeInterface(::getCppuType((const css::uno::Reference< css::lang::XEventListener >*)NULL), xListener);
316 }
317 
318 //*****************************************************************************************************************
319 void TabWindowService::impl_initializePropInfo()
320 {
321     impl_setPropertyChangeBroadcaster(static_cast< css::awt::XSimpleTabController* >(this));
322 
323     impl_addPropertyInfo(
324         css::beans::Property(
325             TABWINDOWSERVICE_PROPNAME_WINDOW,
326             TABWINDOWSERVICE_PROPHANDLE_WINDOW,
327             ::getCppuType((const css::uno::Reference< css::awt::XWindow >*)NULL),
328             css::beans::PropertyAttribute::TRANSIENT));
329 }
330 
331 //*****************************************************************************************************************
332 void SAL_CALL TabWindowService::impl_setPropertyValue(const ::rtl::OUString& /*sProperty*/,
333                                                               sal_Int32        /*nHandle  */,
334                                                         const css::uno::Any&   /*aValue   */)
335 
336 {
337 }
338 
339 //*****************************************************************************************************************
340 css::uno::Any SAL_CALL TabWindowService::impl_getPropertyValue(const ::rtl::OUString& /*sProperty*/,
341                                                                        sal_Int32        nHandle      )
342 {
343     /* There is no need to lock any mutex here. Because we share the
344        solar mutex with our base class. And we said to our base class: "dont release it on calling us" .-)
345        see ctor of PropertySetHelper for further informations.
346     */
347     css::uno::Any aValue;
348 
349     switch (nHandle)
350     {
351         case TABWINDOWSERVICE_PROPHANDLE_WINDOW:
352             {
353                 mem_TabWin (); // force "creation on demand" of m_xTabWin :-)
354                 aValue <<= m_xTabWin;
355             }
356             break;
357     }
358 
359     return aValue;
360 }
361 
362 //*****************************************************************************************************************
363 //  TabWindowService
364 //*****************************************************************************************************************
365 IMPL_LINK( TabWindowService, EventListener, VclSimpleEvent*, pEvent )
366 {
367 
368     if ( !pEvent && !pEvent->ISA(VclWindowEvent))
369         return 0;
370 
371     sal_uLong           nEventId = pEvent->GetId();
372     VclWindowEvent* pWinEvt  = static_cast< VclWindowEvent* >(pEvent);
373 
374     css::uno::Reference< css::uno::XInterface > xThis ( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
375     css::lang::EventObject aEvent( xThis );
376 
377     if (nEventId == VCLEVENT_OBJECT_DYING)
378     {
379         m_lListener.disposeAndClear (aEvent);
380 
381 		m_pTabWin->RemoveEventListener( LINK( this, TabWindowService, EventListener ) );
382 		m_pTabWin = NULL;
383 		m_xTabWin.clear();
384 
385         return 0;
386     }
387 
388     ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer(::getCppuType((const css::uno::Reference< css::awt::XTabListener >*) NULL));
389     if ( ! pContainer)
390         return 0;
391 
392     ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
393     while (pIterator.hasMoreElements())
394     {
395         try
396         {
397             css::awt::XTabListener* pListener = (css::awt::XTabListener*)pIterator.next();
398 
399             switch (nEventId)
400             {
401                 case VCLEVENT_TABPAGE_ACTIVATE :
402                     pListener->activated( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
403                     break;
404 
405                 case VCLEVENT_TABPAGE_DEACTIVATE :
406                     pListener->deactivated( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
407                     break;
408 
409                 case VCLEVENT_TABPAGE_INSERTED :
410                     pListener->inserted( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
411                     break;
412 
413                 case VCLEVENT_TABPAGE_REMOVED :
414                     pListener->removed( (sal_Int32)(sal_uLong)pWinEvt->GetData() );
415                     break;
416 
417                 case VCLEVENT_TABPAGE_PAGETEXTCHANGED :
418                 case VCLEVENT_TABPAGE_REMOVEDALL :
419                     break;
420             }
421         }
422         catch(const css::uno::RuntimeException&)
423         {
424             pIterator.remove();
425         }
426     }
427 
428     return 0;
429 }
430 
431 //*****************************************************************************************************************
432 //  TabWindowService
433 //*****************************************************************************************************************
434 void TabWindowService::impl_checkTabIndex (::sal_Int32 nID)
435     throw (css::lang::IndexOutOfBoundsException)
436 {
437     if (
438         (nID <= 0                  ) ||
439         (nID >  m_nPageIndexCounter)
440        )
441     {
442         throw css::lang::IndexOutOfBoundsException(
443                 ::rtl::OUString::createFromAscii("Tab index out of bounds."),
444                 css::uno::Reference< css::uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ));
445     }
446 }
447 
448 //*****************************************************************************************************************
449 //  TabWindowService
450 //*****************************************************************************************************************
451 TTabPageInfoHash::iterator TabWindowService::impl_getTabPageInfo(::sal_Int32 nID)
452     throw (css::lang::IndexOutOfBoundsException)
453 {
454     TTabPageInfoHash::iterator pIt = m_lTabPageInfos.find(nID);
455     if (pIt == m_lTabPageInfos.end ())
456         throw css::lang::IndexOutOfBoundsException(
457                 ::rtl::OUString::createFromAscii("Tab index out of bounds."),
458                 css::uno::Reference< css::uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ));
459     return pIt;
460 }
461 
462 //*****************************************************************************************************************
463 //  TabWindowService
464 //*****************************************************************************************************************
465 FwkTabWindow* TabWindowService::mem_TabWin ()
466 {
467     FwkTabWindow* pWin = NULL;
468 
469     if ( ! m_xTabWin.is ())
470     {
471         Window* pFakeParent = dynamic_cast< Window* >(Application::GetDefaultDevice ());
472 
473         m_pTabWin = new FwkTabWindow (pFakeParent);
474         m_xTabWin = VCLUnoHelper::GetInterface (m_pTabWin);
475 
476         m_pTabWin->AddEventListener( LINK( this, TabWindowService, EventListener ) );
477     }
478 
479     if (m_xTabWin.is ())
480         pWin = m_pTabWin;
481 
482     return pWin;
483 }
484 
485 } //	namespace framework
486