diff options
| author | Neil <nyamatongwe@gmail.com> | 2021-05-12 09:13:07 +1000 | 
|---|---|---|
| committer | Neil <nyamatongwe@gmail.com> | 2021-05-12 09:13:07 +1000 | 
| commit | 2feaeaf738851055a79ffcfb9027a3637610faca (patch) | |
| tree | 6039c295b12073a5269ac667bbb886cf440d737b | |
| parent | 5468995af334359c04625dbd374658bbf91b0449 (diff) | |
| download | scintilla-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.html | 68 | ||||
| -rw-r--r-- | doc/ScintillaHistory.html | 6 | ||||
| -rw-r--r-- | include/Scintilla.h | 3 | ||||
| -rw-r--r-- | include/Scintilla.iface | 7 | ||||
| -rw-r--r-- | src/EditView.cxx | 51 | ||||
| -rw-r--r-- | src/Editor.cxx | 50 | ||||
| -rw-r--r-- | src/Geometry.h | 4 | ||||
| -rw-r--r-- | src/ViewStyle.cxx | 19 | ||||
| -rw-r--r-- | src/ViewStyle.h | 10 | ||||
| -rw-r--r-- | test/simpleTests.py | 101 | 
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 → bool</a><br /> -    <a class="message" href="#SCI_SETCARETLINEBACK">SCI_SETCARETLINEBACK(colour back)</a><br /> -    <a class="message" href="#SCI_GETCARETLINEBACK">SCI_GETCARETLINEBACK → colour</a><br /> -    <a class="message" href="#SCI_SETCARETLINEBACKALPHA">SCI_SETCARETLINEBACKALPHA(alpha alpha)</a><br /> -    <a class="message" href="#SCI_GETCARETLINEBACKALPHA">SCI_GETCARETLINEBACKALPHA → 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 → 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 → 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 → 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 → int</a><br />      <a class="message" href="#SCI_SETCARETLINEFRAME">SCI_SETCARETLINEFRAME(int width)</a><br />      <a class="message" href="#SCI_GETCARETLINEFRAME">SCI_GETCARETLINEFRAME → 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 → 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 → 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 → 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 → int</b><br /> -     <b id="SCI_SETCARETLINEFRAME">SCI_SETCARETLINEFRAME(int width)</b><br /> -     <b id="SCI_GETCARETLINEFRAME">SCI_GETCARETLINEFRAME → 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 → 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 → 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):  | 
