merge the formfield patch from ooo-build
[ooovba.git] / toolkit / source / awt / vclxtabcontrol.cxx
blob908554c9ae0c4548d67cddd5b6e18917c29613b2
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 $
11 * $Revision: 1.5 $
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"
43 namespace layoutimpl
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 ) ),
54 &(pData->maTitle) );
57 VCLXTabControl::ChildData::ChildData( uno::Reference< awt::XLayoutConstrains > const& xChild )
58 : Box_Base::ChildData( xChild )
59 , maTitle()
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()
82 : VCLXWindow()
83 , VCLXTabControl_Base()
84 , Box_Base()
85 , mTabId (1)
86 , bRealized (false)
88 #ifndef __SUNPRO_CC
89 OSL_TRACE ("\n********%s:%x", __PRETTY_FUNCTION__, this);
90 #endif
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();
116 #if 0
117 void SAL_CALL VCLXTabControl::addTabListener( const Reference< XTabListener >& listener ) throw (uno::RuntimeException)
119 if ( listener.is() )
120 maTabListeners.addInterface( listener );
123 void SAL_CALL VCLXTabControl::removeTabListener( const Reference< XTabListener >& listener ) throw (uno::RuntimeException)
125 if ( listener.is() )
126 maTabListeners.removeInterface( listener );
128 #endif
130 TabControl *VCLXTabControl::getTabControl() const throw (uno::RuntimeException)
132 TabControl *pTabControl = static_cast< TabControl* >( GetWindow() );
133 if ( pTabControl )
134 return pTabControl;
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 ) );
145 return id;
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 )
176 // already added
177 return;
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 );
191 break;
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 ) { \
223 NamedValue value; \
224 value.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( name ) ); \
225 value.Value = uno::makeAny( val ); \
226 seq[i] = value; \
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 ) ) );
232 #undef ADD_PROP
233 return props;
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() ) );
243 if ( pTabPage )
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)
261 #ifndef __SUNPRO_CC
262 OSL_TRACE ("%s: children: %d", __PRETTY_FUNCTION__, maChildren.size ());
263 #endif
264 mIdMap[ xChild ] = mTabId++;
265 Box_Base::AddChild( xChild );
266 #ifndef __SUNPRO_CC
267 OSL_TRACE ("%s: children: %d", __PRETTY_FUNCTION__, maChildren.size ());
268 #endif
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);
290 if ( xWin.is() )
292 xWin->setVisible( visible );
295 uno::Reference < awt::XLayoutContainer > xCont( xChild, uno::UNO_QUERY );
296 if ( xCont.is())
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)
309 #ifndef __SUNPRO_CC
310 OSL_TRACE ("\n%s", __PRETTY_FUNCTION__);
311 #endif
312 maAllocation = area;
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
322 // straight.
324 #if 0
325 setPosSize( area.X, area.Y, area.Width, area.Height, awt::PosSize::POSSIZE );
326 #else
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 ();
342 const int wc = 0;
343 const int hc = 20;
344 static int pwc = 0;
345 static int phc = 40;
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();
356 #ifndef __SUNPRO_CC
357 #ifdef GCC_MAJOR
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() );
368 #endif
370 //bRealized = false;
371 if (!bRealized)
373 setPosSize( area.X, area.Y, requestedSize.Width, requestedSize.Height, awt::PosSize::POSSIZE );
374 bRealized = true;
376 else
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 );
383 #endif
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())
393 unsigned i = 0;
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 );
398 uno::Reference
399 < awt::XLayoutConstrains > xChild( child->mxChild );
400 if ( xChild.is() )
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
407 #if 0
408 if ( xWin.is() )
409 xWin->setVisible( active );
410 #else
411 setChildrenVisible( xChild, active );
412 #endif
414 if ( 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() );
438 if ( !pTabControl )
439 return requestedSize;
441 // calculate size to accomodate all children
442 unsigned i = 0;
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 );
458 #ifndef __SUNPRO_CC
459 #ifdef GCC_MAJOR
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 );
464 #endif
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() );
477 if ( !pTabControl )
478 return;
480 switch ( _rVclWindowEvent.GetId() )
482 case VCLEVENT_TABPAGE_ACTIVATE:
483 forceRecalc();
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++)
495 uno::Reference
496 < awt::XTabListener > listener = *it;
498 switch ( _rVclWindowEvent.GetId() )
501 case VCLEVENT_TABPAGE_ACTIVATE:
502 listener->activated( page );
503 break;
504 case VCLEVENT_TABPAGE_DEACTIVATE:
505 listener->deactivated( page );
506 break;
507 case VCLEVENT_TABPAGE_INSERTED:
508 listener->inserted( page );
509 break;
510 case VCLEVENT_TABPAGE_REMOVED:
511 listener->removed( page );
512 break;
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 );
519 break;
520 case VCLEVENT_TABPAGE_PAGETEXTCHANGED:
521 listener->changed( page, getTabProps( page ) );
522 break;
525 break;
527 default:
528 aGuard.clear();
529 VCLXWindow::ProcessWindowEvent( _rVclWindowEvent );
530 break;
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