1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: vclxtabcontrol.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 #include "vclxtabcontrol.hxx"
34 #include <com/sun/star/awt/PosSize.hpp>
35 #include <sal/macros.h>
36 #include <toolkit/helper/property.hxx>
37 #include <toolkit/helper/vclunohelper.hxx>
38 #include <vcl/tabctrl.hxx>
39 #include <vcl/tabpage.hxx>
41 #include "forward.hxx"
46 using namespace ::com::sun::star::lang
;
47 using namespace ::com::sun::star::beans
;
48 using namespace ::com::sun::star
;
50 VCLXTabControl::ChildProps::ChildProps( VCLXTabControl::ChildData
*pData
)
52 addProp( RTL_CONSTASCII_USTRINGPARAM( "Title" ),
53 ::getCppuType( static_cast< const rtl::OUString
* >( NULL
) ),
57 VCLXTabControl::ChildData::ChildData( uno::Reference
< awt::XLayoutConstrains
> const& xChild
)
58 : Box_Base::ChildData( xChild
)
63 VCLXTabControl::ChildData
*
64 VCLXTabControl::createChild( uno::Reference
< awt::XLayoutConstrains
> const& xChild
)
66 return new ChildData( xChild
);
69 VCLXTabControl::ChildProps
*
70 VCLXTabControl::createChildProps( Box_Base::ChildData
*pData
)
72 return new ChildProps( static_cast<VCLXTabControl::ChildData
*> ( pData
) );
75 DBG_NAME( VCLXTabControl
);
77 #if !defined (__GNUC__)
78 #define __PRETTY_FUNCTION__ __FUNCTION__
79 #endif /* !__GNUC__ */
81 VCLXTabControl::VCLXTabControl()
83 , VCLXTabControl_Base()
89 OSL_TRACE ("\n********%s:%x", __PRETTY_FUNCTION__
, this);
91 DBG_CTOR( VCLXTabControl
, NULL
);
94 VCLXTabControl::~VCLXTabControl()
96 DBG_DTOR( VCLXTabControl
, NULL
);
99 IMPLEMENT_2_FORWARD_XINTERFACE2( VCLXTabControl
, VCLXWindow
, Container
, VCLXTabControl_Base
);
101 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXTabControl
, VCLXWindow
, VCLXTabControl_Base
);
103 void SAL_CALL
VCLXTabControl::dispose( ) throw(uno::RuntimeException
)
106 ::vos::OGuard
aGuard( GetMutex() );
108 EventObject aDisposeEvent
;
109 aDisposeEvent
.Source
= W3K_EXPLICIT_CAST (*this);
110 // maTabListeners.disposeAndClear( aDisposeEvent );
113 VCLXWindow::dispose();
117 void SAL_CALL
VCLXTabControl::addTabListener( const Reference
< XTabListener
>& listener
) throw (uno::RuntimeException
)
120 maTabListeners
.addInterface( listener
);
123 void SAL_CALL
VCLXTabControl::removeTabListener( const Reference
< XTabListener
>& listener
) throw (uno::RuntimeException
)
126 maTabListeners
.removeInterface( listener
);
130 TabControl
*VCLXTabControl::getTabControl() const throw (uno::RuntimeException
)
132 TabControl
*pTabControl
= static_cast< TabControl
* >( GetWindow() );
135 throw uno::RuntimeException();
138 sal_Int32 SAL_CALL
VCLXTabControl::insertTab() throw (uno::RuntimeException
)
140 TabControl
*pTabControl
= getTabControl();
141 USHORT id
= sal::static_int_cast
< USHORT
>( mTabId
++ );
142 rtl::OUString
title (RTL_CONSTASCII_USTRINGPARAM( "" ) );
143 pTabControl
->InsertPage( id
, title
.getStr(), TAB_APPEND
);
144 pTabControl
->SetTabPage( id
, new TabPage( pTabControl
) );
148 void SAL_CALL
VCLXTabControl::removeTab( sal_Int32 ID
) throw (uno::RuntimeException
, IndexOutOfBoundsException
)
150 TabControl
*pTabControl
= getTabControl();
151 if ( pTabControl
->GetTabPage( sal::static_int_cast
< USHORT
>( ID
) ) == NULL
)
152 throw IndexOutOfBoundsException();
153 pTabControl
->RemovePage( sal::static_int_cast
< USHORT
>( ID
) );
156 void SAL_CALL
VCLXTabControl::activateTab( sal_Int32 ID
) throw (uno::RuntimeException
, IndexOutOfBoundsException
)
158 TabControl
*pTabControl
= getTabControl();
159 if ( pTabControl
->GetTabPage( sal::static_int_cast
< USHORT
>( ID
) ) == NULL
)
160 throw IndexOutOfBoundsException();
161 pTabControl
->SelectTabPage( sal::static_int_cast
< USHORT
>( ID
) );
164 sal_Int32 SAL_CALL
VCLXTabControl::getActiveTabID() throw (uno::RuntimeException
)
166 return getTabControl()->GetCurPageId( );
169 void SAL_CALL
VCLXTabControl::addTabListener( const uno::Reference
< awt::XTabListener
>& xListener
) throw (uno::RuntimeException
)
171 for ( std::list
< uno::Reference
172 < awt::XTabListener
> >::const_iterator it
173 = mxTabListeners
.begin(); it
!= mxTabListeners
.end(); it
++ )
175 if ( *it
== xListener
)
179 mxTabListeners
.push_back( xListener
);
182 void SAL_CALL
VCLXTabControl::removeTabListener( const uno::Reference
< awt::XTabListener
>& xListener
) throw (uno::RuntimeException
)
184 for ( std::list
< uno::Reference
185 < awt::XTabListener
> >::iterator it
186 = mxTabListeners
.begin(); it
!= mxTabListeners
.end(); it
++ )
188 if ( *it
== xListener
)
190 mxTabListeners
.erase( it
);
196 void SAL_CALL
VCLXTabControl::setTabProps( sal_Int32 ID
, const uno::Sequence
< NamedValue
>& Properties
) throw (uno::RuntimeException
, IndexOutOfBoundsException
)
198 TabControl
*pTabControl
= getTabControl();
199 if ( pTabControl
->GetTabPage( sal::static_int_cast
< USHORT
>( ID
) ) == NULL
)
200 throw IndexOutOfBoundsException();
202 for ( int i
= 0; i
< Properties
.getLength(); i
++ )
204 const rtl::OUString
&name
= Properties
[i
].Name
;
205 const uno::Any
&value
= Properties
[i
].Value
;
207 if ( name
== rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ) )
209 rtl::OUString title
= value
.get
<rtl::OUString
>();
210 pTabControl
->SetPageText( sal::static_int_cast
< USHORT
>( ID
), title
.getStr() );
215 uno::Sequence
< NamedValue
> SAL_CALL
VCLXTabControl::getTabProps( sal_Int32 ID
)
216 throw (IndexOutOfBoundsException
, uno::RuntimeException
)
218 TabControl
*pTabControl
= getTabControl();
219 if ( pTabControl
->GetTabPage( sal::static_int_cast
< USHORT
>( ID
) ) == NULL
)
220 throw IndexOutOfBoundsException();
222 #define ADD_PROP( seq, i, name, val ) { \
224 value.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( name ) ); \
225 value.Value = uno::makeAny( val ); \
229 uno::Sequence
< NamedValue
> props( 2 );
230 ADD_PROP( props
, 0, "Title", rtl::OUString( pTabControl
->GetPageText( sal::static_int_cast
< USHORT
>( ID
) ) ) );
231 ADD_PROP( props
, 1, "Position", pTabControl
->GetPagePos( sal::static_int_cast
< USHORT
>( ID
) ) );
236 // TODO: draw tab border here
237 void SAL_CALL
VCLXTabControl::draw( sal_Int32 nX
, sal_Int32 nY
) throw(uno::RuntimeException
)
239 ::vos::OGuard
aGuard( GetMutex() );
241 TabControl
*pTabControl
= getTabControl();
242 TabPage
*pTabPage
= pTabControl
->GetTabPage( sal::static_int_cast
< USHORT
>( getActiveTabID() ) );
245 ::Point
aPos( nX
, nY
);
246 ::Size aSize
= pTabPage
->GetSizePixel();
248 OutputDevice
* pDev
= VCLUnoHelper::GetOutputDevice( getGraphics() );
249 aPos
= pDev
->PixelToLogic( aPos
);
250 aSize
= pDev
->PixelToLogic( aSize
);
252 pTabPage
->Draw( pDev
, aPos
, aSize
, 0 );
255 VCLXWindow::draw( nX
, nY
);
258 void VCLXTabControl::AddChild (uno::Reference
< awt::XLayoutConstrains
> const& xChild
)
262 OSL_TRACE ("%s: children: %d", __PRETTY_FUNCTION__
, maChildren
.size ());
264 mIdMap
[ xChild
] = mTabId
++;
265 Box_Base::AddChild( xChild
);
267 OSL_TRACE ("%s: children: %d", __PRETTY_FUNCTION__
, maChildren
.size ());
271 void SAL_CALL
VCLXTabControl::addChild(
272 const uno::Reference
< awt::XLayoutConstrains
> &xChild
)
273 throw (uno::RuntimeException
, awt::MaxChildrenException
)
275 mIdMap
[ xChild
] = insertTab();
276 Box_Base::addChild( xChild
);
279 void SAL_CALL
VCLXTabControl::removeChild( const uno::Reference
< awt::XLayoutConstrains
> &xChild
)
280 throw (uno::RuntimeException
)
282 removeTab( mIdMap
[xChild
] );
283 mIdMap
[ xChild
] = -1;
284 Box_Base::removeChild( xChild
);
287 static void setChildrenVisible( uno::Reference
< awt::XLayoutConstrains
> xChild
, bool visible
)
289 uno::Reference
< awt::XWindow
> xWin( xChild
, uno::UNO_QUERY
);
292 xWin
->setVisible( visible
);
295 uno::Reference
< awt::XLayoutContainer
> xCont( xChild
, uno::UNO_QUERY
);
298 uno::Sequence
< uno::Reference
< awt::XLayoutConstrains
> > children
= xCont
->getChildren();
299 for ( int i
= 0; i
< children
.getLength(); i
++ )
301 setChildrenVisible( children
[i
], visible
);
306 void SAL_CALL
VCLXTabControl::allocateArea (awt::Rectangle
const &area
)
307 throw (uno::RuntimeException
)
310 OSL_TRACE ("\n%s", __PRETTY_FUNCTION__
);
314 TabControl
*pTabControl
= getTabControl();
316 // FIXME: this is wrong. We just want to set tab controls pos/size for
317 // the tabs menu, otherwise, it gets events that should go to children
318 // (I guess we could solve this by making the tabcontrol as the actual
319 // XWindow parent of its children, when importing...) Not sure about
320 // TabPage drawing... That doesn't work on gtk+; just ignoring that.
321 // LATER: Nah, the proper fix is to get the XWindow hierarchy
325 setPosSize( area
.X
, area
.Y
, area
.Width
, area
.Height
, awt::PosSize::POSSIZE
);
327 awt::Size currentSize
= getSize();
328 awt::Size
requestedSize (area
.Width
, area
.Height
);
329 // requestedSize.Height = getHeightForWidth( area.Width );
331 awt::Size minimumSize
= getMinimumSize();
332 if (requestedSize
.Width
< minimumSize
.Width
)
333 requestedSize
.Width
= minimumSize
.Width
;
334 if (requestedSize
.Height
< minimumSize
.Height
)
335 requestedSize
.Height
= minimumSize
.Height
;
337 Size pageSize
= static_cast<TabControl
*> (GetWindow ())->GetTabPageSizePixel ();
338 awt::Size
pageBasedSize (0, 0);
339 pageBasedSize
.Width
= pageSize
.Width ();
340 pageBasedSize
.Height
= pageSize
.Height ();
347 if (requestedSize
.Width
< pageBasedSize
.Width
)
348 requestedSize
.Width
= pageBasedSize
.Width
+ wc
;
349 if (requestedSize
.Height
< pageBasedSize
.Height
)
350 requestedSize
.Height
= pageBasedSize
.Height
+ hc
;
352 Size windowSize
= GetWindow()->GetSizePixel();
353 Window
*parent
= GetWindow()->GetParent();
354 Size parentSize
= parent
->GetSizePixel();
358 OSL_TRACE ("\n%s", __PRETTY_FUNCTION__
);
359 #endif /* GCC_MAJOR */
360 OSL_TRACE ("%s: cursize: %d ,%d", __FUNCTION__
, currentSize
.Width
, currentSize
.Height
);
361 OSL_TRACE ("%s: area: %d, %d", __FUNCTION__
, area
.Width
, area
.Height
);
362 OSL_TRACE ("%s: minimum: %d, %d", __FUNCTION__
, minimumSize
.Width
, minimumSize
.Height
);
363 OSL_TRACE ("%s: requestedSize: %d, %d", __FUNCTION__
, requestedSize
.Width
, requestedSize
.Height
);
364 OSL_TRACE ("%s: pageBasedSize: %d, %d", __FUNCTION__
, pageBasedSize
.Width
, pageBasedSize
.Height
);
366 //OSL_TRACE ("%s: parent: %d, %d", __FUNCTION__, parentSize.Width(), parentSize.Height() );
367 //OSL_TRACE ("%s: window: %d, %d", __FUNCTION__, windowSize.Width(), windowSize.Height() );
373 setPosSize( area
.X
, area
.Y
, requestedSize
.Width
, requestedSize
.Height
, awt::PosSize::POSSIZE
);
378 if ( requestedSize
.Width
> currentSize
.Width
+ 10)
379 setPosSize( 0, 0, requestedSize
.Width
, 0, awt::PosSize::WIDTH
);
380 if ( requestedSize
.Height
> currentSize
.Height
+ 10)
381 setPosSize( 0, 0, 0, requestedSize
.Height
, awt::PosSize::HEIGHT
);
385 if (pageBasedSize
.Width
> parentSize
.Width ()
386 || pageBasedSize
.Height
> parentSize
.Height ())
387 //parent->SetSizePixel ( Size (pageBasedSize.Width, pageBasedSize.Height));
388 //parent->SetSizePixel ( Size (pageBasedSize.Width + pwc, pageBasedSize.Height + phc));
389 parent
->SetSizePixel ( Size (requestedSize
.Width
+ pwc
, requestedSize
.Height
+ phc
));
391 // FIXME: we can save cycles by setting visibility more sensibly. Having
392 // it here does makes it easier when changing tabs (just needs a recalc())
394 for ( std::list
<Box_Base::ChildData
*>::const_iterator it
395 = maChildren
.begin(); it
!= maChildren
.end(); it
++, i
++ )
397 ChildData
*child
= static_cast<VCLXTabControl::ChildData
*> ( *it
);
399 < awt::XLayoutConstrains
> xChild( child
->mxChild
);
402 uno::Reference
< awt::XWindow
> xWin( xChild
, uno::UNO_QUERY
);
403 bool active
= (i
+1 == (unsigned) getActiveTabID());
405 // HACK: since our layout:: container don't implement XWindow, we have no easy
406 // way to set them invisible; lets just set all their children as such :P
409 xWin
->setVisible( active
);
411 setChildrenVisible( xChild
, active
);
416 ::Rectangle label_rect
= pTabControl
->GetTabBounds( sal::static_int_cast
< USHORT
>( i
+1 ) );
417 ::Rectangle page_rect
= pTabControl
->GetTabPageBounds( sal::static_int_cast
< USHORT
>( i
+1 ) );
419 awt::Rectangle childRect
;
420 childRect
.X
= page_rect
.Left();
421 childRect
.Y
= SAL_MAX( label_rect
.Bottom(), page_rect
.Top() );
422 childRect
.Width
= page_rect
.Right() - page_rect
.Left();
423 childRect
.Height
= page_rect
.Bottom() - childRect
.Y
;
425 allocateChildAt( xChild
, childRect
);
431 awt::Size SAL_CALL
VCLXTabControl::getMinimumSize()
432 throw(uno::RuntimeException
)
434 awt::Size requestedSize
= VCLXWindow::getMinimumSize();
435 awt::Size
childrenSize( 0, 0 );
437 TabControl
* pTabControl
= static_cast< TabControl
* >( GetWindow() );
439 return requestedSize
;
441 // calculate size to accomodate all children
443 for ( std::list
<Box_Base::ChildData
*>::const_iterator it
444 = maChildren
.begin(); it
!= maChildren
.end(); it
++, i
++ )
446 ChildData
*child
= static_cast<VCLXTabControl::ChildData
*> ( *it
);
447 if ( child
->mxChild
.is() )
449 // set the title prop here...
450 pTabControl
->SetPageText( sal::static_int_cast
< USHORT
>( i
+1 ), child
->maTitle
.getStr() );
452 awt::Size
childSize( child
->mxChild
->getMinimumSize() );
453 childrenSize
.Width
= SAL_MAX( childSize
.Width
, childrenSize
.Width
);
454 childrenSize
.Height
= SAL_MAX( childSize
.Height
, childrenSize
.Height
);
460 OSL_TRACE ("\n%s", __PRETTY_FUNCTION__
);
461 #endif /* GCC_MAJOR */
462 OSL_TRACE ("%s: children: %d", __FUNCTION__
, i
);
463 OSL_TRACE ("%s: childrenSize: %d, %d", __FUNCTION__
, childrenSize
.Width
, childrenSize
.Height
);
466 requestedSize
.Width
+= childrenSize
.Width
;
467 requestedSize
.Height
+= childrenSize
.Height
+ 20;
469 maRequisition
= requestedSize
;
470 return requestedSize
;
473 void VCLXTabControl::ProcessWindowEvent( const VclWindowEvent
& _rVclWindowEvent
)
475 ::vos::OClearableGuard
aGuard( GetMutex() );
476 TabControl
* pTabControl
= static_cast< TabControl
* >( GetWindow() );
480 switch ( _rVclWindowEvent
.GetId() )
482 case VCLEVENT_TABPAGE_ACTIVATE
:
484 case VCLEVENT_TABPAGE_DEACTIVATE
:
485 case VCLEVENT_TABPAGE_INSERTED
:
486 case VCLEVENT_TABPAGE_REMOVED
:
487 case VCLEVENT_TABPAGE_REMOVEDALL
:
488 case VCLEVENT_TABPAGE_PAGETEXTCHANGED
:
490 ULONG page
= (ULONG
) _rVclWindowEvent
.GetData();
491 for ( std::list
< uno::Reference
492 < awt::XTabListener
> >::iterator it
493 = mxTabListeners
.begin(); it
!= mxTabListeners
.end(); it
++)
496 < awt::XTabListener
> listener
= *it
;
498 switch ( _rVclWindowEvent
.GetId() )
501 case VCLEVENT_TABPAGE_ACTIVATE
:
502 listener
->activated( page
);
504 case VCLEVENT_TABPAGE_DEACTIVATE
:
505 listener
->deactivated( page
);
507 case VCLEVENT_TABPAGE_INSERTED
:
508 listener
->inserted( page
);
510 case VCLEVENT_TABPAGE_REMOVED
:
511 listener
->removed( page
);
513 case VCLEVENT_TABPAGE_REMOVEDALL
:
514 for ( int i
= 1; i
< mTabId
; i
++)
516 if ( pTabControl
->GetTabPage( sal::static_int_cast
< USHORT
>( i
) ) )
517 listener
->removed( i
);
520 case VCLEVENT_TABPAGE_PAGETEXTCHANGED
:
521 listener
->changed( page
, getTabProps( page
) );
529 VCLXWindow::ProcessWindowEvent( _rVclWindowEvent
);
534 void SAL_CALL
VCLXTabControl::setProperty( const ::rtl::OUString
& PropertyName
, const uno::Any
&Value
) throw(uno::RuntimeException
)
536 VCLXWindow::setProperty( PropertyName
, Value
);
539 uno::Any SAL_CALL
VCLXTabControl::getProperty( const ::rtl::OUString
& PropertyName
) throw(uno::RuntimeException
)
541 return VCLXWindow::getProperty( PropertyName
);
544 } // namespace layoutimpl