mirror of https://github.com/buggins/dlangui.git
replace mode support in editors (toggled by INS)
This commit is contained in:
parent
f5bf1bb9ec
commit
37194b81b2
|
@ -557,6 +557,9 @@ enum EditorActions {
|
||||||
/// insert new line after current position (Ctrl+Enter)
|
/// insert new line after current position (Ctrl+Enter)
|
||||||
PrependNewLine,
|
PrependNewLine,
|
||||||
|
|
||||||
|
/// Turn On/Off replace mode
|
||||||
|
ToggleReplaceMode,
|
||||||
|
|
||||||
/// Copy selection to clipboard
|
/// Copy selection to clipboard
|
||||||
Copy,
|
Copy,
|
||||||
/// Cut selection to clipboard
|
/// Cut selection to clipboard
|
||||||
|
@ -590,8 +593,6 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
protected bool _useSpacesForTabs = false;
|
protected bool _useSpacesForTabs = false;
|
||||||
|
|
||||||
protected bool _replaceMode;
|
protected bool _replaceMode;
|
||||||
protected bool _readOnly;
|
|
||||||
|
|
||||||
|
|
||||||
this(string ID) {
|
this(string ID) {
|
||||||
super(ID);
|
super(ID);
|
||||||
|
@ -654,6 +655,9 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
|
|
||||||
new Action(EditorActions.Tab, KeyCode.TAB, 0),
|
new Action(EditorActions.Tab, KeyCode.TAB, 0),
|
||||||
new Action(EditorActions.BackTab, KeyCode.TAB, KeyFlag.Shift),
|
new Action(EditorActions.BackTab, KeyCode.TAB, KeyFlag.Shift),
|
||||||
|
|
||||||
|
new Action(EditorActions.ToggleReplaceMode, KeyCode.INS, 0),
|
||||||
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,16 +674,12 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
|
|
||||||
/// readonly flag (when true, user cannot change content of editor)
|
/// readonly flag (when true, user cannot change content of editor)
|
||||||
@property bool readOnly() {
|
@property bool readOnly() {
|
||||||
return _readOnly;
|
return !enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// sets readonly flag
|
/// sets readonly flag
|
||||||
@property EditWidgetBase readOnly(bool readOnly) {
|
@property EditWidgetBase readOnly(bool readOnly) {
|
||||||
_readOnly = readOnly;
|
enabled = !readOnly;
|
||||||
if (_readOnly)
|
|
||||||
resetState(State.Enabled);
|
|
||||||
else
|
|
||||||
setState(State.Enabled);
|
|
||||||
invalidate();
|
invalidate();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -768,6 +768,40 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
|
|
||||||
abstract protected Point measureVisibleText();
|
abstract protected Point measureVisibleText();
|
||||||
|
|
||||||
|
/// returns cursor rectangle
|
||||||
|
protected Rect caretRect() {
|
||||||
|
Rect caretRc = textPosToClient(_caretPos);
|
||||||
|
if (_replaceMode) {
|
||||||
|
dstring s = _content[_caretPos.line];
|
||||||
|
if (_caretPos.pos < s.length) {
|
||||||
|
TextPosition nextPos = _caretPos;
|
||||||
|
nextPos.pos++;
|
||||||
|
Rect nextRect = textPosToClient(nextPos);
|
||||||
|
caretRc.right = nextRect.right;
|
||||||
|
} else {
|
||||||
|
caretRc.right += _spaceWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
caretRc.offset(_clientRc.left, _clientRc.top);
|
||||||
|
return caretRc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// draws caret
|
||||||
|
protected void drawCaret(DrawBuf buf) {
|
||||||
|
if (focused) {
|
||||||
|
// draw caret
|
||||||
|
Rect caretRc = caretRect();
|
||||||
|
if (caretRc.intersects(_clientRc)) {
|
||||||
|
Rect rc1 = caretRc;
|
||||||
|
rc1.right = rc1.left + 1;
|
||||||
|
caretRc.left++;
|
||||||
|
if (_replaceMode)
|
||||||
|
buf.fillRect(caretRc, 0x808080FF);
|
||||||
|
buf.fillRect(rc1, 0x000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void updateFontProps() {
|
protected void updateFontProps() {
|
||||||
FontRef font = font();
|
FontRef font = font();
|
||||||
_fixedFont = font.isFixed;
|
_fixedFont = font.isFixed;
|
||||||
|
@ -933,7 +967,7 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case EditorActions.DelPrevChar:
|
case EditorActions.DelPrevChar:
|
||||||
if (_readOnly)
|
if (readOnly)
|
||||||
return true;
|
return true;
|
||||||
if (!_selectionRange.empty) {
|
if (!_selectionRange.empty) {
|
||||||
// clear selection
|
// clear selection
|
||||||
|
@ -960,7 +994,7 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case EditorActions.DelNextChar:
|
case EditorActions.DelNextChar:
|
||||||
if (_readOnly)
|
if (readOnly)
|
||||||
return true;
|
return true;
|
||||||
if (!_selectionRange.empty) {
|
if (!_selectionRange.empty) {
|
||||||
EditOperation op = new EditOperation(EditAction.Replace, _selectionRange, [""d]);
|
EditOperation op = new EditOperation(EditAction.Replace, _selectionRange, [""d]);
|
||||||
|
@ -993,7 +1027,7 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
if (!_selectionRange.empty) {
|
if (!_selectionRange.empty) {
|
||||||
dstring selectionText = concatDStrings(_content.rangeText(_selectionRange));
|
dstring selectionText = concatDStrings(_content.rangeText(_selectionRange));
|
||||||
platform.setClipboardText(selectionText);
|
platform.setClipboardText(selectionText);
|
||||||
if (_readOnly)
|
if (readOnly)
|
||||||
return true;
|
return true;
|
||||||
EditOperation op = new EditOperation(EditAction.Replace, _selectionRange, [""d]);
|
EditOperation op = new EditOperation(EditAction.Replace, _selectionRange, [""d]);
|
||||||
_content.performOperation(op);
|
_content.performOperation(op);
|
||||||
|
@ -1001,7 +1035,7 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
return true;
|
return true;
|
||||||
case EditorActions.Paste:
|
case EditorActions.Paste:
|
||||||
{
|
{
|
||||||
if (_readOnly)
|
if (readOnly)
|
||||||
return true;
|
return true;
|
||||||
dstring selectionText = platform.getClipboardText();
|
dstring selectionText = platform.getClipboardText();
|
||||||
dstring[] lines;
|
dstring[] lines;
|
||||||
|
@ -1016,21 +1050,21 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
return true;
|
return true;
|
||||||
case EditorActions.Undo:
|
case EditorActions.Undo:
|
||||||
{
|
{
|
||||||
if (_readOnly)
|
if (readOnly)
|
||||||
return true;
|
return true;
|
||||||
_content.undo();
|
_content.undo();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case EditorActions.Redo:
|
case EditorActions.Redo:
|
||||||
{
|
{
|
||||||
if (_readOnly)
|
if (readOnly)
|
||||||
return true;
|
return true;
|
||||||
_content.redo();
|
_content.redo();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case EditorActions.Tab:
|
case EditorActions.Tab:
|
||||||
{
|
{
|
||||||
if (_readOnly)
|
if (readOnly)
|
||||||
return true;
|
return true;
|
||||||
if (_selectionRange.empty) {
|
if (_selectionRange.empty) {
|
||||||
if (_useSpacesForTabs) {
|
if (_useSpacesForTabs) {
|
||||||
|
@ -1064,7 +1098,7 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
return true;
|
return true;
|
||||||
case EditorActions.BackTab:
|
case EditorActions.BackTab:
|
||||||
{
|
{
|
||||||
if (_readOnly)
|
if (readOnly)
|
||||||
return true;
|
return true;
|
||||||
if (_selectionRange.empty) {
|
if (_selectionRange.empty) {
|
||||||
// remove spaces before caret
|
// remove spaces before caret
|
||||||
|
@ -1098,6 +1132,9 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
case EditorActions.ToggleReplaceMode:
|
||||||
|
replaceMode = !replaceMode;
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1195,7 +1232,7 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
/// map key to action
|
/// map key to action
|
||||||
override protected Action findKeyAction(uint keyCode, uint flags) {
|
override protected Action findKeyAction(uint keyCode, uint flags) {
|
||||||
// don't handle tabs when disabled
|
// don't handle tabs when disabled
|
||||||
if (keyCode == KeyCode.TAB && (flags == 0 || flags == KeyFlag.Shift) && (!_wantTabs || _readOnly))
|
if (keyCode == KeyCode.TAB && (flags == 0 || flags == KeyFlag.Shift) && (!_wantTabs || readOnly))
|
||||||
return null;
|
return null;
|
||||||
return super.findKeyAction(keyCode, flags);
|
return super.findKeyAction(keyCode, flags);
|
||||||
}
|
}
|
||||||
|
@ -1204,12 +1241,20 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
override bool onKeyEvent(KeyEvent event) {
|
override bool onKeyEvent(KeyEvent event) {
|
||||||
if (event.action == KeyAction.Text && event.text.length) {
|
if (event.action == KeyAction.Text && event.text.length) {
|
||||||
Log.d("text entered: ", event.text);
|
Log.d("text entered: ", event.text);
|
||||||
if (_readOnly)
|
if (readOnly)
|
||||||
return true;
|
return true;
|
||||||
dchar ch = event.text[0];
|
dchar ch = event.text[0];
|
||||||
if (ch >= 32) { // ignore Backspace and Return
|
if (ch >= 32) { // ignore Backspace, Tab, Return, etc. chars
|
||||||
EditOperation op = new EditOperation(EditAction.Replace, _selectionRange, [event.text]);
|
if (replaceMode && _selectionRange.empty && _content[_caretPos.line].length >= _caretPos.pos + event.text.length) {
|
||||||
_content.performOperation(op);
|
// replace next char(s)
|
||||||
|
TextRange range = _selectionRange;
|
||||||
|
range.end.pos += cast(int)event.text.length;
|
||||||
|
EditOperation op = new EditOperation(EditAction.Replace, range, [event.text]);
|
||||||
|
_content.performOperation(op);
|
||||||
|
} else {
|
||||||
|
EditOperation op = new EditOperation(EditAction.Replace, _selectionRange, [event.text]);
|
||||||
|
_content.performOperation(op);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1411,12 +1456,8 @@ class EditLine : EditWidgetBase {
|
||||||
visibleRect.right = _clientRc.right;
|
visibleRect.right = _clientRc.right;
|
||||||
drawLineBackground(buf, lineRect, visibleRect);
|
drawLineBackground(buf, lineRect, visibleRect);
|
||||||
font.drawText(buf, rc.left - _scrollPos.x, rc.top, txt, textColor, tabSize);
|
font.drawText(buf, rc.left - _scrollPos.x, rc.top, txt, textColor, tabSize);
|
||||||
if (focused) {
|
|
||||||
// draw caret
|
drawCaret(buf);
|
||||||
Rect caretRc = textPosToClient(_caretPos);
|
|
||||||
caretRc.offset(_clientRc.left, _clientRc.top);
|
|
||||||
buf.fillRect(caretRc, 0x000000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1779,6 +1820,7 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// draw content
|
/// draw content
|
||||||
override void onDraw(DrawBuf buf) {
|
override void onDraw(DrawBuf buf) {
|
||||||
if (visibility != Visibility.Visible)
|
if (visibility != Visibility.Visible)
|
||||||
|
@ -1809,13 +1851,7 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//buf.fillRect(_clientRc, 0x80E0E0FF); // testing clientRc
|
drawCaret(buf);
|
||||||
if (focused) {
|
|
||||||
// draw caret
|
|
||||||
Rect caretRc = textPosToClient(_caretPos);
|
|
||||||
caretRc.offset(_clientRc.left, _clientRc.top);
|
|
||||||
buf.fillRect(caretRc, 0x000000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -640,7 +640,7 @@ Theme createDefaultTheme() {
|
||||||
res.fontFace = "Verdana";
|
res.fontFace = "Verdana";
|
||||||
}
|
}
|
||||||
//res.fontFace = "Arial Narrow";
|
//res.fontFace = "Arial Narrow";
|
||||||
res.fontSize = 13; // TODO: choose based on DPI
|
res.fontSize = 15; // TODO: choose based on DPI
|
||||||
Style button = res.createSubstyle("BUTTON").backgroundImageId("btn_default_small").alignment(Align.Center);
|
Style button = res.createSubstyle("BUTTON").backgroundImageId("btn_default_small").alignment(Align.Center);
|
||||||
res.createSubstyle("BUTTON_TRANSPARENT").backgroundImageId("btn_default_small_transparent").alignment(Align.Center);
|
res.createSubstyle("BUTTON_TRANSPARENT").backgroundImageId("btn_default_small_transparent").alignment(Align.Center);
|
||||||
res.createSubstyle("BUTTON_LABEL").layoutWidth(FILL_PARENT).alignment(Align.Left|Align.VCenter);
|
res.createSubstyle("BUTTON_LABEL").layoutWidth(FILL_PARENT).alignment(Align.Left|Align.VCenter);
|
||||||
|
|
Loading…
Reference in New Issue