summaryrefslogtreecommitdiff
path: root/ui/pane.h
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2021-11-18 13:52:25 -0500
committerRusty Wagner <rusty.wagner@gmail.com>2022-01-10 15:25:18 -0700
commit7f6e54fdc8ff4a06fdcd3c510a37add337f04bac (patch)
tree60cce5955fcc05fc84f35f9662d49c7e0790dde1 /ui/pane.h
parentd9661f34eec6855d495a10eaafc2a8e2679756a7 (diff)
Refactor main area to use pane system
Diffstat (limited to 'ui/pane.h')
-rw-r--r--ui/pane.h356
1 files changed, 356 insertions, 0 deletions
diff --git a/ui/pane.h b/ui/pane.h
new file mode 100644
index 00000000..dfda17a4
--- /dev/null
+++ b/ui/pane.h
@@ -0,0 +1,356 @@
+#pragma once
+
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QSplitter>
+#include <QtWidgets/QStackedWidget>
+#include <QtWidgets/QVBoxLayout>
+#include <QtWidgets/QRubberBand>
+#include "uicontext.h"
+#include "clickablelabel.h"
+
+class ViewFrame;
+class FeatureMap;
+class PaneHeader;
+class CloseButton;
+class TabDragIndicator;
+
+class BINARYNINJAUIAPI Pane: public QWidget
+{
+ Q_OBJECT
+
+ QWidget* m_widget;
+ QWidget* m_headerContainer = nullptr;
+ PaneHeader* m_header = nullptr;
+ CloseButton* m_closeButton = nullptr;
+ bool m_active = false;
+
+public:
+ Pane(QWidget* widget);
+
+ QWidget* widget() const { return m_widget; }
+ virtual bool canSplitPane() const { return false; }
+ virtual Pane* createSplitPane() { return nullptr; }
+ virtual void updateStatus();
+ virtual void focus();
+ virtual QString title() = 0;
+ void closePane();
+ void splitPane(Qt::Orientation orientation);
+
+ virtual void setIsSinglePane(bool isSinglePane);
+ virtual void setIsActivePane(bool active);
+ virtual Qt::Orientation defaultSplitDirection() const { return Qt::Horizontal; }
+ virtual void setDefaultSplitDirection(Qt::Orientation orientation);
+
+protected:
+ void init(PaneHeader* header);
+
+Q_SIGNALS:
+ void paneCloseRequested();
+ void paneSplitRequested(Pane* newPane, Qt::Edge edge);
+ void movePane(Pane* target, Qt::Edge edge);
+ void newWindowForPane(QScreen* screen, QPoint pos);
+ void notifyViewChanged(ViewFrame* frame);
+
+public Q_SLOTS:
+ void splitButtonClicked(Qt::Orientation orientation);
+ void closeButtonClicked();
+ void headerClicked();
+ void movePaneRequested(Pane* target, Qt::Edge edge);
+ void newWindowForPaneRequested(QScreen* screen, QPoint pos);
+};
+
+class BINARYNINJAUIAPI SplitButton: public ClickableIcon
+{
+ Q_OBJECT
+
+ Qt::Orientation m_defaultOrientation;
+ bool m_mouseInside = false;
+ bool m_inverted = false;
+
+ void setIconForOrientation(Qt::Orientation orientation);
+
+public:
+ SplitButton();
+
+ void setDefaultOrientation(Qt::Orientation orientation);
+ Qt::Orientation orientation() const;
+ Qt::Orientation defaultOrientation() const { return m_defaultOrientation; }
+
+protected:
+ virtual void enterEvent(QEnterEvent* event) override;
+ virtual void leaveEvent(QEvent* event) override;
+ virtual bool eventFilter(QObject* obj, QEvent* event) override;
+};
+
+class BINARYNINJAUIAPI PaneHeader: public QWidget
+{
+ Q_OBJECT
+
+ Pane* m_owner = nullptr;
+ std::optional<QPoint> m_dragStart;
+ TabDragIndicator* m_dragIndicator = nullptr;
+ bool m_dragNewWindow = false;
+ Pane* m_dropTarget = nullptr;
+ Qt::Edge m_dropEdge = Qt::RightEdge;
+ QRubberBand* m_dropIndicator = nullptr;
+
+public:
+ PaneHeader();
+
+ void setOwner(Pane* pane) { m_owner = pane; }
+
+protected:
+ virtual void mousePressEvent(QMouseEvent* event) override;
+ virtual void mouseMoveEvent(QMouseEvent* event) override;
+ virtual void mouseReleaseEvent(QMouseEvent* event) override;
+
+Q_SIGNALS:
+ void paneCloseRequested();
+ void paneSplitRequested(Qt::Orientation orientation);
+ void movePane(Pane* target, Qt::Edge edge);
+ void newWindowForPane(QScreen* screen, QPoint pos);
+ void headerClicked();
+};
+
+class ViewFrame;
+class ViewPaneHeader;
+
+class BINARYNINJAUIAPI ViewPane: public Pane
+{
+ Q_OBJECT
+
+ ViewFrame* m_frame;
+ UIActionHandler m_actionHandler;
+ ViewPaneHeader* m_header;
+
+public:
+ ViewPane(ViewFrame* frame);
+
+ ViewFrame* viewFrame() const { return m_frame; }
+ virtual bool canSplitPane() const override { return true; }
+ virtual Pane* createSplitPane() override;
+ virtual void updateStatus() override;
+ virtual Qt::Orientation defaultSplitDirection() const override;
+ virtual void setDefaultSplitDirection(Qt::Orientation orientation) override;
+ virtual void focus() override;
+ virtual QString title() override;
+
+private Q_SLOTS:
+ void viewChanged(ViewFrame* frame);
+ void viewChangeRequested(QString type);
+};
+
+class DataTypeList;
+class ViewList;
+class SyncGroupWidget;
+
+class BINARYNINJAUIAPI ViewPaneHeaderSubtypeWidget: public QWidget
+{
+ Q_OBJECT
+
+public:
+ ViewPaneHeaderSubtypeWidget() {}
+ virtual void updateStatus() = 0;
+};
+
+class BINARYNINJAUIAPI ViewPaneHeader: public PaneHeader
+{
+ Q_OBJECT
+
+ ViewPane* m_owner;
+ DataTypeList* m_dataTypeList;
+ ViewList* m_viewList;
+ SyncGroupWidget* m_syncGroup;
+
+ View* m_subtypeView = nullptr;
+ ViewPaneHeaderSubtypeWidget* m_subtypeWidget = nullptr;
+ QWidget* m_optionsWidget = nullptr;
+ QStackedWidget* m_subtypeWidgetContainer;
+ QStackedWidget* m_optionsWidgetContainer;
+
+ SplitButton* m_splitButton;
+
+public:
+ ViewPaneHeader(ViewPane* owner, UIActionHandler* handler);
+
+ void updateStatus();
+ Qt::Orientation defaultSplitDirection() const;
+ void setDefaultSplitDirection(Qt::Orientation orientation);
+
+Q_SIGNALS:
+ void viewChanged(QString type);
+
+private Q_SLOTS:
+ void splitButtonClicked();
+ void viewChangeRequested(QString type);
+ void updateViewType(ViewFrame* frame);
+};
+
+class BINARYNINJAUIAPI WidgetPane: public Pane
+{
+ Q_OBJECT
+
+ QString m_title;
+
+public:
+ WidgetPane(QWidget* widget, QString title);
+ virtual QString title() override { return m_title; }
+ virtual void updateStatus() override;
+
+Q_SIGNALS:
+ void updateWidgetStatus();
+};
+
+class BINARYNINJAUIAPI WidgetPaneHeader: public PaneHeader
+{
+ Q_OBJECT
+
+ QString m_title;
+
+public:
+ WidgetPaneHeader(const QString& title);
+
+protected:
+ virtual void paintEvent(QPaintEvent* event) override;
+};
+
+class SplitPaneWidget;
+
+class BINARYNINJAUIAPI SplitPaneContainer: public QWidget
+{
+ Q_OBJECT
+
+ Pane* m_pane = nullptr;
+ QSplitter* m_splitter = nullptr;
+ SplitPaneContainer* m_parent = nullptr;
+ std::vector<SplitPaneContainer*> m_children;
+ Pane* m_currentChild = nullptr;
+ ViewPane* m_currentViewPane = nullptr;
+ QVBoxLayout* m_layout;
+ FileContext* m_fileContext = nullptr;
+
+ SplitPaneContainer(const std::vector<SplitPaneContainer*>& children, Qt::Orientation orientation);
+
+ void removeChild(SplitPaneContainer* child);
+ void promoteChild(SplitPaneContainer* child);
+ void updateDefaultSplitDirectionForColumnCount(uint64_t count);
+ void removePaneForRelocation();
+ void emitNewWindowForPane(SplitPaneWidget* paneWidget, QRect rect);
+ void openForColumnCount(Pane* pane, Qt::Orientation primaryDirection, uint64_t count);
+ void deactivateIfCurrent(Pane* pane);
+ void notifyCurrentChanged(Pane* pane);
+
+public:
+ SplitPaneContainer(Pane* initial);
+ Pane* currentPane() const { return m_currentChild; }
+ ViewPane* currentViewPane() const { return m_currentViewPane; }
+ void notifyFocused();
+ void updateStatus();
+
+ void enumeratePanes(const std::function<void(Pane*)>& func);
+ void enumerateViewPanes(const std::function<void(ViewPane*)>& func);
+
+ bool isSinglePane();
+ bool canSplitCurrentPane();
+ void closeCurrentPane();
+ void splitCurrentPane(Qt::Orientation orientation);
+ Qt::Orientation defaultSplitDirection() const;
+ void nextPane();
+ void prevPane();
+ void focusPaneForEdge(Qt::Edge edge);
+
+ SplitPaneContainer* root();
+ static SplitPaneContainer* containerForWidget(QWidget* widget);
+
+ FileContext* fileContext() const { return m_fileContext; }
+ void setFileContext(FileContext* fileContext) { m_fileContext = fileContext; }
+
+ void open(Pane* pane, Qt::Orientation primaryDirection = Qt::Vertical);
+
+Q_SIGNALS:
+ void paneClosed(Pane* pane);
+ void currentChanged(Pane* pane);
+ void layoutChanged();
+ void notifyViewChanged(ViewFrame* frame);
+ void lastPaneClosed();
+ void newWindowForPane(SplitPaneWidget* paneWidget, QRect rect);
+
+private Q_SLOTS:
+ void paneCloseRequested();
+ void paneSplitRequested(Pane* newPane, Qt::Edge edge);
+ void movePane(Pane* target, Qt::Edge edge);
+ void newWindowForPaneRequested(QScreen* screen, QPoint pos);
+ void paneViewChanged(ViewFrame* frame);
+ void childPaneClosed(Pane* pane);
+ void childLayoutChanged();
+ void childViewChanged(ViewFrame* frame);
+};
+
+class BINARYNINJAUIAPI SplitPaneWidget: public QWidget
+{
+ Q_OBJECT
+
+ SplitPaneContainer* m_container;
+
+ QStackedWidget* m_featureMapContainer;
+ std::map<BinaryViewRef, FeatureMap*> m_featureMaps;
+ QSplitter* m_featureMapSplitter;
+ bool m_rightSideFeatureMap = true;
+
+ UIActionHandler m_actionHandler;
+
+ void bindActions();
+
+public:
+ SplitPaneWidget(Pane* initial, FileContext* fileContext);
+ Pane* currentPane() const;
+ ViewPane* currentViewPane() const;
+ ViewFrame* currentViewFrame() const;
+ SplitPaneContainer* container() const { return m_container; }
+ FileContext* fileContext() const { return m_container->fileContext(); }
+
+ void enumeratePanes(const std::function<void(Pane*)>& func);
+ void enumerateViewPanes(const std::function<void(ViewPane*)>& func);
+
+ void createFeatureMap();
+ void recreateFeatureMaps();
+ void refreshFeatureMap();
+ void updateFeatureMapLocation(const ViewLocation& location);
+ BinaryViewRef getCurrentBinaryView();
+
+ void updateStatus();
+
+ bool isSinglePane();
+ bool canSplitCurrentPane();
+ void closeCurrentPane();
+ void splitCurrentPane(Qt::Orientation orientation);
+ Qt::Orientation defaultSplitDirection() const;
+ void nextPane();
+ void prevPane();
+ void focusPaneForEdge(Qt::Edge edge);
+
+ QString getTabName();
+
+ void open(Pane* pane, Qt::Orientation primaryDirection = Qt::Vertical);
+
+ bool closeRequest();
+ void closing();
+
+ static void registerActions();
+
+Q_SIGNALS:
+ void paneClosed(Pane* pane);
+ void currentChanged(Pane* pane);
+ void layoutChanged();
+ void notifyViewChanged(ViewFrame* frame);
+ void newWindowForPane(SplitPaneWidget* paneWidget, QRect rect);
+
+private Q_SLOTS:
+ void containerPaneClosed(Pane* pane);
+ void containerCurrentChanged(Pane* pane);
+ void containerLayoutChanged();
+ void containerNotifyViewChanged(ViewFrame* frame);
+ void containerLastPaneClosed();
+ void containerNewWindowForPane(SplitPaneWidget* paneWidget, QRect rect);
+ void featureMapSplitterMoved(int pos, int idx);
+};