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