mirror of https://github.com/buggins/dlangui.git
clipboard support in editors, part 1
This commit is contained in:
parent
99e4e4e732
commit
4348b859c7
|
@ -484,6 +484,11 @@ class Platform {
|
|||
abstract void setClipboardText(dstring text, bool mouseBuffer = false);
|
||||
}
|
||||
|
||||
/// get current platform object instance
|
||||
@property Platform platform() {
|
||||
return Platform.instance;
|
||||
}
|
||||
|
||||
version (USE_OPENGL) {
|
||||
private __gshared bool _OPENGL_ENABLED = false;
|
||||
/// check if hardware acceleration is enabled
|
||||
|
|
|
@ -563,7 +563,7 @@ class Win32Platform : Platform {
|
|||
override void setClipboardText(dstring text, bool mouseBuffer = false) {
|
||||
if (text.length < 1 || mouseBuffer)
|
||||
return;
|
||||
if (!OpenClipboard(NULL))
|
||||
if (!OpenClipboard(NULL))
|
||||
return;
|
||||
EmptyClipboard();
|
||||
wstring w = toUTF16(text);
|
||||
|
|
|
@ -23,6 +23,7 @@ module dlangui.widgets.editors;
|
|||
import dlangui.widgets.widget;
|
||||
import dlangui.widgets.controls;
|
||||
import dlangui.core.signals;
|
||||
import dlangui.platforms.common.platform;
|
||||
|
||||
import std.algorithm;
|
||||
|
||||
|
@ -32,10 +33,15 @@ immutable dchar EOL = '\n';
|
|||
dstring[] splitDString(dstring source, dchar delimiter = EOL) {
|
||||
int start = 0;
|
||||
dstring[] res;
|
||||
dchar lastchar;
|
||||
for (int i = 0; i <= source.length; i++) {
|
||||
if (i == source.length || source[i] == delimiter) {
|
||||
if (i >= start) {
|
||||
dstring line = i > start ? cast(dstring)(source[start .. i].dup) : ""d;
|
||||
dchar prevchar = i > 1 && i > start + 1 ? source[i - 1] : 0;
|
||||
int end = i;
|
||||
if (delimiter == EOL && prevchar == '\r') // windows CR/LF
|
||||
end--;
|
||||
dstring line = i > start ? cast(dstring)(source[start .. end].dup) : ""d;
|
||||
res ~= line;
|
||||
}
|
||||
start = i + 1;
|
||||
|
@ -44,6 +50,41 @@ dstring[] splitDString(dstring source, dchar delimiter = EOL) {
|
|||
return res;
|
||||
}
|
||||
|
||||
version (Windows) {
|
||||
immutable dstring SYSTEM_DEFAULT_EOL = "\r\n";
|
||||
} else {
|
||||
immutable dstring SYSTEM_DEFAULT_EOL = "\n";
|
||||
}
|
||||
|
||||
/// concat strings from array using delimiter
|
||||
dstring concatDStrings(dstring[] lines, dstring delimiter = SYSTEM_DEFAULT_EOL) {
|
||||
dchar[] buf;
|
||||
foreach(line; lines) {
|
||||
if (buf.length)
|
||||
buf ~= delimiter;
|
||||
buf ~= line;
|
||||
}
|
||||
return cast(dstring)buf;
|
||||
}
|
||||
|
||||
/// replace end of lines with spaces
|
||||
dstring replaceEolsWithSpaces(dstring source) {
|
||||
dchar[] buf;
|
||||
dchar lastch;
|
||||
foreach(ch; source) {
|
||||
if (ch == '\r') {
|
||||
buf ~= ' ';
|
||||
} else if (ch == '\n') {
|
||||
if (lastch != '\r')
|
||||
buf ~= ' ';
|
||||
} else {
|
||||
buf ~= ch;
|
||||
}
|
||||
lastch = ch;
|
||||
}
|
||||
return cast(dstring)buf;
|
||||
}
|
||||
|
||||
/// text content position
|
||||
struct TextPosition {
|
||||
/// line number, zero based
|
||||
|
@ -137,6 +178,9 @@ class EditableContent {
|
|||
_lines.length = 1; // initial state: single empty line
|
||||
}
|
||||
protected bool _multiline;
|
||||
/// returns true if miltyline content is supported
|
||||
@property bool multiline() { return _multiline; }
|
||||
|
||||
protected dstring[] _lines;
|
||||
/// returns all lines concatenated delimited by '\n'
|
||||
@property dstring text() {
|
||||
|
@ -358,6 +402,12 @@ enum EditorActions {
|
|||
DelNextWord,
|
||||
/// insert new line (Enter)
|
||||
InsertNewLine,
|
||||
/// Copy selection to clipboard
|
||||
Copy,
|
||||
/// Cut selection to clipboard
|
||||
Cut,
|
||||
/// Paste selection from clipboard
|
||||
Paste,
|
||||
}
|
||||
|
||||
/// base for all editor widgets
|
||||
|
@ -410,6 +460,14 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
|||
new Action(EditorActions.DelNextChar, KeyCode.DEL, 0),
|
||||
new Action(EditorActions.DelPrevWord, KeyCode.BACK, KeyFlag.Control),
|
||||
new Action(EditorActions.DelNextWord, KeyCode.DEL, KeyFlag.Control),
|
||||
|
||||
new Action(EditorActions.Copy, KeyCode.KEY_C, KeyFlag.Control),
|
||||
new Action(EditorActions.Copy, KeyCode.INS, KeyFlag.Control),
|
||||
new Action(EditorActions.Cut, KeyCode.KEY_X, KeyFlag.Control),
|
||||
new Action(EditorActions.Cut, KeyCode.DEL, KeyFlag.Shift),
|
||||
new Action(EditorActions.Paste, KeyCode.KEY_V, KeyFlag.Control),
|
||||
new Action(EditorActions.Paste, KeyCode.INS, KeyFlag.Shift),
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -657,6 +715,33 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
|||
EditOperation op = new EditOperation(EditAction.Replace, range, [""d]);
|
||||
_content.performOperation(op);
|
||||
}
|
||||
return true;
|
||||
case EditorActions.Copy:
|
||||
if (!_selectionRange.empty) {
|
||||
dstring selectionText = concatDStrings(_content.rangeText(_selectionRange));
|
||||
platform.setClipboardText(selectionText);
|
||||
}
|
||||
return true;
|
||||
case EditorActions.Cut:
|
||||
if (!_selectionRange.empty) {
|
||||
dstring selectionText = concatDStrings(_content.rangeText(_selectionRange));
|
||||
platform.setClipboardText(selectionText);
|
||||
EditOperation op = new EditOperation(EditAction.Replace, _selectionRange, [""d]);
|
||||
_content.performOperation(op);
|
||||
}
|
||||
return true;
|
||||
case EditorActions.Paste:
|
||||
{
|
||||
dstring selectionText = platform.getClipboardText();
|
||||
dstring[] lines;
|
||||
if (_content.multiline) {
|
||||
lines = splitDString(selectionText);
|
||||
} else {
|
||||
lines = [replaceEolsWithSpaces(selectionText)];
|
||||
}
|
||||
EditOperation op = new EditOperation(EditAction.Replace, _selectionRange, lines);
|
||||
_content.performOperation(op);
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue