From 083241ce3fc91a04f9a511f031331d7931ce8874 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Sun, 20 Apr 2014 08:34:21 +0400 Subject: [PATCH] can enter text into editline --- src/dlangui/core/signals.d | 4 ++ src/dlangui/platforms/windows/winapp.d | 9 +++- src/dlangui/widgets/editors.d | 68 ++++++++++++++++++++++++-- 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/dlangui/core/signals.d b/src/dlangui/core/signals.d index d9713d33..ec78ccb8 100644 --- a/src/dlangui/core/signals.d +++ b/src/dlangui/core/signals.d @@ -180,6 +180,10 @@ struct Signal(T1) if (is(T1 == interface) && __traits(allMembers, T1).length == if (listener !is null) _listeners ~= listener; } + /// replace all previously assigned listeners with new one (if null passed, remove all listeners) + final void opAssign(T1 listener) { + opAssign(&__traits(getMember, listener, __traits(allMembers, T1)[0])); + } /// call all listeners; for signals having non-void return type, stop iterating when first return value is nonzero static if (is (return_t == void)) { // call all listeners diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d index 903a916c..6b212437 100644 --- a/src/dlangui/platforms/windows/winapp.d +++ b/src/dlangui/platforms/windows/winapp.d @@ -748,7 +748,6 @@ LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) int repeatCount = lParam & 0xFFFF; if (window.onKey(message == WM_KEYDOWN ? KeyAction.KeyDown : KeyAction.KeyUp, wParam, repeatCount)) return 0; // processed - return 0; } break; case WM_UNICHAR: @@ -759,6 +758,14 @@ LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return 1; } break; + case WM_CHAR: + if (window !is null) { + int repeatCount = lParam & 0xFFFF; + if (window.onKey(KeyAction.Text, wParam, repeatCount, wParam == UNICODE_NOCHAR ? 0 : wParam)) + return 1; // processed + return 1; + } + break; case WM_GETMINMAXINFO: case WM_NCCREATE: case WM_NCCALCSIZE: diff --git a/src/dlangui/widgets/editors.d b/src/dlangui/widgets/editors.d index 127076fc..24f316c9 100644 --- a/src/dlangui/widgets/editors.d +++ b/src/dlangui/widgets/editors.d @@ -76,15 +76,38 @@ enum EditAction { /// edit operation details for EditableContent class EditOperation { /// action performed - EditAction action; + protected EditAction _action; + @property EditAction action() { return _action; } /// range - TextRange range; + protected TextRange _range; + @property ref TextRange range() { return _range; } /// new content for range (if required for this action) - dstring[] content; + protected dstring[] _content; + @property ref dstring[] content() { return _content; } + + this(EditAction action) { + _action = action; + } + this(EditAction action, TextPosition pos, dstring text) { + this(action, TextRange(pos, pos), text); + } + this(EditAction action, TextRange range, dstring text) { + _action = action; + _range = range; + _content.length = 1; + _content[0] = text; + } +} + +interface EditableContentListener { + bool onContentChange(EditableContent content, EditOperation operation, ref TextRange rangeBefore, ref TextRange rangeAfter); } /// editable plain text (multiline) class EditableContent { + /// listeners for edit operations + Signal!EditableContentListener contentChangeListeners; + this(bool multiline) { _multiline = multiline; _lines.length = 1; // initial state: single empty line @@ -121,6 +144,31 @@ class EditableContent { dstring line(int index) { return _lines[index]; } + + bool handleContentChange(EditOperation op, ref TextRange rangeBefore, ref TextRange rangeAfter) { + return contentChangeListeners(this, op, rangeBefore, rangeAfter); + } + + bool performOperation(EditOperation op) { + if (op.action == EditAction.Insert) { + // TODO: multiline + TextPosition pos = op.range.start; + TextRange rangeBefore = TextRange(pos, pos); + dchar[] buf; + dstring srcline = _lines[pos.line]; + dstring newline = op.content[0]; + buf ~= srcline[0 .. pos.pos]; + buf ~= newline; + buf ~= srcline[pos.pos .. $]; + _lines[pos.line] = cast(dstring)buf; + TextPosition newPos = pos; + newPos.pos += newline.length; + TextRange rangeAfter = TextRange(pos, newPos); + handleContentChange(op, rangeBefore, rangeAfter); + return true; + } + return false; + } } enum EditorActions { @@ -140,14 +188,21 @@ enum EditorActions { } /// single line editor -class EditLine : Widget { +class EditLine : Widget, EditableContentListener { protected EditableContent _content; 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) { super(ID); _content = new EditableContent(false); + _content.contentChangeListeners = this; styleId = "EDIT_LINE"; focusable = true; text = initialContent; @@ -295,6 +350,11 @@ class EditLine : Widget { //switch(event.keyCode) { // //} + } else if (event.action == KeyAction.Text && event.text.length) { + Log.d("text entered: ", event.text); + EditOperation op = new EditOperation(EditAction.Insert, _caretPos, event.text); + _content.performOperation(op); + return true; } return super.onKeyEvent(event); }