Coverage Report

Created: 2026-03-31 11:00

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