mirror of https://github.com/buggins/dlangui.git
text editor line marks
This commit is contained in:
parent
47487535c5
commit
732685c99d
src/dlangui
|
@ -99,13 +99,6 @@ ubyte tokenCategory(ubyte t) {
|
|||
return t & 0xF0;
|
||||
}
|
||||
|
||||
class TextLineMark {
|
||||
}
|
||||
|
||||
class TextLineMarks {
|
||||
}
|
||||
|
||||
|
||||
/// split dstring by delimiters
|
||||
dstring[] splitDString(dstring source, dchar delimiter = EOL) {
|
||||
int start = 0;
|
||||
|
@ -545,6 +538,9 @@ class EditableContent {
|
|||
_readOnly = readOnly;
|
||||
}
|
||||
|
||||
protected LineIcons _lineIcons;
|
||||
@property ref LineIcons lineIcons() { return _lineIcons; }
|
||||
|
||||
protected int _tabSize = 4;
|
||||
protected bool _useSpacesForTabs = true;
|
||||
/// returns tab size (in number of spaces)
|
||||
|
@ -587,8 +583,6 @@ class EditableContent {
|
|||
|
||||
/// listeners for edit operations
|
||||
Signal!EditableContentListener contentChanged;
|
||||
/// contentChanged signal alias for backward compatibility; will be deprecated in future
|
||||
alias contentChangeListeners = contentChanged;
|
||||
|
||||
protected bool _multiline;
|
||||
/// returns true if miltyline content is supported
|
||||
|
@ -966,8 +960,8 @@ class EditableContent {
|
|||
// update highlight if necessary
|
||||
updateTokenProps(rangeAfter.start.line, rangeAfter.end.line + 1);
|
||||
// call listeners
|
||||
if (contentChangeListeners.assigned)
|
||||
contentChangeListeners(this, op, rangeBefore, rangeAfter, source);
|
||||
if (contentChanged.assigned)
|
||||
contentChanged(this, op, rangeBefore, rangeAfter, source);
|
||||
}
|
||||
|
||||
/// 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
|
||||
if (_content !is null) {
|
||||
// disconnect old content
|
||||
_content.contentChangeListeners.disconnect(this);
|
||||
_content.contentChanged.disconnect(this);
|
||||
if (_ownContent) {
|
||||
destroy(_content);
|
||||
}
|
||||
}
|
||||
_content = content;
|
||||
_ownContent = false;
|
||||
_content.contentChangeListeners.connect(this);
|
||||
_content.contentChanged.connect(this);
|
||||
if (_content.readOnly)
|
||||
enabled = false;
|
||||
return this;
|
||||
|
@ -1511,7 +1511,7 @@ class EditLine : EditWidgetBase {
|
|||
this(string ID, dstring initialContent = null) {
|
||||
super(ID, ScrollBarMode.Invisible, ScrollBarMode.Invisible);
|
||||
_content = new EditableContent(false);
|
||||
_content.contentChangeListeners = this;
|
||||
_content.contentChanged = this;
|
||||
wantTabs = false;
|
||||
styleId = STYLE_EDIT_LINE;
|
||||
text = initialContent;
|
||||
|
@ -1702,7 +1702,7 @@ class EditBox : EditWidgetBase {
|
|||
this(string ID, dstring initialContent = null, ScrollBarMode hscrollbarMode = ScrollBarMode.Visible, ScrollBarMode vscrollbarMode = ScrollBarMode.Visible) {
|
||||
super(ID, hscrollbarMode, vscrollbarMode);
|
||||
_content = new EditableContent(true); // multiline
|
||||
_content.contentChangeListeners = this;
|
||||
_content.contentChanged = this;
|
||||
styleId = STYLE_EDIT_BOX;
|
||||
text = initialContent;
|
||||
acceleratorMap.add( [
|
||||
|
|
Loading…
Reference in New Issue