aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2021-05-12 09:13:07 +1000
committerNeil <nyamatongwe@gmail.com>2021-05-12 09:13:07 +1000
commit2feaeaf738851055a79ffcfb9027a3637610faca (patch)
tree6039c295b12073a5269ac667bbb886cf440d737b
parent5468995af334359c04625dbd374658bbf91b0449 (diff)
downloadscintilla-mirror-2feaeaf738851055a79ffcfb9027a3637610faca.tar.gz
Switch caret line background colour to SC_ELEMENT_CARET_LINE_BACK element and
add SetCaretLineLayer. Older caret line APIs SCI_SETCARETLINEVISIBLE, SCI_SETCARETLINEBACK, SCI_SETCARETLINEBACKALPHA now discouraged.
-rw-r--r--doc/ScintillaDoc.html68
-rw-r--r--doc/ScintillaHistory.html6
-rw-r--r--include/Scintilla.h3
-rw-r--r--include/Scintilla.iface7
-rw-r--r--src/EditView.cxx51
-rw-r--r--src/Editor.cxx50
-rw-r--r--src/Geometry.h4
-rw-r--r--src/ViewStyle.cxx19
-rw-r--r--src/ViewStyle.h10
-rw-r--r--test/simpleTests.py101
10 files changed, 240 insertions, 79 deletions
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index fcce51dd0..2ba53c837 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -3408,6 +3408,13 @@ struct Sci_TextToFind {
<td>All</td>
<td>Colour of carets when another window has focus</td>
</tr>
+ <tr>
+ <th align="left"><code>SC_ELEMENT_CARET_LINE_BACK</code></th>
+ <td>50</td>
+ <td>Translucent</td>
+ <td>All</td>
+ <td>Colour of caret line background</td>
+ </tr>
</tbody>
</table>
@@ -3454,12 +3461,15 @@ struct Sci_TextToFind {
<a class="element" href="#SC_ELEMENT_SELECTION_NO_FOCUS_TEXT">SC_ELEMENT_SELECTION_NO_FOCUS_TEXT : colouralpha</a><br />
<a class="element" href="#SC_ELEMENT_SELECTION_NO_FOCUS_BACK">SC_ELEMENT_SELECTION_NO_FOCUS_BACK : colouralpha</a><br />
<br />
- <a class="message" href="#SCI_SETCARETLINEVISIBLE">SCI_SETCARETLINEVISIBLE(bool show)</a><br />
- <a class="message" href="#SCI_GETCARETLINEVISIBLE">SCI_GETCARETLINEVISIBLE &rarr; bool</a><br />
- <a class="message" href="#SCI_SETCARETLINEBACK">SCI_SETCARETLINEBACK(colour back)</a><br />
- <a class="message" href="#SCI_GETCARETLINEBACK">SCI_GETCARETLINEBACK &rarr; colour</a><br />
- <a class="message" href="#SCI_SETCARETLINEBACKALPHA">SCI_SETCARETLINEBACKALPHA(alpha alpha)</a><br />
- <a class="message" href="#SCI_GETCARETLINEBACKALPHA">SCI_GETCARETLINEBACKALPHA &rarr; int</a><br />
+ <a class="element" href="#SC_ELEMENT_CARET_LINE_BACK">SC_ELEMENT_CARET_LINE_BACK : colouralpha</a><br />
+ <a class="message" href="#SCI_SETCARETLINELAYER">SCI_SETCARETLINELAYER(int layer)</a><br />
+ <a class="message" href="#SCI_GETCARETLINELAYER">SCI_GETCARETLINELAYER &rarr; int</a><br />
+ <a class="discouraged message" href="#SCI_SETCARETLINEVISIBLE">SCI_SETCARETLINEVISIBLE(bool show)</a><br />
+ <a class="discouraged message" href="#SCI_GETCARETLINEVISIBLE">SCI_GETCARETLINEVISIBLE &rarr; bool</a><br />
+ <a class="discouraged message" href="#SCI_SETCARETLINEBACK">SCI_SETCARETLINEBACK(colour back)</a><br />
+ <a class="discouraged message" href="#SCI_GETCARETLINEBACK">SCI_GETCARETLINEBACK &rarr; colour</a><br />
+ <a class="discouraged message" href="#SCI_SETCARETLINEBACKALPHA">SCI_SETCARETLINEBACKALPHA(alpha alpha)</a><br />
+ <a class="discouraged message" href="#SCI_GETCARETLINEBACKALPHA">SCI_GETCARETLINEBACKALPHA &rarr; int</a><br />
<a class="message" href="#SCI_SETCARETLINEFRAME">SCI_SETCARETLINEFRAME(int width)</a><br />
<a class="message" href="#SCI_GETCARETLINEFRAME">SCI_GETCARETLINEFRAME &rarr; int</a><br />
<a class="message" href="#SCI_SETCARETLINEVISIBLEALWAYS">SCI_SETCARETLINEVISIBLEALWAYS(bool alwaysVisible)</a><br />
@@ -3565,14 +3575,47 @@ struct Sci_TextToFind {
These elements define the colours to be used for selections without focus.
</p>
+ <p>
+ <b id="SC_ELEMENT_CARET_LINE_BACK">SC_ELEMENT_CARET_LINE_BACK : colouralpha</b><br />
+ <b id="SCI_SETCARETLINELAYER">SCI_SETCARETLINELAYER(int layer)</b><br />
+ <b id="SCI_GETCARETLINELAYER">SCI_GETCARETLINELAYER &rarr; int</b><br />
+ You can choose to make the background colour of the line containing the caret different by setting the
+ <code>SC_ELEMENT_CARET_LINE_BACK</code> element with
+ <a class="message" href="#SCI_SETELEMENTCOLOUR"><code>SCI_SETELEMENTCOLOUR(SC_ELEMENT_CARET_LINE_BACK)</code></a>.
+ This effect may be drawn translucently over the text or opaquely on the base layer with <code>SCI_SETCARETLINELAYER</code>.
+ Background colouring has highest priority when a line has markers that would otherwise change
+ the background colour. When drawn translucently other background colours can show through.
+ The <code class="parameter">layer</code> argument can be one of:</p>
+
+ <table class="standard" summary="Layer">
+ <tbody valign="top">
+ <tr>
+ <th align="left"><code>SC_LAYER_BASE</code></th>
+
+ <td>0</td>
+
+ <td>Draw the caret line background opaquely on the base layer</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>SC_LAYER_OVER_TEXT</code></th>
+
+ <td>10</td>
+
+ <td>Draw the caret line background translucently over the text</td>
+ </tr>
+
+ </tbody>
+ </table>
+
<p><b id="SCI_SETCARETLINEVISIBLE">SCI_SETCARETLINEVISIBLE(bool show)</b><br />
<b id="SCI_GETCARETLINEVISIBLE">SCI_GETCARETLINEVISIBLE &rarr; bool</b><br />
<b id="SCI_SETCARETLINEBACK">SCI_SETCARETLINEBACK(<a class="jump" href="#colour">colour</a> back)</b><br />
<b id="SCI_GETCARETLINEBACK">SCI_GETCARETLINEBACK &rarr; colour</b><br />
<b id="SCI_SETCARETLINEBACKALPHA">SCI_SETCARETLINEBACKALPHA(<a class="jump" href="#alpha">alpha</a> alpha)</b><br />
<b id="SCI_GETCARETLINEBACKALPHA">SCI_GETCARETLINEBACKALPHA &rarr; int</b><br />
- <b id="SCI_SETCARETLINEFRAME">SCI_SETCARETLINEFRAME(int width)</b><br />
- <b id="SCI_GETCARETLINEFRAME">SCI_GETCARETLINEFRAME &rarr; int</b><br />
+ These APIs are discouraged. It is better to use the <code>SC_ELEMENT_CARET_LINE_BACK</code>
+ element mentioned in the previous section.<br />
You can choose to make the background colour of the line containing the caret different with
these messages. To do this, set the desired background colour with
<code>SCI_SETCARETLINEBACK</code>, then use <code>SCI_SETCARETLINEVISIBLE(true)</code> to
@@ -3584,10 +3627,15 @@ struct Sci_TextToFind {
through. This is done by setting the alpha (translucency) value by calling
SCI_SETCARETLINEBACKALPHA. When the alpha is not SC_ALPHA_NOALPHA,
the caret line is drawn after all other features so will affect the colour of all other features.
- Alternatively <code>SCI_SETCARETLINEFRAME</code> can be used to display the caret line framed
- instead of filling the whole background. Set width != 0 to enable this option and width = 0 to disable it.
</p>
+ <p>
+ <b id="SCI_SETCARETLINEFRAME">SCI_SETCARETLINEFRAME(int width)</b><br />
+ <b id="SCI_GETCARETLINEFRAME">SCI_GETCARETLINEFRAME &rarr; int</b><br />
+ <code>SCI_SETCARETLINEFRAME</code> can be used to display the caret line framed
+ instead of filling the whole background. Set width != 0 to enable this option and width = 0 to disable it.
+ </p>
+
<p><b id="SCI_SETCARETLINEVISIBLEALWAYS">SCI_SETCARETLINEVISIBLEALWAYS(bool alwaysVisible)</b><br />
<b id="SCI_GETCARETLINEVISIBLEALWAYS">SCI_GETCARETLINEVISIBLEALWAYS &rarr; bool</b><br />
Choose to make the caret line always visible even when the window is not in focus.
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index 64260aa88..6985807e1 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -586,6 +586,12 @@
translucently over text or opaquely underneath other drawing.
</li>
<li>
+ Change caret line drawing to use SC_ELEMENT_CARET_LINE_BACK element and
+ SCI_SETCARETLINELAYER method.
+ Older caret line APIs SCI_SETCARETLINEVISIBLE, SCI_SETCARETLINEBACK,
+ SCI_SETCARETLINEBACKALPHA now discouraged.
+ </li>
+ <li>
Add SCI_GETELEMENTBASECOLOUR to return the default values for element colours.
</li>
<li>
diff --git a/include/Scintilla.h b/include/Scintilla.h
index 820dc470a..d48ad6c5a 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -284,6 +284,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_ELEMENT_CARET 40
#define SC_ELEMENT_CARET_ADDITIONAL 41
#define SC_ELEMENT_CARET_SECONDARY 42
+#define SC_ELEMENT_CARET_LINE_BACK 50
#define SCI_SETELEMENTCOLOUR 2753
#define SCI_GETELEMENTCOLOUR 2754
#define SCI_RESETELEMENTCOLOUR 2755
@@ -300,6 +301,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_LAYER_OVER_TEXT 10
#define SCI_GETSELECTIONLAYER 2762
#define SCI_SETSELECTIONLAYER 2763
+#define SCI_GETCARETLINELAYER 2764
+#define SCI_SETCARETLINELAYER 2765
#define SCI_SETCARETFORE 2069
#define SCI_ASSIGNCMDKEY 2070
#define SCI_CLEARCMDKEY 2071
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index a51c0d611..8a2b0de66 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -687,6 +687,7 @@ val SC_ELEMENT_SELECTION_NO_FOCUS_BACK=17
val SC_ELEMENT_CARET=40
val SC_ELEMENT_CARET_ADDITIONAL=41
val SC_ELEMENT_CARET_SECONDARY=42
+val SC_ELEMENT_CARET_LINE_BACK=50
# Set the colour of an element. Translucency (alpha) may or may not be significant
# and this may depend on the platform. The alpha byte should commonly be 0xff for opaque.
@@ -736,6 +737,12 @@ get Layer GetSelectionLayer=2762(,)
# Set the layer for drawing selections: either opaquely on base layer or translucently over text
set void SetSelectionLayer=2763(Layer layer,)
+# Get the layer of the background of the line containing the caret.
+get Layer GetCaretLineLayer=2764(,)
+
+# Set the layer of the background of the line containing the caret.
+set void SetCaretLineLayer=2765(Layer layer,)
+
# Set the foreground colour of the caret.
set void SetCaretFore=2069(colour fore,)
diff --git a/src/EditView.cxx b/src/EditView.cxx
index 5549e73db..2b389ecee 100644
--- a/src/EditView.cxx
+++ b/src/EditView.cxx
@@ -919,35 +919,35 @@ static void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle r
textBack, textFore);
}
-static void DrawFrame(Surface *surface, ColourAlpha colour, int alpha, PRectangle rcFrame) {
- if (alpha != SC_ALPHA_NOALPHA) {
- surface->AlphaRectangle(rcFrame, 0, FillStroke(ColourAlpha(colour, alpha)));
- } else {
- surface->FillRectangleAligned(rcFrame, Fill(colour));
+static void DrawCaretLineFramed(Surface *surface, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine, int subLine) {
+ const std::optional<ColourAlpha> caretlineBack = vsDraw.ElementColour(SC_ELEMENT_CARET_LINE_BACK);
+ if (!caretlineBack) {
+ return;
}
-}
-static void DrawCaretLineFramed(Surface *surface, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine, int subLine) {
+ const ColourAlpha colourFrame = (vsDraw.caretLine.layer == Layer::base) ?
+ caretlineBack->Opaque() : *caretlineBack;
+
const int width = vsDraw.GetFrameWidth();
- if (subLine == 0 || ll->wrapIndent == 0 || vsDraw.caretLine.alpha != SC_ALPHA_NOALPHA) {
+
+ // Avoid double drawing the corners by removing the left and right sides when drawing top and bottom borders
+ const PRectangle rcWithoutLeftRight = rcLine.Inset(Point(width, 0.0));
+
+ if (subLine == 0 || ll->wrapIndent == 0 || vsDraw.caretLine.layer == Layer::over) {
// Left
- DrawFrame(surface, vsDraw.caretLine.background, vsDraw.caretLine.alpha,
- PRectangle(rcLine.left, rcLine.top, rcLine.left + width, rcLine.bottom));
+ surface->FillRectangleAligned(Side(rcLine, Edge::left, width), colourFrame);
}
if (subLine == 0) {
// Top
- DrawFrame(surface, vsDraw.caretLine.background, vsDraw.caretLine.alpha,
- PRectangle(rcLine.left + width, rcLine.top, rcLine.right - width, rcLine.top + width));
+ surface->FillRectangleAligned(Side(rcWithoutLeftRight, Edge::top, width), colourFrame);
}
- if (subLine == ll->lines - 1 || vsDraw.caretLine.alpha != SC_ALPHA_NOALPHA) {
+ if (subLine == ll->lines - 1 || vsDraw.caretLine.layer == Layer::over) {
// Right
- DrawFrame(surface, vsDraw.caretLine.background, vsDraw.caretLine.alpha,
- PRectangle(rcLine.right - width, rcLine.top, rcLine.right, rcLine.bottom));
+ surface->FillRectangleAligned(Side(rcLine, Edge::right, width), colourFrame);
}
if (subLine == ll->lines - 1) {
// Bottom
- DrawFrame(surface, vsDraw.caretLine.background, vsDraw.caretLine.alpha,
- PRectangle(rcLine.left + width, rcLine.bottom - width, rcLine.right - width, rcLine.bottom));
+ surface->FillRectangleAligned(Side(rcWithoutLeftRight, Edge::bottom, width), colourFrame);
}
}
@@ -1082,10 +1082,9 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0;
}
if (vsDraw.IsLineFrameOpaque(model.caret.active, ll->containsCaret)) {
- const int width = vsDraw.GetFrameWidth();
// Draw right of frame under marker
- DrawFrame(surface, vsDraw.caretLine.background, vsDraw.caretLine.alpha,
- PRectangle(rcLine.right - width, rcLine.top, rcLine.right, rcLine.bottom));
+ surface->FillRectangleAligned(Side(rcLine, Edge::right, vsDraw.GetFrameWidth()),
+ vsDraw.ElementColour(SC_ELEMENT_CARET_LINE_BACK)->Opaque());
}
}
@@ -1667,10 +1666,9 @@ static void DrawWrapIndentAndMarker(Surface *surface, const ViewStyle &vsDraw, c
vsDraw.styles[STYLE_DEFAULT].back));
if (vsDraw.IsLineFrameOpaque(caretActive, ll->containsCaret)) {
- const int width = vsDraw.GetFrameWidth();
// Draw left of frame under marker
- DrawFrame(surface, vsDraw.caretLine.background, vsDraw.caretLine.alpha,
- PRectangle(rcLine.left, rcLine.top, rcLine.left + width, rcLine.bottom));
+ surface->FillRectangleAligned(Side(rcLine, Edge::left, vsDraw.GetFrameWidth()),
+ vsDraw.ElementColour(SC_ELEMENT_CARET_LINE_BACK)->Opaque());
}
if (vsDraw.wrap.visualFlags & SC_WRAPVISUALFLAG_START) {
@@ -1872,12 +1870,12 @@ static void DrawTranslucentSelection(Surface *surface, const EditModel &model, c
// Draw any translucent whole line states
static void DrawTranslucentLineState(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
Sci::Line line, PRectangle rcLine, int subLine) {
- if ((model.caret.active || vsDraw.caretLine.alwaysShow) && vsDraw.caretLine.show && ll->containsCaret &&
- vsDraw.caretLine.alpha != SC_ALPHA_NOALPHA) {
+ if ((model.caret.active || vsDraw.caretLine.alwaysShow) && vsDraw.ElementColour(SC_ELEMENT_CARET_LINE_BACK) && ll->containsCaret &&
+ vsDraw.caretLine.layer == Layer::over) {
if (vsDraw.caretLine.frame) {
DrawCaretLineFramed(surface, vsDraw, ll, rcLine, subLine);
} else {
- SimpleAlphaRectangle(surface, rcLine, vsDraw.caretLine.background, vsDraw.caretLine.alpha);
+ surface->FillRectangleAligned(rcLine, *vsDraw.ElementColour(SC_ELEMENT_CARET_LINE_BACK));
}
}
const int marksOfLine = model.pdoc->GetMark(line);
@@ -2526,7 +2524,6 @@ Sci::Position EditView::FormatRange(bool draw, const Sci_RangeToFormat *pfr, Sur
vsPrint.elementBaseColours.clear();
vsPrint.whitespaceColours.back.reset();
vsPrint.whitespaceColours.fore.reset();
- vsPrint.caretLine.show = false;
vsPrint.caretLine.alwaysShow = false;
// Don't highlight matching braces using indicators
vsPrint.braceHighlightIndicatorSet = false;
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 35ca7bb77..694ac2f5f 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -7248,10 +7248,18 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
return pdoc->GetMaxLineState();
case SCI_GETCARETLINEVISIBLE:
- return vs.caretLine.show;
+ return vs.ElementColour(SC_ELEMENT_CARET_LINE_BACK) ? 1 : 0;
case SCI_SETCARETLINEVISIBLE:
- vs.caretLine.show = wParam != 0;
- InvalidateStyleRedraw();
+ if (wParam) {
+ if (!vs.elementColours.count(SC_ELEMENT_CARET_LINE_BACK)) {
+ vs.elementColours[SC_ELEMENT_CARET_LINE_BACK] = ColourAlpha(0xFF, 0xFF, 0);
+ InvalidateStyleRedraw();
+ }
+ } else {
+ if (vs.ResetElement(SC_ELEMENT_CARET_LINE_BACK)) {
+ InvalidateStyleRedraw();
+ }
+ }
break;
case SCI_GETCARETLINEVISIBLEALWAYS:
return vs.caretLine.alwaysShow;
@@ -7267,16 +7275,38 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
InvalidateStyleRedraw();
break;
case SCI_GETCARETLINEBACK:
- return vs.caretLine.background.OpaqueRGB();
+ if (vs.ElementColour(SC_ELEMENT_CARET_LINE_BACK))
+ return vs.ElementColour(SC_ELEMENT_CARET_LINE_BACK)->OpaqueRGB();
+ else
+ return 0;
+
case SCI_SETCARETLINEBACK:
- vs.caretLine.background = ColourAlpha::FromRGB(static_cast<int>(wParam));
+ vs.SetElementRGB(SC_ELEMENT_CARET_LINE_BACK, static_cast<int>(wParam));
InvalidateStyleRedraw();
break;
+
+ case SCI_GETCARETLINELAYER:
+ return static_cast<sptr_t>(vs.caretLine.layer);
+
+ case SCI_SETCARETLINELAYER:
+ if (vs.caretLine.layer != static_cast<Layer>(wParam)) {
+ vs.caretLine.layer = static_cast<Layer>(wParam);
+ UpdateBaseElements();
+ InvalidateStyleRedraw();
+ }
+ break;
+
case SCI_GETCARETLINEBACKALPHA:
- return vs.caretLine.alpha;
- case SCI_SETCARETLINEBACKALPHA:
- vs.caretLine.alpha = static_cast<int>(wParam);
- InvalidateStyleRedraw();
+ if (vs.caretLine.layer == Layer::base)
+ return SC_ALPHA_NOALPHA;
+ return vs.ElementColour(SC_ELEMENT_CARET_LINE_BACK).value_or(ColourAlpha()).GetAlpha();
+
+ case SCI_SETCARETLINEBACKALPHA: {
+ const Layer layerNew = (wParam == SC_ALPHA_NOALPHA) ? Layer::base : Layer::over;
+ vs.caretLine.layer = layerNew;
+ vs.SetElementAlpha(SC_ELEMENT_CARET_LINE_BACK, static_cast<int>(wParam));
+ InvalidateStyleRedraw();
+ }
break;
// Folding messages
@@ -7441,7 +7471,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
break;
case SCI_SETSELALPHA: {
- Layer layerNew = (wParam == SC_ALPHA_NOALPHA) ? Layer::base : Layer::over;
+ const Layer layerNew = (wParam == SC_ALPHA_NOALPHA) ? Layer::base : Layer::over;
if (vs.selection.layer != layerNew) {
vs.selection.layer = layerNew;
UpdateBaseElements();
diff --git a/src/Geometry.h b/src/Geometry.h
index 01af92969..a6e49ad5b 100644
--- a/src/Geometry.h
+++ b/src/Geometry.h
@@ -129,6 +129,10 @@ public:
return PRectangle(left + delta, top + delta, right - delta, bottom - delta);
}
+ constexpr PRectangle Inset(Point delta) const noexcept {
+ return PRectangle(left + delta.x, top + delta.y, right - delta.x, bottom - delta.y);
+ }
+
constexpr Point Centre() const noexcept {
return Point((left + right) / 2, (top + bottom) / 2);
}
diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx
index a8fcd2d8c..60334c2ea 100644
--- a/src/ViewStyle.cxx
+++ b/src/ViewStyle.cxx
@@ -243,10 +243,10 @@ void ViewStyle::Init(size_t stylesSize_) {
caret.style = CARETSTYLE_LINE;
caret.width = 1;
- caretLine.background = ColourAlpha(0xff, 0xff, 0);
- caretLine.show = false;
+ elementColours.erase(SC_ELEMENT_CARET_LINE_BACK);
+ elementAllowsTranslucent.insert(SC_ELEMENT_CARET_LINE_BACK);
caretLine.alwaysShow = false;
- caretLine.alpha = SC_ALPHA_NOALPHA;
+ caretLine.layer = Layer::base;
caretLine.frame = 0;
someStylesProtected = false;
@@ -461,9 +461,10 @@ int ViewStyle::GetFrameWidth() const noexcept {
return std::clamp(caretLine.frame, 1, lineHeight / 3);
}
-bool ViewStyle::IsLineFrameOpaque(bool caretActive, bool lineContainsCaret) const noexcept {
- return caretLine.frame && (caretActive || caretLine.alwaysShow) && caretLine.show &&
- (caretLine.alpha == SC_ALPHA_NOALPHA) && lineContainsCaret;
+bool ViewStyle::IsLineFrameOpaque(bool caretActive, bool lineContainsCaret) const {
+ return caretLine.frame && (caretActive || caretLine.alwaysShow) &&
+ ElementColour(SC_ELEMENT_CARET_LINE_BACK) &&
+ (caretLine.layer == Layer::base) && lineContainsCaret;
}
// See if something overrides the line background colour: Either if caret is on the line
@@ -474,9 +475,9 @@ bool ViewStyle::IsLineFrameOpaque(bool caretActive, bool lineContainsCaret) cons
// the colour for the highest numbered one is used.
std::optional<ColourAlpha> ViewStyle::Background(int marksOfLine, bool caretActive, bool lineContainsCaret) const {
std::optional<ColourAlpha> background;
- if (!caretLine.frame && (caretActive || caretLine.alwaysShow) && caretLine.show &&
- (caretLine.alpha == SC_ALPHA_NOALPHA) && lineContainsCaret) {
- background = caretLine.background;
+ if (!caretLine.frame && (caretActive || caretLine.alwaysShow) &&
+ (caretLine.layer == Layer::base) && lineContainsCaret) {
+ background = ElementColour(SC_ELEMENT_CARET_LINE_BACK);
}
if (!background && marksOfLine) {
int marks = marksOfLine;
diff --git a/src/ViewStyle.h b/src/ViewStyle.h
index 13c489aa2..9f3cae123 100644
--- a/src/ViewStyle.h
+++ b/src/ViewStyle.h
@@ -73,14 +73,10 @@ struct SelectionAppearance {
};
struct CaretLineAppearance {
- // Colour of caret line
- ColourAlpha background;
- // Whether to show the caret line
- bool show;
+ // Whether to draw on base layer or over text
+ Layer layer;
// Also show when non-focused
bool alwaysShow;
- // Translucency. SC_ALPHA_NOALPHA: draw selection background beneath text
- int alpha;
// Non-0: draw a rectangle around line instead of filling line. Value is pixel width of frame
int frame;
};
@@ -222,7 +218,7 @@ public:
bool ValidStyle(size_t styleIndex) const noexcept;
void CalcLargestMarkerHeight() noexcept;
int GetFrameWidth() const noexcept;
- bool IsLineFrameOpaque(bool caretActive, bool lineContainsCaret) const noexcept;
+ bool IsLineFrameOpaque(bool caretActive, bool lineContainsCaret) const;
std::optional<ColourAlpha> Background(int marksOfLine, bool caretActive, bool lineContainsCaret) const;
bool SelectionBackgroundDrawn() const noexcept;
bool SelectionTextDrawn() const;
diff --git a/test/simpleTests.py b/test/simpleTests.py
index c1407ad7c..9ac1c43fd 100644
--- a/test/simpleTests.py
+++ b/test/simpleTests.py
@@ -1933,50 +1933,119 @@ class TestElements(unittest.TestCase):
self.ed.ClearAll()
self.ed.EmptyUndoBuffer()
self.testColourAlpha = 0x18171615
+ self.opaque = 0xff000000
+ self.dropAlpha = 0x00ffffff
def tearDown(self):
pass
+
+ def ElementColour(self, element):
+ # & 0xffffffff prevents sign extension issues
+ return self.ed.GetElementColour(element) & 0xffffffff
+
+ def RestoreCaretLine(self):
+ self.ed.CaretLineLayer = 0
+ self.ed.CaretLineFrame = 0
+ self.ed.ResetElementColour(self.ed.SC_ELEMENT_CARET_LINE_BACK)
+ self.ed.CaretLineVisibleAlways = False
def testIsSet(self):
- self.assertEquals(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_SELECTION_TEXT), 0)
+ self.assertFalse(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_SELECTION_TEXT))
def testAllowsTranslucent(self):
- self.assertEquals(self.ed.GetElementAllowsTranslucent(self.ed.SC_ELEMENT_LIST), 0)
- self.assertEquals(self.ed.GetElementAllowsTranslucent(self.ed.SC_ELEMENT_SELECTION_TEXT), 1)
+ self.assertFalse(self.ed.GetElementAllowsTranslucent(self.ed.SC_ELEMENT_LIST))
+ self.assertTrue(self.ed.GetElementAllowsTranslucent(self.ed.SC_ELEMENT_SELECTION_TEXT))
def testChanging(self):
self.ed.SetElementColour(self.ed.SC_ELEMENT_LIST_BACK, self.testColourAlpha)
- self.assertEquals(self.ed.GetElementColour(self.ed.SC_ELEMENT_LIST_BACK), self.testColourAlpha)
- self.assertEquals(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_LIST_BACK), 1)
+ self.assertEquals(self.ElementColour(self.ed.SC_ELEMENT_LIST_BACK), self.testColourAlpha)
+ self.assertTrue(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_LIST_BACK))
def testReset(self):
self.ed.SetElementColour(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT, self.testColourAlpha)
- self.assertEquals(self.ed.GetElementColour(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT), self.testColourAlpha)
+ self.assertEquals(self.ElementColour(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT), self.testColourAlpha)
self.ed.ResetElementColour(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT)
- self.assertEquals(self.ed.GetElementColour(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT), 0)
- self.assertEquals(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT), 0)
+ self.assertEquals(self.ElementColour(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT), 0)
+ self.assertFalse(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_SELECTION_ADDITIONAL_TEXT))
def testBaseColour(self):
if sys.platform == "win32":
# SC_ELEMENT_LIST* base colours only currently implemented on Win32
- opaque = 0xff000000
- dropAlpha = 0x00ffffff
text = self.ed.GetElementBaseColour(self.ed.SC_ELEMENT_LIST)
back = self.ed.GetElementBaseColour(self.ed.SC_ELEMENT_LIST_BACK)
- self.assertEquals(text & opaque, opaque)
- self.assertEquals(back & opaque, opaque)
- self.assertNotEquals(text & dropAlpha, back & dropAlpha)
+ self.assertEquals(text & self.opaque, self.opaque)
+ self.assertEquals(back & self.opaque, self.opaque)
+ self.assertNotEquals(text & self.dropAlpha, back & self.dropAlpha)
selText = self.ed.GetElementBaseColour(self.ed.SC_ELEMENT_LIST_SELECTED)
selBack = self.ed.GetElementBaseColour(self.ed.SC_ELEMENT_LIST_SELECTED_BACK)
- self.assertEquals(selText & opaque, opaque)
- self.assertEquals(selBack & opaque, opaque)
- self.assertNotEquals(selText & dropAlpha, selBack & dropAlpha)
+ self.assertEquals(selText & self.opaque, self.opaque)
+ self.assertEquals(selBack & self.opaque, self.opaque)
+ self.assertNotEquals(selText & self.dropAlpha, selBack & self.dropAlpha)
def testSelectionLayer(self):
self.ed.SelectionLayer = self.ed.SC_LAYER_OVER_TEXT
self.assertEquals(self.ed.SelectionLayer, self.ed.SC_LAYER_OVER_TEXT)
self.ed.SelectionLayer = self.ed.SC_LAYER_BASE
self.assertEquals(self.ed.SelectionLayer, self.ed.SC_LAYER_BASE)
+
+ def testCaretLine(self):
+ # Newer Layer / ElementColour API
+ self.assertEquals(self.ed.CaretLineLayer, 0)
+ self.assertFalse(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_CARET_LINE_BACK))
+ self.assertEquals(self.ed.CaretLineFrame, 0)
+ self.assertFalse(self.ed.CaretLineVisibleAlways)
+
+ self.ed.CaretLineLayer = 10
+ self.assertEquals(self.ed.CaretLineLayer, 10)
+ self.ed.CaretLineFrame = 2
+ self.assertEquals(self.ed.CaretLineFrame, 2)
+ self.ed.CaretLineVisibleAlways = True
+ self.assertTrue(self.ed.CaretLineVisibleAlways)
+ self.ed.SetElementColour(self.ed.SC_ELEMENT_CARET_LINE_BACK, self.testColourAlpha)
+ self.assertEquals(self.ElementColour(self.ed.SC_ELEMENT_CARET_LINE_BACK), self.testColourAlpha)
+
+ self.RestoreCaretLine()
+
+ def testCaretLineLayerDiscouraged(self):
+ # Check old discouraged APIs
+ # This is s bit tricky as there is no clean mapping: parts of the old state are distributed to
+ # sometimes-multiple parts of the new state.
+ backColour = 0x102030
+ backColourOpaque = backColour | self.opaque
+ self.assertEquals(self.ed.CaretLineVisible, 0)
+ self.ed.CaretLineVisible = 1
+ self.assertTrue(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_CARET_LINE_BACK))
+ self.assertEquals(self.ed.CaretLineVisible, 1)
+ self.ed.CaretLineBack = backColour
+ self.assertEquals(self.ed.CaretLineBack, backColour)
+ # Check with newer API
+ self.assertTrue(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_CARET_LINE_BACK))
+ self.assertEquals(self.ElementColour(self.ed.SC_ELEMENT_CARET_LINE_BACK), backColourOpaque)
+ self.assertEquals(self.ed.CaretLineLayer, 0)
+
+ alpha = 0x7f
+ self.ed.CaretLineBackAlpha = alpha
+ self.assertEquals(self.ed.CaretLineBackAlpha, alpha)
+ backColourTranslucent = backColour | (alpha << 24)
+ self.assertEquals(self.ElementColour(self.ed.SC_ELEMENT_CARET_LINE_BACK), backColourTranslucent)
+ self.assertEquals(self.ed.CaretLineLayer, 10)
+
+ self.ed.CaretLineBackAlpha = 0x100
+ self.assertEquals(self.ed.CaretLineBackAlpha, 0x100)
+ self.assertEquals(self.ed.CaretLineLayer, 0) # SC_ALPHA_NOALPHA moved to base layer
+
+ self.RestoreCaretLine()
+
+ # Try other orders
+
+ self.ed.CaretLineBackAlpha = 0x100
+ self.assertEquals(self.ed.CaretLineBackAlpha, 0x100)
+ self.assertEquals(self.ed.CaretLineLayer, 0) # SC_ALPHA_NOALPHA moved to base layer
+ self.assertTrue(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_CARET_LINE_BACK))
+ self.ed.CaretLineVisible = 0
+ self.assertFalse(self.ed.GetElementIsSet(self.ed.SC_ELEMENT_CARET_LINE_BACK))
+
+ self.RestoreCaretLine()
class TestIndices(unittest.TestCase):
def setUp(self):