mirror of https://github.com/buggins/dlangui.git
dotted pattern fill support, tab positions marks support
This commit is contained in:
parent
2f5a481d2e
commit
9f52be92b8
|
@ -868,6 +868,40 @@ class EditableContent {
|
||||||
return (pos + tabSize) / tabSize * tabSize;
|
return (pos + tabSize) / tabSize * tabSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// to return information about line space positions
|
||||||
|
static struct LineWhiteSpace {
|
||||||
|
int firstNonSpaceIndex = -1;
|
||||||
|
int firstNonSpaceColumn = -1;
|
||||||
|
int lastNonSpaceIndex = -1;
|
||||||
|
int lastNonSpaceColumn = -1;
|
||||||
|
@property bool empty() { return firstNonSpaceColumn < 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
LineWhiteSpace getLineWhiteSpace(int lineIndex) {
|
||||||
|
LineWhiteSpace res;
|
||||||
|
if (lineIndex < 0 || lineIndex >= _lines.length)
|
||||||
|
return res;
|
||||||
|
dstring s = _lines[lineIndex];
|
||||||
|
int x = 0;
|
||||||
|
for (int i = 0; i < s.length; i++) {
|
||||||
|
dchar ch = s[i];
|
||||||
|
if (ch == '\t') {
|
||||||
|
x = (x + _tabSize) / _tabSize * _tabSize;
|
||||||
|
} else if (ch == ' ') {
|
||||||
|
x++;
|
||||||
|
} else {
|
||||||
|
if (res.firstNonSpaceIndex < 0) {
|
||||||
|
res.firstNonSpaceIndex = i;
|
||||||
|
res.firstNonSpaceColumn = x;
|
||||||
|
}
|
||||||
|
res.lastNonSpaceIndex = i;
|
||||||
|
res.lastNonSpaceColumn = x;
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/// returns spaces/tabs for filling from the beginning of line to specified position
|
/// returns spaces/tabs for filling from the beginning of line to specified position
|
||||||
dstring fillSpace(int pos) {
|
dstring fillSpace(int pos) {
|
||||||
dchar[] buf;
|
dchar[] buf;
|
||||||
|
|
|
@ -34,6 +34,11 @@ struct NinePatch {
|
||||||
Rect padding;
|
Rect padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum PatternType : int {
|
||||||
|
solid,
|
||||||
|
dotted,
|
||||||
|
}
|
||||||
|
|
||||||
static if (ENABLE_OPENGL) {
|
static if (ENABLE_OPENGL) {
|
||||||
/// non thread safe
|
/// non thread safe
|
||||||
private __gshared uint drawBufIdGenerator = 0;
|
private __gshared uint drawBufIdGenerator = 0;
|
||||||
|
@ -278,6 +283,11 @@ class DrawBuf : RefCountedObject {
|
||||||
abstract void fill(uint color);
|
abstract void fill(uint color);
|
||||||
/// fill rectangle with solid color (clipping is applied)
|
/// fill rectangle with solid color (clipping is applied)
|
||||||
abstract void fillRect(Rect rc, uint color);
|
abstract void fillRect(Rect rc, uint color);
|
||||||
|
/// fill rectangle with solid color and pattern (clipping is applied) 0=solid fill, 1 = dotted
|
||||||
|
void fillRectPattern(Rect rc, uint color, int pattern) {
|
||||||
|
// default implementation: does not support patterns
|
||||||
|
fillRect(rc, color);
|
||||||
|
}
|
||||||
/// draw pixel at (x, y) with specified color
|
/// draw pixel at (x, y) with specified color
|
||||||
abstract void drawPixel(int x, int y, uint color);
|
abstract void drawPixel(int x, int y, uint color);
|
||||||
/// draw 8bit alpha image - usually font glyph using specified color (clipping is applied)
|
/// draw 8bit alpha image - usually font glyph using specified color (clipping is applied)
|
||||||
|
@ -701,10 +711,10 @@ class ColorDrawBufBase : DrawBuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
override void fillRect(Rect rc, uint color) {
|
override void fillRect(Rect rc, uint color) {
|
||||||
|
uint alpha = color >> 24;
|
||||||
if (applyClipping(rc)) {
|
if (applyClipping(rc)) {
|
||||||
foreach(y; rc.top .. rc.bottom) {
|
foreach(y; rc.top .. rc.bottom) {
|
||||||
uint * row = scanLine(y);
|
uint * row = scanLine(y);
|
||||||
uint alpha = color >> 24;
|
|
||||||
if (!alpha) {
|
if (!alpha) {
|
||||||
row[rc.left .. rc.right] = color;
|
row[rc.left .. rc.right] = color;
|
||||||
} else if (alpha < 254) {
|
} else if (alpha < 254) {
|
||||||
|
@ -717,6 +727,34 @@ class ColorDrawBufBase : DrawBuf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// fill rectangle with solid color and pattern (clipping is applied) 0=solid fill, 1 = dotted
|
||||||
|
override void fillRectPattern(Rect rc, uint color, int pattern) {
|
||||||
|
uint alpha = color >> 24;
|
||||||
|
if (alpha == 255) // fully transparent
|
||||||
|
return;
|
||||||
|
if (applyClipping(rc)) {
|
||||||
|
foreach(y; rc.top .. rc.bottom) {
|
||||||
|
uint * row = scanLine(y);
|
||||||
|
if (!alpha) {
|
||||||
|
if (pattern == 1) {
|
||||||
|
foreach(x; rc.left .. rc.right) {
|
||||||
|
if ((x ^ y) & 1)
|
||||||
|
row[x] = color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
row[rc.left .. rc.right] = color;
|
||||||
|
}
|
||||||
|
} else if (alpha < 254) {
|
||||||
|
foreach(x; rc.left .. rc.right) {
|
||||||
|
// apply blending
|
||||||
|
if (pattern != 1 || ((x ^ y) & 1) != 0)
|
||||||
|
row[x] = blendARGB(row[x], color, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// draw pixel at (x, y) with specified color
|
/// draw pixel at (x, y) with specified color
|
||||||
override void drawPixel(int x, int y, uint color) {
|
override void drawPixel(int x, int y, uint color) {
|
||||||
if (!_clipRect.isPointInside(x, y))
|
if (!_clipRect.isPointInside(x, y))
|
||||||
|
|
|
@ -112,6 +112,19 @@ class GLDrawBuf : DrawBuf, GLConfigCallback {
|
||||||
if (!isFullyTransparentColor(color) && applyClipping(rc))
|
if (!isFullyTransparentColor(color) && applyClipping(rc))
|
||||||
_scene.add(new SolidRectSceneItem(rc, color));
|
_scene.add(new SolidRectSceneItem(rc, color));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// fill rectangle with solid color and pattern (clipping is applied) 0=solid fill, 1 = dotted
|
||||||
|
override void fillRectPattern(Rect rc, uint color, int pattern) {
|
||||||
|
if (pattern == PatternType.solid)
|
||||||
|
fillRect(rc, color);
|
||||||
|
else {
|
||||||
|
assert(_scene !is null);
|
||||||
|
color = applyAlpha(color);
|
||||||
|
if (!isFullyTransparentColor(color) && applyClipping(rc))
|
||||||
|
_scene.add(new PatternRectSceneItem(rc, color, pattern));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// draw pixel at (x, y) with specified color
|
/// draw pixel at (x, y) with specified color
|
||||||
override void drawPixel(int x, int y, uint color) {
|
override void drawPixel(int x, int y, uint color) {
|
||||||
assert(_scene !is null);
|
assert(_scene !is null);
|
||||||
|
@ -718,6 +731,30 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class PatternRectSceneItem : SceneItem {
|
||||||
|
private:
|
||||||
|
Rect _rc;
|
||||||
|
uint _color;
|
||||||
|
int _pattern;
|
||||||
|
|
||||||
|
public:
|
||||||
|
this(Rect rc, uint color, int pattern) {
|
||||||
|
_rc = rc;
|
||||||
|
_color = color;
|
||||||
|
_pattern = pattern;
|
||||||
|
}
|
||||||
|
override void draw() {
|
||||||
|
// TODO: support patterns
|
||||||
|
// TODO: optimize
|
||||||
|
for (int y = _rc.top; y < _rc.bottom; y++) {
|
||||||
|
for (int x = _rc.left; x < _rc.right; x++)
|
||||||
|
if ((x ^ y) & 1) {
|
||||||
|
glSupport.drawSolidFillRect(Rect(x, y, x + 1, y + 1), _color, _color, _color, _color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class TextureSceneItem : SceneItem {
|
private class TextureSceneItem : SceneItem {
|
||||||
private:
|
private:
|
||||||
uint objectId;
|
uint objectId;
|
||||||
|
|
|
@ -252,9 +252,9 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction
|
||||||
protected uint _selectionColorNormal = 0xD060A0FF;
|
protected uint _selectionColorNormal = 0xD060A0FF;
|
||||||
protected uint _leftPaneBackgroundColor = 0xF4F4F4;
|
protected uint _leftPaneBackgroundColor = 0xF4F4F4;
|
||||||
protected uint _leftPaneBackgroundColor2 = 0xFFFFFF;
|
protected uint _leftPaneBackgroundColor2 = 0xFFFFFF;
|
||||||
protected uint _leftPaneBackgroundColor3 = 0xE0E0E0;
|
protected uint _leftPaneBackgroundColor3 = 0xF8F8F8;
|
||||||
protected uint _leftPaneLineNumberColor = 0x4060D0;
|
protected uint _leftPaneLineNumberColor = 0x4060D0;
|
||||||
protected uint _leftPaneLineNumberBackgroundColor = 0xF0F0F0;
|
protected uint _leftPaneLineNumberBackgroundColor = 0xF4F4F4;
|
||||||
protected uint _colorIconBreakpoint = 0xFF0000;
|
protected uint _colorIconBreakpoint = 0xFF0000;
|
||||||
protected uint _colorIconBookmark = 0x0000FF;
|
protected uint _colorIconBookmark = 0x0000FF;
|
||||||
protected uint _colorIconError = 0x80FF0000;
|
protected uint _colorIconError = 0x80FF0000;
|
||||||
|
@ -2680,6 +2680,47 @@ class EditBox : EditWidgetBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// find max tab mark column position for line
|
||||||
|
protected int findMaxTabMarkColumn(int lineIndex) {
|
||||||
|
if (lineIndex < 0 || lineIndex >= content.length)
|
||||||
|
return -1;
|
||||||
|
int maxSpace = -1;
|
||||||
|
auto space = content.getLineWhiteSpace(lineIndex);
|
||||||
|
maxSpace = space.firstNonSpaceColumn;
|
||||||
|
if (maxSpace >= 0)
|
||||||
|
return maxSpace;
|
||||||
|
for(int i = lineIndex - 1; i >= 0; i--) {
|
||||||
|
space = content.getLineWhiteSpace(i);
|
||||||
|
if (!space.empty) {
|
||||||
|
maxSpace = space.firstNonSpaceColumn;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int i = lineIndex + 1; i < content.length; i++) {
|
||||||
|
space = content.getLineWhiteSpace(i);
|
||||||
|
if (!space.empty) {
|
||||||
|
if (maxSpace < 0 || maxSpace < space.firstNonSpaceColumn)
|
||||||
|
maxSpace = space.firstNonSpaceColumn;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawTabPositionMarks(DrawBuf buf, ref FontRef font, int lineIndex, Rect lineRect) {
|
||||||
|
int maxCol = findMaxTabMarkColumn(lineIndex);
|
||||||
|
if (maxCol > 0) {
|
||||||
|
int spaceWidth = font.charWidth(' ');
|
||||||
|
Rect rc = lineRect;
|
||||||
|
uint color = addAlpha(textColor, 0xC0);
|
||||||
|
for (int i = 0; i < maxCol; i += tabSize) {
|
||||||
|
rc.left = lineRect.left + i * spaceWidth;
|
||||||
|
rc.right = rc.left + 1;
|
||||||
|
buf.fillRectPattern(rc, color, PatternType.dotted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void drawWhiteSpaceMarks(DrawBuf buf, ref FontRef font, dstring txt, int tabSize, Rect lineRect, Rect visibleRect) {
|
void drawWhiteSpaceMarks(DrawBuf buf, ref FontRef font, dstring txt, int tabSize, Rect lineRect, Rect visibleRect) {
|
||||||
// _showTabPositionMarks
|
// _showTabPositionMarks
|
||||||
// _showWhiteSpaceMarks
|
// _showWhiteSpaceMarks
|
||||||
|
@ -2715,17 +2756,6 @@ class EditBox : EditWidgetBase {
|
||||||
rc.right = lineRect.left + textSizeBuffer[i];
|
rc.right = lineRect.left + textSizeBuffer[i];
|
||||||
int h = rc.height;
|
int h = rc.height;
|
||||||
if (rc.intersects(visibleRect)) {
|
if (rc.intersects(visibleRect)) {
|
||||||
if (_showTabPositionMarks && i < firstNonSpace) {
|
|
||||||
if (spaceIndex % ts == 0) {
|
|
||||||
// draw mark
|
|
||||||
buf.fillRect(Rect(rc.left, rc.top, rc.left + 1, rc.bottom), color);
|
|
||||||
}
|
|
||||||
if (ch == ' ')
|
|
||||||
spaceIndex++;
|
|
||||||
else if (ch == '\t')
|
|
||||||
spaceIndex = (spaceIndex + ts) / ts * ts;
|
|
||||||
}
|
|
||||||
if (_showWhiteSpaceMarks) {
|
|
||||||
// draw space mark
|
// draw space mark
|
||||||
if (ch == ' ') {
|
if (ch == ' ') {
|
||||||
// space
|
// space
|
||||||
|
@ -2755,7 +2785,6 @@ class EditBox : EditWidgetBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override protected void drawClient(DrawBuf buf) {
|
override protected void drawClient(DrawBuf buf) {
|
||||||
// update matched braces
|
// update matched braces
|
||||||
|
@ -2778,9 +2807,11 @@ class EditBox : EditWidgetBase {
|
||||||
visibleRect.left = _clientRect.left;
|
visibleRect.left = _clientRect.left;
|
||||||
visibleRect.right = _clientRect.right;
|
visibleRect.right = _clientRect.right;
|
||||||
drawLineBackground(buf, _firstVisibleLine + i, lineRect, visibleRect);
|
drawLineBackground(buf, _firstVisibleLine + i, lineRect, visibleRect);
|
||||||
|
if (_showTabPositionMarks)
|
||||||
|
drawTabPositionMarks(buf, font, _firstVisibleLine + i, lineRect);
|
||||||
if (!txt.length)
|
if (!txt.length)
|
||||||
continue;
|
continue;
|
||||||
if (_showWhiteSpaceMarks || _showTabPositionMarks)
|
if (_showWhiteSpaceMarks)
|
||||||
drawWhiteSpaceMarks(buf, font, txt, tabSize, lineRect, visibleRect);
|
drawWhiteSpaceMarks(buf, font, txt, tabSize, lineRect, visibleRect);
|
||||||
if (_leftPaneWidth > 0) {
|
if (_leftPaneWidth > 0) {
|
||||||
Rect leftPaneRect = visibleRect;
|
Rect leftPaneRect = visibleRect;
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
<color id="editor_selection_normal" value="#D060A0FF"/>
|
<color id="editor_selection_normal" value="#D060A0FF"/>
|
||||||
<color id="editor_left_pane_background" value="#F4F4F4"/>
|
<color id="editor_left_pane_background" value="#F4F4F4"/>
|
||||||
<color id="editor_left_pane_background2" value="#FFFFFF"/>
|
<color id="editor_left_pane_background2" value="#FFFFFF"/>
|
||||||
<color id="editor_left_pane_background3" value="#E0E0E0"/>
|
<color id="editor_left_pane_background3" value="#F0F0F0"/>
|
||||||
<color id="editor_left_pane_line_number_text" value="#4060D0"/>
|
<color id="editor_left_pane_line_number_text" value="#4060D0"/>
|
||||||
<color id="editor_left_pane_line_number_background" value="#F0F0F0"/>
|
<color id="editor_left_pane_line_number_background" value="#F8F8F8"/>
|
||||||
<color id="editor_left_pane_line_icon_color_breakpoint" value="#FF0000"/>
|
<color id="editor_left_pane_line_icon_color_breakpoint" value="#FF0000"/>
|
||||||
<color id="editor_left_pane_line_icon_color_bookmark" value="#0000FF"/>
|
<color id="editor_left_pane_line_icon_color_bookmark" value="#0000FF"/>
|
||||||
<color id="editor_left_pane_line_icon_color_error" value="#80FF0000"/>
|
<color id="editor_left_pane_line_icon_color_error" value="#80FF0000"/>
|
||||||
|
|
Loading…
Reference in New Issue