Loading...
Searching...
No Matches
SplitPanel.h
Go to the documentation of this file.
1//
2// SplitPanel.h
3//
4
5#ifndef MALENA_SPLITPANEL_H
6#define MALENA_SPLITPANEL_H
7
8#pragma once
9
12#include <Malena/Core/Core.h>
20#include <functional>
21#include <memory>
22#include <vector>
23#include <type_traits>
26
27namespace ml
28{
30 {
31 public:
32 enum class Flag {};
33 enum class State { IDLE, DIVIDER_HOVER, DIVIDER_DRAG };
34 };
35
81 class MALENA_API SplitPanel : public ComponentWith<SplitPanelManifest>,
82 public SplitPanelSettings,
83 public SplitPanelTheme,
84 public Themeable
85 {
86 public:
91
92 private:
93 struct Pane
94 {
95 std::unique_ptr<ml::Core> content;
96 std::function<void(sf::Vector2f)> resizeFn;
97 float size = 0.f;
98 float minSize = 0.f;
99 float maxSize = 0.f;
100 bool flex = true;
101 };
102
103 std::vector<Pane> _panes;
104
105 sf::Vector2f _position = {0.f, 0.f};
106 sf::Vector2f _size = {400.f, 300.f};
107
108 int _hoveredDivider = -1;
109 int _draggingDiv = -1;
110 float _dragStartMouse = 0.f;
111 float _dragStartSizeA = 0.f;
112 float _dragStartSizeB = 0.f;
113 bool _prevMouseDown = false;
114
115 std::function<void(std::size_t, float)> _onDividerMoved;
116
117 // ── Internal ──────────────────────────────────────────────────────────
118 float totalAvailable() const;
119 float dividerPos(int divIdx) const;
120 int hitTestDivider(const sf::Vector2f& wp) const;
121 void layoutPanes();
122 void distributeSizes();
123 void drawDivider(sf::RenderTarget& target,
124 const sf::RenderStates& states,
125 int divIdx, bool hovered, bool dragging) const;
126
127 protected:
128 void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
129 void onThemeApplied(const Theme& theme) override;
130
131 public:
132
133 public:
134 explicit SplitPanel(Orientation orientation = Orientation::HORIZONTAL,
136
137 SplitPanel(const SplitPanel&) = delete;
138 SplitPanel& operator=(const SplitPanel&) = delete;
139
140 // ── Apply ─────────────────────────────────────────────────────────────
141
142 template<typename S>
143 void applySettings(const S& s)
144 {
145 static_assert(std::is_base_of_v<SplitPanelSettings, S>,
146 "applySettings() requires SplitPanelSettings");
147 static_cast<SplitPanelSettings&>(*this) = s;
148 layoutPanes();
149 }
150
151 template<typename T>
152 void applyTheme(const T& t)
153 {
154 static_assert(std::is_base_of_v<SplitPanelTheme, T>,
155 "applyTheme() requires SplitPanelTheme");
156 static_cast<SplitPanelTheme&>(*this) = t;
157 }
158
159 template<typename St>
160 void applyStyle(const St& s)
161 {
162 static_assert(std::is_base_of_v<SplitPanelSettings, St> &&
163 std::is_base_of_v<SplitPanelTheme, St>,
164 "applyStyle() requires SplitPanelSettings and SplitPanelTheme");
165 static_cast<SplitPanelSettings&>(*this) = s;
166 static_cast<SplitPanelTheme&>(*this) = s;
167 layoutPanes();
168 }
169
170 // ── Pane management ───────────────────────────────────────────────────
171
185 template<typename T>
186 T& addPane(std::unique_ptr<T> content, float initialSize = 0.f)
187 {
188 static_assert(std::is_base_of_v<ml::Core, T>,
189 "addPane() content must derive from ml::Core");
190
191 T* ptr = content.get();
192
193 Pane pane;
194 pane.content = std::move(content);
195 pane.size = initialSize;
196 pane.flex = (initialSize == 0.f);
197
198 if constexpr (detail::has_setSize<T>::value)
199 pane.resizeFn = [ptr](sf::Vector2f sz){ ptr->setSize(sz); };
200
201 _panes.push_back(std::move(pane));
202 addComponent(*ptr);
203 distributeSizes();
204 layoutPanes();
205
206 return *ptr;
207 }
208
210 void setPaneMinSize(std::size_t index, float minSize);
211
213 void setPaneMaxSize(std::size_t index, float maxSize);
214
216 void setDividerPosition(std::size_t dividerIndex, float position);
217
219 [[nodiscard]] std::size_t paneCount() const { return _panes.size(); }
220
221 // ── Callback ─────────────────────────────────────────────────────────
222
224 void onDividerMoved(std::function<void(std::size_t, float)> cb);
225
226 // ── Size / position ───────────────────────────────────────────────────
227
228 void setSize(const sf::Vector2f& size);
229 [[nodiscard]] sf::Vector2f getSize() const { return _size; }
230
231 void setPosition(const sf::Vector2f& position) override;
232 sf::Vector2f getPosition() const override;
234 };
235
236 template<typename MANIFEST>
237 class SplitPanelWith : public SplitPanel, public Customizable<MANIFEST>
238 { public: using SplitPanel::SplitPanel; };
239
240} // namespace ml
241#endif // MALENA_SPLITPANEL_H
static const sf::Font & getDefault()
Return the built-in Arial font.
Base class for all Malena manifests.
Definition Manifest.h:51
void setDividerPosition(std::size_t dividerIndex, float position)
Programmatically set a divider position.
SplitPanel(Orientation orientation=Orientation::HORIZONTAL, const sf::Font &font=FontManager<>::getDefault())
sf::Vector2f getSize() const
Definition SplitPanel.h:229
void setPosition(const sf::Vector2f &position) override
SplitPanelSettings::Orientation Orientation
Definition SplitPanel.h:89
SplitPanel(const SplitPanel &)=delete
void applyTheme(const T &t)
Definition SplitPanel.h:152
sf::Vector2f getPosition() const override
void draw(sf::RenderTarget &target, sf::RenderStates states) const override
void onDividerMoved(std::function< void(std::size_t, float)> cb)
Fired whenever a divider is moved (by drag or API).
void applyStyle(const St &s)
Definition SplitPanel.h:160
void setPaneMaxSize(std::size_t index, float maxSize)
Set the maximum size of a pane by index.
T & addPane(std::unique_ptr< T > content, float initialSize=0.f)
Add a pane with owned content.
Definition SplitPanel.h:186
SplitPanelManifest::State State
Definition SplitPanel.h:88
SplitPanelSettings::HandleStyle HandleStyle
Definition SplitPanel.h:90
void applySettings(const S &s)
Definition SplitPanel.h:143
SplitPanelManifest::Flag Flag
Definition SplitPanel.h:87
SplitPanel & operator=(const SplitPanel &)=delete
void setPaneMinSize(std::size_t index, float minSize)
Set the minimum size of a pane by index.
sf::FloatRect getGlobalBounds() const override
void setSize(const sf::Vector2f &size)
std::size_t paneCount() const
Return the number of panes.
Definition SplitPanel.h:219
void onThemeApplied(const Theme &theme) override
Called by ThemeManager when the active theme changes.
SplitPanel(Orientation orientation=Orientation::HORIZONTAL, const sf::Font &font=FontManager<>::getDefault())
Component< M, Traits... > ComponentWith
Alias for Component<M, Traits...>.
Definition Component.h:316
#define MALENA_API
Definition Component.h:22
Rect< float > FloatRect
Vector2< float > Vector2f
const sf::Font * font
Universal design token set applied across all Themeable components.
Definition Theme.h:70