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 : #ifndef INCLUDED_SVTOOLS_TABBAR_HXX
21 : #define INCLUDED_SVTOOLS_TABBAR_HXX
22 :
23 : #include <svtools/svtdllapi.h>
24 : #include <tools/link.hxx>
25 : #include <vcl/window.hxx>
26 : #include <vector>
27 :
28 : /*
29 :
30 : Allowed StylbeBits
31 : ------------------
32 :
33 : WB_SCROLL - The tabs can be scrolled via an extra field
34 : WB_MINSCROLL - The tabs can be scrolled via 2 additional buttons
35 : WB_RANGESELECT - Connected ranges can be selected
36 : WB_MULTISELECT - single tabs can be selected
37 : WB_BORDER - a border is drawn in the top and in the bottom
38 : WB_TOPBORDER - a border is drawn in the top
39 : WB_3DTAB - the tabs and the border are drawn in 3D
40 : WB_DRAG - A StartDrag handler is called by the TabBar, if drag
41 : and drop should be started. In addition, drag and drop
42 : is activated in the TabBar with EnableDrop().
43 : WB_SIZEABLE - a Split handler is called by the TabBar, if the user
44 : wants to change the width of the TabBar
45 : WB_STDTABBAR - WB_BORDER
46 :
47 : If the TabBar should be used for example as Property bar, the WinBits
48 : WB_TOPBORDER and WB_3DTAB should be set instead of WB_BORDER.
49 :
50 :
51 : Allowed PageBits
52 : -----------------
53 :
54 : TPB_SPECIAL - Different display of the TabText, e.g. for scenario pages.
55 :
56 : Handlers
57 : -------
58 :
59 : Select - is called when a tab is selected or unselected
60 : DoubleClick - Is called when a DoubleClick has been fired in the
61 : TabBar. Inside of the handler, GetCurPageId() returns
62 : the clicked tab or 0, if no tab has been clicked.
63 : ActivatePage - Is called, if another page is activated.
64 : GetCurPageId() returns the activated page.
65 : DeactivatePage - Is called, when a page is deactivated. If another page
66 : may be activated, true must be returned; if another
67 : page shall be excluded from the activation, false must
68 : be returned. GetCurPageId() returns the page to be
69 : deactivated.
70 :
71 :
72 :
73 : Drag and Drop
74 : -------------
75 :
76 : For Drag and Drop, the WinBit WB_DRAG must be set. In addition, the
77 : Command handler, the QueryDrop handler and the Drop handler must be overlaid.
78 : In doing so, the following must be implemented in the handlers:
79 :
80 : Command - If dragging should be started in this handler,
81 : StartDrag() must be called. This method
82 : then selects the respective entry or returns
83 : false, if dragging cannot be carried out.
84 :
85 : QueryDrop - This handler is always called by StarView, when the
86 : mouse is pulled over the window while dragging
87 : (s.a. SV documentation). In this handler, it must be
88 : determined whether a drop is possible. The drop
89 : position can be shown in TabBar using ShowDropPos().
90 : When calling, the position of the Event must be passed.
91 : If the position is at the left or right border,
92 : scrolling automatically takes place in the TabBar.
93 : This method also returns the respective drop position,
94 : which is also needed for a drop. If the window is left
95 : while dragging, the drop position can be taken back
96 : using HideDropPos(). Thus, it is also possible to handle
97 : a drag which was triggered from outside the TabBar.
98 :
99 : Drop - In the Drop handler, the pages have to be moved, or
100 : the new pages have to be inserted. The respective
101 : drop position can be determined using ShowDropPos().
102 :
103 : The following methods are needed for Drag and Drop and must be called
104 : by the handlers:
105 :
106 : StartDrag - Must be called from the Command handler. As parameters,
107 : the CommandEvent and a reference to a Region must be
108 : passed. This vcl::Region then must be passed in
109 : ExecuteDrag(), if the return value indicates that
110 : ExecuteDrag shall be carried out. If the entry is not
111 : selected, it is set as the current entry beforehand.
112 : Because of this, attention must be paid that the Select
113 : handler can be called from this method.
114 :
115 : ShowDropPos - This method must be called by the QueryDrop handler,
116 : so that the TabBar shows where the Tabs are
117 : inserted. This method can also be used in the Drop
118 : handler, in order to determine the position at which
119 : the Tabs shall be inserted. In the method, the
120 : position of the Event must be passed. This method
121 : returns the position, at which the Tabs shall be inserted.
122 :
123 : HideDropPos - This method takes back the DropPosition previously
124 : displayed using ShowDropPos(). This method should be
125 : called, when the window is left in the QueryDrop()
126 : handler or the drag process has been ended.
127 :
128 : The following methods can be used if the pages should be switched
129 : in the Drag and Drop:
130 :
131 : SwitchPage - This method must be called by the QueryDrop handler
132 : if the page, over which the mouse pointer resides,
133 : should be switched. This method should be called
134 : each time the QueryDrop-Handler is called.
135 : Switching the page happens with a delay (500 ms) and
136 : is automatically managed by this method.
137 : The Position of the Event must be passed in the method.
138 : This method returns true if the page has been switched.
139 :
140 : EndSwitchPage - This method resets the data for the switching of the
141 : page. This method should be called when the window
142 : is left in QueryDrop() or the drag process has been
143 : ended.
144 :
145 : IsInSwitching - With this method, it can be queried in
146 : ActivatePage()/DeactivatePage() whether this has been
147 : caused by SwitchPage(). Thus, for example, switching
148 : can be avoided in DeactivatePage() without an error
149 : box.
150 :
151 :
152 : Window Resize
153 : --------------
154 :
155 : If the window width can be changed by the user, the WinBit WB_SIZEABLE
156 : must be set. In this case, the following handler must be overlaid:
157 :
158 : Split - When this handler is called, the window should be
159 : adapted to the width that is returned by GetSplitSize().
160 : In doing so, no minimal or maximum width is taken into
161 : account. A minimal size can be queried using
162 : GetMinSize() and the maximum width must be calculated
163 : by the application itself. As only Online Resize is
164 : supported, the window width must be changed inside
165 : this handler and possibly the width of dependent windows
166 : as well. For this handler, a link can also be set using
167 : SetSplitHdl().
168 :
169 : The following methods deliver more information while Splitting:
170 :
171 : GetSplitSize() - Returns the width of the TabBar, to which the user
172 : wants to resize the window. No minimum or maximum
173 : width is taken into account. However, a width < 5
174 : is never returned. This method only returns valid
175 : values as long as splitting is active.
176 :
177 : GetMinSize() - With this method, a minimum window width can be
178 : queried, so that at least something of a Tab is
179 : visible. Still, the TabBar can be set more narrow
180 : then the width that this method returns.
181 : This method can also be called, when no splitting
182 : is active.
183 :
184 :
185 : Edit Mode
186 : ----------
187 :
188 : The TabBar also offers the user the possibility to change the names
189 : in the Tabs.
190 :
191 : EnableEditMode - With this, it can be configured that on Alt+LeftClick,
192 : StartEditMode() is automatically called by the TabBar.
193 : In the StartRenaming() handler, the renaming can still
194 : be rejected.
195 : StartEditMode - With this method, the EditMode is started on a Tab.
196 : false is returned, if the EditMode is already
197 : active, the mode is rejected with StartRenaming()
198 : or no space is available for editing.
199 : EndEditMode - With this method, the EditMode is ended.
200 : SetEditText - With this method, the text in the AllowRenaming()
201 : handler can still be replaced by another text.
202 : GetEditText - With this method, the text, which the user has typed
203 : in, can be queried in the AllowRenaming() handler.
204 : IsInEditMode - This method is used to query whether the EditMode
205 : is active.
206 : IsEditModeCanceled - This method can be used in the EndRenaming()
207 : handler to query whether the renaming has
208 : been canceled.
209 : GetEditPageId - With this method, the tab that is being/has been
210 : renamed is queried in the Renaming handlers.
211 :
212 : StartRenaming() - This handler is called when the EditMode hast been
213 : started using StartEditMode(). GetEditPageId()
214 : can be used to query which Tab should be renamed.
215 : false should be returned if the EditMod should
216 : not be started.
217 : AllowRenaming() - This handler is called when the EditMode is ended
218 : (not in case of Cancel). Within this handler, it
219 : can then be tested whether the text is OK.
220 : The Tab which was renamed can be queried using
221 : GetEditPageId().
222 : One of the following values should be returned:
223 : TAB_RENAMING_YES
224 : The Tab is renamed.
225 : TAB_RENAMING_NO
226 : The Tab is not renamed, but the EditMode remains
227 : active, so that the user can adapt the name
228 : accordingly.
229 : TAB_RENAMING_CANCEL
230 : The EditMode was cancelled and the old text
231 : is restored.
232 : EndRenaming() - This handler is called when the EditMode has been
233 : ended. The tab that has been renamed can be
234 : queried using GetEditPageId(). Using
235 : IsEditModeCanceled(), it can be queried whether
236 : the mode has been cancelled and the name has
237 : thus not been changed.
238 :
239 :
240 : Maximum Page width
241 : -------------------
242 :
243 : The Page width of the tabs can be limited in order to make an easier
244 : navigation by them possible. If then, the text cannot be displayed
245 : completely, it is abbreviated with "..." and the whole text is
246 : displayed in the Tip or in the active help (if no help text is set).
247 : Using EnableAutoMaxPageWidth(), it can be configured whether the
248 : maximum page width should be based on the currently visible width
249 : (which is the default). Otherwise, the maximum page width can
250 : also be set using SetMaxPageWidth() (in pixels) (in this case, the
251 : AutoMaxPageWidth is ignored).
252 :
253 : ContextMenu
254 : -----------
255 :
256 : If a context-sensitive PopupMenu should be displayed, the Command
257 : handler must be overlaid. Using GetPageId() and when passing the
258 : mouse position, it can be determined whether the mouse click has been
259 : carried out over an item resp. over which item the mouse click has
260 : been carried out.
261 : */
262 :
263 :
264 : // - WinBits -
265 :
266 :
267 : #define WB_RANGESELECT ((WinBits)0x00200000)
268 : #define WB_MULTISELECT ((WinBits)0x00400000)
269 : #define WB_TOPBORDER ((WinBits)0x04000000)
270 : #define WB_3DTAB ((WinBits)0x08000000)
271 : #define WB_MINSCROLL ((WinBits)0x20000000)
272 : #define WB_INSERTTAB ((WinBits)0x40000000)
273 : #define WB_STDTABBAR WB_BORDER
274 :
275 :
276 : // - TabBarPageBits -
277 :
278 :
279 : typedef sal_uInt16 TabBarPageBits;
280 :
281 :
282 : // - Bits for TabBarPages -
283 :
284 :
285 : #define TPB_SPECIAL ((TabBarPageBits)0x0001)
286 :
287 :
288 : // - TabBar-Types - used in TabBar::AllowRenaming
289 :
290 : enum TabBarAllowRenamingReturnCode {
291 : TABBAR_RENAMING_NO,
292 : TABBAR_RENAMING_YES,
293 : TABBAR_RENAMING_CANCEL
294 : };
295 :
296 :
297 : // - TabBar -
298 :
299 : class MouseEvent;
300 : class TrackingEvent;
301 : class DataChangedEvent;
302 : class ImplTabButton;
303 : class ImplTabSizer;
304 : class TabBarEdit;
305 :
306 : struct ImplTabBarItem;
307 : struct TabBar_Impl;
308 : typedef std::vector<ImplTabBarItem*> ImplTabBarList;
309 :
310 : class SVT_DLLPUBLIC TabBar : public vcl::Window
311 : {
312 : friend class ImplTabButton;
313 : friend class ImplTabSizer;
314 :
315 : private:
316 : std::unique_ptr<TabBar_Impl> mpImpl;
317 :
318 : ImplTabBarList* mpItemList;
319 :
320 : OUString maEditText;
321 : Color maSelColor;
322 : Color maSelTextColor;
323 : Size maWinSize;
324 : long mnMaxPageWidth;
325 : long mnCurMaxWidth;
326 : long mnOffX;
327 : long mnOffY;
328 : long mnLastOffX;
329 : long mnSplitSize;
330 : sal_uInt64 mnSwitchTime;
331 : WinBits mnWinStyle;
332 : sal_uInt16 mnCurPageId;
333 : sal_uInt16 mnFirstPos;
334 : sal_uInt16 mnDropPos;
335 : sal_uInt16 mnSwitchId;
336 : sal_uInt16 mnEditId;
337 :
338 : bool mbFormat : 1;
339 : bool mbFirstFormat : 1;
340 : bool mbSizeFormat : 1;
341 : bool mbAutoMaxWidth : 1;
342 : bool mbInSwitching : 1;
343 : bool mbAutoEditMode : 1;
344 : bool mbEditCanceled : 1;
345 : bool mbDropPos : 1;
346 : bool mbInSelect : 1;
347 : bool mbSelColor : 1;
348 : bool mbSelTextColor : 1;
349 : bool mbMirrored : 1;
350 : bool mbScrollAlwaysEnabled : 1;
351 :
352 : Link<> maSelectHdl;
353 : Link<> maSplitHdl;
354 : Link<> maScrollAreaContextHdl;
355 : size_t maCurrentItemList;
356 :
357 : using Window::ImplInit;
358 : SVT_DLLPRIVATE void ImplInit( WinBits nWinStyle );
359 : SVT_DLLPRIVATE void ImplInitSettings( bool bFont, bool bBackground );
360 : SVT_DLLPRIVATE void ImplGetColors(const StyleSettings& rStyleSettings,
361 : Color& rFaceColor, Color& rFaceTextColor,
362 : Color& rSelectColor, Color& rSelectTextColor);
363 : SVT_DLLPRIVATE void ImplShowPage( sal_uInt16 nPos );
364 : SVT_DLLPRIVATE bool ImplCalcWidth();
365 : SVT_DLLPRIVATE void ImplFormat();
366 : SVT_DLLPRIVATE sal_uInt16 ImplGetLastFirstPos();
367 : SVT_DLLPRIVATE void ImplInitControls();
368 : SVT_DLLPRIVATE void ImplEnableControls();
369 : SVT_DLLPRIVATE void ImplSelect();
370 : SVT_DLLPRIVATE void ImplActivatePage();
371 : SVT_DLLPRIVATE bool ImplDeactivatePage();
372 : SVT_DLLPRIVATE void ImplPrePaint(vcl::RenderContext& rRenderContext);
373 : SVT_DLLPRIVATE ImplTabBarItem* ImplGetLastTabBarItem( sal_uInt16 nItemCount );
374 :
375 : DECL_DLLPRIVATE_LINK(ImplClickHdl, ImplTabButton*);
376 :
377 : DECL_DLLPRIVATE_LINK(ImplAddClickHandler, void*);
378 :
379 : ImplTabBarItem* seek( size_t i );
380 : ImplTabBarItem* prev();
381 : ImplTabBarItem* next();
382 :
383 : protected:
384 : virtual void AddTabClick();
385 :
386 : public:
387 : static const sal_uInt16 APPEND;
388 : static const sal_uInt16 PAGE_NOT_FOUND;
389 :
390 : TabBar( vcl::Window* pParent, WinBits nWinStyle = WB_STDTABBAR );
391 : virtual ~TabBar();
392 : virtual void dispose() SAL_OVERRIDE;
393 :
394 : virtual void MouseMove( const MouseEvent& rMEvt ) SAL_OVERRIDE;
395 : virtual void MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE;
396 : virtual void MouseButtonUp( const MouseEvent& rMEvt ) SAL_OVERRIDE;
397 : virtual void Paint( vcl::RenderContext& rRenderContext, const Rectangle& rRect ) SAL_OVERRIDE;
398 : virtual void Resize() SAL_OVERRIDE;
399 : virtual void RequestHelp( const HelpEvent& rHEvt ) SAL_OVERRIDE;
400 : virtual void StateChanged( StateChangedType nStateChange ) SAL_OVERRIDE;
401 : virtual void DataChanged( const DataChangedEvent& rDCEvt ) SAL_OVERRIDE;
402 : virtual bool PreNotify( NotifyEvent& rNEvt ) SAL_OVERRIDE;
403 :
404 : virtual void Select();
405 : virtual void DoubleClick();
406 : void Split();
407 : virtual void ActivatePage();
408 : virtual bool DeactivatePage();
409 : virtual bool StartRenaming();
410 : virtual TabBarAllowRenamingReturnCode AllowRenaming();
411 : virtual void EndRenaming();
412 : virtual void Mirror();
413 :
414 : void InsertPage( sal_uInt16 nPageId, const OUString& rText,
415 : TabBarPageBits nBits = 0,
416 : sal_uInt16 nPos = TabBar::APPEND );
417 : void RemovePage( sal_uInt16 nPageId );
418 : void MovePage( sal_uInt16 nPageId, sal_uInt16 nNewPos );
419 :
420 : Color GetTabBgColor( sal_uInt16 nPageId ) const;
421 : void SetTabBgColor( sal_uInt16 nPageId, const Color& aTabBgColor );
422 : bool IsDefaultTabBgColor( sal_uInt16 nPageId );
423 :
424 : void Clear();
425 :
426 : bool IsPageEnabled( sal_uInt16 nPageId ) const;
427 :
428 : void SetPageBits( sal_uInt16 nPageId, TabBarPageBits nBits = 0 );
429 : TabBarPageBits GetPageBits( sal_uInt16 nPageId ) const;
430 :
431 : sal_uInt16 GetPageCount() const;
432 : sal_uInt16 GetPageId( sal_uInt16 nPos ) const;
433 : sal_uInt16 GetPagePos( sal_uInt16 nPageId ) const;
434 : sal_uInt16 GetPageId( const Point& rPos ) const;
435 : Rectangle GetPageRect( sal_uInt16 nPageId ) const;
436 : // returns the rectangle in which page tabs are drawn
437 : Rectangle GetPageArea() const;
438 :
439 : void SetCurPageId( sal_uInt16 nPageId );
440 2132 : sal_uInt16 GetCurPageId() const { return mnCurPageId; }
441 :
442 : void SetFirstPageId( sal_uInt16 nPageId );
443 : sal_uInt16 GetFirstPageId() const { return GetPageId( mnFirstPos ); }
444 : void MakeVisible( sal_uInt16 nPageId );
445 :
446 : void SelectPage( sal_uInt16 nPageId, bool bSelect = true );
447 : sal_uInt16 GetSelectPageCount() const;
448 : bool IsPageSelected( sal_uInt16 nPageId ) const;
449 :
450 : void EnableAutoMaxPageWidth( bool bEnable = true ) { mbAutoMaxWidth = bEnable; }
451 : bool IsAutoMaxPageWidthEnabled() const { return mbAutoMaxWidth; }
452 : void SetMaxPageWidth( long nMaxWidth );
453 : long GetMaxPageWidth() const { return mnMaxPageWidth; }
454 : void ResetMaxPageWidth() { SetMaxPageWidth( 0 ); }
455 : bool IsMaxPageWidth() const { return mnMaxPageWidth != 0; }
456 :
457 567 : void EnableEditMode( bool bEnable = true ) { mbAutoEditMode = bEnable; }
458 : bool IsEditModeEnabled() const { return mbAutoEditMode; }
459 : bool StartEditMode( sal_uInt16 nPageId );
460 : void EndEditMode( bool bCancel = false );
461 0 : void SetEditText( const OUString& rText ) { maEditText = rText; }
462 0 : const OUString& GetEditText() const { return maEditText; }
463 : bool IsInEditMode() const;
464 0 : bool IsEditModeCanceled() const { return mbEditCanceled; }
465 0 : sal_uInt16 GetEditPageId() const { return mnEditId; }
466 :
467 : /** Mirrors the entire control including position of buttons and splitter.
468 : Mirroring is done relative to the current direction of the GUI.
469 : @param bMirrored sal_True = the control will draw itself RTL in LTR GUI,
470 : and vice versa; sal_False = the control behaves according to the
471 : current direction of the GUI. */
472 : void SetMirrored(bool bMirrored = true);
473 : /** Returns true, if the control is set to mirrored mode (see SetMirrored()). */
474 0 : bool IsMirrored() const { return mbMirrored; }
475 :
476 : /** Sets the control to LTR or RTL mode regardless of the GUI direction.
477 : @param bRTL sal_False = the control will draw from left to right;
478 : sal_True = the control will draw from right to left. */
479 : void SetEffectiveRTL( bool bRTL );
480 : /** Returns true, if the control draws from right to left (see SetEffectiveRTL()). */
481 : bool IsEffectiveRTL() const;
482 :
483 : bool StartDrag( const CommandEvent& rCEvt, vcl::Region& rRegion );
484 : sal_uInt16 ShowDropPos( const Point& rPos );
485 : void HideDropPos();
486 : bool SwitchPage( const Point& rPos );
487 : void EndSwitchPage();
488 : bool IsInSwitching() { return mbInSwitching; }
489 :
490 : const Color& GetSelectColor() const { return maSelColor; }
491 : bool IsSelectColor() const { return mbSelColor; }
492 : const Color& GetSelectTextColor() const { return maSelTextColor; }
493 : bool IsSelectTextColor() const { return mbSelTextColor; }
494 :
495 : void SetPageText( sal_uInt16 nPageId, const OUString& rText );
496 : OUString GetPageText( sal_uInt16 nPageId ) const;
497 : OUString GetHelpText( sal_uInt16 nPageId ) const;
498 : OString GetHelpId( sal_uInt16 nPageId ) const;
499 :
500 0 : long GetSplitSize() const { return mnSplitSize; }
501 :
502 : using Window::SetHelpText;
503 : using Window::GetHelpText;
504 : using Window::SetHelpId;
505 : using Window::GetHelpId;
506 :
507 : void SetStyle( WinBits nStyle );
508 1700 : WinBits GetStyle() const { return mnWinStyle; }
509 :
510 : void SetScrollAlwaysEnabled(bool bScrollAlwaysEnabled);
511 :
512 : Size CalcWindowSizePixel() const;
513 :
514 0 : void SetSelectHdl( const Link<>& rLink ) { maSelectHdl = rLink; }
515 481 : void SetSplitHdl( const Link<>& rLink ) { maSplitHdl = rLink; }
516 348 : void SetScrollAreaContextHdl( const Link<>& rLink ) { maScrollAreaContextHdl = rLink; }
517 :
518 : // accessibility
519 : virtual css::uno::Reference<css::accessibility::XAccessible> CreateAccessible() SAL_OVERRIDE;
520 : };
521 :
522 : #endif // INCLUDED_SVTOOLS_TABBAR_HXX
523 :
524 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|