mirror of https://github.com/buggins/dlangui.git
text editor line marks
This commit is contained in:
parent
47487535c5
commit
732685c99d
|
@ -99,13 +99,6 @@ ubyte tokenCategory(ubyte t) {
|
||||||
return t & 0xF0;
|
return t & 0xF0;
|
||||||
}
|
}
|
||||||
|
|
||||||
class TextLineMark {
|
|
||||||
}
|
|
||||||
|
|
||||||
class TextLineMarks {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// split dstring by delimiters
|
/// split dstring by delimiters
|
||||||
dstring[] splitDString(dstring source, dchar delimiter = EOL) {
|
dstring[] splitDString(dstring source, dchar delimiter = EOL) {
|
||||||
int start = 0;
|
int start = 0;
|
||||||
|
@ -545,6 +538,9 @@ class EditableContent {
|
||||||
_readOnly = readOnly;
|
_readOnly = readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected LineIcons _lineIcons;
|
||||||
|
@property ref LineIcons lineIcons() { return _lineIcons; }
|
||||||
|
|
||||||
protected int _tabSize = 4;
|
protected int _tabSize = 4;
|
||||||
protected bool _useSpacesForTabs = true;
|
protected bool _useSpacesForTabs = true;
|
||||||
/// returns tab size (in number of spaces)
|
/// returns tab size (in number of spaces)
|
||||||
|
@ -587,8 +583,6 @@ class EditableContent {
|
||||||
|
|
||||||
/// listeners for edit operations
|
/// listeners for edit operations
|
||||||
Signal!EditableContentListener contentChanged;
|
Signal!EditableContentListener contentChanged;
|
||||||
/// contentChanged signal alias for backward compatibility; will be deprecated in future
|
|
||||||
alias contentChangeListeners = contentChanged;
|
|
||||||
|
|
||||||
protected bool _multiline;
|
protected bool _multiline;
|
||||||
/// returns true if miltyline content is supported
|
/// returns true if miltyline content is supported
|
||||||
|
@ -966,8 +960,8 @@ class EditableContent {
|
||||||
// update highlight if necessary
|
// update highlight if necessary
|
||||||
updateTokenProps(rangeAfter.start.line, rangeAfter.end.line + 1);
|
updateTokenProps(rangeAfter.start.line, rangeAfter.end.line + 1);
|
||||||
// call listeners
|
// call listeners
|
||||||
if (contentChangeListeners.assigned)
|
if (contentChanged.assigned)
|
||||||
contentChangeListeners(this, op, rangeBefore, rangeAfter, source);
|
contentChanged(this, op, rangeBefore, rangeAfter, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return edit marks for specified range
|
/// return edit marks for specified range
|
||||||
|
@ -1432,3 +1426,115 @@ class EditableContent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// types of text editor line icon marks (bookmark / breakpoint / error / ...)
|
||||||
|
enum LineIconType : int {
|
||||||
|
/// bookmark
|
||||||
|
bookmark,
|
||||||
|
/// breakpoint mark
|
||||||
|
breakpoint,
|
||||||
|
/// error mark
|
||||||
|
error,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// text editor line icon
|
||||||
|
class LineIcon {
|
||||||
|
/// line number
|
||||||
|
int line;
|
||||||
|
LineIconType type;
|
||||||
|
Object param;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// text editor line icon list
|
||||||
|
struct LineIcons {
|
||||||
|
private LineIcon[] _items;
|
||||||
|
private int _len;
|
||||||
|
|
||||||
|
/// returns count of items
|
||||||
|
@property int length() { return _len; }
|
||||||
|
/// returns item by index, or null if index out of bounds
|
||||||
|
LineIcon opIndex(int index) {
|
||||||
|
if (index < 0 || index >= _len)
|
||||||
|
return null;
|
||||||
|
return _items[index];
|
||||||
|
}
|
||||||
|
private void insert(LineIcon icon, int index) {
|
||||||
|
if (index < 0)
|
||||||
|
index = 0;
|
||||||
|
if (index > _len)
|
||||||
|
index = _len;
|
||||||
|
if (_items.length <= index)
|
||||||
|
_items.length = index + 16;
|
||||||
|
if (index < _len) {
|
||||||
|
for (size_t i = _len; i > index; i--)
|
||||||
|
_items[i] = _items[i - 1];
|
||||||
|
}
|
||||||
|
_items[index] = icon;
|
||||||
|
_len++;
|
||||||
|
}
|
||||||
|
private int findSortedIndex(int line, LineIconType type) {
|
||||||
|
// TODO: use binary search
|
||||||
|
for (int i = 0; i < _len; i++) {
|
||||||
|
if (_items[i].line > line || _items[i].type > type) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _len;
|
||||||
|
}
|
||||||
|
/// add icon mark
|
||||||
|
void add(LineIcon icon) {
|
||||||
|
int index = findSortedIndex(icon.line, icon.type);
|
||||||
|
insert(icon, index);
|
||||||
|
}
|
||||||
|
/// add all icons from list
|
||||||
|
void addAll(LineIcon[] list) {
|
||||||
|
foreach(item; list)
|
||||||
|
add(item);
|
||||||
|
}
|
||||||
|
/// remove icon mark by index
|
||||||
|
LineIcon remove(int index) {
|
||||||
|
if (index < 0 || index >= _len)
|
||||||
|
return null;
|
||||||
|
LineIcon res = _items[index];
|
||||||
|
for (int i = index; i < _len - 1; i++)
|
||||||
|
_items[i] = _items[i + 1];
|
||||||
|
_len--;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
/// remove icon mark
|
||||||
|
LineIcon remove(LineIcon icon) {
|
||||||
|
for (int i = 0; i < _len; i++) {
|
||||||
|
if (_items[i] is icon)
|
||||||
|
return remove(i);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < _len; i++) {
|
||||||
|
if (_items[i].param !is null && icon.param !is null && _items[i].param is icon.param)
|
||||||
|
return remove(i);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < _len; i++) {
|
||||||
|
if (_items[i].line == icon.line && _items[i].type == icon.type)
|
||||||
|
return remove(i);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/// remove all icon marks of specified type
|
||||||
|
void removeByType(LineIconType type) {
|
||||||
|
for (int i = _len - 1; i >= 0; i--) {
|
||||||
|
if (_items[i].type == type)
|
||||||
|
remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// get array of icons of specified type
|
||||||
|
LineIcon[] findByType(LineIconType type) {
|
||||||
|
LineIcon[] res;
|
||||||
|
for (int i = 0; i < _len; i++) {
|
||||||
|
if (_items[i].type == type)
|
||||||
|
res ~= _items[i];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
/// update mark position lines after text change
|
||||||
|
void updateLinePositions(TextRange rangeBefore, TextRange rangeAfter) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -634,14 +634,14 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction
|
||||||
return this; // not changed
|
return this; // not changed
|
||||||
if (_content !is null) {
|
if (_content !is null) {
|
||||||
// disconnect old content
|
// disconnect old content
|
||||||
_content.contentChangeListeners.disconnect(this);
|
_content.contentChanged.disconnect(this);
|
||||||
if (_ownContent) {
|
if (_ownContent) {
|
||||||
destroy(_content);
|
destroy(_content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_content = content;
|
_content = content;
|
||||||
_ownContent = false;
|
_ownContent = false;
|
||||||
_content.contentChangeListeners.connect(this);
|
_content.contentChanged.connect(this);
|
||||||
if (_content.readOnly)
|
if (_content.readOnly)
|
||||||
enabled = false;
|
enabled = false;
|
||||||
return this;
|
return this;
|
||||||
|
@ -1511,7 +1511,7 @@ class EditLine : EditWidgetBase {
|
||||||
this(string ID, dstring initialContent = null) {
|
this(string ID, dstring initialContent = null) {
|
||||||
super(ID, ScrollBarMode.Invisible, ScrollBarMode.Invisible);
|
super(ID, ScrollBarMode.Invisible, ScrollBarMode.Invisible);
|
||||||
_content = new EditableContent(false);
|
_content = new EditableContent(false);
|
||||||
_content.contentChangeListeners = this;
|
_content.contentChanged = this;
|
||||||
wantTabs = false;
|
wantTabs = false;
|
||||||
styleId = STYLE_EDIT_LINE;
|
styleId = STYLE_EDIT_LINE;
|
||||||
text = initialContent;
|
text = initialContent;
|
||||||
|
@ -1702,7 +1702,7 @@ class EditBox : EditWidgetBase {
|
||||||
this(string ID, dstring initialContent = null, ScrollBarMode hscrollbarMode = ScrollBarMode.Visible, ScrollBarMode vscrollbarMode = ScrollBarMode.Visible) {
|
this(string ID, dstring initialContent = null, ScrollBarMode hscrollbarMode = ScrollBarMode.Visible, ScrollBarMode vscrollbarMode = ScrollBarMode.Visible) {
|
||||||
super(ID, hscrollbarMode, vscrollbarMode);
|
super(ID, hscrollbarMode, vscrollbarMode);
|
||||||
_content = new EditableContent(true); // multiline
|
_content = new EditableContent(true); // multiline
|
||||||
_content.contentChangeListeners = this;
|
_content.contentChanged = this;
|
||||||
styleId = STYLE_EDIT_BOX;
|
styleId = STYLE_EDIT_BOX;
|
||||||
text = initialContent;
|
text = initialContent;
|
||||||
acceleratorMap.add( [
|
acceleratorMap.add( [
|
||||||
|
|
Loading…
Reference in New Issue