diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2021-08-13 16:21:20 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2021-10-04 18:55:01 -0600 |
| commit | c80d3d99b9e11c4120cd3a36349d8161f01c7a24 (patch) | |
| tree | e1a5ed642b638f0a4e4d770b35a86f0c04bda5c4 /ui/tabwidget.h | |
| parent | 072021568045f1bceb39b3dc217235c5eebc37a9 (diff) | |
Custom tab widget for tear-away tabs
Diffstat (limited to 'ui/tabwidget.h')
| -rw-r--r-- | ui/tabwidget.h | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/ui/tabwidget.h b/ui/tabwidget.h new file mode 100644 index 00000000..a02f8cd9 --- /dev/null +++ b/ui/tabwidget.h @@ -0,0 +1,184 @@ +#pragma once + +#include <QtWidgets/QTabWidget> +#include <QtWidgets/QTabBar> +#include <QtWidgets/QStackedWidget> +#include <QtWidgets/QHBoxLayout> +#include <QtWidgets/QAbstractScrollArea> +#include <QtWidgets/QStylePainter> +#include <QtWidgets/QRubberBand> +#include <QtGui/QMouseEvent> +#include "uitypes.h" + + +class DockableTabWidget; + +class BINARYNINJAUIAPI DockableTabCollection +{ + std::set<DockableTabWidget*> m_containers; + +public: + void registerContainer(DockableTabWidget* widget); + void unregisterContainer(DockableTabWidget* widget); + + const std::set<DockableTabWidget*>& containers() const { return m_containers; } +}; + +class BINARYNINJAUIAPI TabDragIndicator: public QWidget +{ + Q_OBJECT + + QPixmap m_pixmap; + QImage m_newWindowImage; + QSize m_size, m_currentSize; + QPoint m_offset; + bool m_newWindow; + +public: + TabDragIndicator(QPixmap pixmap, QSize size, QPoint pt, QPoint offset, bool newWindow); + void moveToMouse(QPoint pt); + + QPixmap pixmap() const { return m_pixmap; } + QSize size() const { return m_size; } + QPoint offset() const { return m_offset; } + +protected: + virtual QSize sizeHint() const override; + virtual QSize minimumSizeHint() const override; + virtual void paintEvent(QPaintEvent* event) override; +}; + +class BINARYNINJAUIAPI DockableTabBar: public QAbstractScrollArea +{ + Q_OBJECT + + struct TabInfo + { + QString title; + QString toolTip; + QRect tabRect, closeButtonRect, closeIconRect; + }; + + DockableTabCollection* m_collection; + std::vector<TabInfo> m_tabs; + int m_active = -1; + + bool m_mouseInside = false; + int m_closeButtonHover = -1; + int m_closeButtonDown = -1; + + std::optional<QPoint> m_tabDragStart; + TabDragIndicator* m_tabDragIndicator = nullptr; + DockableTabBar* m_tabDragTarget = nullptr; + int m_tabDragWidth; + int m_tabDragTargetIndex = -1; + bool m_tabDragNewWindow = false; + QRubberBand* m_tabDropIndicator = nullptr; + + int m_placeholderIndex = -1; + int m_placeholderWidth; + QRect m_placeholderRect; + + QTimer* m_timer; + + QStyleOptionTab styleForTab(int idx, const TabInfo& info) const; + QSize sizeForTab(const QStyleOptionTab& tabStyle, const TabInfo& info) const; + int closeButtonSize() const; + void updateLayout(); + void paintTab(QStylePainter& p, const TabInfo& info, int i, const QRect& rect); + +public: + DockableTabBar(DockableTabCollection* collection); + virtual ~DockableTabBar(); + + int addTab(const QString& title); + int insertTab(int idx, const QString& title); + void removeTab(int idx); + void setCurrentIndex(int idx); + void setTabText(int idx, const QString& title); + void setTabToolTip(int idx, const QString& toolTip); + + int count() const; + int currentIndex() const; + int tabAt(const QPoint& pt); + QRect tabRect(int idx); + QString tabText(int idx); + QString tabToolTip(int idx); + + void ensureCurrentTabVisible(); + +Q_SIGNALS: + void currentChanged(int idx); + void tabCloseRequested(int idx); + void tabMoved(int oldIdx, int newIdx); + void newWindowForTab(int idx, QRect rectHint); + void reparentTab(int oldIdx, DockableTabWidget* target, int newIdx); + +private Q_SLOTS: + void underMouseTimerEvent(); + +protected: + virtual QSize sizeHint() const override; + virtual QSize minimumSizeHint() const override; + virtual void paintEvent(QPaintEvent* event) override; + virtual void enterEvent(QEnterEvent* event) override; + virtual void leaveEvent(QEvent* event) override; + virtual void mouseMoveEvent(QMouseEvent* event) override; + virtual void mousePressEvent(QMouseEvent* event) override; + virtual void mouseReleaseEvent(QMouseEvent* event) override; + virtual void resizeEvent(QResizeEvent* event) override; + virtual void wheelEvent(QWheelEvent* event) override; +}; + +class BINARYNINJAUIAPI DockableTabWidget: public QWidget +{ + Q_OBJECT + + DockableTabCollection* m_collection; + DockableTabBar* m_bar; + QHBoxLayout* m_barLayout; + QStackedWidget* m_widgets; + + void addReparentedTab(DockableTabWidget* source, int idx, QWidget* widget, + const QString& title, const QString& toolTip); + +public: + DockableTabWidget(DockableTabCollection* collection); + + int addTab(QWidget* widget, const QString& title); + int insertTab(int idx, QWidget* widget, const QString& title); + void removeTab(int idx); + + int count(); + int currentIndex(); + QWidget* currentWidget(); + QWidget* widget(int idx); + DockableTabBar* tabBar() const { return m_bar; } + QString tabText(int idx); + int indexOf(QWidget* widget); + + void setCurrentIndex(int idx); + void setTabText(int idx, const QString& title); + + void setCornerWidget(QWidget* widget, Qt::Corner corner = Qt::TopRightCorner); + + virtual QSize sizeHint() const override; + +protected: + virtual void paintEvent(QPaintEvent* event) override; + +Q_SIGNALS: + void tabCloseRequested(int idx); + void currentChanged(int idx); + void tabMoved(int oldIdx, int newIdx); + void newWindowForTab(int idx, QRect rectHint); + void tabRemovedForReparent(int oldIdx, QWidget* widget, DockableTabWidget* target, int newIdx); + void tabAddedForReparent(int idx, DockableTabWidget* source); + +private Q_SLOTS: + void tabBarCurrentChanged(int idx); + void tabBarCloseRequested(int idx); + void tabBarTabMoved(int oldIdx, int newIdx); + void tabBarNewWindowForTab(int idx, QRect rectHint); + void reparentTab(int oldIdx, DockableTabWidget* target, int newIdx); +}; |
