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