mirror of https://github.com/buggins/dlangui.git
accelerator table; editline
This commit is contained in:
parent
31e7a1de19
commit
8e4897aa9b
|
@ -20,15 +20,22 @@ Authors: $(WEB coolreader.org, Vadim Lopatin)
|
|||
module dlangui.core.events;
|
||||
|
||||
import dlangui.core.i18n;
|
||||
import dlangui.core.collections;
|
||||
private import dlangui.widgets.widget;
|
||||
|
||||
import std.conv;
|
||||
|
||||
struct Accelerator {
|
||||
uint keyCode;
|
||||
uint keyFlags;
|
||||
}
|
||||
|
||||
/// UI action
|
||||
class Action {
|
||||
protected int _id;
|
||||
protected UIString _label;
|
||||
protected string _iconId;
|
||||
protected Accelerator[] _accelerators;
|
||||
this(int id, string labelResourceId, string iconResourceId = null) {
|
||||
_id = id;
|
||||
_label = labelResourceId;
|
||||
|
@ -39,6 +46,22 @@ class Action {
|
|||
_label = label;
|
||||
_iconId = iconResourceId;
|
||||
}
|
||||
/// action with accelerator, w/o label
|
||||
this(int id, uint keyCode, uint keyFlags = 0) {
|
||||
_id = id;
|
||||
_accelerators ~= Accelerator(keyCode, keyFlags);
|
||||
}
|
||||
/// returs array of accelerators
|
||||
@property Accelerator[] accelerators() {
|
||||
return _accelerators;
|
||||
}
|
||||
/// returns true if accelerator matches provided key code and flags
|
||||
bool checkAccelerator(uint keyCode, uint keyFlags) {
|
||||
foreach(a; _accelerators)
|
||||
if (a.keyCode == keyCode && a.keyFlags == keyFlags)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@property int id() const {
|
||||
return _id;
|
||||
}
|
||||
|
@ -69,6 +92,60 @@ class Action {
|
|||
}
|
||||
}
|
||||
|
||||
struct ActionMap {
|
||||
protected Action[Accelerator] _map;
|
||||
/// add from list
|
||||
void add(ActionList items) {
|
||||
foreach(a; items) {
|
||||
foreach(acc; a.accelerators)
|
||||
_map[acc] = a;
|
||||
}
|
||||
}
|
||||
/// add array of actions
|
||||
void add(Action[] items) {
|
||||
foreach(a; items) {
|
||||
foreach(acc; a.accelerators)
|
||||
_map[acc] = a;
|
||||
}
|
||||
}
|
||||
/// add action
|
||||
void add(Action a) {
|
||||
foreach(acc; a.accelerators)
|
||||
_map[acc] = a;
|
||||
}
|
||||
/// find action by key, return null if not found
|
||||
Action findByKey(uint keyCode, uint flags) {
|
||||
Accelerator acc;
|
||||
acc.keyCode = keyCode;
|
||||
acc.keyFlags = flags;
|
||||
if (acc in _map)
|
||||
return _map[acc];
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
struct ActionList {
|
||||
private Collection!Action _actions;
|
||||
alias _actions this;
|
||||
|
||||
void add(Action[] items) {
|
||||
foreach(a; items)
|
||||
_actions ~= a;
|
||||
}
|
||||
|
||||
void add(ref ActionList items) {
|
||||
foreach(a; items)
|
||||
_actions ~= a;
|
||||
}
|
||||
|
||||
/// find action by key, return null if not found
|
||||
Action findByKey(uint keyCode, uint flags) {
|
||||
foreach(a; _actions)
|
||||
if (a.checkAccelerator(keyCode, flags))
|
||||
return a;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
enum MouseAction : ubyte {
|
||||
Cancel, // button down handling is cancelled
|
||||
|
|
|
@ -123,6 +123,22 @@ class EditableContent {
|
|||
}
|
||||
}
|
||||
|
||||
enum EditorActions {
|
||||
None = 0,
|
||||
Left = 1000,
|
||||
Right,
|
||||
Up,
|
||||
Down,
|
||||
WordLeft,
|
||||
WordRight,
|
||||
PageUp,
|
||||
PageDown,
|
||||
LineBegin,
|
||||
LineEnd,
|
||||
DocumentBegin,
|
||||
DocumentEnd,
|
||||
}
|
||||
|
||||
/// single line editor
|
||||
class EditLine : Widget {
|
||||
protected EditableContent _content;
|
||||
|
@ -135,6 +151,18 @@ class EditLine : Widget {
|
|||
styleId = "EDIT_LINE";
|
||||
focusable = true;
|
||||
text = initialContent;
|
||||
acceleratorMap.add( [
|
||||
new Action(EditorActions.Up, KeyCode.UP, 0),
|
||||
new Action(EditorActions.Down, KeyCode.DOWN, 0),
|
||||
new Action(EditorActions.Left, KeyCode.LEFT, 0),
|
||||
new Action(EditorActions.Right, KeyCode.RIGHT, 0),
|
||||
new Action(EditorActions.WordLeft, KeyCode.LEFT, KeyFlag.Control),
|
||||
new Action(EditorActions.WordRight, KeyCode.RIGHT, KeyFlag.Control),
|
||||
new Action(EditorActions.LineBegin, KeyCode.HOME, 0),
|
||||
new Action(EditorActions.LineEnd, KeyCode.END, 0),
|
||||
new Action(EditorActions.DocumentBegin, KeyCode.HOME, KeyFlag.Control),
|
||||
new Action(EditorActions.DocumentEnd, KeyCode.END, KeyFlag.Control),
|
||||
]);
|
||||
}
|
||||
|
||||
/// get widget text
|
||||
|
@ -213,6 +241,64 @@ class EditLine : Widget {
|
|||
}
|
||||
}
|
||||
|
||||
override protected bool handleAction(Action a) {
|
||||
switch (a.id) {
|
||||
case EditorActions.Left:
|
||||
if (_caretPos.pos > 0) {
|
||||
_caretPos.pos--;
|
||||
invalidate();
|
||||
}
|
||||
return true;
|
||||
case EditorActions.Right:
|
||||
if (_caretPos.pos < _measuredText.length) {
|
||||
_caretPos.pos++;
|
||||
invalidate();
|
||||
}
|
||||
return true;
|
||||
case EditorActions.Up:
|
||||
break;
|
||||
case EditorActions.Down:
|
||||
break;
|
||||
case EditorActions.WordLeft:
|
||||
break;
|
||||
case EditorActions.WordRight:
|
||||
break;
|
||||
case EditorActions.PageUp:
|
||||
break;
|
||||
case EditorActions.PageDown:
|
||||
break;
|
||||
case EditorActions.DocumentBegin:
|
||||
case EditorActions.LineBegin:
|
||||
if (_caretPos.pos > 0) {
|
||||
_caretPos.pos = 0;
|
||||
invalidate();
|
||||
}
|
||||
return true;
|
||||
case EditorActions.DocumentEnd:
|
||||
case EditorActions.LineEnd:
|
||||
if (_caretPos.pos < _measuredText.length) {
|
||||
_caretPos.pos = _measuredText.length;
|
||||
invalidate();
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
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) {
|
||||
//
|
||||
//}
|
||||
}
|
||||
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, ")");
|
||||
|
|
|
@ -451,6 +451,17 @@ class Widget {
|
|||
// =======================================================
|
||||
// Events
|
||||
|
||||
protected ActionMap _acceleratorMap;
|
||||
@property ref ActionMap acceleratorMap() { return _acceleratorMap; }
|
||||
|
||||
/// override to handle specific actions
|
||||
protected bool handleAction(Action a) {
|
||||
if (parent) // by default, pass to parent widget
|
||||
return parent.handleAction(a);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// called to process click and notify listeners
|
||||
protected bool handleClick() {
|
||||
bool res = onClickListener(this);
|
||||
|
@ -459,6 +470,12 @@ class Widget {
|
|||
|
||||
/// process key event, return true if event is processed.
|
||||
bool onKeyEvent(KeyEvent event) {
|
||||
if (event.action == KeyAction.KeyDown) {
|
||||
Action action = _acceleratorMap.findByKey(event.keyCode, event.flags & (KeyFlag.Shift | KeyFlag.Alt | KeyFlag.Control));
|
||||
if (action !is null) {
|
||||
return handleAction(action);
|
||||
}
|
||||
}
|
||||
if (canClick) {
|
||||
// support onClick event initiated by Space or Return keys
|
||||
if (event.action == KeyAction.KeyDown) {
|
||||
|
|
Loading…
Reference in New Issue