Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <svtools/tabbar.hxx>
22 : #include <tools/time.hxx>
23 : #include <tools/debug.hxx>
24 : #include <tools/poly.hxx>
25 : #include <vcl/svapp.hxx>
26 : #include <vcl/help.hxx>
27 : #include <vcl/decoview.hxx>
28 : #include <vcl/button.hxx>
29 : #include <vcl/edit.hxx>
30 : #include <vcl/image.hxx>
31 : #include <vcl/settings.hxx>
32 : #include "svtaccessiblefactory.hxx"
33 : #include <filectrl.hrc>
34 : #include <svtools/svtresid.hxx>
35 : #include <svtools/svtools.hrc>
36 : #include <limits>
37 :
38 :
39 :
40 : #define TABBAR_OFFSET_X 7
41 : #define TABBAR_OFFSET_X2 2
42 : #define TABBAR_DRAG_SCROLLOFF 5
43 : #define TABBAR_MINSIZE 5
44 :
45 : const sal_uInt16 ADDNEWPAGE_AREAWIDTH = 10;
46 :
47 :
48 :
49 0 : struct ImplTabBarItem
50 : {
51 : sal_uInt16 mnId;
52 : TabBarPageBits mnBits;
53 : OUString maText;
54 : OUString maHelpText;
55 : Rectangle maRect;
56 : long mnWidth;
57 : OString maHelpId;
58 : bool mbShort;
59 : bool mbSelect;
60 : bool mbEnable;
61 : Color maTabBgColor;
62 : Color maTabTextColor;
63 :
64 0 : ImplTabBarItem( sal_uInt16 nItemId, const OUString& rText,
65 : TabBarPageBits nPageBits ) :
66 0 : maText( rText )
67 : {
68 0 : mnId = nItemId;
69 0 : mnBits = nPageBits;
70 0 : mnWidth = 0;
71 0 : mbShort = false;
72 0 : mbSelect = false;
73 0 : mbEnable = true;
74 0 : maTabBgColor = Color( COL_AUTO );
75 0 : maTabTextColor = Color( COL_AUTO );
76 0 : }
77 :
78 0 : bool IsDefaultTabBgColor() const
79 : {
80 0 : return maTabBgColor == Color(COL_AUTO);
81 : }
82 :
83 0 : bool IsSelected(ImplTabBarItem* pCurItem) const
84 : {
85 0 : return mbSelect || (pCurItem == this);
86 : }
87 : };
88 :
89 :
90 :
91 :
92 : // - ImplTabButton -
93 :
94 :
95 0 : class ImplTabButton : public PushButton
96 : {
97 : public:
98 0 : ImplTabButton( TabBar* pParent, WinBits nWinStyle = 0 ) :
99 0 : PushButton( pParent, nWinStyle | WB_RECTSTYLE | WB_SMALLSTYLE | WB_NOLIGHTBORDER | WB_NOPOINTERFOCUS ) {}
100 :
101 0 : TabBar* GetParent() const { return (TabBar*)Window::GetParent(); }
102 :
103 : virtual bool PreNotify( NotifyEvent& rNEvt ) SAL_OVERRIDE;
104 :
105 : virtual void MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE;
106 :
107 : virtual void Command( const CommandEvent& rCEvt ) SAL_OVERRIDE;
108 : };
109 :
110 0 : void ImplTabButton::MouseButtonDown( const MouseEvent& rMEvt )
111 : {
112 0 : PushButton::MouseButtonDown(rMEvt);
113 0 : }
114 :
115 0 : void ImplTabButton::Command( const CommandEvent& rCEvt )
116 : {
117 0 : sal_uInt16 nCmd = rCEvt.GetCommand();
118 0 : if ( nCmd == COMMAND_CONTEXTMENU )
119 : {
120 0 : TabBar *pParent = GetParent();
121 0 : pParent->maScrollAreaContextHdl.Call((void*)&rCEvt);
122 : }
123 0 : PushButton::Command(rCEvt);
124 0 : }
125 :
126 :
127 :
128 0 : bool ImplTabButton::PreNotify( NotifyEvent& rNEvt )
129 : {
130 0 : if ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
131 : {
132 0 : if ( GetParent()->IsInEditMode() )
133 : {
134 0 : GetParent()->EndEditMode();
135 0 : return true;
136 : }
137 : }
138 :
139 0 : return PushButton::PreNotify( rNEvt );
140 : }
141 :
142 :
143 :
144 :
145 : // - ImplTabSizer -
146 :
147 :
148 0 : class ImplTabSizer : public Window
149 : {
150 : public:
151 : ImplTabSizer( TabBar* pParent, WinBits nWinStyle = 0 );
152 :
153 0 : TabBar* GetParent() const { return (TabBar*)Window::GetParent(); }
154 :
155 : private:
156 : void ImplTrack( const Point& rScreenPos );
157 :
158 : virtual void MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE;
159 : virtual void Tracking( const TrackingEvent& rTEvt ) SAL_OVERRIDE;
160 : virtual void Paint( const Rectangle& rRect ) SAL_OVERRIDE;
161 :
162 : Point maStartPos;
163 : long mnStartWidth;
164 : };
165 :
166 :
167 :
168 0 : ImplTabSizer::ImplTabSizer( TabBar* pParent, WinBits nWinStyle )
169 : : Window( pParent, nWinStyle & WB_3DLOOK )
170 0 : , mnStartWidth(0)
171 : {
172 0 : SetPointer( Pointer( POINTER_HSIZEBAR ) );
173 0 : SetSizePixel( Size( 7, 0 ) );
174 0 : }
175 :
176 :
177 :
178 0 : void ImplTabSizer::ImplTrack( const Point& rScreenPos )
179 : {
180 0 : TabBar* pParent = GetParent();
181 0 : long nDiff = rScreenPos.X() - maStartPos.X();
182 0 : pParent->mnSplitSize = mnStartWidth + (pParent->IsMirrored() ? -nDiff : nDiff);
183 0 : if ( pParent->mnSplitSize < TABBAR_MINSIZE )
184 0 : pParent->mnSplitSize = TABBAR_MINSIZE;
185 0 : pParent->Split();
186 0 : pParent->Update();
187 0 : }
188 :
189 :
190 :
191 0 : void ImplTabSizer::MouseButtonDown( const MouseEvent& rMEvt )
192 : {
193 0 : if ( GetParent()->IsInEditMode() )
194 : {
195 0 : GetParent()->EndEditMode();
196 0 : return;
197 : }
198 :
199 0 : if ( rMEvt.IsLeft() )
200 : {
201 0 : maStartPos = OutputToScreenPixel( rMEvt.GetPosPixel() );
202 0 : mnStartWidth = GetParent()->GetSizePixel().Width();
203 0 : StartTracking();
204 : }
205 : }
206 :
207 :
208 :
209 0 : void ImplTabSizer::Tracking( const TrackingEvent& rTEvt )
210 : {
211 0 : if ( rTEvt.IsTrackingEnded() )
212 : {
213 0 : if ( rTEvt.IsTrackingCanceled() )
214 0 : ImplTrack( maStartPos );
215 0 : GetParent()->mnSplitSize = 0;
216 : }
217 : else
218 0 : ImplTrack( OutputToScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
219 0 : }
220 :
221 :
222 :
223 0 : void ImplTabSizer::Paint( const Rectangle& )
224 : {
225 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
226 0 : DecorationView aDecoView( this );
227 0 : long nOffX = 0;
228 0 : Size aOutputSize = GetOutputSizePixel();
229 :
230 0 : if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
231 : {
232 0 : SetLineColor( rStyleSettings.GetDarkShadowColor() );
233 0 : DrawLine( Point( 0, 0 ), Point( 0, aOutputSize.Height()-1 ) );
234 0 : nOffX++;
235 0 : aOutputSize.Width()--;
236 : }
237 0 : aDecoView.DrawButton( Rectangle( Point( nOffX, 0 ), aOutputSize ), BUTTON_DRAW_NOLIGHTBORDER );
238 0 : }
239 :
240 :
241 :
242 : // Is not named Impl. as it may be called or overloaded
243 :
244 :
245 : // - TabBarEdit -
246 :
247 :
248 0 : class TabBarEdit : public Edit
249 : {
250 : private:
251 : Timer maLoseFocusTimer;
252 : bool mbPostEvt;
253 :
254 : DECL_LINK( ImplEndEditHdl, void* );
255 : DECL_LINK( ImplEndTimerHdl, void* );
256 :
257 : public:
258 : TabBarEdit( TabBar* pParent, WinBits nWinStyle = 0 );
259 :
260 0 : TabBar* GetParent() const { return (TabBar*)Window::GetParent(); }
261 :
262 0 : void SetPostEvent() { mbPostEvt = true; }
263 0 : void ResetPostEvent() { mbPostEvt = false; }
264 :
265 : virtual bool PreNotify( NotifyEvent& rNEvt ) SAL_OVERRIDE;
266 : virtual void LoseFocus() SAL_OVERRIDE;
267 : };
268 :
269 :
270 :
271 0 : TabBarEdit::TabBarEdit( TabBar* pParent, WinBits nWinStyle ) :
272 0 : Edit( pParent, nWinStyle )
273 : {
274 0 : mbPostEvt = false;
275 0 : }
276 :
277 :
278 :
279 0 : bool TabBarEdit::PreNotify( NotifyEvent& rNEvt )
280 : {
281 0 : if ( rNEvt.GetType() == EVENT_KEYINPUT )
282 : {
283 0 : const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
284 0 : if ( !pKEvt->GetKeyCode().GetModifier() )
285 : {
286 0 : if ( pKEvt->GetKeyCode().GetCode() == KEY_RETURN )
287 : {
288 0 : if ( !mbPostEvt )
289 : {
290 0 : if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_False ) )
291 0 : mbPostEvt = true;
292 : }
293 0 : return true;
294 : }
295 0 : else if ( pKEvt->GetKeyCode().GetCode() == KEY_ESCAPE )
296 : {
297 0 : if ( !mbPostEvt )
298 : {
299 0 : if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_True ) )
300 0 : mbPostEvt = true;
301 : }
302 0 : return true;
303 : }
304 : }
305 : }
306 :
307 0 : return Edit::PreNotify( rNEvt );
308 : }
309 :
310 :
311 :
312 0 : void TabBarEdit::LoseFocus()
313 : {
314 0 : if ( !mbPostEvt )
315 : {
316 0 : if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_False ) )
317 0 : mbPostEvt = true;
318 : }
319 :
320 0 : Edit::LoseFocus();
321 0 : }
322 :
323 :
324 :
325 0 : IMPL_LINK( TabBarEdit, ImplEndEditHdl, void*, pCancel )
326 : {
327 0 : ResetPostEvent();
328 0 : maLoseFocusTimer.Stop();
329 :
330 : // We need this query, because the edit get a losefous event,
331 : // when it shows the context menu or the insert symbol dialog
332 0 : if ( !HasFocus() && HasChildPathFocus( true ) )
333 : {
334 0 : maLoseFocusTimer.SetTimeout( 30 );
335 0 : maLoseFocusTimer.SetTimeoutHdl( LINK( this, TabBarEdit, ImplEndTimerHdl ) );
336 0 : maLoseFocusTimer.Start();
337 : }
338 : else
339 0 : GetParent()->EndEditMode( pCancel != 0 );
340 :
341 0 : return 0;
342 : }
343 :
344 :
345 :
346 0 : IMPL_LINK_NOARG(TabBarEdit, ImplEndTimerHdl)
347 : {
348 0 : if ( HasFocus() )
349 0 : return 0;
350 :
351 : // We need this query, because the edit get a losefous event,
352 : // when it shows the context menu or the insert symbol dialog
353 0 : if ( HasChildPathFocus( true ) )
354 0 : maLoseFocusTimer.Start();
355 : else
356 0 : GetParent()->EndEditMode( true );
357 :
358 0 : return 0;
359 : }
360 :
361 :
362 : struct TabBar_Impl
363 : {
364 : ImplTabSizer* mpSizer;
365 : ::svt::AccessibleFactoryAccess maAccessibleFactory;
366 :
367 0 : TabBar_Impl()
368 0 : :mpSizer( NULL )
369 : {
370 0 : }
371 0 : ~TabBar_Impl()
372 0 : {
373 0 : delete mpSizer;
374 0 : }
375 : };
376 :
377 :
378 :
379 : const sal_uInt16 TabBar::APPEND = ::std::numeric_limits<sal_uInt16>::max();
380 : const sal_uInt16 TabBar::PAGE_NOT_FOUND = ::std::numeric_limits<sal_uInt16>::max();
381 : const sal_uInt16 TabBar::INSERT_TAB_POS = ::std::numeric_limits<sal_uInt16>::max() - 1;
382 :
383 0 : void TabBar::ImplInit( WinBits nWinStyle )
384 : {
385 0 : mpItemList = new ImplTabBarList;
386 0 : mpFirstBtn = NULL;
387 0 : mpPrevBtn = NULL;
388 0 : mpNextBtn = NULL;
389 0 : mpLastBtn = NULL;
390 0 : mpImpl = new TabBar_Impl;
391 0 : mpEdit = NULL;
392 0 : mnMaxPageWidth = 0;
393 0 : mnCurMaxWidth = 0;
394 0 : mnOffX = 0;
395 0 : mnOffY = 0;
396 0 : mnLastOffX = 0;
397 0 : mnSplitSize = 0;
398 0 : mnSwitchTime = 0;
399 0 : mnWinStyle = nWinStyle;
400 0 : mnCurPageId = 0;
401 0 : mnFirstPos = 0;
402 0 : mnDropPos = 0;
403 0 : mnSwitchId = 0;
404 0 : mnEditId = 0;
405 0 : mbFormat = true;
406 0 : mbFirstFormat = true;
407 0 : mbSizeFormat = true;
408 0 : mbAutoMaxWidth = true;
409 0 : mbInSwitching = false;
410 0 : mbAutoEditMode = false;
411 0 : mbEditCanceled = false;
412 0 : mbDropPos = false;
413 0 : mbInSelect = false;
414 0 : mbSelColor = false;
415 0 : mbSelTextColor = false;
416 0 : mbMirrored = false;
417 0 : mbMirrored = false;
418 0 : mbScrollAlwaysEnabled = false;
419 :
420 0 : if ( nWinStyle & WB_3DTAB )
421 0 : mnOffY++;
422 :
423 0 : ImplInitControls();
424 :
425 0 : if(mpFirstBtn)
426 0 : mpFirstBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVET0HOME));
427 0 : if(mpPrevBtn)
428 0 : mpPrevBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVELEFT));
429 0 : if(mpNextBtn)
430 0 : mpNextBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVERIGHT));
431 0 : if(mpLastBtn)
432 0 : mpLastBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVETOEND));
433 :
434 0 : SetSizePixel( Size( 100, CalcWindowSizePixel().Height() ) );
435 0 : ImplInitSettings( true, true );
436 0 : }
437 :
438 :
439 :
440 0 : TabBar::TabBar( Window* pParent, WinBits nWinStyle ) :
441 0 : Window( pParent, (nWinStyle & WB_3DLOOK) | WB_CLIPCHILDREN )
442 : {
443 0 : ImplInit( nWinStyle );
444 0 : maCurrentItemList = 0;
445 0 : }
446 :
447 :
448 :
449 0 : TabBar::~TabBar()
450 : {
451 0 : EndEditMode( true );
452 :
453 : // Controls loeschen
454 0 : if ( mpPrevBtn )
455 0 : delete mpPrevBtn;
456 0 : if ( mpNextBtn )
457 0 : delete mpNextBtn;
458 0 : if ( mpFirstBtn )
459 0 : delete mpFirstBtn;
460 0 : if ( mpLastBtn )
461 0 : delete mpLastBtn;
462 0 : delete mpImpl;
463 :
464 0 : for ( size_t i = 0, n = mpItemList->size(); i < n; ++i ) {
465 0 : delete (*mpItemList)[ i ];
466 : }
467 0 : delete mpItemList;
468 0 : }
469 :
470 :
471 0 : ImplTabBarItem* TabBar::seek( size_t i )
472 : {
473 0 : if ( i < mpItemList->size() )
474 : {
475 0 : maCurrentItemList = i;
476 0 : return (*mpItemList)[ maCurrentItemList ];
477 : }
478 0 : return NULL;
479 : }
480 :
481 0 : ImplTabBarItem* TabBar::prev()
482 : {
483 0 : if ( maCurrentItemList > 0 ) {
484 0 : return (*mpItemList)[ --maCurrentItemList ];
485 : }
486 0 : return NULL;
487 : }
488 :
489 0 : ImplTabBarItem* TabBar::next()
490 : {
491 0 : if ( maCurrentItemList+1 < mpItemList->size() ) {
492 0 : return (*mpItemList)[ ++maCurrentItemList ];
493 : }
494 0 : return NULL;
495 : }
496 :
497 :
498 :
499 0 : void TabBar::ImplInitSettings( bool bFont, bool bBackground )
500 : {
501 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
502 :
503 0 : if ( bFont )
504 : {
505 0 : Font aToolFont;
506 0 : aToolFont = rStyleSettings.GetToolFont();
507 0 : if ( IsControlFont() )
508 0 : aToolFont.Merge( GetControlFont() );
509 0 : aToolFont.SetWeight( WEIGHT_BOLD );
510 0 : SetZoomedPointFont( aToolFont );
511 :
512 : // Adapt font size if window too small?
513 0 : while ( GetTextHeight() > (GetOutputSizePixel().Height()-1) )
514 : {
515 0 : Font aFont = GetFont();
516 0 : if ( aFont.GetHeight() <= 6 )
517 0 : break;
518 0 : aFont.SetHeight( aFont.GetHeight()-1 );
519 0 : SetFont( aFont );
520 0 : }
521 : }
522 :
523 0 : if ( bBackground )
524 : {
525 0 : Color aColor;
526 0 : if ( IsControlBackground() )
527 0 : aColor = GetControlBackground();
528 : else
529 0 : aColor = rStyleSettings.GetFaceColor();
530 0 : SetBackground( aColor );
531 : }
532 0 : }
533 :
534 :
535 :
536 0 : void TabBar::ImplGetColors( Color& rFaceColor, Color& rFaceTextColor,
537 : Color& rSelectColor, Color& rSelectTextColor )
538 : {
539 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
540 :
541 0 : if ( IsControlBackground() )
542 0 : rFaceColor = GetControlBackground();
543 : else
544 0 : rFaceColor = rStyleSettings.GetInactiveTabColor();
545 0 : if ( IsControlForeground() )
546 0 : rFaceTextColor = GetControlForeground();
547 : else
548 0 : rFaceTextColor = rStyleSettings.GetButtonTextColor();
549 0 : if ( mbSelColor )
550 0 : rSelectColor = maSelColor;
551 : else
552 0 : rSelectColor = rStyleSettings.GetActiveTabColor();
553 0 : if ( mbSelTextColor )
554 0 : rSelectTextColor = maSelTextColor;
555 : else
556 0 : rSelectTextColor = rStyleSettings.GetWindowTextColor();
557 :
558 : // For 3D-tabs the selection- and face-colours are swapped,
559 : // as the selected tabs should appear in 3D
560 0 : if ( mnWinStyle & WB_3DTAB )
561 : {
562 0 : Color aTempColor = rFaceColor;
563 0 : rFaceColor = rSelectColor;
564 0 : rSelectColor = aTempColor;
565 0 : aTempColor = rFaceTextColor;
566 0 : rFaceTextColor = rSelectTextColor;
567 0 : rSelectTextColor = rFaceTextColor;
568 : }
569 0 : }
570 :
571 :
572 :
573 0 : bool TabBar::ImplCalcWidth()
574 : {
575 : // Sizes should only be retrieved if the text or the font was changed
576 0 : if ( !mbSizeFormat )
577 0 : return false;
578 :
579 : // retrieve width of tabs with bold font
580 0 : Font aFont = GetFont();
581 0 : if ( aFont.GetWeight() != WEIGHT_BOLD )
582 : {
583 0 : aFont.SetWeight( WEIGHT_BOLD );
584 0 : SetFont( aFont );
585 : }
586 :
587 0 : if ( mnMaxPageWidth )
588 0 : mnCurMaxWidth = mnMaxPageWidth;
589 0 : else if ( mbAutoMaxWidth )
590 : {
591 0 : mnCurMaxWidth = mnLastOffX-mnOffX-
592 : TABBAR_OFFSET_X-TABBAR_OFFSET_X-
593 0 : TABBAR_OFFSET_X2-TABBAR_OFFSET_X2-TABBAR_OFFSET_X2;
594 0 : if ( mnCurMaxWidth < 1 )
595 0 : mnCurMaxWidth = 1;
596 : }
597 : else
598 0 : mnCurMaxWidth = 0;
599 :
600 0 : bool bChanged = false;
601 0 : for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
602 : {
603 0 : ImplTabBarItem* pItem = (*mpItemList)[ i ];
604 0 : long nNewWidth = GetTextWidth( pItem->maText );
605 0 : if ( mnCurMaxWidth && (nNewWidth > mnCurMaxWidth) )
606 : {
607 0 : pItem->mbShort = true;
608 0 : nNewWidth = mnCurMaxWidth;
609 : }
610 : else
611 0 : pItem->mbShort = false;
612 0 : nNewWidth += TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
613 0 : if ( pItem->mnWidth != nNewWidth )
614 : {
615 0 : pItem->mnWidth = nNewWidth;
616 0 : if ( !pItem->maRect.IsEmpty() )
617 0 : bChanged = true;
618 : }
619 : }
620 0 : mbSizeFormat = false;
621 0 : mbFormat = true;
622 0 : return bChanged;
623 : }
624 :
625 :
626 :
627 0 : void TabBar::ImplFormat()
628 : {
629 0 : ImplCalcWidth();
630 :
631 0 : if ( !mbFormat )
632 0 : return;
633 :
634 0 : sal_uInt16 n = 0;
635 0 : long x = mnOffX;
636 0 : for ( size_t i = 0, nL = mpItemList->size(); i < nL; ++i )
637 : {
638 0 : ImplTabBarItem* pItem = (*mpItemList)[ i ];
639 : // At all non-visible tabs an empty rectangle is set
640 0 : if ( (n+1 < mnFirstPos) || (x > mnLastOffX) )
641 0 : pItem->maRect.SetEmpty();
642 : else
643 : {
644 : // Slightly before the tab before the first visible page
645 : // should also be visible
646 0 : if ( n+1 == mnFirstPos )
647 0 : pItem->maRect.Left() = x-pItem->mnWidth;
648 : else
649 : {
650 0 : pItem->maRect.Left() = x;
651 0 : x += pItem->mnWidth;
652 : }
653 0 : pItem->maRect.Right() = x+TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
654 0 : pItem->maRect.Bottom() = maWinSize.Height()-1;
655 :
656 0 : if( mbMirrored )
657 : {
658 0 : long nTmp = mnOffX + mnLastOffX - pItem->maRect.Right();
659 0 : pItem->maRect.Right() = mnOffX + mnLastOffX - pItem->maRect.Left();
660 0 : pItem->maRect.Left() = nTmp;
661 : }
662 : }
663 :
664 0 : n++;
665 : }
666 :
667 0 : mbFormat = false;
668 :
669 : // enable/disable button
670 0 : ImplEnableControls();
671 : }
672 :
673 :
674 :
675 0 : sal_uInt16 TabBar::ImplGetLastFirstPos()
676 : {
677 0 : sal_uInt16 nCount = (sal_uInt16)(mpItemList->size());
678 0 : if ( !nCount || mbSizeFormat || mbFormat )
679 0 : return 0;
680 :
681 0 : sal_uInt16 nLastFirstPos = nCount-1;
682 0 : long nWinWidth = mnLastOffX-mnOffX-TABBAR_OFFSET_X-ADDNEWPAGE_AREAWIDTH;
683 0 : long nWidth = (*mpItemList)[ nLastFirstPos ]->mnWidth;
684 0 : while ( nLastFirstPos && (nWidth < nWinWidth) )
685 : {
686 0 : nLastFirstPos--;
687 0 : nWidth += (*mpItemList)[ nLastFirstPos ]->mnWidth;
688 : }
689 0 : if ( (nLastFirstPos != (sal_uInt16)(mpItemList->size()-1)) &&
690 : (nWidth > nWinWidth) )
691 0 : nLastFirstPos++;
692 0 : return nLastFirstPos;
693 : }
694 :
695 :
696 :
697 0 : void TabBar::ImplInitControls()
698 : {
699 0 : if ( mnWinStyle & WB_SIZEABLE )
700 : {
701 0 : if ( !mpImpl->mpSizer )
702 0 : mpImpl->mpSizer = new ImplTabSizer( this, mnWinStyle & (WB_DRAG | WB_3DLOOK) );
703 0 : mpImpl->mpSizer->Show();
704 : }
705 : else
706 : {
707 0 : DELETEZ( mpImpl->mpSizer );
708 : }
709 :
710 0 : Link aLink = LINK( this, TabBar, ImplClickHdl );
711 :
712 0 : if ( mnWinStyle & (WB_MINSCROLL | WB_SCROLL) )
713 : {
714 0 : if ( !mpPrevBtn )
715 : {
716 0 : mpPrevBtn = new ImplTabButton( this, WB_REPEAT );
717 0 : mpPrevBtn->SetClickHdl( aLink );
718 : }
719 0 : mpPrevBtn->SetSymbol( mbMirrored ? SYMBOL_NEXT : SYMBOL_PREV );
720 0 : mpPrevBtn->Show();
721 :
722 0 : if ( !mpNextBtn )
723 : {
724 0 : mpNextBtn = new ImplTabButton( this, WB_REPEAT );
725 0 : mpNextBtn->SetClickHdl( aLink );
726 : }
727 0 : mpNextBtn->SetSymbol( mbMirrored ? SYMBOL_PREV : SYMBOL_NEXT );
728 0 : mpNextBtn->Show();
729 : }
730 : else
731 : {
732 0 : DELETEZ( mpPrevBtn );
733 0 : DELETEZ( mpNextBtn );
734 : }
735 :
736 0 : if ( mnWinStyle & WB_SCROLL )
737 : {
738 0 : if ( !mpFirstBtn )
739 : {
740 0 : mpFirstBtn = new ImplTabButton( this );
741 0 : mpFirstBtn->SetClickHdl( aLink );
742 : }
743 0 : mpFirstBtn->SetSymbol( mbMirrored ? SYMBOL_LAST : SYMBOL_FIRST );
744 0 : mpFirstBtn->Show();
745 :
746 0 : if ( !mpLastBtn )
747 : {
748 0 : mpLastBtn = new ImplTabButton( this );
749 0 : mpLastBtn->SetClickHdl( aLink );
750 : }
751 0 : mpLastBtn->SetSymbol( mbMirrored ? SYMBOL_FIRST : SYMBOL_LAST );
752 0 : mpLastBtn->Show();
753 : }
754 : else
755 : {
756 0 : DELETEZ( mpFirstBtn );
757 0 : DELETEZ( mpLastBtn );
758 : }
759 :
760 0 : mbHasInsertTab = (mnWinStyle & WB_INSERTTAB);
761 0 : }
762 :
763 :
764 :
765 0 : void TabBar::ImplEnableControls()
766 : {
767 0 : if ( mbSizeFormat || mbFormat )
768 0 : return;
769 :
770 : // enable/disable buttons
771 0 : bool bEnableBtn = mbScrollAlwaysEnabled || mnFirstPos > 0;
772 0 : if ( mpFirstBtn )
773 0 : mpFirstBtn->Enable( bEnableBtn );
774 0 : if ( mpPrevBtn )
775 0 : mpPrevBtn->Enable( bEnableBtn );
776 :
777 0 : bEnableBtn = mbScrollAlwaysEnabled || mnFirstPos < ImplGetLastFirstPos();
778 0 : if ( mpNextBtn )
779 0 : mpNextBtn->Enable( bEnableBtn );
780 0 : if ( mpLastBtn )
781 0 : mpLastBtn->Enable( bEnableBtn );
782 : }
783 :
784 0 : void TabBar::SetScrollAlwaysEnabled(bool bScrollAlwaysEnabled)
785 : {
786 0 : mbScrollAlwaysEnabled = bScrollAlwaysEnabled;
787 0 : ImplEnableControls();
788 0 : }
789 :
790 :
791 :
792 0 : void TabBar::ImplShowPage( sal_uInt16 nPos )
793 : {
794 : // calculate width
795 0 : long nWidth = GetOutputSizePixel().Width();
796 0 : if ( nWidth >= TABBAR_OFFSET_X )
797 0 : nWidth -= TABBAR_OFFSET_X;
798 0 : ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
799 0 : if ( nPos < mnFirstPos )
800 0 : SetFirstPageId( pItem->mnId );
801 0 : else if ( pItem->maRect.Right() > nWidth )
802 : {
803 0 : while ( pItem->maRect.Right() > nWidth )
804 : {
805 0 : sal_uInt16 nNewPos = mnFirstPos+1;
806 0 : SetFirstPageId( GetPageId( nNewPos ) );
807 0 : ImplFormat();
808 0 : if ( nNewPos != mnFirstPos )
809 0 : break;
810 : }
811 : }
812 0 : }
813 :
814 :
815 :
816 0 : IMPL_LINK( TabBar, ImplClickHdl, ImplTabButton*, pBtn )
817 : {
818 0 : EndEditMode();
819 :
820 0 : sal_uInt16 nNewPos = mnFirstPos;
821 :
822 0 : if ( pBtn == mpFirstBtn )
823 0 : nNewPos = 0;
824 0 : else if ( pBtn == mpPrevBtn )
825 : {
826 0 : if ( mnFirstPos )
827 0 : nNewPos = mnFirstPos-1;
828 : }
829 0 : else if ( pBtn == mpNextBtn )
830 : {
831 0 : sal_uInt16 nCount = GetPageCount();
832 0 : if ( mnFirstPos < nCount )
833 0 : nNewPos = mnFirstPos+1;
834 : }
835 : else
836 : {
837 0 : sal_uInt16 nCount = GetPageCount();
838 0 : if ( nCount )
839 0 : nNewPos = nCount-1;
840 : }
841 :
842 0 : if ( nNewPos != mnFirstPos )
843 0 : SetFirstPageId( GetPageId( nNewPos ) );
844 0 : return 0;
845 : }
846 :
847 :
848 :
849 0 : void TabBar::MouseMove( const MouseEvent& rMEvt )
850 : {
851 0 : if ( rMEvt.IsLeaveWindow() )
852 0 : mbInSelect = false;
853 :
854 0 : Window::MouseMove( rMEvt );
855 0 : }
856 :
857 :
858 :
859 0 : void TabBar::MouseButtonDown( const MouseEvent& rMEvt )
860 : {
861 : // Only terminate EditModus and do not execute Klick
862 : // if clicked inside our window,
863 0 : if ( IsInEditMode() )
864 : {
865 0 : EndEditMode();
866 0 : return;
867 : }
868 :
869 : ImplTabBarItem* pItem;
870 0 : sal_uInt16 nSelId = GetPageId( rMEvt.GetPosPixel() );
871 :
872 0 : if ( !rMEvt.IsLeft() )
873 : {
874 0 : Window::MouseButtonDown( rMEvt );
875 0 : if ( (nSelId > 0) && (nSelId != mnCurPageId) )
876 : {
877 0 : sal_uInt16 nPos = GetPagePos( nSelId );
878 0 : pItem = (*mpItemList)[ nPos ];
879 :
880 0 : if ( pItem->mbEnable )
881 : {
882 0 : if ( ImplDeactivatePage() )
883 : {
884 0 : SetCurPageId( nSelId );
885 0 : Update();
886 0 : ImplActivatePage();
887 0 : ImplSelect();
888 : }
889 0 : mbInSelect = true;
890 : }
891 : }
892 0 : return;
893 : }
894 :
895 0 : if ( rMEvt.IsMod2() && mbAutoEditMode && nSelId )
896 : {
897 0 : if ( StartEditMode( nSelId ) )
898 0 : return;
899 : }
900 :
901 0 : if ( (rMEvt.GetMode() & (MOUSE_MULTISELECT | MOUSE_RANGESELECT)) && (rMEvt.GetClicks() == 1) )
902 : {
903 0 : if ( nSelId )
904 : {
905 0 : sal_uInt16 nPos = GetPagePos( nSelId );
906 0 : bool bSelectTab = false;
907 0 : pItem = (*mpItemList)[ nPos ];
908 :
909 0 : if ( pItem->mbEnable )
910 : {
911 0 : if ( (rMEvt.GetMode() & MOUSE_MULTISELECT) && (mnWinStyle & WB_MULTISELECT) )
912 : {
913 0 : if ( nSelId != mnCurPageId )
914 : {
915 0 : SelectPage( nSelId, !IsPageSelected( nSelId ) );
916 0 : bSelectTab = true;
917 : }
918 : }
919 0 : else if ( mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT) )
920 : {
921 0 : bSelectTab = true;
922 : sal_uInt16 n;
923 : bool bSelect;
924 0 : sal_uInt16 nCurPos = GetPagePos( mnCurPageId );
925 0 : if ( nPos <= nCurPos )
926 : {
927 : // Deselect all tabs till the clicked tab
928 : // and select all tabs from the clicked tab
929 : // till the the actual position
930 0 : n = 0;
931 0 : while ( n < nCurPos )
932 : {
933 0 : pItem = (*mpItemList)[ n ];
934 0 : if ( n < nPos )
935 0 : bSelect = false;
936 : else
937 0 : bSelect = true;
938 :
939 0 : if ( pItem->mbSelect != bSelect )
940 : {
941 0 : pItem->mbSelect = bSelect;
942 0 : if ( !pItem->maRect.IsEmpty() )
943 0 : Invalidate( pItem->maRect );
944 : }
945 :
946 0 : n++;
947 : }
948 : }
949 :
950 0 : if ( nPos >= nCurPos )
951 : {
952 : // Select all tabs from the actual position till the clicked tab
953 : // and deselect all tabs from the actual position
954 : // till the last tab
955 0 : sal_uInt16 nCount = (sal_uInt16)mpItemList->size();
956 0 : n = nCurPos;
957 0 : while ( n < nCount )
958 : {
959 0 : pItem = (*mpItemList)[ n ];
960 :
961 0 : if ( n <= nPos )
962 0 : bSelect = true;
963 : else
964 0 : bSelect = false;
965 :
966 0 : if ( pItem->mbSelect != bSelect )
967 : {
968 0 : pItem->mbSelect = bSelect;
969 0 : if ( !pItem->maRect.IsEmpty() )
970 0 : Invalidate( pItem->maRect );
971 : }
972 :
973 0 : n++;
974 : }
975 : }
976 : }
977 :
978 : // scroll the selected tab if required
979 0 : if ( bSelectTab )
980 : {
981 0 : ImplShowPage( nPos );
982 0 : Update();
983 0 : ImplSelect();
984 : }
985 : }
986 : else
987 0 : ImplShowPage( nPos );
988 0 : mbInSelect = true;
989 :
990 0 : return;
991 : }
992 : }
993 0 : else if ( rMEvt.GetClicks() == 2 )
994 : {
995 : // call double-click-handler if required
996 0 : if ( !rMEvt.GetModifier() && (!nSelId || (nSelId == mnCurPageId)) )
997 : {
998 0 : sal_uInt16 nOldCurId = mnCurPageId;
999 0 : mnCurPageId = nSelId;
1000 0 : DoubleClick();
1001 : // check, as actual page could be switched inside
1002 : // the doubleclick-handler
1003 0 : if ( mnCurPageId == nSelId )
1004 0 : mnCurPageId = nOldCurId;
1005 : }
1006 :
1007 0 : return;
1008 : }
1009 : else
1010 : {
1011 0 : if ( nSelId )
1012 : {
1013 : // execute Select if not actual page
1014 0 : if ( nSelId != mnCurPageId )
1015 : {
1016 0 : sal_uInt16 nPos = GetPagePos( nSelId );
1017 0 : pItem = (*mpItemList)[ nPos ];
1018 :
1019 0 : if ( pItem->mbEnable )
1020 : {
1021 0 : if ( !pItem->mbSelect )
1022 : {
1023 : // make not valid
1024 0 : bool bUpdate = false;
1025 0 : if ( IsReallyVisible() && IsUpdateMode() )
1026 0 : bUpdate = true;
1027 :
1028 : // deselect all selected items
1029 0 : for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
1030 : {
1031 0 : pItem = (*mpItemList)[ i ];
1032 0 : if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) )
1033 : {
1034 0 : pItem->mbSelect = false;
1035 0 : if ( bUpdate )
1036 0 : Invalidate( pItem->maRect );
1037 : }
1038 : }
1039 : }
1040 :
1041 0 : if ( ImplDeactivatePage() )
1042 : {
1043 0 : SetCurPageId( nSelId );
1044 0 : Update();
1045 0 : ImplActivatePage();
1046 0 : ImplSelect();
1047 : }
1048 : }
1049 : else
1050 0 : ImplShowPage( nPos );
1051 0 : mbInSelect = true;
1052 : }
1053 :
1054 0 : return;
1055 : }
1056 : }
1057 :
1058 0 : Window::MouseButtonDown( rMEvt );
1059 : }
1060 :
1061 :
1062 :
1063 0 : void TabBar::MouseButtonUp( const MouseEvent& rMEvt )
1064 : {
1065 0 : mbInSelect = false;
1066 0 : Window::MouseButtonUp( rMEvt );
1067 0 : }
1068 :
1069 :
1070 :
1071 :
1072 : namespace {
1073 :
1074 : class TabBarPaintGuard
1075 : {
1076 : public:
1077 0 : explicit TabBarPaintGuard(TabBar& rParent) :
1078 : mrParent(rParent),
1079 0 : maFont(rParent.GetFont())
1080 : {
1081 : // #i36013# exclude push buttons from painting area
1082 0 : mrParent.SetClipRegion( Region(mrParent.GetPageArea()) );
1083 0 : }
1084 :
1085 0 : ~TabBarPaintGuard()
1086 0 : {
1087 : // Restore original font.
1088 0 : mrParent.SetFont(maFont);
1089 : // remove clip region
1090 0 : mrParent.SetClipRegion();
1091 0 : }
1092 : private:
1093 : TabBar& mrParent;
1094 : Font maFont;
1095 : };
1096 :
1097 0 : class TabDrawer
1098 : {
1099 : public:
1100 :
1101 0 : explicit TabDrawer(TabBar& rParent) :
1102 : mrParent(rParent),
1103 0 : mpStyleSettings(&mrParent.GetSettings().GetStyleSettings()),
1104 : maPoly(4),
1105 : mbSelected(false),
1106 : mbCustomColored(false),
1107 : mbSpecialTab(false),
1108 0 : mbEnabled(false)
1109 : {
1110 0 : }
1111 :
1112 0 : void drawOutputAreaBorder()
1113 : {
1114 0 : WinBits nWinStyle = mrParent.GetStyle();
1115 :
1116 : // draw extra line if above and below border
1117 0 : if ( (nWinStyle & WB_BORDER) || (nWinStyle & WB_TOPBORDER) )
1118 : {
1119 0 : Size aOutputSize = mrParent.GetOutputSizePixel();
1120 0 : Rectangle aOutRect = mrParent.GetPageArea();
1121 :
1122 : // also draw border in 3D for 3D-tabs
1123 0 : if ( nWinStyle & WB_3DTAB )
1124 : {
1125 0 : mrParent.SetLineColor( mpStyleSettings->GetShadowColor() );
1126 0 : mrParent.DrawLine( Point( aOutRect.Left(), 0 ), Point( aOutputSize.Width(), 0 ) );
1127 : }
1128 :
1129 : // draw border (line above and line below)
1130 0 : mrParent.SetLineColor( mpStyleSettings->GetDarkShadowColor() );
1131 0 : mrParent.DrawLine( aOutRect.TopLeft(), Point( aOutputSize.Width()-1, aOutRect.Top() ) );
1132 : }
1133 0 : }
1134 :
1135 0 : void drawOuterFrame()
1136 : {
1137 0 : mrParent.DrawPolygon(maPoly);
1138 0 : }
1139 :
1140 0 : void drawLeftShadow()
1141 : {
1142 0 : Point p1 = maPoly[0], p2 = maPoly[1];
1143 0 : p1.X()++;
1144 0 : p2.X()++;
1145 0 : p2.Y()--;
1146 0 : mrParent.DrawLine(p1, p2);
1147 0 : }
1148 :
1149 0 : void drawRightShadow()
1150 : {
1151 0 : Point p1 = maPoly[2];
1152 0 : Point p2 = maPoly[3];
1153 0 : p1.X()--;
1154 0 : p2.X()--;
1155 0 : mrParent.DrawLine(p1, p2);
1156 0 : }
1157 :
1158 0 : void drawTopInnerShadow()
1159 : {
1160 0 : Point p1 = maPoly[0], p2 = maPoly[3];
1161 0 : p1.Y()++;
1162 0 : p2.Y()++;
1163 0 : mrParent.DrawLine(p1, p2);
1164 0 : }
1165 :
1166 0 : void drawBottomShadow(bool bColored)
1167 : {
1168 0 : Point p1 = maPoly[1], p2 = maPoly[2];
1169 0 : p1.X() += 1;
1170 0 : p1.Y() -= 1;
1171 0 : p2.X() -= 1;
1172 0 : p2.Y() -= 1;
1173 0 : mrParent.DrawLine(p1, p2);
1174 0 : if (bColored)
1175 : {
1176 0 : p1 += Point(-1, -1);
1177 0 : p2 += Point(1, -1);
1178 0 : mrParent.DrawLine(p1, p2);
1179 : }
1180 0 : }
1181 :
1182 0 : void drawText(const OUString& aText)
1183 : {
1184 0 : Rectangle aRect = maRect;
1185 0 : long nTextWidth = mrParent.GetTextWidth(aText);
1186 0 : long nTextHeight = mrParent.GetTextHeight();
1187 0 : Point aPos = aRect.TopLeft();
1188 0 : aPos.X() += (aRect.getWidth() - nTextWidth) / 2;
1189 0 : aPos.Y() += (aRect.getHeight() - nTextHeight) / 2;
1190 :
1191 0 : if (mbEnabled)
1192 0 : mrParent.DrawText(aPos, aText);
1193 : else
1194 : mrParent.DrawCtrlText( aPos, aText, 0, aText.getLength(),
1195 0 : (TEXT_DRAW_DISABLE | TEXT_DRAW_MNEMONIC));
1196 0 : }
1197 :
1198 0 : void drawOverTopBorder(bool b3DTab)
1199 : {
1200 0 : Point p1 = maPoly[0], p2 = maPoly[3];
1201 0 : p1.X() += 1;
1202 0 : p2.X() -= 1;
1203 0 : Rectangle aDelRect(p1, p2);
1204 0 : mrParent.DrawRect(aDelRect);
1205 0 : if (b3DTab)
1206 : {
1207 0 : aDelRect.Top()--;
1208 0 : mrParent.DrawRect(aDelRect);
1209 : }
1210 0 : }
1211 :
1212 0 : void drawTab()
1213 : {
1214 0 : mrParent.SetLineColor(mpStyleSettings->GetDarkShadowColor());
1215 :
1216 : // set correct FillInBrush depending on status
1217 0 : if ( mbSelected )
1218 : {
1219 : // Currently selected Tab
1220 0 : mrParent.SetFillColor( maSelectedColor );
1221 : }
1222 0 : else if ( mbCustomColored )
1223 : {
1224 0 : mrParent.SetFillColor( maCustomColor );
1225 : }
1226 : else
1227 : {
1228 0 : mrParent.SetFillColor( maUnselectedColor );
1229 : }
1230 :
1231 0 : drawOuterFrame();
1232 :
1233 : // If this is the current tab, draw the left inner shadow the default color,
1234 : // otherwise make it the same as the custom background color
1235 0 : Color aColor = mpStyleSettings->GetLightColor();
1236 0 : if (mbCustomColored && !mbSelected)
1237 0 : aColor = maCustomColor;
1238 :
1239 0 : mrParent.SetLineColor(aColor);
1240 0 : drawLeftShadow();
1241 :
1242 0 : if ( !mbSelected )
1243 0 : drawTopInnerShadow();
1244 :
1245 0 : mrParent.SetLineColor( mpStyleSettings->GetShadowColor() );
1246 0 : drawRightShadow();
1247 0 : if ( mbCustomColored && mbSelected )
1248 : {
1249 0 : mrParent.SetLineColor(maCustomColor);
1250 0 : drawBottomShadow(true);
1251 : }
1252 : else
1253 0 : drawBottomShadow(false);
1254 :
1255 : // Draw the outer frame once more. In some environments, the outer frame
1256 : // gets overpainted.
1257 0 : mrParent.SetLineColor( mpStyleSettings->GetDarkShadowColor() );
1258 0 : mrParent.SetFillColor();
1259 0 : drawOuterFrame();
1260 0 : }
1261 :
1262 0 : void drawPlusImage()
1263 : {
1264 0 : SvtResId id( BMP_LIST_ADD );
1265 0 : Image aPlusImg( id );
1266 : // Center the image within the bounding rectangle.
1267 0 : Size aSize = aPlusImg.GetSizePixel();
1268 0 : Point pt = maRect.TopLeft();
1269 0 : long nXOffSet = (maRect.GetWidth() - aSize.Width()) / 2;
1270 0 : long nYOffset = (maRect.GetHeight() - aSize.Height()) / 2;
1271 0 : pt += Point(nXOffSet, nYOffset);
1272 0 : pt.X() += 1;
1273 0 : mrParent.DrawImage(pt, aPlusImg);
1274 0 : }
1275 :
1276 0 : void setRect(const Rectangle& rRect)
1277 : {
1278 0 : maRect = rRect;
1279 :
1280 0 : long nOffY = mrParent.GetPageArea().getY();
1281 :
1282 : // first draw filled polygon
1283 0 : maPoly[0] = Point( rRect.Left(), nOffY );
1284 0 : maPoly[1] = Point( rRect.Left()+TABBAR_OFFSET_X, rRect.Bottom() );
1285 0 : maPoly[2] = Point( rRect.Right()-TABBAR_OFFSET_X, rRect.Bottom() );
1286 0 : maPoly[3] = Point( rRect.Right(), nOffY );
1287 0 : }
1288 :
1289 0 : void setSelected(bool b)
1290 : {
1291 0 : mbSelected = b;
1292 0 : }
1293 :
1294 0 : void setCustomColored(bool b)
1295 : {
1296 0 : mbCustomColored = b;
1297 0 : }
1298 :
1299 0 : void setSpecialTab(bool b)
1300 : {
1301 0 : mbSpecialTab = b;
1302 0 : }
1303 :
1304 0 : void setEnabled(bool b)
1305 : {
1306 0 : mbEnabled = b;
1307 0 : }
1308 :
1309 0 : void setSelectedFillColor(const Color& rColor)
1310 : {
1311 0 : maSelectedColor = rColor;
1312 0 : }
1313 :
1314 0 : void setUnselectedFillColor(const Color& rColor)
1315 : {
1316 0 : maUnselectedColor = rColor;
1317 0 : }
1318 :
1319 0 : void setCustomColor(const Color& rColor)
1320 : {
1321 0 : maCustomColor = rColor;
1322 0 : }
1323 :
1324 : private:
1325 : TabBar& mrParent;
1326 : const StyleSettings* mpStyleSettings;
1327 :
1328 : Rectangle maRect;
1329 : Polygon maPoly;
1330 :
1331 : Color maSelectedColor;
1332 : Color maCustomColor;
1333 : Color maUnselectedColor;
1334 :
1335 : bool mbSelected:1;
1336 : bool mbCustomColored:1;
1337 : bool mbSpecialTab:1;
1338 : bool mbEnabled:1;
1339 : };
1340 :
1341 : }
1342 :
1343 0 : void TabBar::Paint( const Rectangle& rect )
1344 : {
1345 0 : if(IsNativeControlSupported(CTRL_WINDOW_BACKGROUND,PART_ENTIRE_CONTROL))
1346 : DrawNativeControl(CTRL_WINDOW_BACKGROUND,PART_ENTIRE_CONTROL,rect,
1347 0 : CTRL_STATE_ENABLED,ImplControlValue(0),OUString());
1348 :
1349 : // calculate items and emit
1350 0 : sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
1351 0 : if (!nItemCount)
1352 0 : return;
1353 :
1354 0 : ImplPrePaint();
1355 :
1356 0 : Color aFaceColor, aSelectColor, aFaceTextColor, aSelectTextColor;
1357 0 : ImplGetColors( aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor );
1358 :
1359 : // select font
1360 0 : Font aFont = GetFont();
1361 0 : Font aLightFont = aFont;
1362 0 : aLightFont.SetWeight( WEIGHT_NORMAL );
1363 :
1364 0 : TabBarPaintGuard aGuard(*this);
1365 0 : TabDrawer aDrawer(*this);
1366 0 : aDrawer.setSelectedFillColor(aSelectColor);
1367 0 : aDrawer.setUnselectedFillColor(aFaceColor);
1368 0 : aDrawer.drawOutputAreaBorder();
1369 :
1370 : // Now, start drawing the tabs.
1371 :
1372 0 : ImplTabBarItem* pItem = ImplGetLastTabBarItem(nItemCount);
1373 :
1374 0 : if (pItem && mbHasInsertTab)
1375 : {
1376 : // Draw the insert tab at the right end.
1377 0 : Rectangle aRect = ImplGetInsertTabRect(pItem);
1378 0 : aDrawer.setRect(aRect);
1379 0 : aDrawer.drawTab();
1380 0 : aDrawer.drawPlusImage();
1381 : }
1382 :
1383 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1384 0 : ImplTabBarItem* pCurItem = NULL;
1385 0 : while ( pItem )
1386 : {
1387 : // emit CurrentItem last, as it covers all others
1388 0 : if ( !pCurItem && (pItem->mnId == mnCurPageId) )
1389 : {
1390 0 : pCurItem = pItem;
1391 0 : pItem = prev();
1392 0 : if ( !pItem )
1393 0 : pItem = pCurItem;
1394 0 : continue;
1395 : }
1396 :
1397 0 : bool bCurrent = pItem == pCurItem;
1398 :
1399 0 : if ( !pItem->maRect.IsEmpty() )
1400 : {
1401 0 : Rectangle aRect = pItem->maRect;
1402 0 : bool bSelected = pItem->IsSelected(pCurItem);
1403 : // We disable custom background color in high contrast mode.
1404 0 : bool bCustomBgColor = !pItem->IsDefaultTabBgColor() && !rStyleSettings.GetHighContrastMode();
1405 0 : bool bSpecialTab = (pItem->mnBits & TPB_SPECIAL);
1406 0 : bool bEnabled = pItem->mbEnable;
1407 : OUString aText = pItem->mbShort ?
1408 0 : GetEllipsisString(pItem->maText, mnCurMaxWidth, TEXT_DRAW_ENDELLIPSIS) : pItem->maText;
1409 :
1410 0 : aDrawer.setRect(aRect);
1411 0 : aDrawer.setSelected(bSelected);
1412 0 : aDrawer.setCustomColored(bCustomBgColor);
1413 0 : aDrawer.setSpecialTab(bSpecialTab);
1414 0 : aDrawer.setEnabled(bEnabled);
1415 0 : aDrawer.setCustomColor(pItem->maTabBgColor);
1416 0 : aDrawer.drawTab();
1417 :
1418 : // actual page is drawn using a bold font
1419 0 : if ( bCurrent )
1420 0 : SetFont( aFont );
1421 : else
1422 0 : SetFont( aLightFont );
1423 :
1424 : // Set the correct FillInBrush depending on status
1425 :
1426 0 : if ( bSelected )
1427 0 : SetTextColor( aSelectTextColor );
1428 0 : else if ( bCustomBgColor )
1429 0 : SetTextColor( pItem->maTabTextColor );
1430 : else
1431 0 : SetTextColor( aFaceTextColor );
1432 :
1433 : // This tab is "special", and a special tab needs a blue text.
1434 0 : if (bSpecialTab)
1435 0 : SetTextColor(Color(COL_LIGHTBLUE));
1436 :
1437 0 : aDrawer.drawText(aText);
1438 :
1439 0 : if ( bCurrent )
1440 : {
1441 0 : SetLineColor();
1442 0 : SetFillColor(aSelectColor);
1443 0 : aDrawer.drawOverTopBorder(mnWinStyle & WB_3DTAB);
1444 0 : return;
1445 : }
1446 :
1447 0 : pItem = prev();
1448 : }
1449 : else
1450 : {
1451 0 : if ( bCurrent )
1452 0 : return;
1453 :
1454 0 : pItem = NULL;
1455 : }
1456 :
1457 0 : if ( !pItem )
1458 0 : pItem = pCurItem;
1459 0 : }
1460 : }
1461 :
1462 :
1463 0 : void TabBar::Resize()
1464 : {
1465 0 : Size aNewSize = GetOutputSizePixel();
1466 :
1467 0 : long nSizerWidth = 0;
1468 0 : long nButtonWidth = 0;
1469 :
1470 : // Sizer anordnen
1471 0 : if ( mpImpl->mpSizer )
1472 : {
1473 0 : Size aSizerSize = mpImpl->mpSizer->GetSizePixel();
1474 0 : Point aNewSizerPos( mbMirrored ? 0 : (aNewSize.Width()-aSizerSize.Width()), 0 );
1475 0 : Size aNewSizerSize( aSizerSize.Width(), aNewSize.Height() );
1476 0 : mpImpl->mpSizer->SetPosSizePixel( aNewSizerPos, aNewSizerSize );
1477 0 : nSizerWidth = aSizerSize.Width();
1478 : }
1479 :
1480 : // order the scroll buttons
1481 0 : long nHeight = aNewSize.Height();
1482 : // adapt font height?
1483 0 : ImplInitSettings( true, false );
1484 :
1485 0 : long nX = mbMirrored ? (aNewSize.Width()-nHeight) : 0;
1486 0 : long nXDiff = mbMirrored ? -nHeight : nHeight;
1487 :
1488 0 : Size aBtnSize( nHeight, nHeight );
1489 0 : if ( mpFirstBtn )
1490 : {
1491 0 : mpFirstBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1492 0 : nX += nXDiff;
1493 0 : nButtonWidth += nHeight;
1494 : }
1495 0 : if ( mpPrevBtn )
1496 : {
1497 0 : mpPrevBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1498 0 : nX += nXDiff;
1499 0 : nButtonWidth += nHeight;
1500 : }
1501 0 : if ( mpNextBtn )
1502 : {
1503 0 : mpNextBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1504 0 : nX += nXDiff;
1505 0 : nButtonWidth += nHeight;
1506 : }
1507 0 : if ( mpLastBtn )
1508 : {
1509 0 : mpLastBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1510 0 : nX += nXDiff;
1511 0 : nButtonWidth += nHeight;
1512 : }
1513 :
1514 : // store size
1515 0 : maWinSize = aNewSize;
1516 :
1517 0 : if( mbMirrored )
1518 : {
1519 0 : mnOffX = nSizerWidth;
1520 0 : mnLastOffX = maWinSize.Width() - nButtonWidth - 1;
1521 : }
1522 : else
1523 : {
1524 0 : mnOffX = nButtonWidth;
1525 0 : mnLastOffX = maWinSize.Width() - nSizerWidth - 1;
1526 : }
1527 :
1528 : // reformat
1529 0 : mbSizeFormat = true;
1530 0 : if ( IsReallyVisible() )
1531 : {
1532 0 : if ( ImplCalcWidth() )
1533 0 : Invalidate();
1534 :
1535 0 : ImplFormat();
1536 :
1537 : // Ensure as many tabs as possible are visible:
1538 0 : sal_uInt16 nLastFirstPos = ImplGetLastFirstPos();
1539 0 : if ( mnFirstPos > nLastFirstPos )
1540 : {
1541 0 : mnFirstPos = nLastFirstPos;
1542 0 : mbFormat = true;
1543 0 : Invalidate();
1544 : }
1545 : // Ensure the currently selected page is visible
1546 0 : ImplShowPage( GetPagePos( mnCurPageId ) );
1547 :
1548 0 : ImplFormat();
1549 : }
1550 :
1551 : // enable/disable button
1552 0 : ImplEnableControls();
1553 0 : }
1554 :
1555 :
1556 :
1557 0 : void TabBar::RequestHelp( const HelpEvent& rHEvt )
1558 : {
1559 0 : sal_uInt16 nItemId = GetPageId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
1560 0 : if ( nItemId )
1561 : {
1562 0 : if ( rHEvt.GetMode() & HELPMODE_BALLOON )
1563 : {
1564 0 : OUString aStr = GetHelpText( nItemId );
1565 0 : if (!aStr.isEmpty())
1566 : {
1567 0 : Rectangle aItemRect = GetPageRect( nItemId );
1568 0 : Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
1569 0 : aItemRect.Left() = aPt.X();
1570 0 : aItemRect.Top() = aPt.Y();
1571 0 : aPt = OutputToScreenPixel( aItemRect.BottomRight() );
1572 0 : aItemRect.Right() = aPt.X();
1573 0 : aItemRect.Bottom() = aPt.Y();
1574 0 : Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
1575 0 : return;
1576 0 : }
1577 : }
1578 0 : else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
1579 : {
1580 0 : OUString aHelpId( OStringToOUString( GetHelpId( nItemId ), RTL_TEXTENCODING_UTF8 ) );
1581 0 : if ( !aHelpId.isEmpty() )
1582 : {
1583 : // trigger Help if available
1584 0 : Help* pHelp = Application::GetHelp();
1585 0 : if ( pHelp )
1586 0 : pHelp->Start( aHelpId, this );
1587 0 : return;
1588 0 : }
1589 : }
1590 :
1591 : // show text for quick- or balloon-help
1592 : // if this is isolated or not fully visible
1593 0 : if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
1594 : {
1595 0 : sal_uInt16 nPos = GetPagePos( nItemId );
1596 0 : ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
1597 0 : if ( pItem->mbShort ||
1598 0 : (pItem->maRect.Right()-TABBAR_OFFSET_X-5 > mnLastOffX) )
1599 : {
1600 0 : Rectangle aItemRect = GetPageRect( nItemId );
1601 0 : Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
1602 0 : aItemRect.Left() = aPt.X();
1603 0 : aItemRect.Top() = aPt.Y();
1604 0 : aPt = OutputToScreenPixel( aItemRect.BottomRight() );
1605 0 : aItemRect.Right() = aPt.X();
1606 0 : aItemRect.Bottom() = aPt.Y();
1607 0 : OUString aStr = (*mpItemList)[ nPos ]->maText;
1608 0 : if (!aStr.isEmpty())
1609 : {
1610 0 : if ( rHEvt.GetMode() & HELPMODE_BALLOON )
1611 0 : Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
1612 : else
1613 0 : Help::ShowQuickHelp( this, aItemRect, aStr );
1614 0 : return;
1615 0 : }
1616 : }
1617 : }
1618 : }
1619 :
1620 0 : Window::RequestHelp( rHEvt );
1621 : }
1622 :
1623 :
1624 :
1625 0 : void TabBar::StateChanged( StateChangedType nType )
1626 : {
1627 0 : Window::StateChanged( nType );
1628 :
1629 0 : if ( nType == STATE_CHANGE_INITSHOW )
1630 : {
1631 0 : if ( (mbSizeFormat || mbFormat) && !mpItemList->empty() )
1632 0 : ImplFormat();
1633 : }
1634 0 : else if ( (nType == STATE_CHANGE_ZOOM) ||
1635 : (nType == STATE_CHANGE_CONTROLFONT) )
1636 : {
1637 0 : ImplInitSettings( true, false );
1638 0 : Invalidate();
1639 : }
1640 0 : else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
1641 0 : Invalidate();
1642 0 : else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
1643 : {
1644 0 : ImplInitSettings( false, true );
1645 0 : Invalidate();
1646 : }
1647 0 : else if ( nType == STATE_CHANGE_MIRRORING )
1648 : {
1649 : // reacts on calls of EnableRTL, have to mirror all child controls
1650 0 : if( mpFirstBtn ) mpFirstBtn->EnableRTL( IsRTLEnabled() );
1651 0 : if( mpPrevBtn ) mpPrevBtn->EnableRTL( IsRTLEnabled() );
1652 0 : if( mpNextBtn ) mpNextBtn->EnableRTL( IsRTLEnabled() );
1653 0 : if( mpLastBtn ) mpLastBtn->EnableRTL( IsRTLEnabled() );
1654 0 : if( mpImpl->mpSizer ) mpImpl->mpSizer->EnableRTL( IsRTLEnabled() );
1655 0 : if( mpEdit ) mpEdit->EnableRTL( IsRTLEnabled() );
1656 : }
1657 0 : }
1658 :
1659 :
1660 :
1661 0 : void TabBar::DataChanged( const DataChangedEvent& rDCEvt )
1662 : {
1663 0 : Window::DataChanged( rDCEvt );
1664 :
1665 0 : if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1666 0 : (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1667 0 : ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1668 0 : (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1669 : {
1670 0 : ImplInitSettings( true, true );
1671 0 : Invalidate();
1672 : }
1673 0 : }
1674 :
1675 :
1676 :
1677 0 : void TabBar::ImplSelect()
1678 : {
1679 0 : Select();
1680 :
1681 0 : CallEventListeners( VCLEVENT_TABBAR_PAGESELECTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
1682 0 : }
1683 :
1684 :
1685 :
1686 0 : void TabBar::Select()
1687 : {
1688 0 : maSelectHdl.Call( this );
1689 0 : }
1690 :
1691 :
1692 :
1693 0 : void TabBar::DoubleClick()
1694 : {
1695 0 : maDoubleClickHdl.Call( this );
1696 0 : }
1697 :
1698 :
1699 :
1700 0 : void TabBar::Split()
1701 : {
1702 0 : maSplitHdl.Call( this );
1703 0 : }
1704 :
1705 :
1706 :
1707 0 : void TabBar::ImplActivatePage()
1708 : {
1709 0 : ActivatePage();
1710 :
1711 0 : CallEventListeners( VCLEVENT_TABBAR_PAGEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
1712 0 : }
1713 :
1714 :
1715 :
1716 0 : void TabBar::ActivatePage()
1717 : {
1718 0 : maActivatePageHdl.Call( this );
1719 0 : }
1720 :
1721 :
1722 :
1723 0 : long TabBar::ImplDeactivatePage()
1724 : {
1725 0 : long nRet = DeactivatePage();
1726 :
1727 0 : CallEventListeners( VCLEVENT_TABBAR_PAGEDEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
1728 :
1729 0 : return nRet;
1730 : }
1731 :
1732 0 : void TabBar::ImplPrePaint()
1733 : {
1734 0 : sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
1735 0 : if (!nItemCount)
1736 0 : return;
1737 :
1738 : ImplTabBarItem* pItem;
1739 :
1740 : // tabbar should be formatted
1741 0 : ImplFormat();
1742 :
1743 : // assure the actual tabpage becomes visible at first format
1744 0 : if ( mbFirstFormat )
1745 : {
1746 0 : mbFirstFormat = false;
1747 :
1748 0 : if ( mnCurPageId && (mnFirstPos == 0) && !mbDropPos )
1749 : {
1750 0 : pItem = (*mpItemList)[ GetPagePos( mnCurPageId ) ];
1751 0 : if ( pItem->maRect.IsEmpty() )
1752 : {
1753 : // set mbDropPos (or misuse) to prevent Invalidate()
1754 0 : mbDropPos = true;
1755 0 : SetFirstPageId( mnCurPageId );
1756 0 : mbDropPos = false;
1757 0 : if ( mnFirstPos != 0 )
1758 0 : ImplFormat();
1759 : }
1760 : }
1761 : }
1762 : }
1763 :
1764 0 : ImplTabBarItem* TabBar::ImplGetLastTabBarItem( sal_uInt16 nItemCount )
1765 : {
1766 : // find last visible entry
1767 0 : sal_uInt16 n = mnFirstPos+1;
1768 0 : if ( n >= nItemCount )
1769 0 : n = nItemCount-1;
1770 0 : ImplTabBarItem* pItem = seek( n );
1771 0 : while ( pItem )
1772 : {
1773 0 : if ( !pItem->maRect.IsEmpty() )
1774 : {
1775 0 : n++;
1776 0 : pItem = next();
1777 : }
1778 : else
1779 0 : break;
1780 : }
1781 :
1782 : // draw all tabs (from back to front and actual last)
1783 0 : if ( pItem )
1784 0 : n--;
1785 0 : else if ( n >= nItemCount )
1786 0 : n = nItemCount-1;
1787 0 : pItem = seek( n );
1788 0 : return pItem;
1789 : }
1790 :
1791 0 : Rectangle TabBar::ImplGetInsertTabRect(ImplTabBarItem* pItem) const
1792 : {
1793 0 : if (mbHasInsertTab && pItem)
1794 : {
1795 0 : Rectangle aInsTabRect = pItem->maRect;
1796 0 : if ( !mbMirrored )
1797 : aInsTabRect.setX(
1798 0 : aInsTabRect.getX() + aInsTabRect.getWidth() - TABBAR_OFFSET_X - TABBAR_OFFSET_X2);
1799 : else
1800 : aInsTabRect.setX(
1801 0 : aInsTabRect.getX() - 3*TABBAR_OFFSET_X - TABBAR_OFFSET_X2);
1802 0 : aInsTabRect.setWidth(32);
1803 0 : return aInsTabRect;
1804 : }
1805 0 : return Rectangle();
1806 : }
1807 :
1808 :
1809 :
1810 0 : long TabBar::DeactivatePage()
1811 : {
1812 0 : if ( maDeactivatePageHdl.IsSet() )
1813 0 : return maDeactivatePageHdl.Call( this );
1814 : else
1815 0 : return sal_True;
1816 : }
1817 :
1818 :
1819 :
1820 0 : long TabBar::StartRenaming()
1821 : {
1822 0 : if ( maStartRenamingHdl.IsSet() )
1823 0 : return maStartRenamingHdl.Call( this );
1824 : else
1825 0 : return sal_True;
1826 : }
1827 :
1828 :
1829 :
1830 0 : long TabBar::AllowRenaming()
1831 : {
1832 0 : if ( maAllowRenamingHdl.IsSet() )
1833 0 : return maAllowRenamingHdl.Call( this );
1834 : else
1835 0 : return sal_True;
1836 : }
1837 :
1838 :
1839 :
1840 0 : void TabBar::EndRenaming()
1841 : {
1842 0 : maEndRenamingHdl.Call( this );
1843 0 : }
1844 :
1845 :
1846 :
1847 0 : void TabBar::Mirror()
1848 : {
1849 :
1850 0 : }
1851 :
1852 :
1853 :
1854 0 : void TabBar::InsertPage( sal_uInt16 nPageId, const OUString& rText,
1855 : TabBarPageBits nBits, sal_uInt16 nPos )
1856 : {
1857 : DBG_ASSERT( nPageId, "TabBar::InsertPage(): PageId == 0" );
1858 : DBG_ASSERT( GetPagePos( nPageId ) == PAGE_NOT_FOUND,
1859 : "TabBar::InsertPage(): PageId already exists" );
1860 : DBG_ASSERT( nBits <= TPB_SPECIAL, "TabBar::InsertPage(): nBits is wrong" );
1861 :
1862 : // create PageItem and insert in the item list
1863 0 : ImplTabBarItem* pItem = new ImplTabBarItem( nPageId, rText, nBits );
1864 0 : if ( nPos < mpItemList->size() ) {
1865 0 : ImplTabBarList::iterator it = mpItemList->begin();
1866 0 : ::std::advance( it, nPos );
1867 0 : mpItemList->insert( it, pItem );
1868 : } else {
1869 0 : mpItemList->push_back( pItem );
1870 : }
1871 0 : mbSizeFormat = true;
1872 :
1873 : // set CurPageId if required
1874 0 : if ( !mnCurPageId )
1875 0 : mnCurPageId = nPageId;
1876 :
1877 : // redraw bar
1878 0 : if ( IsReallyVisible() && IsUpdateMode() )
1879 0 : Invalidate();
1880 :
1881 0 : CallEventListeners( VCLEVENT_TABBAR_PAGEINSERTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
1882 0 : }
1883 :
1884 :
1885 :
1886 0 : Color TabBar::GetTabBgColor( sal_uInt16 nPageId ) const
1887 : {
1888 0 : sal_uInt16 nPos = GetPagePos( nPageId );
1889 :
1890 0 : if ( nPos != PAGE_NOT_FOUND )
1891 0 : return (*mpItemList)[ nPos ]->maTabBgColor;
1892 : else
1893 0 : return Color( COL_AUTO );
1894 : }
1895 :
1896 0 : void TabBar::SetTabBgColor( sal_uInt16 nPageId, const Color& aTabBgColor )
1897 : {
1898 0 : sal_uInt16 nPos = GetPagePos( nPageId );
1899 : ImplTabBarItem* pItem;
1900 0 : if ( nPos != PAGE_NOT_FOUND )
1901 : {
1902 0 : pItem = (*mpItemList)[ nPos ];
1903 0 : if ( aTabBgColor != Color( COL_AUTO ) )
1904 : {
1905 0 : pItem->maTabBgColor = aTabBgColor;
1906 0 : if ( aTabBgColor.GetLuminance() <= 128 ) //Do not use aTabBgColor.IsDark(), because that threshold is way too low...
1907 0 : pItem->maTabTextColor = Color( COL_WHITE );
1908 : else
1909 0 : pItem->maTabTextColor = Color( COL_BLACK );
1910 : }
1911 : else
1912 : {
1913 0 : pItem->maTabBgColor = Color( COL_AUTO );
1914 0 : pItem->maTabTextColor = Color( COL_AUTO );
1915 : }
1916 : }
1917 0 : }
1918 :
1919 :
1920 :
1921 0 : void TabBar::RemovePage( sal_uInt16 nPageId )
1922 : {
1923 0 : sal_uInt16 nPos = GetPagePos( nPageId );
1924 :
1925 : // does item exist
1926 0 : if ( nPos != PAGE_NOT_FOUND )
1927 : {
1928 0 : if ( mnCurPageId == nPageId )
1929 0 : mnCurPageId = 0;
1930 :
1931 : // check if first visibale page should be moved
1932 0 : if ( mnFirstPos > nPos )
1933 0 : mnFirstPos--;
1934 :
1935 : // delete item data
1936 0 : ImplTabBarList::iterator it = mpItemList->begin();
1937 0 : ::std::advance( it, nPos );
1938 0 : delete *it;
1939 0 : mpItemList->erase( it );
1940 :
1941 : // redraw bar
1942 0 : if ( IsReallyVisible() && IsUpdateMode() )
1943 0 : Invalidate();
1944 :
1945 0 : CallEventListeners( VCLEVENT_TABBAR_PAGEREMOVED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
1946 : }
1947 0 : }
1948 :
1949 :
1950 :
1951 0 : void TabBar::MovePage( sal_uInt16 nPageId, sal_uInt16 nNewPos )
1952 : {
1953 0 : sal_uInt16 nPos = GetPagePos( nPageId );
1954 0 : Pair aPair( nPos, nNewPos );
1955 :
1956 0 : if ( nPos < nNewPos )
1957 0 : nNewPos--;
1958 :
1959 0 : if ( nPos == nNewPos )
1960 0 : return;
1961 :
1962 : // does item exit
1963 0 : if ( nPos != PAGE_NOT_FOUND )
1964 : {
1965 : // move tabbar item in the list
1966 0 : ImplTabBarList::iterator it = mpItemList->begin();
1967 0 : ::std::advance( it, nPos );
1968 0 : ImplTabBarItem* pItem = *it;
1969 0 : mpItemList->erase( it );
1970 0 : if ( nNewPos < mpItemList->size() ) {
1971 0 : it = mpItemList->begin();
1972 0 : ::std::advance( it, nNewPos );
1973 0 : mpItemList->insert( it, pItem );
1974 : } else {
1975 0 : mpItemList->push_back( pItem );
1976 : }
1977 :
1978 : // redraw bar
1979 0 : if ( IsReallyVisible() && IsUpdateMode() )
1980 0 : Invalidate();
1981 :
1982 0 : CallEventListeners( VCLEVENT_TABBAR_PAGEMOVED, (void*) &aPair );
1983 : }
1984 : }
1985 :
1986 :
1987 :
1988 0 : void TabBar::Clear()
1989 : {
1990 : // delete all items
1991 0 : for ( size_t i = 0, n = mpItemList->size(); i < n; ++i ) {
1992 0 : delete (*mpItemList)[ i ];
1993 : }
1994 0 : mpItemList->clear();
1995 :
1996 : // remove items from the list
1997 0 : mbSizeFormat = true;
1998 0 : mnCurPageId = 0;
1999 0 : mnFirstPos = 0;
2000 0 : maCurrentItemList = 0;
2001 :
2002 : // redraw bar
2003 0 : if ( IsReallyVisible() && IsUpdateMode() )
2004 0 : Invalidate();
2005 :
2006 0 : CallEventListeners( VCLEVENT_TABBAR_PAGEREMOVED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(PAGE_NOT_FOUND)) );
2007 0 : }
2008 :
2009 :
2010 :
2011 0 : bool TabBar::IsPageEnabled( sal_uInt16 nPageId ) const
2012 : {
2013 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2014 :
2015 0 : if ( nPos != PAGE_NOT_FOUND )
2016 0 : return (*mpItemList)[ nPos ]->mbEnable;
2017 : else
2018 0 : return false;
2019 : }
2020 :
2021 :
2022 :
2023 0 : void TabBar::SetPageBits( sal_uInt16 nPageId, TabBarPageBits nBits )
2024 : {
2025 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2026 :
2027 0 : if ( nPos != PAGE_NOT_FOUND )
2028 : {
2029 0 : ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2030 :
2031 0 : if ( pItem->mnBits != nBits )
2032 : {
2033 0 : pItem->mnBits = nBits;
2034 :
2035 : // redraw bar
2036 0 : if ( IsReallyVisible() && IsUpdateMode() )
2037 0 : Invalidate( pItem->maRect );
2038 : }
2039 : }
2040 0 : }
2041 :
2042 :
2043 :
2044 0 : TabBarPageBits TabBar::GetPageBits( sal_uInt16 nPageId ) const
2045 : {
2046 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2047 :
2048 0 : if ( nPos != PAGE_NOT_FOUND )
2049 0 : return (*mpItemList)[ nPos ]->mnBits;
2050 : else
2051 0 : return sal_False;
2052 : }
2053 :
2054 :
2055 :
2056 0 : sal_uInt16 TabBar::GetPageCount() const
2057 : {
2058 0 : return (sal_uInt16)mpItemList->size();
2059 : }
2060 :
2061 :
2062 :
2063 0 : sal_uInt16 TabBar::GetPageId( sal_uInt16 nPos ) const
2064 : {
2065 0 : return ( nPos < mpItemList->size() ) ? (*mpItemList)[ nPos ]->mnId : 0;
2066 : }
2067 :
2068 :
2069 :
2070 0 : sal_uInt16 TabBar::GetPagePos( sal_uInt16 nPageId ) const
2071 : {
2072 0 : for ( size_t i = 0, n = mpItemList->size(); i < n; ++i ) {
2073 0 : if ( (*mpItemList)[ i ]->mnId == nPageId ) {
2074 0 : return sal_uInt16( i );
2075 : }
2076 : }
2077 0 : return PAGE_NOT_FOUND;
2078 : }
2079 :
2080 :
2081 :
2082 0 : sal_uInt16 TabBar::GetPageId( const Point& rPos, bool bCheckInsTab ) const
2083 : {
2084 0 : for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
2085 : {
2086 0 : ImplTabBarItem* pItem = (*mpItemList)[ i ];
2087 0 : if ( pItem->maRect.IsInside( rPos ) )
2088 0 : return pItem->mnId;
2089 : }
2090 :
2091 0 : if (bCheckInsTab && mbHasInsertTab && !mpItemList->empty())
2092 : {
2093 0 : ImplTabBarItem* pItem = mpItemList->back();
2094 0 : if (ImplGetInsertTabRect(pItem).IsInside(rPos))
2095 0 : return INSERT_TAB_POS;
2096 : }
2097 :
2098 0 : return 0;
2099 : }
2100 :
2101 :
2102 :
2103 0 : Rectangle TabBar::GetPageRect( sal_uInt16 nPageId ) const
2104 : {
2105 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2106 :
2107 0 : if ( nPos != PAGE_NOT_FOUND )
2108 0 : return (*mpItemList)[ nPos ]->maRect;
2109 : else
2110 0 : return Rectangle();
2111 : }
2112 :
2113 :
2114 :
2115 0 : void TabBar::SetCurPageId( sal_uInt16 nPageId )
2116 : {
2117 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2118 :
2119 : // do nothing if item does not exit
2120 0 : if ( nPos != PAGE_NOT_FOUND )
2121 : {
2122 : // do nothing if the actual page did not change
2123 0 : if ( nPageId == mnCurPageId )
2124 0 : return;
2125 :
2126 : // make invalide
2127 0 : bool bUpdate = false;
2128 0 : if ( IsReallyVisible() && IsUpdateMode() )
2129 0 : bUpdate = true;
2130 :
2131 0 : ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2132 : ImplTabBarItem* pOldItem;
2133 :
2134 0 : if ( mnCurPageId )
2135 0 : pOldItem = (*mpItemList)[ GetPagePos( mnCurPageId ) ];
2136 : else
2137 0 : pOldItem = NULL;
2138 :
2139 : // deselect previous page if page was not selected, if this is the
2140 : // only selected page
2141 0 : if ( !pItem->mbSelect && pOldItem )
2142 : {
2143 0 : sal_uInt16 nSelPageCount = GetSelectPageCount();
2144 0 : if ( nSelPageCount == 1 )
2145 0 : pOldItem->mbSelect = false;
2146 0 : pItem->mbSelect = true;
2147 : }
2148 :
2149 0 : mnCurPageId = nPageId;
2150 0 : mbFormat = true;
2151 :
2152 : // assure the actual page becomes visible
2153 0 : if ( IsReallyVisible() )
2154 : {
2155 0 : if ( nPos < mnFirstPos )
2156 0 : SetFirstPageId( nPageId );
2157 : else
2158 : {
2159 : // calculate visible width
2160 0 : long nWidth = mnLastOffX;
2161 0 : if ( nWidth > TABBAR_OFFSET_X )
2162 0 : nWidth -= TABBAR_OFFSET_X;
2163 0 : if ( nWidth > ADDNEWPAGE_AREAWIDTH )
2164 0 : nWidth -= ADDNEWPAGE_AREAWIDTH;
2165 :
2166 0 : if ( pItem->maRect.IsEmpty() )
2167 0 : ImplFormat();
2168 :
2169 0 : while ( (mbMirrored ? (pItem->maRect.Left() < mnOffX) : (pItem->maRect.Right() > nWidth)) ||
2170 0 : pItem->maRect.IsEmpty() )
2171 : {
2172 0 : sal_uInt16 nNewPos = mnFirstPos+1;
2173 : // assure at least the actual tabpages are visible as first tabpage
2174 0 : if ( nNewPos >= nPos )
2175 : {
2176 0 : SetFirstPageId( nPageId );
2177 0 : break;
2178 : }
2179 : else
2180 0 : SetFirstPageId( GetPageId( nNewPos ) );
2181 0 : ImplFormat();
2182 : // abort if first page is not forwarded
2183 0 : if ( nNewPos != mnFirstPos )
2184 0 : break;
2185 : }
2186 : }
2187 : }
2188 :
2189 : // redraw bar
2190 0 : if ( bUpdate )
2191 : {
2192 0 : Invalidate( pItem->maRect );
2193 0 : if ( pOldItem )
2194 0 : Invalidate( pOldItem->maRect );
2195 : }
2196 : }
2197 : }
2198 :
2199 :
2200 :
2201 0 : void TabBar::MakeVisible( sal_uInt16 nPageId )
2202 : {
2203 0 : if ( !IsReallyVisible() )
2204 0 : return;
2205 :
2206 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2207 :
2208 : // do nothing if item does not exist
2209 0 : if ( nPos != PAGE_NOT_FOUND )
2210 : {
2211 0 : if ( nPos < mnFirstPos )
2212 0 : SetFirstPageId( nPageId );
2213 : else
2214 : {
2215 0 : ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2216 :
2217 : // calculate visible area
2218 0 : long nWidth = mnLastOffX;
2219 0 : if ( nWidth > TABBAR_OFFSET_X )
2220 0 : nWidth -= TABBAR_OFFSET_X;
2221 :
2222 0 : if ( mbFormat || pItem->maRect.IsEmpty() )
2223 : {
2224 0 : mbFormat = true;
2225 0 : ImplFormat();
2226 : }
2227 :
2228 0 : while ( (pItem->maRect.Right() > nWidth) ||
2229 0 : pItem->maRect.IsEmpty() )
2230 : {
2231 0 : sal_uInt16 nNewPos = mnFirstPos+1;
2232 : // assure at least the actual tabpages are visible as first tabpage
2233 0 : if ( nNewPos >= nPos )
2234 : {
2235 0 : SetFirstPageId( nPageId );
2236 0 : break;
2237 : }
2238 : else
2239 0 : SetFirstPageId( GetPageId( nNewPos ) );
2240 0 : ImplFormat();
2241 : // abort if first page is not forwarded
2242 0 : if ( nNewPos != mnFirstPos )
2243 0 : break;
2244 : }
2245 : }
2246 : }
2247 : }
2248 :
2249 :
2250 :
2251 0 : void TabBar::SetFirstPageId( sal_uInt16 nPageId )
2252 : {
2253 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2254 :
2255 : // return false if item does not exist
2256 0 : if ( nPos != PAGE_NOT_FOUND )
2257 : {
2258 0 : if ( nPos != mnFirstPos )
2259 : {
2260 : // assure as much pages are visible as possible
2261 0 : ImplFormat();
2262 0 : sal_uInt16 nLastFirstPos = ImplGetLastFirstPos();
2263 : sal_uInt16 nNewPos;
2264 0 : if ( nPos > nLastFirstPos )
2265 0 : nNewPos = nLastFirstPos;
2266 : else
2267 0 : nNewPos = nPos;
2268 :
2269 0 : if ( nNewPos != mnFirstPos )
2270 : {
2271 0 : mnFirstPos = nNewPos;
2272 0 : mbFormat = true;
2273 :
2274 : // redraw bar (attention: check mbDropPos,
2275 : // as if this flag was set, we do not re-paint immediately
2276 0 : if ( IsReallyVisible() && IsUpdateMode() && !mbDropPos )
2277 0 : Invalidate();
2278 : }
2279 : }
2280 : }
2281 0 : }
2282 :
2283 :
2284 :
2285 0 : void TabBar::SelectPage( sal_uInt16 nPageId, bool bSelect )
2286 : {
2287 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2288 :
2289 0 : if ( nPos != PAGE_NOT_FOUND )
2290 : {
2291 0 : ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2292 :
2293 0 : if ( pItem->mbSelect != bSelect )
2294 : {
2295 0 : pItem->mbSelect = bSelect;
2296 :
2297 : // redraw bar
2298 0 : if ( IsReallyVisible() && IsUpdateMode() )
2299 0 : Invalidate( pItem->maRect );
2300 : }
2301 : }
2302 0 : }
2303 :
2304 :
2305 :
2306 0 : sal_uInt16 TabBar::GetSelectPageCount() const
2307 : {
2308 0 : sal_uInt16 nSelected = 0;
2309 0 : for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
2310 : {
2311 0 : ImplTabBarItem* pItem = (*mpItemList)[ i ];
2312 0 : if ( pItem->mbSelect )
2313 0 : nSelected++;
2314 : }
2315 :
2316 0 : return nSelected;
2317 : }
2318 :
2319 :
2320 :
2321 0 : bool TabBar::IsPageSelected( sal_uInt16 nPageId ) const
2322 : {
2323 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2324 0 : if ( nPos != PAGE_NOT_FOUND )
2325 0 : return (*mpItemList)[ nPos ]->mbSelect;
2326 : else
2327 0 : return false;
2328 : }
2329 :
2330 :
2331 :
2332 0 : bool TabBar::StartEditMode( sal_uInt16 nPageId )
2333 : {
2334 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2335 0 : if ( mpEdit || (nPos == PAGE_NOT_FOUND) || (mnLastOffX < 8) )
2336 0 : return false;
2337 :
2338 0 : mnEditId = nPageId;
2339 0 : if ( StartRenaming() )
2340 : {
2341 0 : ImplShowPage( nPos );
2342 0 : ImplFormat();
2343 0 : Update();
2344 :
2345 0 : mpEdit = new TabBarEdit( this, WB_CENTER );
2346 0 : Rectangle aRect = GetPageRect( mnEditId );
2347 0 : long nX = aRect.Left()+TABBAR_OFFSET_X+(TABBAR_OFFSET_X2/2);
2348 0 : long nWidth = aRect.GetWidth()-(TABBAR_OFFSET_X*2)-TABBAR_OFFSET_X2;
2349 0 : if ( mnEditId != GetCurPageId() )
2350 0 : nX += 1;
2351 0 : if ( nX+nWidth > mnLastOffX )
2352 0 : nWidth = mnLastOffX-nX;
2353 0 : if ( nWidth < 3 )
2354 : {
2355 0 : nX = aRect.Left();
2356 0 : nWidth = aRect.GetWidth();
2357 : }
2358 0 : mpEdit->SetText( GetPageText( mnEditId ) );
2359 0 : mpEdit->setPosSizePixel( nX, aRect.Top()+mnOffY+1, nWidth, aRect.GetHeight()-3 );
2360 0 : Font aFont = GetPointFont();
2361 0 : Color aForegroundColor;
2362 0 : Color aBackgroundColor;
2363 0 : Color aFaceColor;
2364 0 : Color aSelectColor;
2365 0 : Color aFaceTextColor;
2366 0 : Color aSelectTextColor;
2367 0 : ImplGetColors( aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor );
2368 0 : if ( mnEditId != GetCurPageId() )
2369 0 : aFont.SetWeight( WEIGHT_LIGHT );
2370 0 : if ( IsPageSelected( mnEditId ) || (mnEditId == GetCurPageId()) )
2371 : {
2372 0 : aForegroundColor = aSelectTextColor;
2373 0 : aBackgroundColor = aSelectColor;
2374 : }
2375 : else
2376 : {
2377 0 : aForegroundColor = aFaceTextColor;
2378 0 : aBackgroundColor = aFaceColor;
2379 : }
2380 0 : if ( GetPageBits( mnEditId ) & TPB_SPECIAL )
2381 0 : aForegroundColor = Color( COL_LIGHTBLUE );
2382 0 : mpEdit->SetControlFont( aFont );
2383 0 : mpEdit->SetControlForeground( aForegroundColor );
2384 0 : mpEdit->SetControlBackground( aBackgroundColor );
2385 0 : mpEdit->GrabFocus();
2386 0 : mpEdit->SetSelection( Selection( 0, mpEdit->GetText().getLength() ) );
2387 0 : mpEdit->Show();
2388 0 : return true;
2389 : }
2390 : else
2391 : {
2392 0 : mnEditId = 0;
2393 0 : return false;
2394 : }
2395 : }
2396 :
2397 :
2398 :
2399 0 : void TabBar::EndEditMode( bool bCancel )
2400 : {
2401 0 : if ( mpEdit )
2402 : {
2403 : // call hdl
2404 0 : bool bEnd = true;
2405 0 : mbEditCanceled = bCancel;
2406 0 : maEditText = mpEdit->GetText();
2407 0 : mpEdit->SetPostEvent();
2408 0 : if ( !bCancel )
2409 : {
2410 0 : long nAllowRenaming = AllowRenaming();
2411 0 : if ( nAllowRenaming == TABBAR_RENAMING_YES )
2412 0 : SetPageText( mnEditId, maEditText );
2413 0 : else if ( nAllowRenaming == TABBAR_RENAMING_NO )
2414 0 : bEnd = false;
2415 : else // nAllowRenaming == TABBAR_RENAMING_CANCEL
2416 0 : mbEditCanceled = true;
2417 : }
2418 :
2419 : // renaming not allowed, than reset edit data
2420 0 : if ( !bEnd )
2421 : {
2422 0 : mpEdit->ResetPostEvent();
2423 0 : mpEdit->GrabFocus();
2424 : }
2425 : else
2426 : {
2427 : // close edit and call end hdl
2428 0 : delete mpEdit;
2429 0 : mpEdit = NULL;
2430 0 : EndRenaming();
2431 0 : mnEditId = 0;
2432 : }
2433 :
2434 : // reset
2435 0 : maEditText = OUString();
2436 0 : mbEditCanceled = false;
2437 : }
2438 0 : }
2439 :
2440 :
2441 :
2442 0 : void TabBar::SetMirrored(bool bMirrored)
2443 : {
2444 0 : if( mbMirrored != bMirrored )
2445 : {
2446 0 : mbMirrored = bMirrored;
2447 0 : mbSizeFormat = true;
2448 0 : ImplInitControls(); // for button images
2449 0 : Resize(); // recalculates control positions
2450 0 : Mirror();
2451 : }
2452 0 : }
2453 :
2454 0 : void TabBar::SetEffectiveRTL( bool bRTL )
2455 : {
2456 0 : SetMirrored( bRTL != Application::GetSettings().GetLayoutRTL() );
2457 0 : }
2458 :
2459 0 : bool TabBar::IsEffectiveRTL() const
2460 : {
2461 0 : return IsMirrored() != Application::GetSettings().GetLayoutRTL();
2462 : }
2463 :
2464 :
2465 :
2466 0 : void TabBar::SetMaxPageWidth( long nMaxWidth )
2467 : {
2468 0 : if ( mnMaxPageWidth != nMaxWidth )
2469 : {
2470 0 : mnMaxPageWidth = nMaxWidth;
2471 0 : mbSizeFormat = true;
2472 :
2473 : // redraw bar
2474 0 : if ( IsReallyVisible() && IsUpdateMode() )
2475 0 : Invalidate();
2476 : }
2477 0 : }
2478 :
2479 :
2480 :
2481 0 : void TabBar::SetPageText( sal_uInt16 nPageId, const OUString& rText )
2482 : {
2483 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2484 0 : if ( nPos != PAGE_NOT_FOUND )
2485 : {
2486 0 : (*mpItemList)[ nPos ]->maText = rText;
2487 0 : mbSizeFormat = true;
2488 :
2489 : // redraw bar
2490 0 : if ( IsReallyVisible() && IsUpdateMode() )
2491 0 : Invalidate();
2492 :
2493 0 : CallEventListeners( VCLEVENT_TABBAR_PAGETEXTCHANGED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
2494 : }
2495 0 : }
2496 :
2497 :
2498 :
2499 0 : OUString TabBar::GetPageText( sal_uInt16 nPageId ) const
2500 : {
2501 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2502 0 : if ( nPos != PAGE_NOT_FOUND )
2503 0 : return (*mpItemList)[ nPos ]->maText;
2504 0 : return OUString();
2505 : }
2506 :
2507 :
2508 :
2509 0 : OUString TabBar::GetHelpText( sal_uInt16 nPageId ) const
2510 : {
2511 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2512 0 : if ( nPos != PAGE_NOT_FOUND )
2513 : {
2514 0 : ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2515 0 : if (pItem->maHelpText.isEmpty() && !pItem->maHelpId.isEmpty())
2516 : {
2517 0 : Help* pHelp = Application::GetHelp();
2518 0 : if ( pHelp )
2519 0 : pItem->maHelpText = pHelp->GetHelpText( OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
2520 : }
2521 :
2522 0 : return pItem->maHelpText;
2523 : }
2524 0 : return OUString();
2525 : }
2526 :
2527 :
2528 :
2529 0 : OString TabBar::GetHelpId( sal_uInt16 nPageId ) const
2530 : {
2531 0 : sal_uInt16 nPos = GetPagePos( nPageId );
2532 0 : OString aRet;
2533 0 : if ( nPos != PAGE_NOT_FOUND )
2534 0 : return (*mpItemList)[ nPos ]->maHelpId;
2535 0 : return aRet;
2536 : }
2537 :
2538 :
2539 :
2540 0 : bool TabBar::StartDrag( const CommandEvent& rCEvt, Region& rRegion )
2541 : {
2542 0 : if ( !(mnWinStyle & WB_DRAG) || (rCEvt.GetCommand() != COMMAND_STARTDRAG) )
2543 0 : return false;
2544 :
2545 : // Check if the clicked page was selected. If this is not the case
2546 : // set it as actual entry. We check for this only at a mouse action
2547 : // if Drag and Drop can be triggered from the keyboard.
2548 : // We only do this, if Select() was not triggered, as the Select()
2549 : // could have scrolled the area
2550 0 : if ( rCEvt.IsMouseEvent() && !mbInSelect )
2551 : {
2552 0 : sal_uInt16 nSelId = GetPageId( rCEvt.GetMousePosPixel() );
2553 :
2554 : // do not start dragging if no entry was clicked
2555 0 : if ( !nSelId )
2556 0 : return false;
2557 :
2558 : // check if page was selected. If not set it as actual
2559 : // page and call Select()
2560 0 : if ( !IsPageSelected( nSelId ) )
2561 : {
2562 0 : if ( ImplDeactivatePage() )
2563 : {
2564 0 : SetCurPageId( nSelId );
2565 0 : Update();
2566 0 : ImplActivatePage();
2567 0 : ImplSelect();
2568 : }
2569 : else
2570 0 : return false;
2571 : }
2572 : }
2573 0 : mbInSelect = false;
2574 :
2575 0 : Region aRegion;
2576 :
2577 : // assign region
2578 0 : rRegion = aRegion;
2579 :
2580 0 : return true;
2581 : }
2582 :
2583 :
2584 :
2585 0 : sal_uInt16 TabBar::ShowDropPos( const Point& rPos )
2586 : {
2587 : ImplTabBarItem* pItem;
2588 : sal_uInt16 nDropId;
2589 : sal_uInt16 nNewDropPos;
2590 0 : sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
2591 0 : short nScroll = 0;
2592 :
2593 0 : if ( rPos.X() > mnLastOffX-TABBAR_DRAG_SCROLLOFF )
2594 : {
2595 0 : pItem = (*mpItemList)[ mpItemList->size()-1 ];
2596 0 : if ( !pItem->maRect.IsEmpty() && (rPos.X() > pItem->maRect.Right()) )
2597 0 : nNewDropPos = (sal_uInt16)mpItemList->size();
2598 : else
2599 : {
2600 0 : nNewDropPos = mnFirstPos+1;
2601 0 : nScroll = 1;
2602 : }
2603 : }
2604 0 : else if ( (rPos.X() <= mnOffX) ||
2605 0 : (!mnOffX && (rPos.X() <= TABBAR_DRAG_SCROLLOFF)) )
2606 : {
2607 0 : if ( mnFirstPos )
2608 : {
2609 0 : nNewDropPos = mnFirstPos;
2610 0 : nScroll = -1;
2611 : }
2612 : else
2613 0 : nNewDropPos = 0;
2614 : }
2615 : else
2616 : {
2617 0 : nDropId = GetPageId( rPos );
2618 0 : if ( nDropId )
2619 : {
2620 0 : nNewDropPos = GetPagePos( nDropId );
2621 0 : if ( mnFirstPos && (nNewDropPos == mnFirstPos-1) )
2622 0 : nScroll = -1;
2623 : }
2624 : else
2625 0 : nNewDropPos = nItemCount;
2626 : }
2627 :
2628 0 : if ( mbDropPos && (nNewDropPos == mnDropPos) && !nScroll )
2629 0 : return mnDropPos;
2630 :
2631 0 : if ( mbDropPos )
2632 0 : HideDropPos();
2633 0 : mbDropPos = true;
2634 0 : mnDropPos = nNewDropPos;
2635 :
2636 0 : if ( nScroll )
2637 : {
2638 0 : sal_uInt16 nOldFirstPos = mnFirstPos;
2639 0 : SetFirstPageId( GetPageId( mnFirstPos+nScroll ) );
2640 :
2641 : // draw immediately, as Paint not possible during Drag and Drop
2642 0 : if ( nOldFirstPos != mnFirstPos )
2643 : {
2644 0 : Rectangle aRect( mnOffX, 0, mnLastOffX, maWinSize.Height() );
2645 0 : SetFillColor( GetBackground().GetColor() );
2646 0 : DrawRect( aRect );
2647 0 : Paint( aRect );
2648 : }
2649 : }
2650 :
2651 : // draw drop position arrows
2652 0 : Color aBlackColor( COL_BLACK );
2653 : long nX;
2654 0 : long nY = (maWinSize.Height()/2)-1;
2655 0 : sal_uInt16 nCurPos = GetPagePos( mnCurPageId );
2656 :
2657 0 : SetLineColor( aBlackColor );
2658 0 : if ( mnDropPos < nItemCount )
2659 : {
2660 0 : pItem = (*mpItemList)[ mnDropPos ];
2661 0 : nX = pItem->maRect.Left()+TABBAR_OFFSET_X;
2662 0 : if ( mnDropPos == nCurPos )
2663 0 : nX--;
2664 : else
2665 0 : nX++;
2666 0 : if ( !pItem->IsDefaultTabBgColor() && !pItem->mbSelect)
2667 0 : SetLineColor( pItem->maTabTextColor );
2668 0 : DrawLine( Point( nX, nY ), Point( nX, nY ) );
2669 0 : DrawLine( Point( nX+1, nY-1 ), Point( nX+1, nY+1 ) );
2670 0 : DrawLine( Point( nX+2, nY-2 ), Point( nX+2, nY+2 ) );
2671 0 : SetLineColor( aBlackColor );
2672 : }
2673 0 : if ( (mnDropPos > 0) && (mnDropPos < nItemCount+1) )
2674 : {
2675 0 : pItem = (*mpItemList)[ mnDropPos-1 ];
2676 0 : nX = pItem->maRect.Right()-TABBAR_OFFSET_X;
2677 0 : if ( mnDropPos == nCurPos )
2678 0 : nX++;
2679 0 : if ( !pItem->IsDefaultTabBgColor() && !pItem->mbSelect)
2680 0 : SetLineColor( pItem->maTabTextColor );
2681 0 : DrawLine( Point( nX, nY ), Point( nX, nY ) );
2682 0 : DrawLine( Point( nX-1, nY-1 ), Point( nX-1, nY+1 ) );
2683 0 : DrawLine( Point( nX-2, nY-2 ), Point( nX-2, nY+2 ) );
2684 : }
2685 :
2686 0 : return mnDropPos;
2687 : }
2688 :
2689 :
2690 :
2691 0 : void TabBar::HideDropPos()
2692 : {
2693 0 : if ( mbDropPos )
2694 : {
2695 : ImplTabBarItem* pItem;
2696 : long nX;
2697 0 : long nY1 = (maWinSize.Height()/2)-3;
2698 0 : long nY2 = nY1 + 5;
2699 0 : sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
2700 :
2701 0 : if ( mnDropPos < nItemCount )
2702 : {
2703 0 : pItem = (*mpItemList)[ mnDropPos ];
2704 0 : nX = pItem->maRect.Left()+TABBAR_OFFSET_X;
2705 : // immediately call Paint, as it is not possible during drag and drop
2706 0 : Rectangle aRect( nX-1, nY1, nX+3, nY2 );
2707 0 : Region aRegion( aRect );
2708 0 : SetClipRegion( aRegion );
2709 0 : Paint( aRect );
2710 0 : SetClipRegion();
2711 : }
2712 0 : if ( (mnDropPos > 0) && (mnDropPos < nItemCount+1) )
2713 : {
2714 0 : pItem = (*mpItemList)[ mnDropPos-1 ];
2715 0 : nX = pItem->maRect.Right()-TABBAR_OFFSET_X;
2716 : // immediately call Paint, as it is not possible during drag and drop
2717 0 : Rectangle aRect( nX-2, nY1, nX+1, nY2 );
2718 0 : Region aRegion( aRect );
2719 0 : SetClipRegion( aRegion );
2720 0 : Paint( aRect );
2721 0 : SetClipRegion();
2722 : }
2723 :
2724 0 : mbDropPos = false;
2725 0 : mnDropPos = 0;
2726 : }
2727 0 : }
2728 :
2729 :
2730 :
2731 0 : bool TabBar::SwitchPage( const Point& rPos )
2732 : {
2733 0 : bool bSwitch = false;
2734 0 : sal_uInt16 nSwitchId = GetPageId( rPos );
2735 0 : if ( !nSwitchId )
2736 0 : EndSwitchPage();
2737 : else
2738 : {
2739 0 : if ( nSwitchId != mnSwitchId )
2740 : {
2741 0 : mnSwitchId = nSwitchId;
2742 0 : mnSwitchTime = Time::GetSystemTicks();
2743 : }
2744 : else
2745 : {
2746 : // change only after 500 ms
2747 0 : if ( mnSwitchId != GetCurPageId() )
2748 : {
2749 0 : if ( Time::GetSystemTicks() > mnSwitchTime+500 )
2750 : {
2751 0 : mbInSwitching = true;
2752 0 : if ( ImplDeactivatePage() )
2753 : {
2754 0 : SetCurPageId( mnSwitchId );
2755 0 : Update();
2756 0 : ImplActivatePage();
2757 0 : ImplSelect();
2758 0 : bSwitch = true;
2759 : }
2760 0 : mbInSwitching = false;
2761 : }
2762 : }
2763 : }
2764 : }
2765 :
2766 0 : return bSwitch;
2767 : }
2768 :
2769 :
2770 :
2771 0 : void TabBar::EndSwitchPage()
2772 : {
2773 0 : mnSwitchTime = 0;
2774 0 : mnSwitchId = 0;
2775 0 : }
2776 :
2777 :
2778 :
2779 0 : void TabBar::SetStyle( WinBits nStyle )
2780 : {
2781 0 : mnWinStyle = nStyle;
2782 0 : ImplInitControls();
2783 : // order possible controls
2784 0 : if ( IsReallyVisible() && IsUpdateMode() )
2785 0 : Resize();
2786 0 : }
2787 :
2788 :
2789 :
2790 0 : Size TabBar::CalcWindowSizePixel() const
2791 : {
2792 0 : long nWidth = 0;
2793 :
2794 0 : if ( mpItemList->size() )
2795 : {
2796 0 : ((TabBar*)this)->ImplCalcWidth();
2797 0 : for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
2798 : {
2799 0 : ImplTabBarItem* pItem = (*mpItemList)[ i ];
2800 0 : nWidth += pItem->mnWidth;
2801 : }
2802 0 : nWidth += TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
2803 : }
2804 :
2805 0 : return Size( nWidth, GetSettings().GetStyleSettings().GetScrollBarSize() );
2806 : }
2807 :
2808 :
2809 0 : Rectangle TabBar::GetPageArea() const
2810 : {
2811 0 : return Rectangle( Point( mnOffX, mnOffY ), Size( mnLastOffX-mnOffX+1, GetSizePixel().Height()-mnOffY ) );
2812 : }
2813 :
2814 :
2815 :
2816 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > TabBar::CreateAccessible()
2817 : {
2818 0 : return mpImpl->maAccessibleFactory.getFactory().createAccessibleTabBar( *this );
2819 : }
2820 :
2821 :
2822 :
2823 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|