summaryrefslogtreecommitdiff
path: root/ui/tokenizedtextwidget.h
diff options
context:
space:
mode:
authorGlenn Smith <glenn@vector35.com>2023-11-06 15:28:59 -0500
committerGlenn Smith <glenn@vector35.com>2023-11-06 16:10:47 -0500
commit6436615567547349434351468012512505109552 (patch)
treee798973c25805377731c4a199f40379263bc128c /ui/tokenizedtextwidget.h
parent4108964609171327618627477163339656037111 (diff)
Type Browser
Diffstat (limited to 'ui/tokenizedtextwidget.h')
-rw-r--r--ui/tokenizedtextwidget.h254
1 files changed, 254 insertions, 0 deletions
diff --git a/ui/tokenizedtextwidget.h b/ui/tokenizedtextwidget.h
new file mode 100644
index 00000000..acbb2af5
--- /dev/null
+++ b/ui/tokenizedtextwidget.h
@@ -0,0 +1,254 @@
+#pragma once
+
+#include <QtWidgets/QAbstractScrollArea>
+#include <QtCore/QTimer>
+#include <optional>
+#include "binaryninjaapi.h"
+#include "viewframe.h"
+#include "render.h"
+#include "commentdialog.h"
+#include "menus.h"
+#include "uicontext.h"
+
+/*!
+
+ \defgroup tokenizedtextwidget TokenizedTextWidget
+ \ingroup uiapi
+*/
+
+
+/*!
+
+ \ingroup tokenizedtextwidget
+*/
+enum BINARYNINJAUIAPI TokenizedTextWidgetSelectionStyle
+{
+ NoSelection = 1 << 0,
+ SelectLines = 1 << 1,
+ SelectOneToken = 1 << 2,
+ SelectTokens = 1 << 3,
+ SelectCharacters = 1 << 4,
+
+ AllStyles = NoSelection | SelectLines | SelectOneToken | SelectTokens | SelectCharacters,
+};
+
+
+/*!
+
+ \ingroup tokenizedtextwidget
+*/
+struct BINARYNINJAUIAPI TokenizedTextWidgetCursorPosition
+{
+ /// Index of line in widget
+ size_t lineIndex = BN_INVALID_OPERAND;
+ /// Index of token in current line
+ size_t tokenIndex = BN_INVALID_OPERAND;
+ /// Index of character in current token
+ size_t characterIndex = BN_INVALID_OPERAND;
+
+ // Directly from QMouseEvent, not used in comparator
+ int cursorX;
+ int cursorY;
+
+ bool isValid() const { return lineIndex != BN_INVALID_OPERAND; }
+ bool operator==(const TokenizedTextWidgetCursorPosition& other) const;
+ bool operator!=(const TokenizedTextWidgetCursorPosition& other) const { return !(*this == other); }
+ bool operator<(const TokenizedTextWidgetCursorPosition& other) const;
+};
+
+/*!
+ QWidget that displays lines of InstructionTextTokens with the ability to make selections
+
+ \ingroup tokenizedtextwidget
+*/
+class BINARYNINJAUIAPI TokenizedTextWidget :
+ public QAbstractScrollArea
+{
+protected:
+ struct LineMetadata
+ {
+ size_t charWidth;
+ int copyStyles;
+
+ LineMetadata():
+ charWidth(0),
+ copyStyles(TokenizedTextWidgetSelectionStyle::AllStyles)
+ {}
+ };
+ struct TokenMetadata
+ {
+ size_t charOffset;
+ int copyStyles;
+ bool selectLineTarget;
+
+ TokenMetadata():
+ charOffset(0),
+ copyStyles(TokenizedTextWidgetSelectionStyle::AllStyles),
+ selectLineTarget(false)
+ {}
+ };
+
+private:
+ Q_OBJECT
+
+ UIActionHandler m_actionHandler;
+ ContextMenuManager* m_contextMenuManager;
+ Menu m_contextMenu;
+
+ RenderContext m_render;
+ int m_cols, m_rows;
+ int m_contentsCols, m_contentsRows;
+ int m_verticalWheelDelta, m_horizontalWheelDelta;
+ bool m_updatingScrollBar;
+ bool m_autoScrollHorizontal, m_autoScrollVertical;
+
+ TokenizedTextWidgetCursorPosition m_cursorPos, m_selectionStartPos, m_hoverPos;
+ TokenizedTextWidgetSelectionStyle m_selectionMode;
+ size_t m_hoverLine;
+ bool m_selectionStartedPastWidth;
+ bool m_selectionStartedPastHeight;
+ bool m_cursorKeys;
+ bool m_forceLineSelect;
+
+ std::vector<BinaryNinja::LinearDisassemblyLine> m_lines;
+ std::vector<LineMetadata> m_lineMetadata;
+ std::vector<std::vector<TokenMetadata>> m_tokenMetadata;
+ DisassemblySettingsRef m_settings;
+
+ void adjustSize(int width, int height);
+ void clampCursorPosition(TokenizedTextWidgetCursorPosition& pos);
+ void clampSelectionToValid();
+
+ protected:
+ virtual void updateMetadata(const std::vector<BinaryNinja::LinearDisassemblyLine>& lines, int& width, int& height);
+
+ private Q_SLOTS:
+ void verticalScrollBarMoved(int value);
+ void verticalScrollBarAction(int action);
+ void horizontalScrollBarMoved(int value);
+ void horizontalScrollBarAction(int action);
+
+ public:
+ explicit TokenizedTextWidget(QWidget* parent,
+ const std::vector<BinaryNinja::LinearDisassemblyLine>& lines =
+ std::vector<BinaryNinja::LinearDisassemblyLine>());
+ virtual ~TokenizedTextWidget();
+
+ void bindActions();
+
+ QFont font() const;
+ void setFont(const QFont& font);
+
+ DisassemblySettingsRef settings() { return m_settings; }
+ const DisassemblySettingsRef& settings() const { return m_settings; }
+
+ int topLineIndex() const;
+ int leftmostCharIndex() const;
+ int visibleColumnCount() const { return m_cols; }
+ int visibleRowCount() const { return m_rows; }
+ int contentsColumnCount() const { return m_contentsCols; }
+ int contentsRowCount() const { return m_contentsRows; }
+
+ bool hasSelection() const;
+ // Lines vs Tokens vs Characters vs NoSelection
+ TokenizedTextWidgetSelectionStyle selectionStyle() const;
+ // Lower bound of selection
+ TokenizedTextWidgetCursorPosition selectionBegin() const;
+ // Upper bound of selection
+ TokenizedTextWidgetCursorPosition selectionEnd() const;
+ // Originally highlighted selection base
+ TokenizedTextWidgetCursorPosition selectionBase() const;
+ // Position of cursor for movement operations
+ TokenizedTextWidgetCursorPosition cursorPosition() const;
+ bool forceLineSelect() const { return m_forceLineSelect; }
+ void setForceLineSelect(bool value) { m_forceLineSelect = value; }
+
+ void setSelection(TokenizedTextWidgetCursorPosition base, TokenizedTextWidgetCursorPosition cursor, TokenizedTextWidgetSelectionStyle mode);
+ void setCursorPosition(TokenizedTextWidgetCursorPosition newPosition, bool selecting, bool cursorKeys, bool evenIfNoChange);
+ void moveCursorHorizontal(int count, bool allTheWay, bool selecting, bool cursorKeys);
+ void moveCursorVertical(int count, bool allTheWay, bool selecting, bool cursorKeys);
+
+ bool autoScrollHorizontal() const { return m_autoScrollHorizontal; }
+ void setAutoScrollHorizontal(bool value) { m_autoScrollHorizontal = value; }
+ bool autoScrollVertical() const { return m_autoScrollVertical; }
+ void setAutoScrollVertical(bool value) { m_autoScrollVertical = value; }
+
+ HighlightTokenState highlightTokenState();
+ UIActionHandler* actionHandler() { return &m_actionHandler; }
+
+ virtual UIActionContext actionContext();
+ Menu& contextMenu() { return m_contextMenu; }
+ void showContextMenu();
+
+ void left(size_t count, bool selecting);
+ void right(size_t count, bool selecting);
+ void leftToWord(bool selecting);
+ void rightToWord(bool selecting);
+ void up(bool selecting);
+ void down(bool selecting);
+ void pageUp(bool selecting);
+ void pageDown(bool selecting);
+ void moveToStartOfLine(bool selecting);
+ void moveToEndOfLine(bool selecting);
+ void moveToStartOfView(bool selecting);
+ void moveToEndOfView(bool selecting);
+ void selectAll();
+ void selectNone();
+
+ void scrollLines(int count);
+ void scrollLineToVisible(int lineIndex);
+ void scrollLineToTop(int lineIndex);
+
+ void scrollChars(int count);
+ void scrollCharToVisible(int charIndex);
+ void scrollCharToLeftmost(int charIndex);
+
+ void copy() const;
+ std::string selectedText() const;
+
+ const std::vector<BinaryNinja::LinearDisassemblyLine>& lines() const { return m_lines; }
+ std::optional<std::reference_wrapper<const BinaryNinja::LinearDisassemblyLine>> lineAtPosition(const TokenizedTextWidgetCursorPosition& position) const;
+ std::optional<std::reference_wrapper<const BinaryNinja::InstructionTextToken>> tokenAtPosition(const TokenizedTextWidgetCursorPosition& position) const;
+ std::optional<char> charAtPosition(const TokenizedTextWidgetCursorPosition& position) const;
+
+ void clearLines();
+ void setLines(const std::vector<BinaryNinja::LinearDisassemblyLine>& lines, bool resetScroll = true);
+ void setLines(const std::vector<BinaryNinja::DisassemblyTextLine>& lines, bool resetScroll = true);
+ void setLines(const std::vector<BinaryNinja::TypeDefinitionLine>& lines, bool resetScroll = true);
+
+ int lineCopyStyles(size_t lineIndex) const;
+ void setLineCopyStyles(size_t lineIndex, int styles);
+
+ int tokenCopyStyles(size_t lineIndex, size_t tokenIndex) const;
+ void setTokenCopyStyles(size_t lineIndex, size_t tokenIndex, int styles);
+ bool tokenSelectLineTarget(size_t lineIndex, size_t tokenIndex) const;
+ void setTokenSelectLineTarget(size_t lineIndex, size_t tokenIndex, bool selectLineTarget);
+
+ Q_SIGNALS:
+ void sizeChanged(int cols, int rows);
+ void visibleChanged(int leftCol, int topRow);
+ void linesChanged();
+ void selectionChanged(const TokenizedTextWidgetCursorPosition& begin, const TokenizedTextWidgetCursorPosition& end);
+ void tokenLeftClicked(const TokenizedTextWidgetCursorPosition& position);
+ void tokenRightClicked(const TokenizedTextWidgetCursorPosition& position);
+ void tokenDoubleClicked(const TokenizedTextWidgetCursorPosition& position);
+ void tokenOtherClicked(const TokenizedTextWidgetCursorPosition& position, Qt::MouseButton button);
+ void tokenHovered(const TokenizedTextWidgetCursorPosition& position);
+ void lineLeftClicked(size_t lineIndex);
+ void lineRightClicked(size_t lineIndex);
+ void lineDoubleClicked(size_t lineIndex);
+ void lineOtherClicked(size_t lineIndex, Qt::MouseButton button);
+ void lineHovered(size_t lineIndex);
+
+ protected:
+ virtual void resizeEvent(QResizeEvent* event) override;
+ virtual void paintEvent(QPaintEvent* event) override;
+ virtual void wheelEvent(QWheelEvent* event) override;
+ virtual void mousePressEvent(QMouseEvent* event) override;
+ virtual void mouseMoveEvent(QMouseEvent* event) override;
+ virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
+ virtual void leaveEvent(QEvent* event) override;
+ virtual void focusInEvent(QFocusEvent* event) override;
+ virtual void focusOutEvent(QFocusEvent* event) override;
+ virtual void contextMenuEvent(QContextMenuEvent* event) override;
+};