summaryrefslogtreecommitdiff
path: root/ui/splitter.h
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2024-01-12 10:11:19 -0700
committerRusty Wagner <rusty.wagner@gmail.com>2024-02-05 13:42:52 -0500
commit97ac519092fc87e27c49ab21aafb41b77f40dc03 (patch)
tree33d1a72b835a73c25868cb170106f865d9d54430 /ui/splitter.h
parentefa49ca6d23530b5e1ececccea4a2dc0bbe3406b (diff)
Sidebar improvements
Diffstat (limited to 'ui/splitter.h')
-rw-r--r--ui/splitter.h123
1 files changed, 123 insertions, 0 deletions
diff --git a/ui/splitter.h b/ui/splitter.h
new file mode 100644
index 00000000..089de444
--- /dev/null
+++ b/ui/splitter.h
@@ -0,0 +1,123 @@
+#pragma once
+
+#include <QtWidgets/QWidget>
+#include <QtCore/QSettings>
+#include <vector>
+#include <set>
+#include <map>
+#include "uicontext.h"
+
+/*!
+ \defgroup splitter Splitter
+ \ingroup uiapi
+*/
+
+/*!
+ \ingroup splitter
+*/
+enum SplitterWidgetSizingStyle
+{
+ RelativeWidgetSize,
+ WidgetSizeInPoints
+};
+
+/*!
+ \ingroup splitter
+*/
+struct BINARYNINJAUIAPI SplitterWidgetSizing
+{
+ SplitterWidgetSizingStyle style;
+ float referenceSize;
+ bool isDefault;
+ float requestedSize;
+ QString group;
+
+ static SplitterWidgetSizing relativeSize(float relativeSize = 1, const QString& group = QString());
+ static SplitterWidgetSizing pointSize(int size);
+
+ QVariantMap serialize() const;
+ static std::optional<SplitterWidgetSizing> deserialize(const QVariantMap& value);
+};
+
+/*!
+ \ingroup splitter
+*/
+struct BINARYNINJAUIAPI SplitterWidget
+{
+ QString key;
+ QWidget* widget;
+ bool visible;
+ SplitterWidgetSizing sizing;
+ int actualSize, minimumSize;
+};
+
+/*!
+ \ingroup splitter
+*/
+class BINARYNINJAUIAPI Splitter: public QWidget
+{
+ Q_OBJECT
+
+ struct SplitterDragInfo
+ {
+ size_t left, right;
+ int offset;
+ };
+
+ struct GroupInfo
+ {
+ QString group;
+ std::set<SplitterWidget*> widgets;
+ SplitterWidgetSizing sizing;
+ int actualSize, minimumSize;
+ };
+
+ Qt::Orientation m_orientation;
+ int m_handleSize;
+
+ std::vector<SplitterWidget> m_widgets;
+ std::map<QString, SplitterWidgetSizing> m_sizing;
+ std::map<QString, SplitterWidgetSizing> m_groupSizing;
+
+ std::optional<size_t> m_handleHover;
+ std::optional<SplitterDragInfo> m_handleDrag;
+
+ bool m_updatingLayout = false;
+
+public:
+ Splitter(Qt::Orientation orientation);
+
+ void addWidget(const QString& key, QWidget* widget, const SplitterWidgetSizing& defaultSize);
+ void insertWidget(const QString& key, size_t index, QWidget* widget, const SplitterWidgetSizing& defaultSize);
+ void addRelativeSizeGroup(const QString& group, float relativeSize);
+
+ QVariantMap saveState();
+ void saveState(QSettings& settings, const QString& stateName);
+ void restoreState(const QVariantMap& state);
+ void restoreState(const QSettings& settings, const QString& stateName);
+ void resetToDefault();
+
+protected:
+ virtual void paintEvent(QPaintEvent* event) override;
+ virtual void mousePressEvent(QMouseEvent* event) override;
+ virtual void mouseMoveEvent(QMouseEvent* event) override;
+ virtual void mouseReleaseEvent(QMouseEvent* event) override;
+ virtual void leaveEvent(QEvent* event) override;
+ virtual void resizeEvent(QResizeEvent* event) override;
+ virtual void childEvent(QChildEvent* event) override;
+ virtual bool event(QEvent* event) override;
+
+private:
+ void forAllSplitterHandles(const std::function<void(size_t leftIdx, size_t rightIdx, int pos)>& func);
+ void processLayout(const std::function<int(int availablePointSize)>& processPointSizeWidgets,
+ const std::function<void(int availableWidgetSize)>& processRelativeSizeWidgets);
+ void getWidgetsForSizingStyle(SplitterWidgetSizingStyle style,
+ std::set<SplitterWidget*>& widgets, std::vector<GroupInfo>& groups);
+ void regenerateLayoutForRelativeSizedWidgets(
+ std::set<SplitterWidget*> widgets, std::vector<GroupInfo> groups, int availableSize);
+ void regenerateLayout();
+ void calculateRequestedSizesForRelativeSizedWidgets(
+ const std::set<SplitterWidget*>& widgets, const std::vector<GroupInfo>& groups, int availableSize);
+ void calculateRequestedSizesForActualLayout();
+ void updateWidgetPositions();
+};