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 :
21 : #include "tools/debug.hxx"
22 : #include "tools/rc.h"
23 :
24 : #include "vcl/svapp.hxx"
25 : #include "vcl/help.hxx"
26 : #include "vcl/event.hxx"
27 : #include "vcl/menu.hxx"
28 : #include "vcl/button.hxx"
29 : #include "vcl/tabpage.hxx"
30 : #include "vcl/tabctrl.hxx"
31 : #include "vcl/controllayout.hxx"
32 : #include "vcl/lstbox.hxx"
33 :
34 : #include "controldata.hxx"
35 : #include "svdata.hxx"
36 : #include "window.h"
37 :
38 : #include <boost/unordered_map.hpp>
39 : #include <vector>
40 :
41 : // =======================================================================
42 :
43 0 : struct ImplTabItem
44 : {
45 : sal_uInt16 mnId;
46 : TabPage* mpTabPage;
47 : String maText;
48 : String maFormatText;
49 : String maHelpText;
50 : OString maHelpId;
51 : OString maTabName;
52 : Rectangle maRect;
53 : sal_uInt16 mnLine;
54 : bool mbFullVisible;
55 : bool mbEnabled;
56 : Image maTabImage;
57 :
58 0 : ImplTabItem()
59 : : mnId( 0 ), mpTabPage( NULL ),
60 0 : mnLine( 0 ), mbFullVisible( sal_False ), mbEnabled( true )
61 0 : {}
62 : };
63 :
64 : // -----------------------------------------------------------------------
65 :
66 0 : struct ImplTabCtrlData
67 : {
68 : boost::unordered_map< int, int > maLayoutPageIdToLine;
69 : boost::unordered_map< int, int > maLayoutLineToPageId;
70 : std::vector< Rectangle > maTabRectangles;
71 : Point maItemsOffset; // offset of the tabitems
72 : std::vector< ImplTabItem > maItemList;
73 : ListBox* mpListBox;
74 : };
75 :
76 : // -----------------------------------------------------------------------
77 :
78 : #define TAB_OFFSET 3
79 : #define TAB_TABOFFSET_X 3
80 : #define TAB_TABOFFSET_Y 3
81 : #define TAB_EXTRASPACE_X 6
82 : #define TAB_BORDER_LEFT 1
83 : #define TAB_BORDER_TOP 1
84 : #define TAB_BORDER_RIGHT 2
85 : #define TAB_BORDER_BOTTOM 2
86 :
87 : // Fuer die Ermittlung von den Tab-Positionen
88 : #define TAB_PAGERECT 0xFFFF
89 :
90 : // =======================================================================
91 :
92 0 : void TabControl::ImplInit( Window* pParent, WinBits nStyle )
93 : {
94 0 : mbLayoutDirty = true;
95 :
96 0 : if ( !(nStyle & WB_NOTABSTOP) )
97 0 : nStyle |= WB_TABSTOP;
98 0 : if ( !(nStyle & WB_NOGROUP) )
99 0 : nStyle |= WB_GROUP;
100 0 : if ( !(nStyle & WB_NODIALOGCONTROL) )
101 0 : nStyle |= WB_DIALOGCONTROL;
102 :
103 0 : Control::ImplInit( pParent, nStyle, NULL );
104 :
105 0 : mnLastWidth = 0;
106 0 : mnLastHeight = 0;
107 0 : mnBtnSize = 0;
108 0 : mnMaxPageWidth = 0;
109 0 : mnActPageId = 0;
110 0 : mnCurPageId = 0;
111 0 : mbFormat = sal_True;
112 0 : mbRestoreHelpId = sal_False;
113 0 : mbRestoreUnqId = sal_False;
114 0 : mbSmallInvalidate = sal_False;
115 0 : mpTabCtrlData = new ImplTabCtrlData;
116 0 : mpTabCtrlData->mpListBox = NULL;
117 :
118 :
119 0 : ImplInitSettings( sal_True, sal_True, sal_True );
120 :
121 0 : if( (nStyle & WB_DROPDOWN) )
122 : {
123 0 : mpTabCtrlData->mpListBox = new ListBox( this, WB_DROPDOWN );
124 0 : mpTabCtrlData->mpListBox->SetPosSizePixel( Point( 0, 0 ), Size( 200, 20 ) );
125 0 : mpTabCtrlData->mpListBox->SetSelectHdl( LINK( this, TabControl, ImplListBoxSelectHdl ) );
126 0 : mpTabCtrlData->mpListBox->Show();
127 : }
128 :
129 : // if the tabcontrol is drawn (ie filled) by a native widget, make sure all contols will have transparent background
130 : // otherwise they will paint with a wrong background
131 0 : if( IsNativeControlSupported(CTRL_TAB_PANE, PART_ENTIRE_CONTROL) )
132 0 : EnableChildTransparentMode( sal_True );
133 :
134 0 : if ( pParent->IsDialog() )
135 0 : pParent->AddChildEventListener( LINK( this, TabControl, ImplWindowEventListener ) );
136 0 : }
137 :
138 : // -----------------------------------------------------------------
139 :
140 0 : const Font& TabControl::GetCanonicalFont( const StyleSettings& _rStyle ) const
141 : {
142 0 : return _rStyle.GetAppFont();
143 : }
144 :
145 : // -----------------------------------------------------------------
146 0 : const Color& TabControl::GetCanonicalTextColor( const StyleSettings& _rStyle ) const
147 : {
148 0 : return _rStyle.GetButtonTextColor();
149 : }
150 :
151 : // -----------------------------------------------------------------------
152 :
153 0 : void TabControl::ImplInitSettings( sal_Bool bFont,
154 : sal_Bool bForeground, sal_Bool bBackground )
155 : {
156 0 : Control::ImplInitSettings( bFont, bForeground );
157 :
158 0 : if ( bBackground )
159 : {
160 0 : Window* pParent = GetParent();
161 0 : if ( !IsControlBackground() &&
162 0 : (pParent->IsChildTransparentModeEnabled()
163 0 : || IsNativeControlSupported(CTRL_TAB_PANE, PART_ENTIRE_CONTROL)
164 0 : || IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL) ) )
165 :
166 : {
167 : // set transparent mode for NWF tabcontrols to have
168 : // the background always cleared properly
169 0 : EnableChildTransparentMode( sal_True );
170 0 : SetParentClipMode( PARENTCLIPMODE_NOCLIP );
171 0 : SetPaintTransparent( sal_True );
172 0 : SetBackground();
173 0 : ImplGetWindowImpl()->mbUseNativeFocus = ImplGetSVData()->maNWFData.mbNoFocusRects;
174 : }
175 : else
176 : {
177 0 : EnableChildTransparentMode( sal_False );
178 0 : SetParentClipMode( 0 );
179 0 : SetPaintTransparent( sal_False );
180 :
181 0 : if ( IsControlBackground() )
182 0 : SetBackground( GetControlBackground() );
183 : else
184 0 : SetBackground( pParent->GetBackground() );
185 : }
186 : }
187 0 : }
188 :
189 : // -----------------------------------------------------------------------
190 :
191 0 : void TabControl::ImplFreeLayoutData()
192 : {
193 0 : if( HasLayoutData() )
194 : {
195 0 : ImplClearLayoutData();
196 0 : mpTabCtrlData->maLayoutPageIdToLine.clear();
197 0 : mpTabCtrlData->maLayoutLineToPageId.clear();
198 : }
199 0 : }
200 :
201 : // -----------------------------------------------------------------------
202 :
203 0 : TabControl::TabControl( Window* pParent, WinBits nStyle ) :
204 0 : Control( WINDOW_TABCONTROL )
205 : {
206 0 : ImplInit( pParent, nStyle );
207 : OSL_TRACE("*** TABCONTROL no notabs? %s", ( GetStyle() & WB_NOBORDER ) ? "true" : "false" );
208 0 : }
209 :
210 : // -----------------------------------------------------------------------
211 :
212 0 : TabControl::TabControl( Window* pParent, const ResId& rResId ) :
213 0 : Control( WINDOW_TABCONTROL )
214 : {
215 0 : rResId.SetRT( RSC_TABCONTROL );
216 0 : WinBits nStyle = ImplInitRes( rResId );
217 0 : ImplInit( pParent, nStyle );
218 0 : ImplLoadRes( rResId );
219 :
220 0 : if ( !(nStyle & WB_HIDE) )
221 0 : Show();
222 0 : }
223 :
224 : // -----------------------------------------------------------------------
225 :
226 0 : void TabControl::ImplLoadRes( const ResId& rResId )
227 : {
228 0 : Control::ImplLoadRes( rResId );
229 :
230 0 : sal_uLong nObjMask = ReadLongRes();
231 :
232 0 : if ( nObjMask & RSC_TABCONTROL_ITEMLIST )
233 : {
234 0 : sal_uLong nEle = ReadLongRes();
235 :
236 : // Item hinzufuegen
237 0 : for( sal_uLong i = 0; i < nEle; i++ )
238 : {
239 0 : InsertPage( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
240 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
241 : }
242 : }
243 0 : }
244 :
245 : // -----------------------------------------------------------------------
246 :
247 0 : TabControl::~TabControl()
248 : {
249 0 : if ( GetParent()->IsDialog() )
250 0 : GetParent()->RemoveChildEventListener( LINK( this, TabControl, ImplWindowEventListener ) );
251 :
252 0 : ImplFreeLayoutData();
253 :
254 : // TabCtrl-Daten loeschen
255 0 : if ( mpTabCtrlData )
256 : {
257 0 : if( mpTabCtrlData->mpListBox )
258 0 : delete mpTabCtrlData->mpListBox;
259 0 : delete mpTabCtrlData;
260 : }
261 0 : }
262 :
263 : // -----------------------------------------------------------------------
264 :
265 0 : ImplTabItem* TabControl::ImplGetItem( sal_uInt16 nId ) const
266 : {
267 0 : for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
268 0 : it != mpTabCtrlData->maItemList.end(); ++it )
269 : {
270 0 : if( it->mnId == nId )
271 0 : return &(*it);
272 : }
273 :
274 0 : return NULL;
275 : }
276 :
277 : // -----------------------------------------------------------------------
278 :
279 0 : Size TabControl::ImplGetItemSize( ImplTabItem* pItem, long nMaxWidth )
280 : {
281 0 : pItem->maFormatText = pItem->maText;
282 0 : Size aSize( GetCtrlTextWidth( pItem->maFormatText ), GetTextHeight() );
283 0 : Size aImageSize( 0, 0 );
284 0 : if( !!pItem->maTabImage )
285 : {
286 0 : aImageSize = pItem->maTabImage.GetSizePixel();
287 0 : if( pItem->maFormatText.Len() )
288 0 : aImageSize.Width() += GetTextHeight()/4;
289 : }
290 0 : aSize.Width() += aImageSize.Width();
291 0 : if( aImageSize.Height() > aSize.Height() )
292 0 : aSize.Height() = aImageSize.Height();
293 :
294 0 : aSize.Width() += TAB_TABOFFSET_X*2;
295 0 : aSize.Height() += TAB_TABOFFSET_Y*2;
296 :
297 0 : Rectangle aCtrlRegion( Point( 0, 0 ), aSize );
298 0 : Rectangle aBoundingRgn, aContentRgn;
299 0 : const ImplControlValue aControlValue;
300 0 : if(GetNativeControlRegion( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, aCtrlRegion,
301 : CTRL_STATE_ENABLED, aControlValue, rtl::OUString(),
302 0 : aBoundingRgn, aContentRgn ) )
303 : {
304 0 : return aContentRgn.GetSize();
305 : }
306 :
307 : // For languages with short names (e.g. Chinese), because the space is
308 : // normally only one pixel per char
309 0 : if ( pItem->maFormatText.Len() < TAB_EXTRASPACE_X )
310 0 : aSize.Width() += TAB_EXTRASPACE_X-pItem->maFormatText.Len();
311 :
312 : // Evt. den Text kuerzen
313 0 : if ( aSize.Width()+4 >= nMaxWidth )
314 : {
315 0 : rtl::OUString aAppendStr("...");
316 0 : pItem->maFormatText += aAppendStr;
317 0 : do
318 : {
319 0 : pItem->maFormatText.Erase( pItem->maFormatText.Len()-aAppendStr.getLength()-1, 1 );
320 0 : aSize.Width() = GetCtrlTextWidth( pItem->maFormatText );
321 0 : aSize.Width() += aImageSize.Width();
322 0 : aSize.Width() += TAB_TABOFFSET_X*2;
323 : }
324 0 : while ( (aSize.Width()+4 >= nMaxWidth) && (pItem->maFormatText.Len() > aAppendStr.getLength()) );
325 0 : if ( aSize.Width()+4 >= nMaxWidth )
326 : {
327 0 : pItem->maFormatText.Assign( '.' );
328 0 : aSize.Width() = 1;
329 0 : }
330 : }
331 :
332 0 : if( pItem->maFormatText.Len() == 0 )
333 : {
334 0 : if( aSize.Height() < aImageSize.Height()+4 ) //leave space for focus rect
335 0 : aSize.Height() = aImageSize.Height()+4;
336 : }
337 :
338 0 : return aSize;
339 : }
340 :
341 : // -----------------------------------------------------------------------
342 :
343 0 : Rectangle TabControl::ImplGetTabRect( sal_uInt16 nItemPos, long nWidth, long nHeight )
344 : {
345 0 : Size aWinSize = Control::GetOutputSizePixel();
346 0 : if ( nWidth < 0 )
347 0 : nWidth = aWinSize.Width();
348 0 : if ( nHeight < 0 )
349 0 : nHeight = aWinSize.Height();
350 :
351 0 : if ( mpTabCtrlData->maItemList.empty() )
352 : {
353 0 : long nW = nWidth-TAB_OFFSET*2;
354 0 : long nH = nHeight-TAB_OFFSET*2;
355 : return (nW > 0 && nH > 0)
356 : ? Rectangle( Point( TAB_OFFSET, TAB_OFFSET ), Size( nW, nH ) )
357 0 : : Rectangle();
358 : }
359 :
360 0 : if ( nItemPos == TAB_PAGERECT )
361 : {
362 : sal_uInt16 nLastPos;
363 0 : if ( mnCurPageId )
364 0 : nLastPos = GetPagePos( mnCurPageId );
365 : else
366 0 : nLastPos = 0;
367 :
368 0 : Rectangle aRect = ImplGetTabRect( nLastPos, nWidth, nHeight );
369 0 : long nW = nWidth-TAB_OFFSET*2;
370 0 : long nH = nHeight-aRect.Bottom()-TAB_OFFSET*2;
371 : aRect = (nW > 0 && nH > 0)
372 0 : ? Rectangle( Point( TAB_OFFSET, aRect.Bottom()+TAB_OFFSET ), Size( nW, nH ) )
373 0 : : Rectangle();
374 0 : return aRect;
375 : }
376 :
377 0 : nWidth -= 1;
378 :
379 0 : if ( (nWidth <= 0) || (nHeight <= 0) )
380 0 : return Rectangle();
381 :
382 0 : if ( mbFormat || (mnLastWidth != nWidth) || (mnLastHeight != nHeight) )
383 : {
384 0 : Font aFont( GetFont() );
385 0 : aFont.SetTransparent( sal_True );
386 0 : SetFont( aFont );
387 :
388 0 : Size aSize;
389 0 : const long nOffsetX = 2 + GetItemsOffset().X();
390 0 : const long nOffsetY = 2 + GetItemsOffset().Y();
391 0 : long nX = nOffsetX;
392 0 : long nY = nOffsetY;
393 0 : long nMaxWidth = nWidth;
394 0 : sal_uInt16 nPos = 0;
395 :
396 0 : if ( (mnMaxPageWidth > 0) && (mnMaxPageWidth < nMaxWidth) )
397 0 : nMaxWidth = mnMaxPageWidth;
398 0 : nMaxWidth -= GetItemsOffset().X();
399 :
400 0 : sal_uInt16 nLines = 0;
401 0 : sal_uInt16 nCurLine = 0;
402 : long nLineWidthAry[100];
403 : sal_uInt16 nLinePosAry[101];
404 :
405 0 : nLineWidthAry[0] = 0;
406 0 : nLinePosAry[0] = 0;
407 0 : for( std::vector<ImplTabItem>::iterator it = mpTabCtrlData->maItemList.begin();
408 0 : it != mpTabCtrlData->maItemList.end(); ++it )
409 : {
410 0 : aSize = ImplGetItemSize( &(*it), nMaxWidth );
411 :
412 0 : if ( ((nX+aSize.Width()) > nWidth - 2) && (nWidth > 2+nOffsetX) )
413 : {
414 0 : if ( nLines == 99 )
415 : break;
416 :
417 0 : nX = nOffsetX;
418 0 : nY += aSize.Height();
419 0 : nLines++;
420 0 : nLineWidthAry[nLines] = 0;
421 0 : nLinePosAry[nLines] = nPos;
422 : }
423 :
424 0 : Rectangle aNewRect( Point( nX, nY ), aSize );
425 0 : if ( mbSmallInvalidate && (it->maRect != aNewRect) )
426 0 : mbSmallInvalidate = sal_False;
427 0 : it->maRect = aNewRect;
428 0 : it->mnLine = nLines;
429 0 : it->mbFullVisible = sal_True;
430 :
431 0 : nLineWidthAry[nLines] += aSize.Width();
432 0 : nX += aSize.Width();
433 :
434 0 : if ( it->mnId == mnCurPageId )
435 0 : nCurLine = nLines;
436 :
437 0 : nPos++;
438 : }
439 :
440 0 : if ( nLines && !mpTabCtrlData->maItemList.empty() )
441 : {
442 0 : long nDX = 0;
443 0 : long nModDX = 0;
444 0 : long nIDX = 0;
445 : sal_uInt16 i;
446 : sal_uInt16 n;
447 : long nLineHeightAry[100];
448 0 : long nIH = mpTabCtrlData->maItemList[0].maRect.Bottom()-2;
449 :
450 0 : i = 0;
451 0 : while ( i < nLines+1 )
452 : {
453 0 : if ( i <= nCurLine )
454 0 : nLineHeightAry[i] = nIH*(nLines-(nCurLine-i)) + GetItemsOffset().Y();
455 : else
456 0 : nLineHeightAry[i] = nIH*(i-nCurLine-1) + GetItemsOffset().Y();
457 0 : i++;
458 : }
459 :
460 0 : i = 0;
461 0 : n = 0;
462 0 : nLinePosAry[nLines+1] = (sal_uInt16)mpTabCtrlData->maItemList.size();
463 0 : for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
464 0 : it != mpTabCtrlData->maItemList.end(); ++it )
465 : {
466 0 : if ( i == nLinePosAry[n] )
467 : {
468 0 : if ( n == nLines+1 )
469 0 : break;
470 :
471 0 : nIDX = 0;
472 0 : if( nLinePosAry[n+1]-i > 0 )
473 : {
474 0 : nDX = (nWidth-nOffsetX-nLineWidthAry[n]) / (nLinePosAry[n+1]-i);
475 0 : nModDX = (nWidth-nOffsetX-nLineWidthAry[n]) % (nLinePosAry[n+1]-i);
476 : }
477 : else
478 : {
479 : // FIXME: this is a bad case of tabctrl way too small
480 0 : nDX = 0;
481 0 : nModDX = 0;
482 : }
483 0 : n++;
484 : }
485 :
486 0 : it->maRect.Left() += nIDX;
487 0 : it->maRect.Right() += nIDX+nDX;
488 0 : it->maRect.Top() = nLineHeightAry[n-1];
489 0 : it->maRect.Bottom() = nLineHeightAry[n-1]+nIH;
490 0 : nIDX += nDX;
491 :
492 0 : if ( nModDX )
493 : {
494 0 : nIDX++;
495 0 : it->maRect.Right()++;
496 0 : nModDX--;
497 : }
498 :
499 0 : i++;
500 : }
501 : }
502 : else
503 : {//only one line
504 0 : if(ImplGetSVData()->maNWFData.mbCenteredTabs)
505 : {
506 0 : int nRightSpace=nMaxWidth;//space left on the right by the tabs
507 0 : for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
508 0 : it != mpTabCtrlData->maItemList.end(); ++it )
509 : {
510 0 : nRightSpace-=it->maRect.Right()-it->maRect.Left();
511 : }
512 0 : for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
513 0 : it != mpTabCtrlData->maItemList.end(); ++it )
514 : {
515 0 : it->maRect.Left()+=(int) (nRightSpace/2);
516 0 : it->maRect.Right()+=(int) (nRightSpace/2);
517 : }
518 : }
519 : }
520 :
521 0 : mnLastWidth = nWidth;
522 0 : mnLastHeight = nHeight;
523 0 : mbFormat = sal_False;
524 : }
525 :
526 0 : return size_t(nItemPos) < mpTabCtrlData->maItemList.size() ? mpTabCtrlData->maItemList[nItemPos].maRect : Rectangle();
527 : }
528 :
529 : // -----------------------------------------------------------------------
530 :
531 0 : void TabControl::ImplChangeTabPage( sal_uInt16 nId, sal_uInt16 nOldId )
532 : {
533 0 : ImplFreeLayoutData();
534 :
535 0 : ImplTabItem* pOldItem = ImplGetItem( nOldId );
536 0 : ImplTabItem* pItem = ImplGetItem( nId );
537 0 : TabPage* pOldPage = (pOldItem) ? pOldItem->mpTabPage : NULL;
538 0 : TabPage* pPage = (pItem) ? pItem->mpTabPage : NULL;
539 0 : Window* pCtrlParent = GetParent();
540 :
541 0 : if ( IsReallyVisible() && IsUpdateMode() )
542 : {
543 0 : sal_uInt16 nPos = GetPagePos( nId );
544 0 : Rectangle aRect = ImplGetTabRect( nPos );
545 :
546 0 : if ( !pOldItem || (pOldItem->mnLine != pItem->mnLine) )
547 : {
548 0 : aRect.Left() = 0;
549 0 : aRect.Top() = 0;
550 0 : aRect.Right() = Control::GetOutputSizePixel().Width();
551 : }
552 : else
553 : {
554 0 : aRect.Left() -= 3;
555 0 : aRect.Top() -= 2;
556 0 : aRect.Right() += 3;
557 0 : Invalidate( aRect );
558 0 : nPos = GetPagePos( nOldId );
559 0 : aRect = ImplGetTabRect( nPos );
560 0 : aRect.Left() -= 3;
561 0 : aRect.Top() -= 2;
562 0 : aRect.Right() += 3;
563 : }
564 0 : Invalidate( aRect );
565 : }
566 :
567 0 : if ( pOldPage == pPage )
568 0 : return;
569 :
570 0 : Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
571 :
572 0 : if ( pOldPage )
573 : {
574 0 : if ( mbRestoreHelpId )
575 0 : pCtrlParent->SetHelpId( rtl::OString() );
576 0 : if ( mbRestoreUnqId )
577 0 : pCtrlParent->SetUniqueId( rtl::OString() );
578 0 : pOldPage->DeactivatePage();
579 : }
580 :
581 0 : if ( pPage )
582 : {
583 0 : if ( ( GetStyle() & WB_NOBORDER ) )
584 : {
585 0 : Rectangle aRectNoTab( (const Point&)Point( 0, 0 ), GetSizePixel() );
586 0 : pPage->SetPosSizePixel( aRectNoTab.TopLeft(), aRectNoTab.GetSize() );
587 : }
588 : else
589 0 : pPage->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() );
590 :
591 : // activate page here so the conbtrols can be switched
592 : // also set the help id of the parent window to that of the tab page
593 0 : if ( GetHelpId().isEmpty() )
594 : {
595 0 : mbRestoreHelpId = sal_True;
596 0 : pCtrlParent->SetHelpId( pPage->GetHelpId() );
597 : }
598 0 : if ( pCtrlParent->GetUniqueId().isEmpty() )
599 : {
600 0 : mbRestoreUnqId = sal_True;
601 0 : pCtrlParent->SetUniqueId( pPage->GetUniqueId() );
602 : }
603 :
604 0 : pPage->ActivatePage();
605 :
606 0 : if ( pOldPage && pOldPage->HasChildPathFocus() )
607 : {
608 0 : sal_uInt16 n = 0;
609 0 : Window* pFirstChild = pPage->ImplGetDlgWindow( n, DLGWINDOW_FIRST );
610 0 : if ( pFirstChild )
611 0 : pFirstChild->ImplControlFocus( GETFOCUS_INIT );
612 : else
613 0 : GrabFocus();
614 : }
615 :
616 0 : pPage->Show();
617 : }
618 :
619 0 : if ( pOldPage )
620 0 : pOldPage->Hide();
621 :
622 : // Invalidate the same region that will be send to NWF
623 : // to always allow for bitmap caching
624 : // see Window::DrawNativeControl()
625 0 : if( IsNativeControlSupported( CTRL_TAB_PANE, PART_ENTIRE_CONTROL ) )
626 : {
627 0 : aRect.Left() -= TAB_OFFSET;
628 0 : aRect.Top() -= TAB_OFFSET;
629 0 : aRect.Right() += TAB_OFFSET;
630 0 : aRect.Bottom() += TAB_OFFSET;
631 : }
632 :
633 0 : Invalidate( aRect );
634 : }
635 :
636 : // -----------------------------------------------------------------------
637 :
638 0 : sal_Bool TabControl::ImplPosCurTabPage()
639 : {
640 : // Aktuelle TabPage resizen/positionieren
641 0 : ImplTabItem* pItem = ImplGetItem( GetCurPageId() );
642 0 : if ( pItem && pItem->mpTabPage )
643 : {
644 0 : if ( ( GetStyle() & WB_NOBORDER ) )
645 : {
646 0 : Rectangle aRectNoTab( (const Point&)Point( 0, 0 ), GetSizePixel() );
647 0 : pItem->mpTabPage->SetPosSizePixel( aRectNoTab.TopLeft(), aRectNoTab.GetSize() );
648 0 : return sal_True;
649 : }
650 0 : Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
651 0 : pItem->mpTabPage->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() );
652 0 : return sal_True;
653 : }
654 :
655 0 : return sal_False;
656 : }
657 :
658 : // -----------------------------------------------------------------------
659 :
660 0 : void TabControl::ImplActivateTabPage( sal_Bool bNext )
661 : {
662 0 : sal_uInt16 nCurPos = GetPagePos( GetCurPageId() );
663 :
664 0 : if ( bNext )
665 0 : nCurPos = (nCurPos + 1) % GetPageCount();
666 : else
667 : {
668 0 : if ( !nCurPos )
669 0 : nCurPos = GetPageCount()-1;
670 : else
671 0 : nCurPos--;
672 : }
673 :
674 0 : SelectTabPage( GetPageId( nCurPos ) );
675 0 : }
676 :
677 : // -----------------------------------------------------------------------
678 :
679 0 : void TabControl::ImplShowFocus()
680 : {
681 0 : if ( !GetPageCount() || mpTabCtrlData->mpListBox )
682 0 : return;
683 :
684 0 : sal_uInt16 nCurPos = GetPagePos( mnCurPageId );
685 0 : Rectangle aRect = ImplGetTabRect( nCurPos );
686 0 : const ImplTabItem& rItem = mpTabCtrlData->maItemList[ nCurPos ];
687 0 : Size aTabSize = aRect.GetSize();
688 0 : Size aImageSize( 0, 0 );
689 0 : long nTextHeight = GetTextHeight();
690 0 : long nTextWidth = GetCtrlTextWidth( rItem.maFormatText );
691 : sal_uInt16 nOff;
692 :
693 0 : if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_MONO) )
694 0 : nOff = 1;
695 : else
696 0 : nOff = 0;
697 :
698 0 : if( !! rItem.maTabImage )
699 : {
700 0 : aImageSize = rItem.maTabImage.GetSizePixel();
701 0 : if( rItem.maFormatText.Len() )
702 0 : aImageSize.Width() += GetTextHeight()/4;
703 : }
704 :
705 0 : if( rItem.maFormatText.Len() )
706 : {
707 : // show focus around text
708 0 : aRect.Left() = aRect.Left()+aImageSize.Width()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-1-1;
709 0 : aRect.Top() = aRect.Top()+((aTabSize.Height()-nTextHeight)/2)-1-1;
710 0 : aRect.Right() = aRect.Left()+nTextWidth+2;
711 0 : aRect.Bottom() = aRect.Top()+nTextHeight+2;
712 : }
713 : else
714 : {
715 : // show focus around image
716 0 : long nXPos = aRect.Left()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-1;
717 0 : long nYPos = aRect.Top();
718 0 : if( aImageSize.Height() < aRect.GetHeight() )
719 0 : nYPos += (aRect.GetHeight() - aImageSize.Height())/2;
720 :
721 0 : aRect.Left() = nXPos - 2;
722 0 : aRect.Top() = nYPos - 2;
723 0 : aRect.Right() = aRect.Left() + aImageSize.Width() + 4;
724 0 : aRect.Bottom() = aRect.Top() + aImageSize.Height() + 4;
725 : }
726 0 : ShowFocus( aRect );
727 : }
728 :
729 : // -----------------------------------------------------------------------
730 :
731 0 : void TabControl::ImplDrawItem( ImplTabItem* pItem, const Rectangle& rCurRect, bool bLayout, bool bFirstInGroup, bool bLastInGroup, bool /* bIsCurrentItem */ )
732 : {
733 0 : if ( pItem->maRect.IsEmpty() )
734 0 : return;
735 :
736 0 : if( bLayout )
737 : {
738 0 : if( !HasLayoutData() )
739 : {
740 0 : mpControlData->mpLayoutData = new vcl::ControlLayoutData();
741 0 : mpTabCtrlData->maLayoutLineToPageId.clear();
742 0 : mpTabCtrlData->maLayoutPageIdToLine.clear();
743 0 : mpTabCtrlData->maTabRectangles.clear();
744 : }
745 : }
746 :
747 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
748 0 : Rectangle aRect = pItem->maRect;
749 0 : long nLeftBottom = aRect.Bottom();
750 0 : long nRightBottom = aRect.Bottom();
751 0 : sal_Bool bLeftBorder = sal_True;
752 0 : sal_Bool bRightBorder = sal_True;
753 : sal_uInt16 nOff;
754 0 : sal_Bool bNativeOK = sal_False;
755 :
756 0 : sal_uInt16 nOff2 = 0;
757 0 : sal_uInt16 nOff3 = 0;
758 :
759 0 : if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
760 0 : nOff = 1;
761 : else
762 0 : nOff = 0;
763 :
764 : // Wenn wir die aktuelle Page sind, muessen wir etwas mehr zeichnen
765 0 : if ( pItem->mnId == mnCurPageId )
766 : {
767 0 : nOff2 = 2;
768 0 : if( ! ImplGetSVData()->maNWFData.mbNoActiveTabTextRaise )
769 0 : nOff3 = 1;
770 : }
771 : else
772 : {
773 0 : Point aLeftTestPos = aRect.BottomLeft();
774 0 : Point aRightTestPos = aRect.BottomRight();
775 0 : if ( aLeftTestPos.Y() == rCurRect.Bottom() )
776 : {
777 0 : aLeftTestPos.X() -= 2;
778 0 : if ( rCurRect.IsInside( aLeftTestPos ) )
779 0 : bLeftBorder = sal_False;
780 0 : aRightTestPos.X() += 2;
781 0 : if ( rCurRect.IsInside( aRightTestPos ) )
782 0 : bRightBorder = sal_False;
783 : }
784 : else
785 : {
786 0 : if ( rCurRect.IsInside( aLeftTestPos ) )
787 0 : nLeftBottom -= 2;
788 0 : if ( rCurRect.IsInside( aRightTestPos ) )
789 0 : nRightBottom -= 2;
790 : }
791 : }
792 :
793 0 : if( !bLayout && (bNativeOK = IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL)) == sal_True )
794 : {
795 0 : Rectangle aCtrlRegion( pItem->maRect );
796 0 : ControlState nState = 0;
797 :
798 0 : if( pItem->mnId == mnCurPageId )
799 : {
800 0 : nState |= CTRL_STATE_SELECTED;
801 : // only the selected item can be focussed
802 0 : if ( HasFocus() )
803 0 : nState |= CTRL_STATE_FOCUSED;
804 : }
805 0 : if ( IsEnabled() )
806 0 : nState |= CTRL_STATE_ENABLED;
807 0 : if( IsMouseOver() && pItem->maRect.IsInside( GetPointerPosPixel() ) )
808 : {
809 0 : nState |= CTRL_STATE_ROLLOVER;
810 0 : for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
811 0 : it != mpTabCtrlData->maItemList.end(); ++it )
812 : {
813 0 : if( (&(*it) != pItem) && (it->maRect.IsInside( GetPointerPosPixel() ) ) )
814 : {
815 0 : nState &= ~CTRL_STATE_ROLLOVER; // avoid multiple highlighted tabs
816 0 : break;
817 : }
818 : }
819 : }
820 :
821 0 : TabitemValue tiValue;
822 0 : if(pItem->maRect.Left() < 5)
823 0 : tiValue.mnAlignment |= TABITEM_LEFTALIGNED;
824 0 : if(pItem->maRect.Right() > mnLastWidth - 5)
825 0 : tiValue.mnAlignment |= TABITEM_RIGHTALIGNED;
826 0 : if ( bFirstInGroup )
827 0 : tiValue.mnAlignment |= TABITEM_FIRST_IN_GROUP;
828 0 : if ( bLastInGroup )
829 0 : tiValue.mnAlignment |= TABITEM_LAST_IN_GROUP;
830 :
831 : bNativeOK = DrawNativeControl( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, aCtrlRegion, nState,
832 0 : tiValue, rtl::OUString() );
833 : }
834 :
835 0 : if( ! bLayout && !bNativeOK )
836 : {
837 0 : if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
838 : {
839 0 : SetLineColor( rStyleSettings.GetLightColor() );
840 0 : DrawPixel( Point( aRect.Left()+1-nOff2, aRect.Top()+1-nOff2 ) ); // diagonally indented top-left pixel
841 0 : if ( bLeftBorder )
842 : {
843 0 : DrawLine( Point( aRect.Left()-nOff2, aRect.Top()+2-nOff2 ),
844 0 : Point( aRect.Left()-nOff2, nLeftBottom-1 ) );
845 : }
846 0 : DrawLine( Point( aRect.Left()+2-nOff2, aRect.Top()-nOff2 ), // top line starting 2px from left border
847 0 : Point( aRect.Right()+nOff2-3, aRect.Top()-nOff2 ) ); // ending 3px from right border
848 :
849 0 : if ( bRightBorder )
850 : {
851 0 : SetLineColor( rStyleSettings.GetShadowColor() );
852 0 : DrawLine( Point( aRect.Right()+nOff2-2, aRect.Top()+1-nOff2 ),
853 0 : Point( aRect.Right()+nOff2-2, nRightBottom-1 ) );
854 :
855 0 : SetLineColor( rStyleSettings.GetDarkShadowColor() );
856 0 : DrawLine( Point( aRect.Right()+nOff2-1, aRect.Top()+3-nOff2 ),
857 0 : Point( aRect.Right()+nOff2-1, nRightBottom-1 ) );
858 : }
859 : }
860 : else
861 : {
862 0 : SetLineColor( Color( COL_BLACK ) );
863 0 : DrawPixel( Point( aRect.Left()+1-nOff2, aRect.Top()+1-nOff2 ) );
864 0 : DrawPixel( Point( aRect.Right()+nOff2-2, aRect.Top()+1-nOff2 ) );
865 0 : if ( bLeftBorder )
866 : {
867 0 : DrawLine( Point( aRect.Left()-nOff2, aRect.Top()+2-nOff2 ),
868 0 : Point( aRect.Left()-nOff2, nLeftBottom-1 ) );
869 : }
870 0 : DrawLine( Point( aRect.Left()+2-nOff2, aRect.Top()-nOff2 ),
871 0 : Point( aRect.Right()-3, aRect.Top()-nOff2 ) );
872 0 : if ( bRightBorder )
873 : {
874 0 : DrawLine( Point( aRect.Right()+nOff2-1, aRect.Top()+2-nOff2 ),
875 0 : Point( aRect.Right()+nOff2-1, nRightBottom-1 ) );
876 : }
877 : }
878 : }
879 :
880 0 : if( bLayout )
881 : {
882 0 : int nLine = mpControlData->mpLayoutData->m_aLineIndices.size();
883 0 : mpControlData->mpLayoutData->m_aLineIndices.push_back( mpControlData->mpLayoutData->m_aDisplayText.Len() );
884 0 : mpTabCtrlData->maLayoutPageIdToLine[ (int)pItem->mnId ] = nLine;
885 0 : mpTabCtrlData->maLayoutLineToPageId[ nLine ] = (int)pItem->mnId;
886 0 : mpTabCtrlData->maTabRectangles.push_back( aRect );
887 : }
888 :
889 : // set font accordingly, current item is painted bold
890 : // we set the font attributes always before drawing to be re-entrant (DrawNativeControl may trigger additional paints)
891 0 : Font aFont( GetFont() );
892 0 : aFont.SetTransparent( sal_True );
893 0 : SetFont( aFont );
894 :
895 0 : Size aTabSize = aRect.GetSize();
896 0 : Size aImageSize( 0, 0 );
897 0 : long nTextHeight = GetTextHeight();
898 0 : long nTextWidth = GetCtrlTextWidth( pItem->maFormatText );
899 0 : if( !! pItem->maTabImage )
900 : {
901 0 : aImageSize = pItem->maTabImage.GetSizePixel();
902 0 : if( pItem->maFormatText.Len() )
903 0 : aImageSize.Width() += GetTextHeight()/4;
904 : }
905 0 : long nXPos = aRect.Left()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-nOff3;
906 0 : long nYPos = aRect.Top()+((aTabSize.Height()-nTextHeight)/2)-nOff3;
907 0 : if( pItem->maFormatText.Len() )
908 : {
909 0 : sal_uInt16 nStyle = TEXT_DRAW_MNEMONIC;
910 0 : if( ! pItem->mbEnabled )
911 0 : nStyle |= TEXT_DRAW_DISABLE;
912 0 : DrawCtrlText( Point( nXPos + aImageSize.Width(), nYPos ),
913 : pItem->maFormatText,
914 : 0, STRING_LEN, nStyle,
915 : bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL,
916 : bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL
917 0 : );
918 : }
919 :
920 0 : if( !! pItem->maTabImage )
921 : {
922 0 : Point aImgTL( nXPos, aRect.Top() );
923 0 : if( aImageSize.Height() < aRect.GetHeight() )
924 0 : aImgTL.Y() += (aRect.GetHeight() - aImageSize.Height())/2;
925 0 : DrawImage( aImgTL, pItem->maTabImage, pItem->mbEnabled ? 0 : IMAGE_DRAW_DISABLE );
926 0 : }
927 : }
928 :
929 : // -----------------------------------------------------------------------
930 :
931 0 : long TabControl::ImplHandleKeyEvent( const KeyEvent& rKeyEvent )
932 : {
933 0 : long nRet = 0;
934 :
935 0 : if ( GetPageCount() > 1 )
936 : {
937 0 : KeyCode aKeyCode = rKeyEvent.GetKeyCode();
938 0 : sal_uInt16 nKeyCode = aKeyCode.GetCode();
939 :
940 0 : if ( aKeyCode.IsMod1() )
941 : {
942 0 : if ( aKeyCode.IsShift() || (nKeyCode == KEY_PAGEUP) )
943 : {
944 0 : if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEUP) )
945 : {
946 0 : ImplActivateTabPage( sal_False );
947 0 : nRet = 1;
948 : }
949 : }
950 : else
951 : {
952 0 : if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEDOWN) )
953 : {
954 0 : ImplActivateTabPage( sal_True );
955 0 : nRet = 1;
956 : }
957 : }
958 : }
959 : }
960 :
961 0 : return nRet;
962 : }
963 :
964 :
965 : // -----------------------------------------------------------------------
966 :
967 0 : IMPL_LINK_NOARG(TabControl, ImplListBoxSelectHdl)
968 : {
969 0 : SelectTabPage( GetPageId( mpTabCtrlData->mpListBox->GetSelectEntryPos() ) );
970 0 : return 0;
971 : }
972 :
973 : // -----------------------------------------------------------------------
974 :
975 0 : IMPL_LINK( TabControl, ImplWindowEventListener, VclSimpleEvent*, pEvent )
976 : {
977 0 : if ( pEvent && pEvent->ISA( VclWindowEvent ) && (pEvent->GetId() == VCLEVENT_WINDOW_KEYINPUT) )
978 : {
979 0 : VclWindowEvent* pWindowEvent = static_cast< VclWindowEvent* >(pEvent);
980 : // Do not handle events from TabControl or it's children, which is done in Notify(), where the events can be consumed.
981 0 : if ( !IsWindowOrChild( pWindowEvent->GetWindow() ) )
982 : {
983 0 : KeyEvent* pKeyEvent = static_cast< KeyEvent* >(pWindowEvent->GetData());
984 0 : ImplHandleKeyEvent( *pKeyEvent );
985 : }
986 : }
987 0 : return 0;
988 : }
989 :
990 :
991 : // -----------------------------------------------------------------------
992 :
993 0 : void TabControl::MouseButtonDown( const MouseEvent& rMEvt )
994 : {
995 0 : if( mpTabCtrlData->mpListBox == NULL )
996 : {
997 0 : if( rMEvt.IsLeft() )
998 : {
999 0 : sal_uInt16 nPageId = GetPageId( rMEvt.GetPosPixel() );
1000 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
1001 0 : if( pItem && pItem->mbEnabled )
1002 0 : SelectTabPage( nPageId );
1003 : }
1004 : }
1005 0 : }
1006 :
1007 : // -----------------------------------------------------------------------
1008 :
1009 0 : void TabControl::KeyInput( const KeyEvent& rKEvt )
1010 : {
1011 0 : if( mpTabCtrlData->mpListBox )
1012 0 : mpTabCtrlData->mpListBox->KeyInput( rKEvt );
1013 0 : else if ( GetPageCount() > 1 )
1014 : {
1015 0 : KeyCode aKeyCode = rKEvt.GetKeyCode();
1016 0 : sal_uInt16 nKeyCode = aKeyCode.GetCode();
1017 :
1018 0 : if ( (nKeyCode == KEY_LEFT) || (nKeyCode == KEY_RIGHT) )
1019 : {
1020 0 : sal_Bool bNext = (nKeyCode == KEY_RIGHT);
1021 0 : ImplActivateTabPage( bNext );
1022 : }
1023 : }
1024 :
1025 0 : Control::KeyInput( rKEvt );
1026 0 : }
1027 :
1028 : // -----------------------------------------------------------------------
1029 :
1030 0 : void TabControl::Paint( const Rectangle& rRect )
1031 : {
1032 0 : if ( !( GetStyle() & WB_NOBORDER ) )
1033 0 : ImplPaint( rRect, false );
1034 0 : }
1035 :
1036 : // -----------------------------------------------------------------------
1037 :
1038 0 : void TabControl::ImplPaint( const Rectangle& rRect, bool bLayout )
1039 : {
1040 0 : if( ! bLayout )
1041 0 : HideFocus();
1042 :
1043 : // Hier wird gegebenenfalls auch neu formatiert
1044 0 : Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
1045 :
1046 : // find current item
1047 0 : ImplTabItem* pCurItem = NULL;
1048 0 : for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
1049 0 : it != mpTabCtrlData->maItemList.end(); ++it )
1050 : {
1051 0 : if ( it->mnId == mnCurPageId )
1052 : {
1053 0 : pCurItem = &(*it);
1054 0 : break;
1055 : }
1056 : }
1057 :
1058 : // Draw the TabPage border
1059 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1060 0 : Rectangle aCurRect;
1061 0 : aRect.Left() -= TAB_OFFSET;
1062 0 : aRect.Top() -= TAB_OFFSET;
1063 0 : aRect.Right() += TAB_OFFSET;
1064 0 : aRect.Bottom() += TAB_OFFSET;
1065 :
1066 : // if we have an invisible tabpage or no tabpage at all the tabpage rect should be
1067 : // increased to avoid round corners that might be drawn by a theme
1068 : // in this case we're only interested in the top border of the tabpage because the tabitems are used
1069 : // standalone (eg impress)
1070 0 : sal_Bool bNoTabPage = sal_False;
1071 0 : TabPage* pCurPage = pCurItem ? pCurItem->mpTabPage : NULL;
1072 0 : if( !pCurPage || !pCurPage->IsVisible() )
1073 : {
1074 0 : bNoTabPage = sal_True;
1075 0 : aRect.Left()-=10;
1076 0 : aRect.Right()+=10;
1077 : }
1078 :
1079 0 : sal_Bool bNativeOK = sal_False;
1080 0 : if( ! bLayout && (bNativeOK = IsNativeControlSupported( CTRL_TAB_PANE, PART_ENTIRE_CONTROL) ) == sal_True )
1081 : {
1082 0 : const ImplControlValue aControlValue;
1083 :
1084 0 : ControlState nState = CTRL_STATE_ENABLED;
1085 0 : int part = PART_ENTIRE_CONTROL;
1086 0 : if ( !IsEnabled() )
1087 0 : nState &= ~CTRL_STATE_ENABLED;
1088 0 : if ( HasFocus() )
1089 0 : nState |= CTRL_STATE_FOCUSED;
1090 :
1091 0 : Region aClipRgn( GetActiveClipRegion() );
1092 0 : aClipRgn.Intersect( aRect );
1093 0 : if( !rRect.IsEmpty() )
1094 0 : aClipRgn.Intersect( rRect );
1095 :
1096 0 : if( !aClipRgn.IsEmpty() )
1097 : bNativeOK = DrawNativeControl( CTRL_TAB_PANE, part, aRect, nState,
1098 0 : aControlValue, rtl::OUString() );
1099 : }
1100 : else
1101 : {
1102 0 : long nTopOff = 1;
1103 0 : if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
1104 0 : SetLineColor( rStyleSettings.GetLightColor() );
1105 : else
1106 0 : SetLineColor( Color( COL_BLACK ) );
1107 0 : if ( pCurItem && !pCurItem->maRect.IsEmpty() )
1108 : {
1109 0 : aCurRect = pCurItem->maRect;
1110 0 : if( ! bLayout )
1111 0 : DrawLine( aRect.TopLeft(), Point( aCurRect.Left()-2, aRect.Top() ) );
1112 0 : if ( aCurRect.Right()+1 < aRect.Right() )
1113 : {
1114 0 : if( ! bLayout )
1115 0 : DrawLine( Point( aCurRect.Right(), aRect.Top() ), aRect.TopRight() );
1116 : }
1117 : else
1118 0 : nTopOff = 0;
1119 : }
1120 : else
1121 0 : if( ! bLayout )
1122 0 : DrawLine( aRect.TopLeft(), aRect.TopRight() );
1123 :
1124 0 : if( ! bLayout )
1125 : {
1126 0 : DrawLine( aRect.TopLeft(), aRect.BottomLeft() );
1127 :
1128 0 : if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
1129 : {
1130 : // if we have not tab page the bottom line of the tab page
1131 : // directly touches the tab items, so choose a color that fits seamlessly
1132 0 : if( bNoTabPage )
1133 0 : SetLineColor( rStyleSettings.GetDialogColor() );
1134 : else
1135 0 : SetLineColor( rStyleSettings.GetShadowColor() );
1136 0 : DrawLine( Point( 1, aRect.Bottom()-1 ),
1137 0 : Point( aRect.Right()-1, aRect.Bottom()-1 ) );
1138 0 : DrawLine( Point( aRect.Right()-1, aRect.Top()+nTopOff ),
1139 0 : Point( aRect.Right()-1, aRect.Bottom()-1 ) );
1140 0 : if( bNoTabPage )
1141 0 : SetLineColor( rStyleSettings.GetDialogColor() );
1142 : else
1143 0 : SetLineColor( rStyleSettings.GetDarkShadowColor() );
1144 0 : DrawLine( Point( 0, aRect.Bottom() ),
1145 0 : Point( aRect.Right(), aRect.Bottom() ) );
1146 0 : DrawLine( Point( aRect.Right(), aRect.Top()+nTopOff ),
1147 0 : Point( aRect.Right(), aRect.Bottom() ) );
1148 : }
1149 : else
1150 : {
1151 0 : DrawLine( aRect.TopRight(), aRect.BottomRight() );
1152 0 : DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
1153 : }
1154 : }
1155 : }
1156 :
1157 0 : if ( !mpTabCtrlData->maItemList.empty() && mpTabCtrlData->mpListBox == NULL )
1158 : {
1159 : // Some native toolkits (GTK+) draw tabs right-to-left, with an
1160 : // overlap between adjacent tabs
1161 0 : bool bDrawTabsRTL = IsNativeControlSupported( CTRL_TAB_ITEM, PART_TABS_DRAW_RTL );
1162 0 : ImplTabItem * pFirstTab = NULL;
1163 0 : ImplTabItem * pLastTab = NULL;
1164 : size_t idx;
1165 :
1166 : // Event though there is a tab overlap with GTK+, the first tab is not
1167 : // overlapped on the left side. Other tookits ignore this option.
1168 0 : if ( bDrawTabsRTL )
1169 : {
1170 0 : pFirstTab = &mpTabCtrlData->maItemList.front();
1171 0 : pLastTab = &mpTabCtrlData->maItemList.back();
1172 0 : idx = mpTabCtrlData->maItemList.size()-1;
1173 : }
1174 : else
1175 : {
1176 0 : pLastTab = &mpTabCtrlData->maItemList.back();
1177 0 : pFirstTab = &mpTabCtrlData->maItemList.front();
1178 0 : idx = 0;
1179 : }
1180 :
1181 0 : while ( idx < mpTabCtrlData->maItemList.size() )
1182 : {
1183 0 : ImplTabItem* pItem = &mpTabCtrlData->maItemList[idx];
1184 0 : if ( pItem != pCurItem )
1185 : {
1186 0 : Region aClipRgn( GetActiveClipRegion() );
1187 0 : aClipRgn.Intersect( pItem->maRect );
1188 0 : if( !rRect.IsEmpty() )
1189 0 : aClipRgn.Intersect( rRect );
1190 0 : if( bLayout || !aClipRgn.IsEmpty() )
1191 0 : ImplDrawItem( pItem, aCurRect, bLayout, (pItem==pFirstTab), (pItem==pLastTab), sal_False );
1192 : }
1193 :
1194 0 : if ( bDrawTabsRTL )
1195 0 : idx--;
1196 : else
1197 0 : idx++;
1198 : }
1199 :
1200 0 : if ( pCurItem )
1201 : {
1202 0 : Region aClipRgn( GetActiveClipRegion() );
1203 0 : aClipRgn.Intersect( pCurItem->maRect );
1204 0 : if( !rRect.IsEmpty() )
1205 0 : aClipRgn.Intersect( rRect );
1206 0 : if( bLayout || !aClipRgn.IsEmpty() )
1207 0 : ImplDrawItem( pCurItem, aCurRect, bLayout, (pCurItem==pFirstTab), (pCurItem==pLastTab), sal_True );
1208 : }
1209 : }
1210 :
1211 0 : if ( !bLayout && HasFocus() )
1212 0 : ImplShowFocus();
1213 :
1214 0 : if( ! bLayout )
1215 0 : mbSmallInvalidate = sal_True;
1216 0 : }
1217 :
1218 : // -----------------------------------------------------------------------
1219 :
1220 0 : void TabControl::setAllocation(const Size &rAllocation)
1221 : {
1222 0 : ImplFreeLayoutData();
1223 :
1224 0 : if ( !IsReallyShown() )
1225 0 : return;
1226 :
1227 0 : if( mpTabCtrlData->mpListBox )
1228 : {
1229 : // get the listbox' preferred size
1230 0 : Size aTabCtrlSize( GetSizePixel() );
1231 0 : long nPrefWidth = mpTabCtrlData->mpListBox->get_preferred_size().Width();
1232 0 : if( nPrefWidth > aTabCtrlSize.Width() )
1233 0 : nPrefWidth = aTabCtrlSize.Width();
1234 0 : Size aNewSize( nPrefWidth, LogicToPixel( Size( 12, 12 ), MapMode( MAP_APPFONT ) ).Height() );
1235 0 : Point aNewPos( (aTabCtrlSize.Width() - nPrefWidth) / 2, 0 );
1236 0 : mpTabCtrlData->mpListBox->SetPosSizePixel( aNewPos, aNewSize );
1237 : }
1238 :
1239 0 : mbFormat = sal_True;
1240 :
1241 : // Aktuelle TabPage resizen/positionieren
1242 0 : sal_Bool bTabPage = ImplPosCurTabPage();
1243 : // Feststellen, was invalidiert werden muss
1244 0 : Size aNewSize = rAllocation;
1245 0 : long nNewWidth = aNewSize.Width();
1246 0 : for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
1247 0 : it != mpTabCtrlData->maItemList.end(); ++it )
1248 : {
1249 0 : if ( !it->mbFullVisible ||
1250 0 : (it->maRect.Right()-2 >= nNewWidth) )
1251 : {
1252 0 : mbSmallInvalidate = sal_False;
1253 0 : break;
1254 : }
1255 : }
1256 :
1257 0 : if ( mbSmallInvalidate )
1258 : {
1259 0 : Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
1260 0 : aRect.Left() -= TAB_OFFSET+TAB_BORDER_LEFT;
1261 0 : aRect.Top() -= TAB_OFFSET+TAB_BORDER_TOP;
1262 0 : aRect.Right() += TAB_OFFSET+TAB_BORDER_RIGHT;
1263 0 : aRect.Bottom() += TAB_OFFSET+TAB_BORDER_BOTTOM;
1264 0 : if ( bTabPage )
1265 0 : Invalidate( aRect, INVALIDATE_NOCHILDREN );
1266 : else
1267 0 : Invalidate( aRect );
1268 :
1269 : }
1270 : else
1271 : {
1272 0 : if ( bTabPage )
1273 0 : Invalidate( INVALIDATE_NOCHILDREN );
1274 : else
1275 0 : Invalidate();
1276 : }
1277 :
1278 0 : mbLayoutDirty = false;
1279 : }
1280 :
1281 0 : void TabControl::SetPosSizePixel(const Point& rNewPos, const Size& rNewSize)
1282 : {
1283 0 : Window::SetPosSizePixel(rNewPos, rNewSize);
1284 : //if size changed, TabControl::Resize got called already
1285 0 : if (mbLayoutDirty)
1286 0 : setAllocation(rNewSize);
1287 0 : }
1288 :
1289 0 : void TabControl::SetSizePixel(const Size& rNewSize)
1290 : {
1291 0 : Window::SetSizePixel(rNewSize);
1292 : //if size changed, TabControl::Resize got called already
1293 0 : if (mbLayoutDirty)
1294 0 : setAllocation(rNewSize);
1295 0 : }
1296 :
1297 0 : void TabControl::SetPosPixel(const Point& rPos)
1298 : {
1299 0 : Window::SetPosPixel(rPos);
1300 0 : if (mbLayoutDirty)
1301 0 : setAllocation(GetOutputSizePixel());
1302 0 : }
1303 :
1304 0 : void TabControl::Resize()
1305 : {
1306 0 : setAllocation(Control::GetOutputSizePixel());
1307 0 : }
1308 :
1309 : // -----------------------------------------------------------------------
1310 :
1311 0 : void TabControl::GetFocus()
1312 : {
1313 0 : if( ! mpTabCtrlData->mpListBox )
1314 : {
1315 0 : ImplShowFocus();
1316 0 : SetInputContext( InputContext( GetFont() ) );
1317 : }
1318 : else
1319 : {
1320 0 : if( mpTabCtrlData->mpListBox->IsReallyVisible() )
1321 0 : mpTabCtrlData->mpListBox->GrabFocus();
1322 : }
1323 0 : Control::GetFocus();
1324 0 : }
1325 :
1326 : // -----------------------------------------------------------------------
1327 :
1328 0 : void TabControl::LoseFocus()
1329 : {
1330 0 : if( ! mpTabCtrlData->mpListBox )
1331 0 : HideFocus();
1332 0 : Control::LoseFocus();
1333 0 : }
1334 :
1335 : // -----------------------------------------------------------------------
1336 :
1337 0 : void TabControl::RequestHelp( const HelpEvent& rHEvt )
1338 : {
1339 0 : sal_uInt16 nItemId = rHEvt.KeyboardActivated() ? mnCurPageId : GetPageId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
1340 :
1341 0 : if ( nItemId )
1342 : {
1343 0 : if ( rHEvt.GetMode() & HELPMODE_BALLOON )
1344 : {
1345 0 : XubString aStr = GetHelpText( nItemId );
1346 0 : if ( aStr.Len() )
1347 : {
1348 0 : Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) );
1349 0 : Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
1350 0 : aItemRect.Left() = aPt.X();
1351 0 : aItemRect.Top() = aPt.Y();
1352 0 : aPt = OutputToScreenPixel( aItemRect.BottomRight() );
1353 0 : aItemRect.Right() = aPt.X();
1354 0 : aItemRect.Bottom() = aPt.Y();
1355 0 : Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
1356 : return;
1357 0 : }
1358 : }
1359 0 : else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
1360 : {
1361 0 : rtl::OUString aHelpId( rtl::OStringToOUString( GetHelpId( nItemId ), RTL_TEXTENCODING_UTF8 ) );
1362 0 : if ( !aHelpId.isEmpty() )
1363 : {
1364 : // Wenn eine Hilfe existiert, dann ausloesen
1365 0 : Help* pHelp = Application::GetHelp();
1366 0 : if ( pHelp )
1367 0 : pHelp->Start( aHelpId, this );
1368 : return;
1369 0 : }
1370 : }
1371 :
1372 : // Bei Quick- oder Balloon-Help zeigen wir den Text an,
1373 : // wenn dieser abgeschnitten ist
1374 0 : if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
1375 : {
1376 0 : ImplTabItem* pItem = ImplGetItem( nItemId );
1377 0 : const XubString& rStr = pItem->maText;
1378 0 : if ( rStr != pItem->maFormatText )
1379 : {
1380 0 : Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) );
1381 0 : Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
1382 0 : aItemRect.Left() = aPt.X();
1383 0 : aItemRect.Top() = aPt.Y();
1384 0 : aPt = OutputToScreenPixel( aItemRect.BottomRight() );
1385 0 : aItemRect.Right() = aPt.X();
1386 0 : aItemRect.Bottom() = aPt.Y();
1387 0 : if ( rStr.Len() )
1388 : {
1389 0 : if ( rHEvt.GetMode() & HELPMODE_BALLOON )
1390 0 : Help::ShowBalloon( this, aItemRect.Center(), aItemRect, rStr );
1391 : else
1392 0 : Help::ShowQuickHelp( this, aItemRect, rStr );
1393 : return;
1394 : }
1395 : }
1396 : }
1397 :
1398 0 : if ( rHEvt.GetMode() & HELPMODE_QUICK )
1399 : {
1400 0 : ImplTabItem* pItem = ImplGetItem( nItemId );
1401 0 : const XubString& rHelpText = pItem->maHelpText;
1402 : // show tooltip if not text but image is set and helptext is available
1403 0 : if ( rHelpText.Len() > 0 && pItem->maText.Len() == 0 && !!pItem->maTabImage )
1404 : {
1405 0 : Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) );
1406 0 : Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
1407 0 : aItemRect.Left() = aPt.X();
1408 0 : aItemRect.Top() = aPt.Y();
1409 0 : aPt = OutputToScreenPixel( aItemRect.BottomRight() );
1410 0 : aItemRect.Right() = aPt.X();
1411 0 : aItemRect.Bottom() = aPt.Y();
1412 0 : Help::ShowQuickHelp( this, aItemRect, rHelpText );
1413 : return;
1414 : }
1415 : }
1416 : }
1417 :
1418 0 : Control::RequestHelp( rHEvt );
1419 : }
1420 :
1421 : // -----------------------------------------------------------------------
1422 :
1423 0 : void TabControl::Command( const CommandEvent& rCEvt )
1424 : {
1425 0 : if( (mpTabCtrlData->mpListBox == NULL) && (rCEvt.GetCommand() == COMMAND_CONTEXTMENU) && (GetPageCount() > 1) )
1426 : {
1427 0 : Point aMenuPos;
1428 : sal_Bool bMenu;
1429 0 : if ( rCEvt.IsMouseEvent() )
1430 : {
1431 0 : aMenuPos = rCEvt.GetMousePosPixel();
1432 0 : bMenu = GetPageId( aMenuPos ) != 0;
1433 : }
1434 : else
1435 : {
1436 0 : aMenuPos = ImplGetTabRect( GetPagePos( mnCurPageId ) ).Center();
1437 0 : bMenu = sal_True;
1438 : }
1439 :
1440 0 : if ( bMenu )
1441 : {
1442 0 : PopupMenu aMenu;
1443 0 : for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
1444 0 : it != mpTabCtrlData->maItemList.end(); ++it )
1445 : {
1446 0 : aMenu.InsertItem( it->mnId, it->maText, MIB_CHECKABLE | MIB_RADIOCHECK );
1447 0 : if ( it->mnId == mnCurPageId )
1448 0 : aMenu.CheckItem( it->mnId );
1449 0 : aMenu.SetHelpId( it->mnId, it->maHelpId );
1450 : }
1451 :
1452 0 : sal_uInt16 nId = aMenu.Execute( this, aMenuPos );
1453 0 : if ( nId && (nId != mnCurPageId) )
1454 0 : SelectTabPage( nId );
1455 0 : return;
1456 : }
1457 : }
1458 :
1459 0 : Control::Command( rCEvt );
1460 : }
1461 :
1462 : // -----------------------------------------------------------------------
1463 :
1464 0 : void TabControl::StateChanged( StateChangedType nType )
1465 : {
1466 0 : Control::StateChanged( nType );
1467 :
1468 0 : if ( nType == STATE_CHANGE_INITSHOW )
1469 : {
1470 0 : ImplPosCurTabPage();
1471 0 : if( mpTabCtrlData->mpListBox )
1472 0 : Resize();
1473 : }
1474 0 : else if ( nType == STATE_CHANGE_UPDATEMODE )
1475 : {
1476 0 : if ( IsUpdateMode() )
1477 0 : Invalidate();
1478 : }
1479 0 : else if ( (nType == STATE_CHANGE_ZOOM) ||
1480 : (nType == STATE_CHANGE_CONTROLFONT) )
1481 : {
1482 0 : ImplInitSettings( sal_True, sal_False, sal_False );
1483 0 : Invalidate();
1484 : }
1485 0 : else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
1486 : {
1487 0 : ImplInitSettings( sal_False, sal_True, sal_False );
1488 0 : Invalidate();
1489 : }
1490 0 : else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
1491 : {
1492 0 : ImplInitSettings( sal_False, sal_False, sal_True );
1493 0 : Invalidate();
1494 : }
1495 0 : }
1496 :
1497 : // -----------------------------------------------------------------------
1498 :
1499 0 : void TabControl::DataChanged( const DataChangedEvent& rDCEvt )
1500 : {
1501 0 : Control::DataChanged( rDCEvt );
1502 :
1503 0 : if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1504 0 : (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1505 0 : ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1506 0 : (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1507 : {
1508 0 : ImplInitSettings( sal_True, sal_True, sal_True );
1509 0 : Invalidate();
1510 : }
1511 0 : }
1512 :
1513 : // -----------------------------------------------------------------------
1514 :
1515 0 : Rectangle* TabControl::ImplFindPartRect( const Point& rPt )
1516 : {
1517 0 : ImplTabItem* pFoundItem = NULL;
1518 0 : int nFound = 0;
1519 0 : for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
1520 0 : it != mpTabCtrlData->maItemList.end(); ++it )
1521 : {
1522 0 : if ( it->maRect.IsInside( rPt ) )
1523 : {
1524 : // assure that only one tab is highlighted at a time
1525 0 : nFound++;
1526 0 : pFoundItem = &(*it);
1527 : }
1528 : }
1529 : // assure that only one tab is highlighted at a time
1530 0 : return nFound == 1 ? &pFoundItem->maRect : NULL;
1531 : }
1532 :
1533 0 : long TabControl::PreNotify( NotifyEvent& rNEvt )
1534 : {
1535 0 : long nDone = 0;
1536 0 : const MouseEvent* pMouseEvt = NULL;
1537 :
1538 0 : if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
1539 : {
1540 0 : if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
1541 : {
1542 : // trigger redraw if mouse over state has changed
1543 0 : if( IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL) )
1544 : {
1545 0 : Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
1546 0 : Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() );
1547 0 : if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) )
1548 : {
1549 0 : Region aClipRgn;
1550 0 : if( pLastRect )
1551 : {
1552 : // allow for slightly bigger tabitems
1553 : // as used by gtk
1554 : // TODO: query for the correct sizes
1555 0 : Rectangle aRect(*pLastRect);
1556 0 : aRect.Left()-=2;
1557 0 : aRect.Right()+=2;
1558 0 : aRect.Top()-=3;
1559 0 : aClipRgn.Union( aRect );
1560 : }
1561 0 : if( pRect )
1562 : {
1563 : // allow for slightly bigger tabitems
1564 : // as used by gtk
1565 : // TODO: query for the correct sizes
1566 0 : Rectangle aRect(*pRect);
1567 0 : aRect.Left()-=2;
1568 0 : aRect.Right()+=2;
1569 0 : aRect.Top()-=3;
1570 0 : aClipRgn.Union( aRect );
1571 : }
1572 0 : if( !aClipRgn.IsEmpty() )
1573 0 : Invalidate( aClipRgn );
1574 : }
1575 : }
1576 : }
1577 : }
1578 :
1579 0 : return nDone ? nDone : Control::PreNotify(rNEvt);
1580 : }
1581 :
1582 : // -----------------------------------------------------------------------
1583 :
1584 0 : long TabControl::Notify( NotifyEvent& rNEvt )
1585 : {
1586 0 : long nRet = 0;
1587 :
1588 0 : if ( rNEvt.GetType() == EVENT_KEYINPUT )
1589 0 : nRet = ImplHandleKeyEvent( *rNEvt.GetKeyEvent() );
1590 :
1591 0 : return nRet ? nRet : Control::Notify( rNEvt );
1592 : }
1593 :
1594 : // -----------------------------------------------------------------------
1595 :
1596 0 : void TabControl::ActivatePage()
1597 : {
1598 0 : maActivateHdl.Call( this );
1599 0 : }
1600 :
1601 : // -----------------------------------------------------------------------
1602 :
1603 0 : long TabControl::DeactivatePage()
1604 : {
1605 0 : if ( maDeactivateHdl.IsSet() )
1606 0 : return maDeactivateHdl.Call( this );
1607 : else
1608 0 : return sal_True;
1609 : }
1610 :
1611 : // -----------------------------------------------------------------------
1612 :
1613 0 : void TabControl::SetTabPageSizePixel( const Size& rSize )
1614 : {
1615 0 : ImplFreeLayoutData();
1616 :
1617 0 : Size aNewSize( rSize );
1618 0 : aNewSize.Width() += TAB_OFFSET*2;
1619 : Rectangle aRect = ImplGetTabRect( TAB_PAGERECT,
1620 0 : aNewSize.Width(), aNewSize.Height() );
1621 0 : aNewSize.Height() += aRect.Top()+TAB_OFFSET;
1622 0 : Window::SetOutputSizePixel( aNewSize );
1623 0 : }
1624 :
1625 : // -----------------------------------------------------------------------
1626 :
1627 0 : Size TabControl::GetTabPageSizePixel() const
1628 : {
1629 0 : Rectangle aRect = ((TabControl*)this)->ImplGetTabRect( TAB_PAGERECT );
1630 0 : return aRect.GetSize();
1631 : }
1632 :
1633 : // -----------------------------------------------------------------------
1634 :
1635 0 : void TabControl::InsertPage( const ResId& rResId, sal_uInt16 nPos )
1636 : {
1637 0 : GetRes( rResId.SetRT( RSC_TABCONTROLITEM ) );
1638 :
1639 0 : sal_uLong nObjMask = ReadLongRes();
1640 0 : sal_uInt16 nItemId = 1;
1641 :
1642 : // ID
1643 0 : if ( nObjMask & RSC_TABCONTROLITEM_ID )
1644 0 : nItemId = sal::static_int_cast<sal_uInt16>(ReadLongRes());
1645 :
1646 : // Text
1647 0 : XubString aTmpStr;
1648 0 : if( nObjMask & RSC_TABCONTROLITEM_TEXT )
1649 0 : aTmpStr = ReadStringRes();
1650 0 : InsertPage( nItemId, aTmpStr, nPos );
1651 :
1652 : // PageResID
1653 0 : if ( nObjMask & RSC_TABCONTROLITEM_PAGERESID )
1654 : {
1655 : //skip unused TabPageResId value
1656 0 : ReadLongRes();
1657 0 : }
1658 0 : }
1659 :
1660 : // -----------------------------------------------------------------------
1661 :
1662 0 : void TabControl::InsertPage( sal_uInt16 nPageId, const XubString& rText,
1663 : sal_uInt16 nPos )
1664 : {
1665 : DBG_ASSERT( nPageId, "TabControl::InsertPage(): PageId == 0" );
1666 : DBG_ASSERT( GetPagePos( nPageId ) == TAB_PAGE_NOTFOUND,
1667 : "TabControl::InsertPage(): PageId already exists" );
1668 :
1669 : // insert new page item
1670 0 : ImplTabItem* pItem = NULL;
1671 0 : if( nPos == TAB_APPEND || size_t(nPos) >= mpTabCtrlData->maItemList.size() )
1672 : {
1673 0 : mpTabCtrlData->maItemList.push_back( ImplTabItem() );
1674 0 : pItem = &mpTabCtrlData->maItemList.back();
1675 0 : if( mpTabCtrlData->mpListBox )
1676 0 : mpTabCtrlData->mpListBox->InsertEntry( rText );
1677 : }
1678 : else
1679 : {
1680 : std::vector< ImplTabItem >::iterator new_it =
1681 0 : mpTabCtrlData->maItemList.insert( mpTabCtrlData->maItemList.begin() + nPos, ImplTabItem() );
1682 0 : pItem = &(*new_it);
1683 0 : if( mpTabCtrlData->mpListBox )
1684 0 : mpTabCtrlData->mpListBox->InsertEntry( rText, nPos);
1685 : }
1686 0 : if( mpTabCtrlData->mpListBox )
1687 : {
1688 0 : if( ! mnCurPageId )
1689 0 : mpTabCtrlData->mpListBox->SelectEntryPos( 0 );
1690 0 : mpTabCtrlData->mpListBox->SetDropDownLineCount( mpTabCtrlData->mpListBox->GetEntryCount() );
1691 : }
1692 :
1693 : // set current page id
1694 0 : if ( !mnCurPageId )
1695 0 : mnCurPageId = nPageId;
1696 :
1697 : // init new page item
1698 0 : pItem->mnId = nPageId;
1699 0 : pItem->mpTabPage = NULL;
1700 0 : pItem->maText = rText;
1701 0 : pItem->mbFullVisible = sal_False;
1702 :
1703 0 : mbFormat = sal_True;
1704 0 : if ( IsUpdateMode() )
1705 0 : Invalidate();
1706 :
1707 0 : ImplFreeLayoutData();
1708 0 : if( mpTabCtrlData->mpListBox ) // reposition/resize listbox
1709 0 : Resize();
1710 :
1711 0 : ImplCallEventListeners( VCLEVENT_TABPAGE_INSERTED, (void*) (sal_uLong)nPageId );
1712 0 : }
1713 :
1714 : // -----------------------------------------------------------------------
1715 :
1716 0 : void TabControl::RemovePage( sal_uInt16 nPageId )
1717 : {
1718 0 : sal_uInt16 nPos = GetPagePos( nPageId );
1719 :
1720 : // does the item exist ?
1721 0 : if ( nPos != TAB_PAGE_NOTFOUND )
1722 : {
1723 : //remove page item
1724 0 : std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin() + nPos;
1725 0 : bool bIsCurrentPage = (it->mnId == mnCurPageId);
1726 0 : mpTabCtrlData->maItemList.erase( it );
1727 0 : if( mpTabCtrlData->mpListBox )
1728 : {
1729 0 : mpTabCtrlData->mpListBox->RemoveEntry( nPos );
1730 0 : mpTabCtrlData->mpListBox->SetDropDownLineCount( mpTabCtrlData->mpListBox->GetEntryCount() );
1731 : }
1732 :
1733 : // If current page is removed, than first page gets the current page
1734 0 : if ( bIsCurrentPage )
1735 : {
1736 0 : mnCurPageId = 0;
1737 :
1738 0 : if( ! mpTabCtrlData->maItemList.empty() )
1739 : {
1740 : // don't do this by simply setting mnCurPageId to pFirstItem->mnId
1741 : // this leaves a lot of stuff (such trivias as _showing_ the new current page) undone
1742 : // instead, call SetCurPageId
1743 : // without this, the next (outside) call to SetCurPageId with the id of the first page
1744 : // will result in doing nothing (as we assume that nothing changed, then), and the page
1745 : // will never be shown.
1746 : // 86875 - 05/11/2001 - frank.schoenheit@germany.sun.com
1747 :
1748 0 : SetCurPageId( mpTabCtrlData->maItemList[0].mnId );
1749 : }
1750 : }
1751 :
1752 0 : mbFormat = sal_True;
1753 0 : if ( IsUpdateMode() )
1754 0 : Invalidate();
1755 :
1756 0 : ImplFreeLayoutData();
1757 :
1758 0 : ImplCallEventListeners( VCLEVENT_TABPAGE_REMOVED, (void*) (sal_uLong) nPageId );
1759 : }
1760 0 : }
1761 :
1762 : // -----------------------------------------------------------------------
1763 :
1764 0 : void TabControl::Clear()
1765 : {
1766 : // clear item list
1767 0 : mpTabCtrlData->maItemList.clear();
1768 0 : mnCurPageId = 0;
1769 0 : if( mpTabCtrlData->mpListBox )
1770 0 : mpTabCtrlData->mpListBox->Clear();
1771 :
1772 0 : ImplFreeLayoutData();
1773 :
1774 0 : mbFormat = sal_True;
1775 0 : if ( IsUpdateMode() )
1776 0 : Invalidate();
1777 :
1778 0 : ImplCallEventListeners( VCLEVENT_TABPAGE_REMOVEDALL );
1779 0 : }
1780 :
1781 : // -----------------------------------------------------------------------
1782 :
1783 0 : void TabControl::EnablePage( sal_uInt16 i_nPageId, bool i_bEnable )
1784 : {
1785 0 : ImplTabItem* pItem = ImplGetItem( i_nPageId );
1786 :
1787 0 : if ( pItem && pItem->mbEnabled != i_bEnable )
1788 : {
1789 0 : pItem->mbEnabled = i_bEnable;
1790 0 : mbFormat = sal_True;
1791 0 : if( mpTabCtrlData->mpListBox )
1792 0 : mpTabCtrlData->mpListBox->SetEntryFlags( GetPagePos( i_nPageId ),
1793 0 : i_bEnable ? 0 : (LISTBOX_ENTRY_FLAG_DISABLE_SELECTION | LISTBOX_ENTRY_FLAG_DRAW_DISABLED) );
1794 0 : if( pItem->mnId == mnCurPageId )
1795 : {
1796 : // SetCurPageId will change to an enabled page
1797 0 : SetCurPageId( mnCurPageId );
1798 : }
1799 0 : else if ( IsUpdateMode() )
1800 0 : Invalidate();
1801 : }
1802 0 : }
1803 :
1804 : // -----------------------------------------------------------------------
1805 :
1806 0 : sal_uInt16 TabControl::GetPageCount() const
1807 : {
1808 0 : return (sal_uInt16)mpTabCtrlData->maItemList.size();
1809 : }
1810 :
1811 : // -----------------------------------------------------------------------
1812 :
1813 0 : sal_uInt16 TabControl::GetPageId( sal_uInt16 nPos ) const
1814 : {
1815 0 : if( size_t(nPos) < mpTabCtrlData->maItemList.size() )
1816 0 : return mpTabCtrlData->maItemList[ nPos ].mnId;
1817 0 : return 0;
1818 : }
1819 :
1820 : // -----------------------------------------------------------------------
1821 :
1822 0 : sal_uInt16 TabControl::GetPagePos( sal_uInt16 nPageId ) const
1823 : {
1824 0 : for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
1825 0 : it != mpTabCtrlData->maItemList.end(); ++it )
1826 : {
1827 0 : if ( it->mnId == nPageId )
1828 0 : return (sal_uInt16)(it - mpTabCtrlData->maItemList.begin());
1829 : }
1830 :
1831 0 : return TAB_PAGE_NOTFOUND;
1832 : }
1833 :
1834 : // -----------------------------------------------------------------------
1835 :
1836 0 : sal_uInt16 TabControl::GetPageId( const Point& rPos ) const
1837 : {
1838 0 : for( size_t i = 0; i < mpTabCtrlData->maItemList.size(); ++i )
1839 : {
1840 0 : if ( ((TabControl*)this)->ImplGetTabRect( static_cast<sal_uInt16>(i) ).IsInside( rPos ) )
1841 0 : return mpTabCtrlData->maItemList[ i ].mnId;
1842 : }
1843 :
1844 0 : return 0;
1845 : }
1846 :
1847 0 : sal_uInt16 TabControl::GetPageId( const TabPage& rPage ) const
1848 : {
1849 0 : for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
1850 0 : it != mpTabCtrlData->maItemList.end(); ++it )
1851 : {
1852 0 : if ( it->mpTabPage == &rPage )
1853 0 : return it->mnId;
1854 : }
1855 :
1856 0 : return 0;
1857 : }
1858 :
1859 0 : sal_uInt16 TabControl::GetPageId( const OString& rName ) const
1860 : {
1861 0 : for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
1862 0 : it != mpTabCtrlData->maItemList.end(); ++it )
1863 : {
1864 0 : if ( it->maTabName == rName )
1865 0 : return it->mnId;
1866 : }
1867 :
1868 0 : return 0;
1869 : }
1870 :
1871 : // -----------------------------------------------------------------------
1872 :
1873 0 : void TabControl::SetCurPageId( sal_uInt16 nPageId )
1874 : {
1875 0 : sal_uInt16 nPos = GetPagePos( nPageId );
1876 0 : while( nPos != TAB_PAGE_NOTFOUND &&
1877 0 : ! mpTabCtrlData->maItemList[nPos].mbEnabled )
1878 : {
1879 0 : nPos++;
1880 0 : if( size_t(nPos) >= mpTabCtrlData->maItemList.size() )
1881 0 : nPos = 0;
1882 0 : if( mpTabCtrlData->maItemList[nPos].mnId == nPageId )
1883 0 : break;
1884 : }
1885 :
1886 0 : if( nPos != TAB_PAGE_NOTFOUND )
1887 : {
1888 0 : nPageId = mpTabCtrlData->maItemList[nPos].mnId;
1889 0 : if ( nPageId == mnCurPageId )
1890 : {
1891 0 : if ( mnActPageId )
1892 0 : mnActPageId = nPageId;
1893 0 : return;
1894 : }
1895 :
1896 0 : if ( mnActPageId )
1897 0 : mnActPageId = nPageId;
1898 : else
1899 : {
1900 0 : mbFormat = sal_True;
1901 0 : sal_uInt16 nOldId = mnCurPageId;
1902 0 : mnCurPageId = nPageId;
1903 0 : ImplChangeTabPage( nPageId, nOldId );
1904 : }
1905 : }
1906 : }
1907 :
1908 : // -----------------------------------------------------------------------
1909 :
1910 0 : sal_uInt16 TabControl::GetCurPageId() const
1911 : {
1912 0 : if ( mnActPageId )
1913 0 : return mnActPageId;
1914 : else
1915 0 : return mnCurPageId;
1916 : }
1917 :
1918 : // -----------------------------------------------------------------------
1919 :
1920 0 : void TabControl::SelectTabPage( sal_uInt16 nPageId )
1921 : {
1922 0 : if ( nPageId && (nPageId != mnCurPageId) )
1923 : {
1924 0 : ImplFreeLayoutData();
1925 :
1926 0 : ImplCallEventListeners( VCLEVENT_TABPAGE_DEACTIVATE, (void*) (sal_uLong) mnCurPageId );
1927 0 : if ( DeactivatePage() )
1928 : {
1929 0 : mnActPageId = nPageId;
1930 0 : ActivatePage();
1931 : // Page koennte im Activate-Handler umgeschaltet wurden sein
1932 0 : nPageId = mnActPageId;
1933 0 : mnActPageId = 0;
1934 0 : SetCurPageId( nPageId );
1935 0 : if( mpTabCtrlData->mpListBox )
1936 0 : mpTabCtrlData->mpListBox->SelectEntryPos( GetPagePos( nPageId ) );
1937 0 : ImplCallEventListeners( VCLEVENT_TABPAGE_ACTIVATE, (void*) (sal_uLong) nPageId );
1938 : }
1939 : }
1940 0 : }
1941 :
1942 : // -----------------------------------------------------------------------
1943 :
1944 0 : void TabControl::SetTabPage( sal_uInt16 nPageId, TabPage* pTabPage )
1945 : {
1946 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
1947 :
1948 0 : if ( pItem && (pItem->mpTabPage != pTabPage) )
1949 : {
1950 0 : if ( pTabPage )
1951 : {
1952 : DBG_ASSERT( !pTabPage->IsVisible() || pTabPage->isLayoutEnabled(),
1953 : "TabControl::SetTabPage() - Non-Layout Enabled Page is visible" );
1954 :
1955 0 : if ( IsDefaultSize() )
1956 0 : SetTabPageSizePixel( pTabPage->GetSizePixel() );
1957 :
1958 : // Erst hier setzen, damit Resize nicht TabPage umpositioniert
1959 0 : pItem->mpTabPage = pTabPage;
1960 0 : queue_resize();
1961 0 : if ( pItem->mnId == mnCurPageId )
1962 0 : ImplChangeTabPage( pItem->mnId, 0 );
1963 : }
1964 : else
1965 : {
1966 0 : pItem->mpTabPage = NULL;
1967 0 : queue_resize();
1968 : }
1969 : }
1970 0 : }
1971 :
1972 : // -----------------------------------------------------------------------
1973 :
1974 0 : TabPage* TabControl::GetTabPage( sal_uInt16 nPageId ) const
1975 : {
1976 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
1977 :
1978 0 : if ( pItem )
1979 0 : return pItem->mpTabPage;
1980 : else
1981 0 : return NULL;
1982 : }
1983 :
1984 : // -----------------------------------------------------------------------
1985 :
1986 0 : void TabControl::SetPageText( sal_uInt16 nPageId, const XubString& rText )
1987 : {
1988 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
1989 :
1990 0 : if ( pItem && pItem->maText != rText )
1991 : {
1992 0 : pItem->maText = rText;
1993 0 : mbFormat = sal_True;
1994 0 : if( mpTabCtrlData->mpListBox )
1995 : {
1996 0 : sal_uInt16 nPos = GetPagePos( nPageId );
1997 0 : mpTabCtrlData->mpListBox->RemoveEntry( nPos );
1998 0 : mpTabCtrlData->mpListBox->InsertEntry( rText, nPos );
1999 : }
2000 0 : if ( IsUpdateMode() )
2001 0 : Invalidate();
2002 0 : ImplFreeLayoutData();
2003 0 : ImplCallEventListeners( VCLEVENT_TABPAGE_PAGETEXTCHANGED, (void*) (sal_uLong) nPageId );
2004 : }
2005 0 : }
2006 :
2007 : // -----------------------------------------------------------------------
2008 :
2009 0 : XubString TabControl::GetPageText( sal_uInt16 nPageId ) const
2010 : {
2011 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
2012 :
2013 0 : if ( pItem )
2014 0 : return pItem->maText;
2015 : else
2016 0 : return ImplGetSVEmptyStr();
2017 : }
2018 :
2019 : // -----------------------------------------------------------------------
2020 :
2021 0 : void TabControl::SetHelpText( sal_uInt16 nPageId, const XubString& rText )
2022 : {
2023 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
2024 :
2025 0 : if ( pItem )
2026 0 : pItem->maHelpText = rText;
2027 0 : }
2028 :
2029 : // -----------------------------------------------------------------------
2030 :
2031 0 : const XubString& TabControl::GetHelpText( sal_uInt16 nPageId ) const
2032 : {
2033 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
2034 :
2035 0 : if ( pItem )
2036 : {
2037 0 : if ( !pItem->maHelpText.Len() && !pItem->maHelpId.isEmpty() )
2038 : {
2039 0 : Help* pHelp = Application::GetHelp();
2040 0 : if ( pHelp )
2041 0 : pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
2042 : }
2043 :
2044 0 : return pItem->maHelpText;
2045 : }
2046 : else
2047 0 : return ImplGetSVEmptyStr();
2048 : }
2049 :
2050 : // -----------------------------------------------------------------------
2051 :
2052 0 : void TabControl::SetHelpId( sal_uInt16 nPageId, const OString& rId ) const
2053 : {
2054 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
2055 :
2056 0 : if ( pItem )
2057 0 : pItem->maHelpId = rId;
2058 0 : }
2059 :
2060 0 : OString TabControl::GetHelpId( sal_uInt16 nPageId ) const
2061 : {
2062 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
2063 :
2064 0 : if (pItem)
2065 0 : return pItem->maHelpId;
2066 :
2067 0 : return OString();
2068 : }
2069 :
2070 0 : void TabControl::SetPageName( sal_uInt16 nPageId, const OString& rName ) const
2071 : {
2072 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
2073 :
2074 0 : if ( pItem )
2075 0 : pItem->maTabName = rName;
2076 0 : }
2077 :
2078 0 : OString TabControl::GetPageName( sal_uInt16 nPageId ) const
2079 : {
2080 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
2081 :
2082 0 : if (pItem)
2083 0 : return pItem->maTabName;
2084 :
2085 0 : return OString();
2086 : }
2087 :
2088 : // -----------------------------------------------------------------------
2089 :
2090 0 : void TabControl::SetPageImage( sal_uInt16 i_nPageId, const Image& i_rImage )
2091 : {
2092 0 : ImplTabItem* pItem = ImplGetItem( i_nPageId );
2093 :
2094 0 : if ( pItem )
2095 : {
2096 0 : pItem->maTabImage = i_rImage;
2097 0 : mbFormat = sal_True;
2098 0 : if ( IsUpdateMode() )
2099 0 : Invalidate();
2100 : }
2101 0 : }
2102 :
2103 : // -----------------------------------------------------------------------
2104 :
2105 0 : Rectangle TabControl::GetCharacterBounds( sal_uInt16 nPageId, long nIndex ) const
2106 : {
2107 0 : Rectangle aRet;
2108 :
2109 0 : if( !HasLayoutData() || ! mpTabCtrlData->maLayoutPageIdToLine.size() )
2110 0 : FillLayoutData();
2111 :
2112 0 : if( HasLayoutData() )
2113 : {
2114 0 : boost::unordered_map< int, int >::const_iterator it = mpTabCtrlData->maLayoutPageIdToLine.find( (int)nPageId );
2115 0 : if( it != mpTabCtrlData->maLayoutPageIdToLine.end() )
2116 : {
2117 0 : Pair aPair = mpControlData->mpLayoutData->GetLineStartEnd( it->second );
2118 0 : if( (aPair.B() - aPair.A()) >= nIndex )
2119 0 : aRet = mpControlData->mpLayoutData->GetCharacterBounds( aPair.A() + nIndex );
2120 : }
2121 : }
2122 :
2123 0 : return aRet;
2124 : }
2125 :
2126 : // -----------------------------------------------------------------------
2127 :
2128 0 : long TabControl::GetIndexForPoint( const Point& rPoint, sal_uInt16& rPageId ) const
2129 : {
2130 0 : long nRet = -1;
2131 :
2132 0 : if( !HasLayoutData() || ! mpTabCtrlData->maLayoutPageIdToLine.size() )
2133 0 : FillLayoutData();
2134 :
2135 0 : if( HasLayoutData() )
2136 : {
2137 0 : int nIndex = mpControlData->mpLayoutData->GetIndexForPoint( rPoint );
2138 0 : if( nIndex != -1 )
2139 : {
2140 : // what line (->pageid) is this index in ?
2141 0 : int nLines = mpControlData->mpLayoutData->GetLineCount();
2142 0 : int nLine = -1;
2143 0 : while( ++nLine < nLines )
2144 : {
2145 0 : Pair aPair = mpControlData->mpLayoutData->GetLineStartEnd( nLine );
2146 0 : if( aPair.A() <= nIndex && aPair.B() >= nIndex )
2147 : {
2148 0 : nRet = nIndex - aPair.A();
2149 0 : rPageId = (sal_uInt16)mpTabCtrlData->maLayoutLineToPageId[ nLine ];
2150 : break;
2151 : }
2152 : }
2153 : }
2154 : }
2155 :
2156 0 : return nRet;
2157 : }
2158 :
2159 : // -----------------------------------------------------------------------
2160 :
2161 0 : void TabControl::FillLayoutData() const
2162 : {
2163 0 : mpTabCtrlData->maLayoutLineToPageId.clear();
2164 0 : mpTabCtrlData->maLayoutPageIdToLine.clear();
2165 0 : const_cast<TabControl*>(this)->ImplPaint( Rectangle(), true );
2166 0 : }
2167 :
2168 : // -----------------------------------------------------------------------
2169 :
2170 0 : Rectangle TabControl::GetTabBounds( sal_uInt16 nPageId ) const
2171 : {
2172 0 : Rectangle aRet;
2173 :
2174 0 : ImplTabItem* pItem = ImplGetItem( nPageId );
2175 0 : if(pItem)
2176 0 : aRet = pItem->maRect;
2177 :
2178 0 : return aRet;
2179 : }
2180 :
2181 : // -----------------------------------------------------------------------
2182 :
2183 0 : void TabControl::SetItemsOffset( const Point& rOffs )
2184 : {
2185 0 : if( mpTabCtrlData )
2186 0 : mpTabCtrlData->maItemsOffset = rOffs;
2187 0 : }
2188 :
2189 0 : Point TabControl::GetItemsOffset() const
2190 : {
2191 0 : if( mpTabCtrlData )
2192 0 : return mpTabCtrlData->maItemsOffset;
2193 : else
2194 0 : return Point();
2195 : }
2196 :
2197 : // -----------------------------------------------------------------------
2198 :
2199 0 : Size TabControl::calculateRequisition() const
2200 : {
2201 0 : Size aOptimalPageSize(0, 0);
2202 :
2203 0 : for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
2204 0 : it != mpTabCtrlData->maItemList.end(); ++it )
2205 : {
2206 0 : const TabPage *pPage = it->mpTabPage;
2207 : //it's a real nuisance if the page is not inserted yet :-(
2208 : //We need to force all tabs to exist to get overall optimal size for dialog
2209 0 : if (!pPage)
2210 : {
2211 0 : TabControl *pThis = const_cast<TabControl*>(this);
2212 0 : sal_uInt16 nLastPageId = pThis->GetCurPageId();
2213 0 : pThis->SetCurPageId(it->mnId);
2214 0 : pThis->ActivatePage();
2215 0 : pThis->SetCurPageId(nLastPageId);
2216 0 : pPage = it->mpTabPage;
2217 : }
2218 :
2219 0 : if (!pPage)
2220 0 : continue;
2221 :
2222 0 : Size aPageSize(pPage->GetOptimalSize(WINDOWSIZE_PREFERRED));
2223 :
2224 0 : if (aPageSize.Width() > aOptimalPageSize.Width())
2225 0 : aOptimalPageSize.Width() = aPageSize.Width();
2226 0 : if (aPageSize.Height() > aOptimalPageSize.Height())
2227 0 : aOptimalPageSize.Height() = aPageSize.Height();
2228 : }
2229 :
2230 0 : long nTabLabelsBottom = 0, nTabLabelsRight = 0;
2231 0 : for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
2232 0 : it != mpTabCtrlData->maItemList.end(); ++it )
2233 : {
2234 0 : TabControl* pThis = const_cast<TabControl*>(this);
2235 :
2236 0 : sal_uInt16 nPos = it - mpTabCtrlData->maItemList.begin();
2237 0 : Rectangle aTabRect = pThis->ImplGetTabRect(nPos, aOptimalPageSize.Width(), LONG_MAX);
2238 0 : if (aTabRect.Bottom() > nTabLabelsBottom)
2239 0 : nTabLabelsBottom = aTabRect.Bottom();
2240 0 : if (aTabRect.Right() > nTabLabelsRight)
2241 0 : nTabLabelsRight = aTabRect.Right();
2242 : }
2243 :
2244 0 : Size aOptimalSize(aOptimalPageSize);
2245 0 : aOptimalSize.Height() += nTabLabelsBottom;
2246 0 : aOptimalSize.Width() = std::max(nTabLabelsRight, aOptimalSize.Width());
2247 :
2248 0 : aOptimalSize.Width() += TAB_OFFSET * 2;
2249 0 : aOptimalSize.Height() += TAB_OFFSET * 2;
2250 :
2251 0 : return aOptimalSize;
2252 : }
2253 :
2254 0 : Size TabControl::GetOptimalSize(WindowSizeType eType) const
2255 : {
2256 0 : if (eType == WINDOWSIZE_MINIMUM)
2257 0 : return Size();
2258 0 : return calculateRequisition();
2259 : }
2260 :
2261 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|