1/*
2 * LegacyClonk
3 *
4 * Copyright (c) RedWolf Design
5 * Copyright (c) 2001, Sven2
6 * Copyright (c) 2017-2023, The LegacyClonk Team and contributors
7 *
8 * Distributed under the terms of the ISC license; see accompanying file
9 * "COPYING" for details.
10 *
11 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12 * See accompanying file "TRADEMARK" for details.
13 *
14 * To redistribute this file separately, substitute the full license texts
15 * for the above references.
16 */
17
18#pragma once
19
20#include "C4Gui.h"
21
22namespace C4GUI
23{
24// tabbing panel
25class Tabular : public Control
26{
27public:
28 // sheet covering the client area of a tabular
29 class Sheet : public Window
30 {
31 protected:
32 StdStrBuf sTitle; // sheet label
33 int32_t icoTitle; // sheet label icon
34 char cHotkey;
35 uint32_t dwCaptionClr; // caption color - default if 0
36 bool fHasCloseButton, fCloseButtonHighlighted;
37 bool fTitleMarkup;
38
39 Sheet(const char *szTitle, const C4Rect &rcBounds, int32_t icoTitle = Ico_None, bool fHasCloseButton = false, bool fTitleMarkup = true); // expands hotkey markup in title
40
41 void DrawCaption(C4FacetEx &cgo, int32_t x, int32_t y, int32_t iMaxWdt, bool fLarge, bool fActive, bool fFocus, C4FacetEx *pfctClip, C4FacetEx *pfctIcon, CStdFont *pUseFont);
42 void GetCaptionSize(int32_t *piWdt, int32_t *piHgt, bool fLarge, bool fActive, C4FacetEx *pfctClip, C4FacetEx *pfctIcon, CStdFont *pUseFont);
43 virtual void OnShown(bool fByUser) {} // calklback from tabular after sheet has been made visible
44 void SetCloseButtonHighlight(bool fToVal) { fCloseButtonHighlighted = fToVal; }
45 bool IsPosOnCloseButton(int32_t x, int32_t y, int32_t iCaptWdt, int32_t iCaptHgt, bool fLarge);
46 bool IsActiveSheet();
47
48 public:
49 const char *GetTitle() { return sTitle.getData(); }
50 char GetHotkey() { return cHotkey; }
51 void SetTitle(const char *szNewTitle);
52 void SetCaptionColor(uint32_t dwNewClr = 0) { dwCaptionClr = dwNewClr; }
53 virtual void UserClose() { delete this; } // user pressed close button
54 bool HasCloseButton() const { return fHasCloseButton; }
55
56 friend class Tabular;
57 };
58
59 enum TabPosition
60 {
61 tbNone = 0, // no tabs
62 tbTop, // tabs on top
63 tbLeft, // tabs to the left
64 };
65
66private:
67 Sheet *pActiveSheet; // currently selected sheet
68 TabPosition eTabPos; // whither tabs shalt be shown or nay, en where art thy shown?
69 int32_t iMaxTabWidth; // maximum tab length; used when tabs are positioned left and do not have gfx
70 int32_t iSheetSpacing, iSheetOff; // distances of sheet captions
71 int32_t iCaptionLengthTotal, iCaptionScrollPos; // scrolling in captions (top only)
72 bool fScrollingLeft, fScrollingRight, fScrollingLeftDown, fScrollingRightDown; // scrolling in captions (top only)
73 time_t tLastScrollTime; // set when fScrollingLeftDown or fScrollingRightDown are true: Time for next scrolling if mouse is held down
74 int iSheetMargin;
75 bool fDrawSelf; // if border and bg shall be drawn
76
77 C4FacetEx *pfctBack, *pfctClip, *pfctIcons; // set for tabulars that have custom gfx
78 CStdFont *pSheetCaptionFont; // font to be used for caption drawing; nullptr if default GUI font is to be used
79
80 C4KeyBinding *pKeySelUp, *pKeySelDown, *pKeySelUp2, *pKeySelDown2, *pKeyCloseTab; // key bindings
81
82 void SelectionChanged(bool fByUser); // pActiveSheet changed: sound, tooltip, etc.
83 void SheetsChanged(); // update iMaxTabWidth by new set of sheet labels
84 void UpdateScrolling();
85 void DoCaptionScroll(int32_t iDir);
86
87private:
88 bool HasGfx() { return pfctBack && pfctClip && pfctIcons; } // whether the control uses custom graphics
89
90protected:
91 bool KeySelUp(); // keyboard callback: Select previous sheet
92 bool KeySelDown(); // keyboard callback: Select next sheet
93 bool KeyCloseTab(); // keyboard callback: Close current sheet if possible
94
95 virtual void DrawElement(C4FacetEx &cgo) override;
96 virtual void MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, uint32_t dwKeyParam) override;
97 void MouseLeaveCaptionArea();
98 virtual void MouseLeave(CMouse &rMouse) override;
99 virtual void OnGetFocus(bool fByMouse) override;
100
101 virtual Control *IsFocusElement() override { return eTabPos ? this : nullptr; } // this control can gain focus only if tabs are enabled only
102 virtual bool IsFocusOnClick() override { return false; } // but never get focus on single mouse click, because this would de-focus any contained controls!
103
104 int32_t GetTopSize() { return (eTabPos == tbTop) ? 20 : 0; } // vertical size of tab selection bar
105 int32_t GetLeftSize() { return (eTabPos == tbLeft) ? (HasGfx() ? GetLeftClipSize(pfctForClip: pfctClip) : 20 + iMaxTabWidth) : 0; } // horizontal size of tab selection bar
106 bool HasLargeCaptions() { return eTabPos == tbLeft; }
107
108 virtual int32_t GetMarginTop() override { return iSheetMargin + GetTopSize() + (HasGfx() ? (rcBounds.Hgt - GetTopSize()) * 30 / 483 : 0); }
109 virtual int32_t GetMarginLeft() override { return iSheetMargin + GetLeftSize() + (HasGfx() ? (rcBounds.Wdt - GetLeftSize()) * 13 / 628 : 0); }
110 virtual int32_t GetMarginRight() override { return iSheetMargin + (HasGfx() ? (rcBounds.Wdt - GetLeftSize()) * 30 / 628 : 0); }
111 virtual int32_t GetMarginBottom() override { return iSheetMargin + (HasGfx() ? (rcBounds.Hgt - GetTopSize()) * 32 / 483 : 0); }
112
113 virtual void UpdateSize() override;
114
115 virtual bool IsSelectedChild(Element *pChild) override { return pChild == pActiveSheet || (pActiveSheet && pActiveSheet->IsParentOf(pEl: pChild)); }
116
117public:
118 Tabular(const C4Rect &rtBounds, TabPosition eTabPos);
119 ~Tabular();
120
121 virtual void RemoveElement(Element *pChild) override; // clear ptr
122 Sheet *AddSheet(const char *szTitle, int32_t icoTitle = Ico_None);
123 void AddCustomSheet(Sheet *pAddSheet);
124 void ClearSheets(); // del all sheets
125 void SelectSheet(int32_t iIndex, bool fByUser);
126 void SelectSheet(Sheet *pSelSheet, bool fByUser);
127
128 Sheet *GetSheet(int32_t iIndex) { return static_cast<Sheet *>(GetElementByIndex(i: iIndex)); }
129 Sheet *GetActiveSheet() { return pActiveSheet; }
130 int32_t GetActiveSheetIndex();
131 int32_t GetSheetCount() { return GetElementCount(); }
132 int32_t GetTabButtonWidth() const; // return iMaxTabWidth; useful when tabs are positioned left
133
134 void SetGfx(C4FacetEx *pafctBack, C4FacetEx *pafctClip, C4FacetEx *pafctIcons, CStdFont *paSheetCaptionFont, bool fResizeByAspect);
135 static int32_t GetLeftClipSize(C4FacetEx *pfctForClip) { return pfctForClip->Wdt * 95 / 120; } // left clip area size by gfx
136 void SetSheetMargin(int32_t iMargin) { iSheetMargin = iMargin; UpdateOwnPos(); }
137 void SetDrawDecoration(bool fToVal) { fDrawSelf = fToVal; }
138
139 friend class Sheet;
140};
141}
142