diff --git a/src/dialogs/katedialogs.cpp b/src/dialogs/katedialogs.cpp --- a/src/dialogs/katedialogs.cpp +++ b/src/dialogs/katedialogs.cpp @@ -705,6 +705,8 @@ observeChanges(textareaUi->chkAnimateBracketMatching); observeChanges(textareaUi->chkDynWrapAnywhere); observeChanges(textareaUi->chkDynWrapAtStaticMarker); + observeChanges(textareaUi->chkDynWrapFillLeft); + observeChanges(textareaUi->spiDynWrapFillRight); observeChanges(textareaUi->chkFoldFirstLine); observeChanges(textareaUi->chkShowIndentationLines); observeChanges(textareaUi->chkShowLineCount); @@ -765,6 +767,8 @@ KateViewConfig::global()->setValue(KateViewConfig::DynWordWrapIndicators, textareaUi->cmbDynamicWordWrapIndicator->currentIndex()); KateViewConfig::global()->setValue(KateViewConfig::DynWrapAnywhere, textareaUi->chkDynWrapAnywhere->isChecked()); KateViewConfig::global()->setValue(KateViewConfig::DynWrapAtStaticMarker, textareaUi->chkDynWrapAtStaticMarker->isChecked()); + KateViewConfig::global()->setValue(KateViewConfig::DynWrapFillLeft,textareaUi->chkDynWrapFillLeft->isChecked()); + KateViewConfig::global()->setValue(KateViewConfig::DynWrapFillRight,textareaUi->spiDynWrapFillRight->value()); KateViewConfig::global()->setValue(KateViewConfig::FoldFirstLine, textareaUi->chkFoldFirstLine->isChecked()); KateViewConfig::global()->setValue(KateViewConfig::ScrollBarMiniMapWidth, bordersUi->spBoxMiniMapWidth->value()); KateViewConfig::global()->setValue(KateViewConfig::ShowFoldingBar, bordersUi->chkShowFoldingMarkers->isChecked()); @@ -802,6 +806,8 @@ textareaUi->chkAnimateBracketMatching->setChecked(KateRendererConfig::global()->animateBracketMatching()); textareaUi->chkDynWrapAnywhere->setChecked(KateViewConfig::global()->dynWrapAnywhere()); textareaUi->chkDynWrapAtStaticMarker->setChecked(KateViewConfig::global()->dynWrapAtStaticMarker()); + textareaUi->chkDynWrapFillLeft->setChecked(KateViewConfig::global()->dynWrapFillLeft()); + textareaUi->spiDynWrapFillRight->setValue(KateViewConfig::global()->dynWrapFillRight()); textareaUi->chkFoldFirstLine->setChecked(KateViewConfig::global()->foldFirstLine()); textareaUi->chkShowIndentationLines->setChecked(KateRendererConfig::global()->showIndentationLines()); textareaUi->chkShowLineCount->setChecked(KateViewConfig::global()->showLineCount()); diff --git a/src/dialogs/textareaappearanceconfigwidget.ui b/src/dialogs/textareaappearanceconfigwidget.ui --- a/src/dialogs/textareaappearanceconfigwidget.ui +++ b/src/dialogs/textareaappearanceconfigwidget.ui @@ -6,8 +6,8 @@ 0 0 - 810 - 752 + 559 + 723 @@ -46,6 +46,16 @@ + + + + D&ynamic word wrap indicators (if applicable): + + + cmbDynamicWordWrapIndicator + + + @@ -59,16 +69,6 @@ - - - - D&ynamic word wrap indicators (if applicable): - - - cmbDynamicWordWrapIndicator - - - @@ -309,6 +309,80 @@ + + + + Dynamic wrap fill left + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Dynamic wrap fill right + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + characters + + + 12 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + diff --git a/src/render/katelinelayout.h b/src/render/katelinelayout.h --- a/src/render/katelinelayout.h +++ b/src/render/katelinelayout.h @@ -94,6 +94,11 @@ int shiftX() const; void setShiftX(int shiftX); + // this contains only the right part of shiftX which comes after the real indentation width + // the real indentation width is thus shiftX()-shiftXRightOnly() + int shiftXRightOnly() const; + void setShiftXRightOnly(int shiftXRightOnly); + QTextLayout *layout() const; void setLayout(QTextLayout *layout); void invalidateLayout(); @@ -115,6 +120,7 @@ int m_line; int m_virtualLine; int m_shiftX; + int m_shiftXRightOnly; QTextLayout *m_layout; QList m_dirtyList; diff --git a/src/render/katelinelayout.cpp b/src/render/katelinelayout.cpp --- a/src/render/katelinelayout.cpp +++ b/src/render/katelinelayout.cpp @@ -36,6 +36,7 @@ , m_line(-1) , m_virtualLine(-1) , m_shiftX(0) + , m_shiftXRightOnly(0) , m_layout(nullptr) , m_layoutDirty(true) , m_usePlainTextLine(false) @@ -116,6 +117,17 @@ m_shiftX = shiftX; } +int KateLineLayout::shiftXRightOnly() const +{ + return m_shiftXRightOnly; +} + +void KateLineLayout::setShiftXRightOnly(int shiftXRightOnly) +{ + m_shiftXRightOnly = shiftXRightOnly; +} + + KTextEditor::DocumentPrivate *KateLineLayout::doc() const { return m_renderer.doc(); diff --git a/src/render/katerenderer.cpp b/src/render/katerenderer.cpp --- a/src/render/katerenderer.cpp +++ b/src/render/katerenderer.cpp @@ -338,8 +338,8 @@ paint.setPen(myPen); const int height = fontHeight(); - const int top = 0; - const int bottom = height - 1; + const int top = y; + const int bottom = top + height - 1; QPainter::RenderHints renderHints = paint.renderHints(); paint.setRenderHints(renderHints, false); @@ -682,12 +682,15 @@ } // Draw indent lines - if (showIndentLines() && i == 0) { + // do this even for i>=0 where we risk of being overpainted by left indent fill + // (or should this be checked here already?) + // check shiftX() as it might be zero where there too little horizontal space for indent fill + if (showIndentLines() && range->shiftX()>0) { const qreal w = spaceWidth(); const int lastIndentColumn = range->textLine()->indentDepth(m_tabWidth); for (int x = m_indentWidth; x < lastIndentColumn; x += m_indentWidth) { - paintIndentMarker(paint, x * w + 1 - xStart, range->line()); + paintIndentMarker(paint, x * w + 1 - xStart, lineHeight() * i); } } } @@ -797,10 +800,14 @@ } // draw word-wrap-honor-indent filling - if ((range->viewLineCount() > 1) && range->shiftX() && (range->shiftX() > xStart)) { + if ((range->viewLineCount() > 1) && (m_view->config()->dynWrapFillLeft() || m_view->config()->dynWrapFillRight()) && range->shiftX() && (range->shiftX() > xStart)) { + const int wdRight = range->shiftXRightOnly(); + int wdLeft = range->shiftX() - xStart - wdRight; + int col0 = (m_view->config()->dynWrapFillLeft() ? 0 : wdLeft); + int wd = (m_view->config()->dynWrapFillLeft() ? wdLeft : 0) + wdRight; if (backgroundBrushSet) - paint.fillRect(0, lineHeight(), range->shiftX() - xStart, lineHeight() * (range->viewLineCount() - 1), backgroundBrush); - paint.fillRect(0, lineHeight(), range->shiftX() - xStart, lineHeight() * (range->viewLineCount() - 1), QBrush(config()->wordWrapMarkerColor(), Qt::Dense4Pattern)); + paint.fillRect(col0, lineHeight(), wd, lineHeight() * (range->viewLineCount() - 1), backgroundBrush); + paint.fillRect(col0, lineHeight(), wd, lineHeight() * (range->viewLineCount() - 1), QBrush(config()->wordWrapMarkerColor(), Qt::Dense4Pattern)); } // Draw caret @@ -1073,6 +1080,7 @@ int height = 0; int shiftX = 0; + int shiftXRightOnly = 0; bool needShiftX = (maxwidth != -1) && m_view && (m_view->config()->dynWordWrapAlignIndent() > 0); @@ -1103,12 +1111,19 @@ // check for too deep shift value and limit if necessary if (shiftX > ((double)maxwidth / 100 * m_view->config()->dynWordWrapAlignIndent())) { shiftX = 0; + shiftXRightOnly = 0; + } else { + // extra indentation on subsequent lines for indent marker itself + shiftXRightOnly = m_view->config()->dynWrapFillRight() * spaceWidth(); + // so far shiftX is only the left part; add right as well here + shiftX += shiftXRightOnly; } // if shiftX > 0, the maxwidth has to adapted maxwidth -= shiftX; lineLayout->setShiftX(shiftX); + lineLayout->setShiftXRightOnly(shiftXRightOnly); } height += lineHeight(); diff --git a/src/utils/kateconfig.h b/src/utils/kateconfig.h --- a/src/utils/kateconfig.h +++ b/src/utils/kateconfig.h @@ -958,6 +958,8 @@ DynWordWrapIndicators, DynWrapAnywhere, DynWrapAtStaticMarker, + DynWrapFillLeft, + DynWrapFillRight, DynamicWordWrap, FoldFirstLine, InputMode, @@ -1023,6 +1025,16 @@ return value(DynWrapAtStaticMarker).toBool(); } + bool dynWrapFillLeft() const + { + return value(DynWrapFillLeft).toBool(); + } + + int dynWrapFillRight() const + { + return value(DynWrapFillRight).toInt(); + } + int dynWordWrapIndicators() const { return value(DynWordWrapIndicators).toInt(); diff --git a/src/utils/kateconfig.cpp b/src/utils/kateconfig.cpp --- a/src/utils/kateconfig.cpp +++ b/src/utils/kateconfig.cpp @@ -531,6 +531,8 @@ addConfigEntry(ConfigEntry(DynWordWrapIndicators, "Dynamic Word Wrap Indicators", QString(), 1, [](const QVariant &value) { return inBounds(1, value, 3); })); addConfigEntry(ConfigEntry(DynWrapAnywhere, "Dynamic Wrap not at word boundaries", QStringLiteral("dynamic-word-wrap-anywhere"), false)); addConfigEntry(ConfigEntry(DynWrapAtStaticMarker, "Dynamic Word Wrap At Static Marker", QString(), false)); + addConfigEntry(ConfigEntry(DynWrapFillLeft, "Fill indent of dynamically wrapped lines (left)", QStringLiteral("dynamic-word-wrap-fill-left"), true)); + addConfigEntry(ConfigEntry(DynWrapFillRight, "Fill indent amount of dynamically wrapped lines (right)", QStringLiteral("dynamic-word-wrap-fill-right"), 0)); addConfigEntry(ConfigEntry(DynamicWordWrap, "Dynamic Word Wrap", QStringLiteral("dynamic-word-wrap"), true)); addConfigEntry(ConfigEntry(FoldFirstLine, "Fold First Line", QString(), false)); addConfigEntry(ConfigEntry(InputMode, "Input Mode", QString(), 0, [](const QVariant &value) { return isPositive(value); }));