123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <AzCore/std/string/conversions.h>
- #include "LUAEditorBreakpointWidget.hxx"
- #include "LUAEditorPlainTextEdit.hxx"
- #include "LUAEditorStyleMessages.h"
- #include <Source/LUA/moc_LUAEditorBreakpointWidget.cpp>
- #include <QTextBlockFormat>
- #include <QTextBlock>
- #include <QTextBlockUserData>
- #include <QPainter>
- namespace LUAEditor
- {
- namespace
- {
- //this used to detect deleted lines, doesnt work for last line though, but that can be detected elsewhere.
- class OriginalLineNumber
- : public QTextBlockUserData
- {
- public:
- AZ_CLASS_ALLOCATOR(OriginalLineNumber, AZ::SystemAllocator);
- OriginalLineNumber(int lineNumber, AZStd::function<void(int)> callback)
- : m_Callback(callback)
- , m_LineNumber(lineNumber) {}
- virtual ~OriginalLineNumber()
- {
- if (m_Callback)
- {
- m_Callback(m_LineNumber);
- }
- }
- int GetLineNumber() const { return m_LineNumber; }
- void CancelLineDelete() { m_Callback.clear(); }
- private:
- AZStd::function<void(int)> m_Callback;
- int m_LineNumber;
- };
- }
- LUAEditorBreakpointWidget::LUAEditorBreakpointWidget(QWidget* pParent)
- : QWidget(pParent)
- , m_textEdit(nullptr)
- , m_currentExecLine(-1)
- {
- setEnabled(false);
- }
- LUAEditorBreakpointWidget::~LUAEditorBreakpointWidget()
- {
- }
- void LUAEditorBreakpointWidget::PreDestruction()
- {
- ClearBreakpoints();
- m_textEdit = nullptr;
- }
- void LUAEditorBreakpointWidget::paintEvent([[maybe_unused]] QPaintEvent* paintEvent)
- {
- QPainter p(this);
- auto colors = AZ::UserSettings::CreateFind<SyntaxStyleSettings>(AZ_CRC_CE("LUA Editor Text Settings"), AZ::UserSettings::CT_GLOBAL);
- auto oldPen = p.pen();
- auto oldBrush = p.brush();
- p.setFont(m_font);
- if (isEnabled())
- {
- p.fillRect(geometry(), colors->GetBreakpointFocusedBackgroundColor());
- }
- else
- {
- p.fillRect(geometry(), colors->GetBreakpointUnfocusedBackgroundColor());
- }
- QFontMetrics metrics(m_font);
- int avgCharWidth = metrics.averageCharWidth();
- m_textEdit->ForEachVisibleBlock([&](const QTextBlock& block, const QRectF& blockRect)
- {
- int lineNum = block.blockNumber() + 1; // offset by one because line number starts from 1
- AZStd::string lineNumStr;
- AZStd::to_string(lineNumStr, lineNum);
- QRectF drawRect = blockRect;
- drawRect.setLeft(c_borderSize);
- drawRect.setRight(c_borderSize + m_numDigits * avgCharWidth);
- p.setPen(colors->GetLineNumberColor());
- p.drawText(drawRect.toRect(), Qt::AlignRight | Qt::AlignBottom, lineNumStr.c_str());
- {
- auto centerY = (drawRect.top() + metrics.leading() + drawRect.bottom()) / 2;
- auto centerX = (2 * drawRect.right() + avgCharWidth + c_borderSize) / 2;
- drawRect.setTop(centerY - (avgCharWidth / 2));
- drawRect.setBottom(centerY + (avgCharWidth / 2));
- drawRect.setLeft(centerX - (avgCharWidth / 2));
- drawRect.setRight(centerX + (avgCharWidth / 2));
- }
- //breakpoint red dot
- if (m_breakpoints.find(lineNum) != m_breakpoints.end())
- {
- p.setPen(QColor::fromRgb(255, 0, 0));
- p.setBrush(QBrush(QColor::fromRgb(255, 0, 0)));
- p.drawEllipse(drawRect);
- }
- //yellow triangle for currently executing line
- if (m_currentExecLine == lineNum)
- {
- const QPointF marker[] = {
- {drawRect.right(), drawRect.center().y()},
- {drawRect.center().x(), drawRect.top() + 1},
- {drawRect.center().x(), drawRect.bottom() - 1}
- };
- p.setPen(QColor::fromRgb(255, 255, 0));
- p.setBrush(QBrush(QColor::fromRgb(255, 255, 0)));
- p.drawPolygon(marker, sizeof(marker) / sizeof(QPointF));
- }
- });
- p.setPen(oldPen);
- p.setBrush(oldBrush);
- }
- void LUAEditorBreakpointWidget::AddBreakpoint(int lineNumber)
- {
- auto block = m_textEdit->document()->findBlockByNumber(lineNumber);
- if (block.isValid())
- {
- if (block.userData() != nullptr)
- {
- ((OriginalLineNumber*)block.userData())->CancelLineDelete();
- }
- block.setUserData(aznew OriginalLineNumber(lineNumber, [&](int lineNumber){ m_DeletedBreakpoints.push_back(lineNumber); }));
- m_breakpoints.insert(lineNumber);
- update();
- }
- }
- void LUAEditorBreakpointWidget::RemoveBreakpoint(int lineNumber)
- {
- auto numRemoved = m_breakpoints.erase(lineNumber);
- if (numRemoved != 0)
- {
- auto block = m_textEdit->document()->findBlockByNumber(lineNumber);
- if (block.isValid())
- {
- if (block.userData() != nullptr)
- {
- ((OriginalLineNumber*)block.userData())->CancelLineDelete();
- }
- block.setUserData(nullptr);
- }
- }
- update();
- }
- bool LUAEditorBreakpointWidget::HasBreakpoint(int lineNumber) const
- {
- return m_breakpoints.find(lineNumber) != m_breakpoints.end();
- }
- void LUAEditorBreakpointWidget::ClearBreakpoints()
- {
- for (auto& breakpoint : m_breakpoints)
- {
- auto block = m_textEdit->document()->findBlockByNumber(breakpoint);
- if (block.isValid())
- {
- if (block.userData() != nullptr)
- {
- ((OriginalLineNumber*)block.userData())->CancelLineDelete();
- }
- block.setUserData(nullptr);
- }
- }
- m_breakpoints.clear();
- update();
- }
- void LUAEditorBreakpointWidget::mouseReleaseEvent(QMouseEvent* event)
- {
- auto mousePos = event->localPos();
- m_textEdit->ForEachVisibleBlock(
- [&](const QTextBlock& block, const QRectF& blockRect)
- {
- if (mousePos.y() >= blockRect.top() && mousePos.y() <= blockRect.bottom())
- {
- emit toggleBreakpoint(block.blockNumber() + 1); // offset by one because line number starts from 1
- }
- });
- event->accept();
- }
- void LUAEditorBreakpointWidget::OnBlockCountChange()
- {
- if (!m_textEdit)
- {
- return;
- }
- AZStd::vector<AZStd::pair<int, int> > movedBreakpoints;
- for (auto block = m_textEdit->document()->begin(); block != m_textEdit->document()->end(); block = block.next())
- {
- if (block.userData() != nullptr)
- {
- if (block.blockNumber() != ((OriginalLineNumber*)block.userData())->GetLineNumber())
- {
- movedBreakpoints.push_back({ ((OriginalLineNumber*)block.userData())->GetLineNumber(), block.blockNumber() });
- }
- }
- if (block.userData() != nullptr)
- {
- ((OriginalLineNumber*)block.userData())->CancelLineDelete();
- }
- block.setUserData(nullptr);
- }
- for (auto& breakpoint : m_breakpoints)
- {
- auto block = m_textEdit->document()->findBlockByNumber(breakpoint);
- if (block.isValid())
- {
- block.setUserData(aznew OriginalLineNumber(block.blockNumber(), [&](int lineNumber){ m_DeletedBreakpoints.push_back(lineNumber); }));
- }
- }
- for (auto& moves : movedBreakpoints)
- {
- emit breakpointLineMove(moves.first, moves.second);
- }
- for (auto& deletes : m_DeletedBreakpoints)
- {
- emit breakpointDelete(deletes);
- }
- m_DeletedBreakpoints.clear();
- UpdateSize();
- update();
- }
- void LUAEditorBreakpointWidget::OnCharsRemoved(int position, int charsRemoved)
- {
- if (!m_textEdit)
- {
- return;
- }
- if (charsRemoved <= 0)
- {
- return;
- }
- auto block = m_textEdit->document()->findBlock(position);
- if (block.userData() && block.blockNumber() != ((OriginalLineNumber*)block.userData())->GetLineNumber())
- {
- m_DeletedBreakpoints.push_back(((OriginalLineNumber*)block.userData())->GetLineNumber());
- ((OriginalLineNumber*)block.userData())->CancelLineDelete();
- block.setUserData(nullptr);
- }
- }
- void LUAEditorBreakpointWidget::SetFont(QFont font)
- {
- m_font = font;
- UpdateSize();
- }
- void LUAEditorBreakpointWidget::UpdateSize()
- {
- QFontMetrics metrics(m_font);
- auto blockCount = m_textEdit->document()->blockCount();
- m_numDigits = 0;
- while (blockCount > 0)
- {
- ++m_numDigits;
- blockCount /= 10;
- }
- setFixedWidth(metrics.averageCharWidth() * (m_numDigits + 1) + 2 * c_borderSize); //+1 for the breakpoint
- }
- }
|