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