diff --git a/src/plugins/lua/bindings/texteditor.cpp b/src/plugins/lua/bindings/texteditor.cpp index 6c3f9e95d9b..0066b96fc54 100644 --- a/src/plugins/lua/bindings/texteditor.cpp +++ b/src/plugins/lua/bindings/texteditor.cpp @@ -5,6 +5,7 @@ #include "../luatr.h" #include +#include #include #include #include @@ -45,22 +46,65 @@ TextEditor::TextEditorWidget *getSuggestionReadyEditorWidget(TextEditor::TextDoc return widget; } -void addFloatingWidget(BaseTextEditor *editor, QWidget *widget, int position) +void fillRemainingViewportWidth(QWidget *widget, const QSize &viewportSize, const QMargins &margins) { - widget->setParent(editor->editorWidget()->viewport()); - const auto editorWidget = editor->editorWidget(); - - QTextCursor cursor = QTextCursor(editor->textDocument()->document()); - cursor.setPosition(position); - const QRect cursorRect = editorWidget->cursorRect(cursor); - - QPoint widgetPos = cursorRect.bottomLeft(); - widgetPos.ry() += (cursorRect.top() - cursorRect.bottom()) / 2; - - widget->move(widgetPos); - widget->show(); + int maxWidth = viewportSize.width() - margins.right() - widget->x(); + widget->setFixedWidth(maxWidth); } +QPoint getPositionOnViewport(const BaseTextEditor * const editor, const QWidget * const widget, + int basePostion, const QSize &viewportSize, const QMargins &margins) +{ + QTextCursor cursor = QTextCursor(editor->textDocument()->document()); + cursor.setPosition(basePostion); + + const QRect cursorRect = editor->editorWidget()->cursorRect(cursor); + QPoint widgetPosDefault = cursorRect.bottomLeft(); + + widgetPosDefault.ry() += (cursorRect.top() - cursorRect.bottom()) / 2; + + int fontSize = editor->textDocument()->fontSettings().fontSize(); + int maxX = viewportSize.width() - margins.right() - widget->width(); + int maxY = viewportSize.height() - widget->height() - fontSize; + + if (maxX < 0) { + qWarning() << QStringLiteral("Floating Widget positioning: x (%1) < 0. Widget will not " + "fit in the viewport. Viewport.width (%2), widget.width (%3), " + "widget margin.right (%4). Setting x to 0.") + .arg(maxX).arg(viewportSize.width()).arg(widget->width()).arg(margins.right()); + maxX = 0; + } + + if (maxY < 0) { + qWarning() << QStringLiteral("Floating Widget positioning: y (%1) < 0. Widget is too big" + "for the viewport. Viewport.height (%2), widget.height (%3)." + "Setting y to 0.") + .arg(maxY).arg(viewportSize.height()).arg(widget->height()); + maxY = 0; + } + + int x = widgetPosDefault.x() > maxX ? maxX : widgetPosDefault.x(); + int y = widgetPosDefault.y() + fontSize; + y = y > maxY ? maxY : y; + + return {x, y}; +} + +void addFloatingWidget(BaseTextEditor *editor, QWidget *widget, int pos, const QRect &margins, + bool fillWidth = false) +{ + QMargins widgetMargins{margins.left(), margins.top(), margins.width(), margins.height()}; + + widget->setParent(editor->editorWidget()->viewport()); + TextEditorWidget *editorWidget = editor->editorWidget(); + const QSize viewportSize = editorWidget->viewport()->size(); + + widget->move(getPositionOnViewport(editor, widget, pos, viewportSize, widgetMargins)); + if (fillWidth) + fillRemainingViewportWidth(widget, viewportSize, widgetMargins); + + widget->show(); +} } // namespace namespace Lua::Internal { @@ -234,17 +278,20 @@ void setupTextEditorModule() }, "addFloatingWidget", sol::overload( - [](const TextEditorPtr &textEditor, QWidget *widget, int position) { + [](const TextEditorPtr &textEditor, QWidget *widget, int position, + const QRect &margins, bool fillWidth) { QTC_ASSERT(textEditor, throw sol::error("TextEditor is not valid")); - addFloatingWidget(textEditor, widget, position); + addFloatingWidget(textEditor, widget, position, margins, fillWidth); }, - [](const TextEditorPtr &textEditor, Layouting::Widget *widget, int position) { + [](const TextEditorPtr &textEditor, Layouting::Widget *widget, int position, + const QRect &margins, bool fillWidth) { QTC_ASSERT(textEditor, throw sol::error("TextEditor is not valid")); - addFloatingWidget(textEditor, widget->emerge(), position); + addFloatingWidget(textEditor, widget->emerge(), position, margins, fillWidth); }, - [](const TextEditorPtr &textEditor, Layouting::Layout *layout, int position) { + [](const TextEditorPtr &textEditor, Layouting::Layout *layout, int position, + const QRect &margins, bool fillWidth = false) { QTC_ASSERT(textEditor, throw sol::error("TextEditor is not valid")); - addFloatingWidget(textEditor, layout->emerge(), position); + addFloatingWidget(textEditor, layout->emerge(), position, margins, fillWidth); }), "cursor", [](const TextEditorPtr &textEditor) { diff --git a/src/plugins/lua/bindings/utils.h b/src/plugins/lua/bindings/utils.h index a6b65c762d0..b42c5f85e72 100644 --- a/src/plugins/lua/bindings/utils.h +++ b/src/plugins/lua/bindings/utils.h @@ -49,5 +49,4 @@ inline void mirrorEnum(sol::table &target, QMetaEnum metaEnum, const QString &na for (int i = 0; i < metaEnum.keyCount(); ++i) widgetAttributes.set(metaEnum.key(i), metaEnum.value(i)); }; - } // namespace Lua::Internal diff --git a/src/plugins/lua/meta/texteditor.lua b/src/plugins/lua/meta/texteditor.lua index d4575c14cae..a11138f7ad2 100644 --- a/src/plugins/lua/meta/texteditor.lua +++ b/src/plugins/lua/meta/texteditor.lua @@ -100,7 +100,9 @@ function TextEditor:cursor() end ---text document and will be automatically managed to stay pined to that position. ---@param widget Widget|Layout The widget to be added as a floating widget. ---@param position integer The position in the document where the widget should appear. -function TextEditor:addFloatingWidget(widget, position) end +---@param margins integer[] Four integers, representing left, top, right, bottom margins +---@param fillWidth boolean If true, the widget will fill remaining space from its x position to size of the TextEditor viewport +function TextEditor:addFloatingWidget(widget, position, margins, fillWidth) end ---Checks if the current suggestion is locked. The suggestion is locked when the user can use it. ---@return boolean True if the suggestion is locked, false otherwise.