editors refactoring

This commit is contained in:
Vadim Lopatin 2014-04-21 09:20:43 +04:00
parent 4170634cf7
commit 91dc5a7e49
1 changed files with 151 additions and 117 deletions

View File

@ -202,25 +202,15 @@ enum EditorActions {
DelNextWord, // ctrl + del key DelNextWord, // ctrl + del key
} }
/// single line editor /// base for all editor widgets
class EditLine : Widget, EditableContentListener { class EditWidgetBase : WidgetGroup, EditableContentListener {
protected EditableContent _content; protected EditableContent _content;
protected Rect _clientRc; protected Rect _clientRc;
override bool onContentChange(EditableContent content, EditOperation operation, ref TextRange rangeBefore, ref TextRange rangeAfter) {
measureText();
_caretPos = rangeAfter.end;
invalidate();
return true;
}
this(string ID, dstring initialContent = null) { this(string ID) {
super(ID); super(ID);
_content = new EditableContent(false);
_content.contentChangeListeners = this;
styleId = "EDIT_LINE";
focusable = true; focusable = true;
text = initialContent;
acceleratorMap.add( [ acceleratorMap.add( [
new Action(EditorActions.Up, KeyCode.UP, 0), new Action(EditorActions.Up, KeyCode.UP, 0),
new Action(EditorActions.Down, KeyCode.DOWN, 0), new Action(EditorActions.Down, KeyCode.DOWN, 0),
@ -239,6 +229,8 @@ class EditLine : Widget, EditableContentListener {
]); ]);
} }
abstract override bool onContentChange(EditableContent content, EditOperation operation, ref TextRange rangeBefore, ref TextRange rangeAfter);
/// get widget text /// get widget text
override @property dstring text() { return _content.text; } override @property dstring text() { return _content.text; }
@ -256,14 +248,99 @@ class EditLine : Widget, EditableContentListener {
return this; return this;
} }
protected TextPosition _caretPos;
protected TextRange _selectionRange;
abstract protected Rect textPosToClient(TextPosition p);
abstract protected TextPosition clientToTextPos(Point pt);
protected void updateCaretPositionByMouse(int x, int y) {
TextPosition newPos = clientToTextPos(Point(x,y));
if (newPos != _caretPos) {
_caretPos = newPos;
invalidate();
}
}
override protected bool handleAction(Action a) {
// todo: place some common action handling here
return super.handleAction(a);
}
/// handle keys
override bool onKeyEvent(KeyEvent event) {
//
if (event.action == KeyAction.KeyDown) {
//EditorAction a = keyToAction(event.keyCode, event.flags & (KeyFlag.Shift | KeyFlag.Alt | KeyFlag.Ctrl));
//switch(event.keyCode) {
//
//}
} else if (event.action == KeyAction.Text && event.text.length) {
Log.d("text entered: ", event.text);
dchar ch = event.text[0];
if (ch != 8) { // ignore Backspace
EditOperation op = new EditOperation(EditAction.Insert, _caretPos, event.text);
_content.performOperation(op);
return true;
}
}
return super.onKeyEvent(event);
}
/// process mouse event; return true if event is processed by widget.
override bool onMouseEvent(MouseEvent event) {
//Log.d("onMouseEvent ", id, " ", event.action, " (", event.x, ",", event.y, ")");
// support onClick
if (event.action == MouseAction.ButtonDown && event.button == MouseButton.Left) {
setFocus();
updateCaretPositionByMouse(event.x - _clientRc.left, event.y - _clientRc.top);
invalidate();
return true;
}
if (event.action == MouseAction.Move && (event.flags & MouseButton.Left) != 0) {
updateCaretPositionByMouse(event.x - _clientRc.left, event.y - _clientRc.top);
return true;
}
if (event.action == MouseAction.ButtonUp && event.button == MouseButton.Left) {
return true;
}
if (event.action == MouseAction.FocusOut || event.action == MouseAction.Cancel) {
return true;
}
if (event.action == MouseAction.FocusIn) {
return true;
}
return false;
}
}
/// single line editor
class EditLine : EditWidgetBase {
this(string ID, dstring initialContent = null) {
super(ID);
_content = new EditableContent(false);
_content.contentChangeListeners = this;
styleId = "EDIT_LINE";
text = initialContent;
}
override bool onContentChange(EditableContent content, EditOperation operation, ref TextRange rangeBefore, ref TextRange rangeAfter) {
measureText();
_caretPos = rangeAfter.end;
invalidate();
return true;
}
protected dstring _measuredText; protected dstring _measuredText;
protected int[] _measuredTextWidths; protected int[] _measuredTextWidths;
protected Point _measuredTextSize; protected Point _measuredTextSize;
protected TextPosition _caretPos; override protected Rect textPosToClient(TextPosition p) {
protected TextRange _selectionRange;
protected Rect textPosToClient(TextPosition p) {
Rect res; Rect res;
res.bottom = _clientRc.height; res.bottom = _clientRc.height;
if (p.pos == 0) if (p.pos == 0)
@ -276,7 +353,7 @@ class EditLine : Widget, EditableContentListener {
return res; return res;
} }
protected TextPosition clientToTextPos(Point pt) { override protected TextPosition clientToTextPos(Point pt) {
TextPosition res; TextPosition res;
for (int i = 0; i < _measuredText.length; i++) { for (int i = 0; i < _measuredText.length; i++) {
int x0 = i > 0 ? _measuredTextWidths[i - 1] : 0; int x0 = i > 0 ? _measuredTextWidths[i - 1] : 0;
@ -307,14 +384,6 @@ class EditLine : Widget, EditableContentListener {
measuredContent(parentWidth, parentHeight, _measuredTextSize.x, _measuredTextSize.y); measuredContent(parentWidth, parentHeight, _measuredTextSize.x, _measuredTextSize.y);
} }
protected void updateCaretPositionByMouse(int x, int y) {
TextPosition newPos = clientToTextPos(Point(x,y));
if (newPos != _caretPos) {
_caretPos = newPos;
invalidate();
}
}
override protected bool handleAction(Action a) { override protected bool handleAction(Action a) {
switch (a.id) { switch (a.id) {
case EditorActions.Left: case EditorActions.Left:
@ -377,50 +446,15 @@ class EditLine : Widget, EditableContentListener {
return super.handleAction(a); return super.handleAction(a);
} }
/// handle keys /// handle keys
override bool onKeyEvent(KeyEvent event) { override bool onKeyEvent(KeyEvent event) {
//
if (event.action == KeyAction.KeyDown) {
//EditorAction a = keyToAction(event.keyCode, event.flags & (KeyFlag.Shift | KeyFlag.Alt | KeyFlag.Ctrl));
//switch(event.keyCode) {
//
//}
} else if (event.action == KeyAction.Text && event.text.length) {
Log.d("text entered: ", event.text);
dchar ch = event.text[0];
if (ch != 8) { // ignore Backspace
EditOperation op = new EditOperation(EditAction.Insert, _caretPos, event.text);
_content.performOperation(op);
return true;
}
}
return super.onKeyEvent(event); return super.onKeyEvent(event);
} }
/// process mouse event; return true if event is processed by widget. /// process mouse event; return true if event is processed by widget.
override bool onMouseEvent(MouseEvent event) { override bool onMouseEvent(MouseEvent event) {
//Log.d("onMouseEvent ", id, " ", event.action, " (", event.x, ",", event.y, ")"); return super.onMouseEvent(event);
// support onClick
if (event.action == MouseAction.ButtonDown && event.button == MouseButton.Left) {
setFocus();
updateCaretPositionByMouse(event.x - _clientRc.left, event.y - _clientRc.top);
invalidate();
return true;
}
if (event.action == MouseAction.Move && (event.flags & MouseButton.Left) != 0) {
updateCaretPositionByMouse(event.x - _clientRc.left, event.y - _clientRc.top);
return true;
}
if (event.action == MouseAction.ButtonUp && event.button == MouseButton.Left) {
return true;
}
if (event.action == MouseAction.FocusOut || event.action == MouseAction.Cancel) {
return true;
}
if (event.action == MouseAction.FocusIn) {
return true;
}
return false;
} }
/// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout). /// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout).