diff options
Diffstat (limited to 'include/svtools/tabbar.hxx')
-rw-r--r-- | include/svtools/tabbar.hxx | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/include/svtools/tabbar.hxx b/include/svtools/tabbar.hxx new file mode 100644 index 000000000..948e60b35 --- /dev/null +++ b/include/svtools/tabbar.hxx @@ -0,0 +1,505 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <svtools/svtdllapi.h> +#include <tools/link.hxx> +#include <vcl/window.hxx> +#include <o3tl/typed_flags_set.hxx> +#include <memory> + +class StyleSettings; + +/* + +Allowed StylbeBits +------------------ + +WB_SCROLL - The tabs can be scrolled via an extra field +WB_MINSCROLL - The tabs can be scrolled via 2 additional buttons +WB_RANGESELECT - Connected ranges can be selected +WB_MULTISELECT - single tabs can be selected +WB_BORDER - a border is drawn in the top and in the bottom +WB_DRAG - A StartDrag handler is called by the TabBar, if drag + and drop should be started. In addition, drag and drop + is activated in the TabBar with EnableDrop(). +WB_SIZEABLE - a Split handler is called by the TabBar, if the user + wants to change the width of the TabBar +WB_STDTABBAR - WB_BORDER + + +Allowed PageBits +----------------- + +Setting page bits modify the display attributes of the tab name + +TabBarPageBits::Blue + - Display tab name in light blue, used in draw for + invisible layers and in calc for scenario pages +TabBarPageBits::Italic + - Display tab name italic, used in draw for + locked layers +TabBarPageBits::Underline + - Display tab name underlined, used in draw for + non-printable layers + + +Handlers +------- + +Select - is called when a tab is selected or unselected +DoubleClick - Is called when a DoubleClick has been fired in the + TabBar. Inside of the handler, GetCurPageId() returns + the clicked tab or 0, if no tab has been clicked. +ActivatePage - Is called, if another page is activated. + GetCurPageId() returns the activated page. +DeactivatePage - Is called, when a page is deactivated. If another page + may be activated, true must be returned; if another + page shall be excluded from the activation, false must + be returned. GetCurPageId() returns the page to be + deactivated. + + +Drag and Drop +------------- + +For Drag and Drop, the WinBit WB_DRAG must be set. In addition, the +Command handler, the QueryDrop handler and the Drop handler must be overlaid. +In doing so, the following must be implemented in the handlers: + +Command - If dragging should be started in this handler, + StartDrag() must be called. This method + then selects the respective entry or returns + false, if dragging cannot be carried out. + +QueryDrop - This handler is always called by StarView, when the + mouse is pulled over the window while dragging + (s.a. SV documentation). In this handler, it must be + determined whether a drop is possible. The drop + position can be shown in TabBar using ShowDropPos(). + When calling, the position of the Event must be passed. + If the position is at the left or right border, + scrolling automatically takes place in the TabBar. + This method also returns the respective drop position, + which is also needed for a drop. If the window is left + while dragging, the drop position can be taken back + using HideDropPos(). Thus, it is also possible to handle + a drag which was triggered from outside the TabBar. + +Drop - In the Drop handler, the pages have to be moved, or + the new pages have to be inserted. The respective + drop position can be determined using ShowDropPos(). + +The following methods are needed for Drag and Drop and must be called +by the handlers: + +StartDrag - Must be called from the Command handler. As parameters, + the CommandEvent and a reference to a Region must be + passed. This vcl::Region then must be passed in + ExecuteDrag(), if the return value indicates that + ExecuteDrag shall be carried out. If the entry is not + selected, it is set as the current entry beforehand. + Because of this, attention must be paid that the Select + handler can be called from this method. + +ShowDropPos - This method must be called by the QueryDrop handler, + so that the TabBar shows where the Tabs are + inserted. This method can also be used in the Drop + handler, in order to determine the position at which + the Tabs shall be inserted. In the method, the + position of the Event must be passed. This method + returns the position, at which the Tabs shall be inserted. + +HideDropPos - This method takes back the DropPosition previously + displayed using ShowDropPos(). This method should be + called, when the window is left in the QueryDrop() + handler or the drag process has been ended. + +The following methods can be used if the pages should be switched +in the Drag and Drop: + +SwitchPage - This method must be called by the QueryDrop handler + if the page, over which the mouse pointer resides, + should be switched. This method should be called + each time the QueryDrop-Handler is called. + Switching the page happens with a delay (500 ms) and + is automatically managed by this method. + The Position of the Event must be passed in the method. + This method returns true if the page has been switched. + +EndSwitchPage - This method resets the data for the switching of the + page. This method should be called when the window + is left in QueryDrop() or the drag process has been + ended. + +IsInSwitching - With this method, it can be queried in + ActivatePage()/DeactivatePage() whether this has been + caused by SwitchPage(). Thus, for example, switching + can be avoided in DeactivatePage() without an error + box. + + +Window Resize +-------------- + +If the window width can be changed by the user, the WinBit WB_SIZEABLE +must be set. In this case, the following handler must be overlaid: + +Split - When this handler is called, the window should be + adapted to the width that is returned by GetSplitSize(). + In doing so, no minimal or maximum width is taken into + account. A minimal size can be queried using + GetMinSize() and the maximum width must be calculated + by the application itself. As only Online Resize is + supported, the window width must be changed inside + this handler and possibly the width of dependent windows + as well. For this handler, a link can also be set using + SetSplitHdl(). + +The following methods deliver more information while Splitting: + +GetSplitSize() - Returns the width of the TabBar, to which the user + wants to resize the window. No minimum or maximum + width is taken into account. However, a width < 5 + is never returned. This method only returns valid + values as long as splitting is active. + +GetMinSize() - With this method, a minimum window width can be + queried, so that at least something of a Tab is + visible. Still, the TabBar can be set more narrow + then the width that this method returns. + This method can also be called, when no splitting + is active. + + +Edit Mode +---------- + +The TabBar also offers the user the possibility to change the names +in the Tabs. + +EnableEditMode - With this, it can be configured that on Alt+LeftClick, + StartEditMode() is automatically called by the TabBar. + In the StartRenaming() handler, the renaming can still + be rejected. +StartEditMode - With this method, the EditMode is started on a Tab. + false is returned, if the EditMode is already + active, the mode is rejected with StartRenaming() + or no space is available for editing. +EndEditMode - With this method, the EditMode is ended. +SetEditText - With this method, the text in the AllowRenaming() + handler can still be replaced by another text. +GetEditText - With this method, the text, which the user has typed + in, can be queried in the AllowRenaming() handler. +IsInEditMode - This method is used to query whether the EditMode + is active. +IsEditModeCanceled - This method can be used in the EndRenaming() + handler to query whether the renaming has + been canceled. +GetEditPageId - With this method, the tab that is being/has been + renamed is queried in the Renaming handlers. + +StartRenaming() - This handler is called when the EditMode hast been + started using StartEditMode(). GetEditPageId() + can be used to query which Tab should be renamed. + false should be returned if the EditMod should + not be started. +AllowRenaming() - This handler is called when the EditMode is ended + (not in case of Cancel). Within this handler, it + can then be tested whether the text is OK. + The Tab which was renamed can be queried using + GetEditPageId(). + One of the following values should be returned: + TAB_RENAMING_YES + The Tab is renamed. + TAB_RENAMING_NO + The Tab is not renamed, but the EditMode remains + active, so that the user can adapt the name + accordingly. + TAB_RENAMING_CANCEL + The EditMode was cancelled and the old text + is restored. +EndRenaming() - This handler is called when the EditMode has been + ended. The tab that has been renamed can be + queried using GetEditPageId(). Using + IsEditModeCanceled(), it can be queried whether + the mode has been cancelled and the name has + thus not been changed. + + +Maximum Page width +------------------- + +The Page width of the tabs can be limited in order to make an easier +navigation by them possible. If then, the text cannot be displayed +completely, it is abbreviated with "..." and the whole text is +displayed in the Tip or in the active help (if no help text is set). +Using EnableAutoMaxPageWidth(), it can be configured whether the +maximum page width should be based on the currently visible width +(which is the default). Otherwise, the maximum page width can +also be set using SetMaxPageWidth() (in pixels) (in this case, the +AutoMaxPageWidth is ignored). + +ContextMenu +----------- + +If a context-sensitive PopupMenu should be displayed, the Command +handler must be overlaid. Using GetPageId() and when passing the +mouse position, it can be determined whether the mouse click has been +carried out over an item resp. over which item the mouse click has +been carried out. +*/ + +namespace weld { +class Button; +} + +#define WB_RANGESELECT (WinBits(0x00200000)) +#define WB_MULTISELECT (WinBits(0x00400000)) +#define WB_MINSCROLL (WinBits(0x20000000)) +#define WB_INSERTTAB (WinBits(0x40000000)) +#define WB_STDTABBAR WB_BORDER + +// Page bits + +enum class TabBarPageBits { + NONE = 0x00, + Blue = 0x01, + Italic = 0x02, + Underline = 0x04, +}; +namespace o3tl { + template<> struct typed_flags<TabBarPageBits> : is_typed_flags<TabBarPageBits, 0x07> {}; +}; + + // interface checks only, do not use in regular control flow + +#define TPB_DISPLAY_NAME_ALLFLAGS (TabBarPageBits::Blue | TabBarPageBits::Italic | TabBarPageBits::Underline) + +// - TabBar-Types - used in TabBar::AllowRenaming + +enum TabBarAllowRenamingReturnCode { + TABBAR_RENAMING_NO, + TABBAR_RENAMING_YES, + TABBAR_RENAMING_CANCEL +}; + +class MouseEvent; +class DataChangedEvent; + +struct ImplTabBarItem; +struct TabBar_Impl; + + +class SVT_DLLPUBLIC TabBar : public vcl::Window +{ + friend class ImplTabSizer; + +private: + std::unique_ptr<TabBar_Impl> mpImpl; + + OUString maEditText; + Size maWinSize; + tools::Long mnMaxPageWidth; + tools::Long mnCurMaxWidth; + tools::Long mnOffX; + tools::Long mnOffY; + tools::Long mnLastOffX; + tools::Long mnSplitSize; + sal_uInt64 mnSwitchTime; + WinBits mnWinStyle; + sal_uInt16 mnCurPageId; + sal_uInt16 mnFirstPos; + sal_uInt16 mnDropPos; + sal_uInt16 mnSwitchId; + sal_uInt16 mnEditId; + + bool mbFormat : 1; + bool mbFirstFormat : 1; + bool mbSizeFormat : 1; + bool mbAutoEditMode : 1; + bool mbEditCanceled : 1; + bool mbDropPos : 1; + bool mbInSelect : 1; + bool mbMirrored : 1; + bool mbScrollAlwaysEnabled : 1; + + Link<TabBar*,void> maSelectHdl; + Link<TabBar*,void> maSplitHdl; + Link<const CommandEvent&, void> maScrollAreaContextHdl; + size_t maCurrentItemList; + + using Window::ImplInit; + SVT_DLLPRIVATE void ImplInit( WinBits nWinStyle ); + SVT_DLLPRIVATE void ImplInitSettings( bool bFont, bool bBackground ); + SVT_DLLPRIVATE void ImplGetColors(const StyleSettings& rStyleSettings, + Color& rFaceColor, Color& rFaceTextColor, + Color& rSelectColor, Color& rSelectTextColor); + SVT_DLLPRIVATE void ImplShowPage( sal_uInt16 nPos ); + SVT_DLLPRIVATE bool ImplCalcWidth(); + SVT_DLLPRIVATE void ImplFormat(); + SVT_DLLPRIVATE sal_uInt16 ImplGetLastFirstPos(); + SVT_DLLPRIVATE void ImplInitControls(); + SVT_DLLPRIVATE void ImplEnableControls(); + SVT_DLLPRIVATE void ImplSelect(); + SVT_DLLPRIVATE void ImplActivatePage(); + SVT_DLLPRIVATE bool ImplDeactivatePage(); + SVT_DLLPRIVATE void ImplPrePaint(); + SVT_DLLPRIVATE ImplTabBarItem* ImplGetLastTabBarItem( sal_uInt16 nItemCount ); + + DECL_DLLPRIVATE_LINK(ImplClickHdl, weld::Button&, void); + DECL_DLLPRIVATE_LINK(ImplAddClickHandler, weld::Button&, void); + DECL_DLLPRIVATE_LINK(MousePressHdl, const MouseEvent&, bool); + DECL_DLLPRIVATE_LINK(ContextMenuHdl, const CommandEvent&, void); + + ImplTabBarItem* seek( size_t i ); + ImplTabBarItem* prev(); + ImplTabBarItem* next(); + +protected: + virtual void AddTabClick(); + OUString GetAuxiliaryText(sal_uInt16 nPageId) const; // needed in derived class LayerTabBar + void SetAuxiliaryText(sal_uInt16 nPageId, const OUString& rText ); + +public: + static const sal_uInt16 APPEND; + static const sal_uInt16 PAGE_NOT_FOUND; + + TabBar( vcl::Window* pParent, WinBits nWinStyle ); + virtual ~TabBar() override; + virtual void dispose() override; + + virtual void MouseMove( const MouseEvent& rMEvt ) override; + virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; + virtual void MouseButtonUp( const MouseEvent& rMEvt ) override; + virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; + virtual void Resize() override; + virtual void RequestHelp( const HelpEvent& rHEvt ) override; + virtual void StateChanged( StateChangedType nStateChange ) override; + virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; + virtual bool PreNotify( NotifyEvent& rNEvt ) override; + + virtual void Select(); + virtual void DoubleClick(); + void Split(); + virtual void ActivatePage(); + virtual bool DeactivatePage(); + virtual bool StartRenaming(); + virtual TabBarAllowRenamingReturnCode AllowRenaming(); + virtual void EndRenaming(); + virtual void Mirror(); + + virtual void InsertPage( sal_uInt16 nPageId, const OUString& rText, + TabBarPageBits nBits = TabBarPageBits::NONE, + sal_uInt16 nPos = TabBar::APPEND ); + void RemovePage( sal_uInt16 nPageId ); + void MovePage( sal_uInt16 nPageId, sal_uInt16 nNewPos ); + + Color GetTabBgColor( sal_uInt16 nPageId ) const; + void SetTabBgColor( sal_uInt16 nPageId, const Color& aTabBgColor ); + + void Clear(); + + bool IsPageEnabled( sal_uInt16 nPageId ) const; + + void SetPageBits( sal_uInt16 nPageId, TabBarPageBits nBits ); + TabBarPageBits GetPageBits( sal_uInt16 nPageId ) const; + + sal_uInt16 GetPageCount() const; + sal_uInt16 GetPageId( sal_uInt16 nPos ) const; + sal_uInt16 GetPagePos( sal_uInt16 nPageId ) const; + sal_uInt16 GetCurPagePos() const { return GetPagePos(GetCurPageId()); } + sal_uInt16 GetPageId( const Point& rPos ) const; + tools::Rectangle GetPageRect( sal_uInt16 nPageId ) const; + // returns the rectangle in which page tabs are drawn + tools::Rectangle GetPageArea() const; + + void SetCurPageId( sal_uInt16 nPageId ); + sal_uInt16 GetCurPageId() const { return mnCurPageId; } + + void SetFirstPageId( sal_uInt16 nPageId ); + void MakeVisible( sal_uInt16 nPageId ); + + void SelectPage( sal_uInt16 nPageId, bool bSelect ); + sal_uInt16 GetSelectPageCount() const; + bool IsPageSelected( sal_uInt16 nPageId ) const; + void SetProtectionSymbol( sal_uInt16 nPageId, bool bProtection ); + + void SetMaxPageWidth( tools::Long nMaxWidth ); + + void EnableEditMode() { mbAutoEditMode = true; } + bool StartEditMode( sal_uInt16 nPageId ); + void EndEditMode( bool bCancel = false ); + void SetEditText( const OUString& rText ) { maEditText = rText; } + const OUString& GetEditText() const { return maEditText; } + bool IsInEditMode() const; + bool IsEditModeCanceled() const { return mbEditCanceled; } + sal_uInt16 GetEditPageId() const { return mnEditId; } + + /** Mirrors the entire control including position of buttons and splitter. + Mirroring is done relative to the current direction of the GUI. + @param bMirrored sal_True = the control will draw itself RTL in LTR GUI, + and vice versa; sal_False = the control behaves according to the + current direction of the GUI. */ + void SetMirrored(bool bMirrored); + /** Returns true, if the control is set to mirrored mode (see SetMirrored()). */ + bool IsMirrored() const { return mbMirrored; } + + /** Sets the control to LTR or RTL mode regardless of the GUI direction. + @param bRTL sal_False = the control will draw from left to right; + sal_True = the control will draw from right to left. */ + void SetEffectiveRTL( bool bRTL ); + /** Returns true, if the control draws from right to left (see SetEffectiveRTL()). */ + bool IsEffectiveRTL() const; + + bool StartDrag( const CommandEvent& rCEvt, vcl::Region& rRegion ); + sal_uInt16 ShowDropPos( const Point& rPos ); + void HideDropPos(); + void SwitchPage( const Point& rPos ); + void EndSwitchPage(); + + virtual void SetPageText( sal_uInt16 nPageId, const OUString& rText ); + OUString GetPageText( sal_uInt16 nPageId ) const; + OUString GetHelpText( sal_uInt16 nPageId ) const; + + tools::Long GetSplitSize() const { return mnSplitSize; } + + using Window::SetHelpText; + using Window::GetHelpText; + using Window::SetHelpId; + using Window::GetHelpId; + + void SetStyle( WinBits nStyle ); + WinBits GetStyle() const { return mnWinStyle; } + + void SetScrollAlwaysEnabled(bool bScrollAlwaysEnabled); + + Size CalcWindowSizePixel() const; + + void SetSelectHdl( const Link<TabBar*,void>& rLink ) { maSelectHdl = rLink; } + void SetSplitHdl( const Link<TabBar*,void>& rLink ) { maSplitHdl = rLink; } + void SetScrollAreaContextHdl( const Link<const CommandEvent&,void>& rLink ) { maScrollAreaContextHdl = rLink; } + void SetAddButtonEnabled(bool bAddButtonEnabled); + + // accessibility + virtual css::uno::Reference<css::accessibility::XAccessible> CreateAccessible() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |