mirror of https://github.com/buggins/dlangui.git
EditBox: scrolling using mouse wheel and scrollbars; font zooming using ctrl + mouse wheel
This commit is contained in:
parent
354095fa8f
commit
7862f897f9
|
@ -186,12 +186,14 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
text ~= " The quick brown fox jumps over the lazy dog.";
|
text ~= " The quick brown fox jumps over the lazy dog.";
|
||||||
}
|
}
|
||||||
editBox.text = text;
|
editBox.text = text;
|
||||||
|
editBox.minFontSize(12).maxFontSize(75);
|
||||||
editors.addChild(createEditorSettingsControl(editBox));
|
editors.addChild(createEditorSettingsControl(editBox));
|
||||||
editors.addChild(editBox);
|
editors.addChild(editBox);
|
||||||
|
|
||||||
editors.addChild(new TextWidget(null, "EditBox: additional view for the same content (split view testing)"d));
|
editors.addChild(new TextWidget(null, "EditBox: additional view for the same content (split view testing)"d));
|
||||||
EditBox editBox2 = new EditBox("editbox2", ""d);
|
EditBox editBox2 = new EditBox("editbox2", ""d);
|
||||||
editBox2.content = editBox.content; // view the same content as first editbox
|
editBox2.content = editBox.content; // view the same content as first editbox
|
||||||
|
editBox2.minFontSize(12).maxFontSize(75);
|
||||||
editors.addChild(editBox2);
|
editors.addChild(editBox2);
|
||||||
editors.layoutHeight(FILL_PARENT).layoutWidth(FILL_PARENT);
|
editors.layoutHeight(FILL_PARENT).layoutWidth(FILL_PARENT);
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,9 @@ class Action {
|
||||||
protected UIString _label;
|
protected UIString _label;
|
||||||
protected string _iconId;
|
protected string _iconId;
|
||||||
protected Accelerator[] _accelerators;
|
protected Accelerator[] _accelerators;
|
||||||
|
this(int id) {
|
||||||
|
_id = id;
|
||||||
|
}
|
||||||
this(int id, string labelResourceId, string iconResourceId = null) {
|
this(int id, string labelResourceId, string iconResourceId = null) {
|
||||||
_id = id;
|
_id = id;
|
||||||
_label = labelResourceId;
|
_label = labelResourceId;
|
||||||
|
|
|
@ -274,6 +274,16 @@ class EditableContent {
|
||||||
|
|
||||||
protected UndoBuffer _undoBuffer;
|
protected UndoBuffer _undoBuffer;
|
||||||
|
|
||||||
|
protected bool _readOnly;
|
||||||
|
|
||||||
|
@property bool readOnly() {
|
||||||
|
return _readOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property void readOnly(bool readOnly) {
|
||||||
|
_readOnly = readOnly;
|
||||||
|
}
|
||||||
|
|
||||||
/// listeners for edit operations
|
/// listeners for edit operations
|
||||||
Signal!EditableContentListener contentChangeListeners;
|
Signal!EditableContentListener contentChangeListeners;
|
||||||
|
|
||||||
|
@ -417,7 +427,10 @@ class EditableContent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// edit content
|
||||||
bool performOperation(EditOperation op, Object source) {
|
bool performOperation(EditOperation op, Object source) {
|
||||||
|
if (_readOnly)
|
||||||
|
throw new Exception("content is readonly");
|
||||||
if (op.action == EditAction.Replace) {
|
if (op.action == EditAction.Replace) {
|
||||||
TextRange rangeBefore = op.range;
|
TextRange rangeBefore = op.range;
|
||||||
dstring[] oldcontent = rangeText(rangeBefore);
|
dstring[] oldcontent = rangeText(rangeBefore);
|
||||||
|
@ -456,6 +469,8 @@ class EditableContent {
|
||||||
bool undo() {
|
bool undo() {
|
||||||
if (!hasUndo)
|
if (!hasUndo)
|
||||||
return false;
|
return false;
|
||||||
|
if (_readOnly)
|
||||||
|
throw new Exception("content is readonly");
|
||||||
EditOperation op = _undoBuffer.undo();
|
EditOperation op = _undoBuffer.undo();
|
||||||
TextRange rangeBefore = op.newRange;
|
TextRange rangeBefore = op.newRange;
|
||||||
dstring[] oldcontent = op.content;
|
dstring[] oldcontent = op.content;
|
||||||
|
@ -470,6 +485,8 @@ class EditableContent {
|
||||||
bool redo() {
|
bool redo() {
|
||||||
if (!hasUndo)
|
if (!hasUndo)
|
||||||
return false;
|
return false;
|
||||||
|
if (_readOnly)
|
||||||
|
throw new Exception("content is readonly");
|
||||||
EditOperation op = _undoBuffer.redo();
|
EditOperation op = _undoBuffer.redo();
|
||||||
TextRange rangeBefore = op.range;
|
TextRange rangeBefore = op.range;
|
||||||
dstring[] oldcontent = op.oldContent;
|
dstring[] oldcontent = op.oldContent;
|
||||||
|
@ -580,6 +597,27 @@ enum EditorActions {
|
||||||
|
|
||||||
/// Select whole content (usually, Ctrl+A)
|
/// Select whole content (usually, Ctrl+A)
|
||||||
SelectAll,
|
SelectAll,
|
||||||
|
|
||||||
|
// Scroll operations
|
||||||
|
|
||||||
|
/// Scroll one line up (not changing cursor)
|
||||||
|
ScrollLineUp,
|
||||||
|
/// Scroll one line down (not changing cursor)
|
||||||
|
ScrollLineDown,
|
||||||
|
/// Scroll one page up (not changing cursor)
|
||||||
|
ScrollPageUp,
|
||||||
|
/// Scroll one page down (not changing cursor)
|
||||||
|
ScrollPageDown,
|
||||||
|
/// Scroll window left
|
||||||
|
ScrollLeft,
|
||||||
|
/// Scroll window right
|
||||||
|
ScrollRight,
|
||||||
|
|
||||||
|
/// Zoom in editor font
|
||||||
|
ZoomIn,
|
||||||
|
/// Zoom out editor font
|
||||||
|
ZoomOut,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// base for all editor widgets
|
/// base for all editor widgets
|
||||||
|
@ -593,6 +631,9 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
protected int _spaceWidth;
|
protected int _spaceWidth;
|
||||||
protected int _tabSize = 4;
|
protected int _tabSize = 4;
|
||||||
|
|
||||||
|
protected int _minFontSize = -1; // disable zooming
|
||||||
|
protected int _maxFontSize = -1; // disable zooming
|
||||||
|
|
||||||
protected bool _wantTabs = true;
|
protected bool _wantTabs = true;
|
||||||
protected bool _useSpacesForTabs = false;
|
protected bool _useSpacesForTabs = false;
|
||||||
|
|
||||||
|
@ -684,7 +725,7 @@ 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 !enabled;
|
return !enabled || _content.readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// sets readonly flag
|
/// sets readonly flag
|
||||||
|
@ -756,6 +797,8 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
_content = content;
|
_content = content;
|
||||||
_ownContent = false;
|
_ownContent = false;
|
||||||
_content.contentChangeListeners.connect(this);
|
_content.contentChangeListeners.connect(this);
|
||||||
|
if (_content.readOnly)
|
||||||
|
enabled = false;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1348,6 +1391,22 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
||||||
if (event.action == MouseAction.FocusIn) {
|
if (event.action == MouseAction.FocusIn) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (event.action == MouseAction.Wheel) {
|
||||||
|
uint keyFlags = event.flags & (MouseFlag.Shift | MouseFlag.Control | MouseFlag.Alt);
|
||||||
|
if (event.wheelDelta < 0) {
|
||||||
|
if (keyFlags == MouseFlag.Shift)
|
||||||
|
return handleAction(new Action(EditorActions.ScrollRight));
|
||||||
|
if (keyFlags == MouseFlag.Control)
|
||||||
|
return handleAction(new Action(EditorActions.ZoomOut));
|
||||||
|
return handleAction(new Action(EditorActions.ScrollLineDown));
|
||||||
|
} else if (event.wheelDelta > 0) {
|
||||||
|
if (keyFlags == MouseFlag.Shift)
|
||||||
|
return handleAction(new Action(EditorActions.ScrollLeft));
|
||||||
|
if (keyFlags == MouseFlag.Control)
|
||||||
|
return handleAction(new Action(EditorActions.ZoomIn));
|
||||||
|
return handleAction(new Action(EditorActions.ScrollLineUp));
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1568,6 +1627,21 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
||||||
_maxLineWidth = maxw;
|
_maxLineWidth = maxw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property int minFontSize() {
|
||||||
|
return _minFontSize;
|
||||||
|
}
|
||||||
|
@property EditBox minFontSize(int size) {
|
||||||
|
_minFontSize = size;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
@property int maxFontSize() {
|
||||||
|
return _maxFontSize;
|
||||||
|
}
|
||||||
|
@property EditBox maxFontSize(int size) {
|
||||||
|
_maxFontSize = size;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
override protected Point measureVisibleText() {
|
override protected Point measureVisibleText() {
|
||||||
Point sz;
|
Point sz;
|
||||||
FontRef font = font();
|
FontRef font = font();
|
||||||
|
@ -1606,16 +1680,36 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
||||||
/// handle scroll event
|
/// handle scroll event
|
||||||
override bool onScrollEvent(AbstractSlider source, ScrollEvent event) {
|
override bool onScrollEvent(AbstractSlider source, ScrollEvent event) {
|
||||||
if (source.id.equal("hscrollbar")) {
|
if (source.id.equal("hscrollbar")) {
|
||||||
if (_scrollPos.x != event.position) {
|
if (event.action == ScrollAction.SliderMoved || event.action == ScrollAction.SliderReleased) {
|
||||||
_scrollPos.x = event.position;
|
if (_scrollPos.x != event.position) {
|
||||||
invalidate();
|
_scrollPos.x = event.position;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
} else if (event.action == ScrollAction.PageUp) {
|
||||||
|
handleAction(new Action(EditorActions.ScrollLeft));
|
||||||
|
} else if (event.action == ScrollAction.PageDown) {
|
||||||
|
handleAction(new Action(EditorActions.ScrollRight));
|
||||||
|
} else if (event.action == ScrollAction.LineUp) {
|
||||||
|
handleAction(new Action(EditorActions.ScrollLeft));
|
||||||
|
} else if (event.action == ScrollAction.LineDown) {
|
||||||
|
handleAction(new Action(EditorActions.ScrollRight));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (source.id.equal("vscrollbar")) {
|
} else if (source.id.equal("vscrollbar")) {
|
||||||
if (_firstVisibleLine != event.position) {
|
if (event.action == ScrollAction.SliderMoved || event.action == ScrollAction.SliderReleased) {
|
||||||
_firstVisibleLine = event.position;
|
if (_firstVisibleLine != event.position) {
|
||||||
measureVisibleText();
|
_firstVisibleLine = event.position;
|
||||||
invalidate();
|
measureVisibleText();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
} else if (event.action == ScrollAction.PageUp) {
|
||||||
|
handleAction(new Action(EditorActions.ScrollPageUp));
|
||||||
|
} else if (event.action == ScrollAction.PageDown) {
|
||||||
|
handleAction(new Action(EditorActions.ScrollPageDown));
|
||||||
|
} else if (event.action == ScrollAction.LineUp) {
|
||||||
|
handleAction(new Action(EditorActions.ScrollLineUp));
|
||||||
|
} else if (event.action == ScrollAction.LineDown) {
|
||||||
|
handleAction(new Action(EditorActions.ScrollLineDown));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1803,6 +1897,115 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EditorActions.ScrollLeft:
|
||||||
|
{
|
||||||
|
if (_scrollPos.x > 0) {
|
||||||
|
int newpos = _scrollPos.x - _spaceWidth * 4;
|
||||||
|
if (newpos < 0)
|
||||||
|
newpos = 0;
|
||||||
|
_scrollPos.x = newpos;
|
||||||
|
updateScrollbars();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case EditorActions.ScrollRight:
|
||||||
|
{
|
||||||
|
if (_scrollPos.x < _maxLineWidth - _clientRc.width) {
|
||||||
|
int newpos = _scrollPos.x + _spaceWidth * 4;
|
||||||
|
if (newpos > _maxLineWidth - _clientRc.width)
|
||||||
|
newpos = _maxLineWidth - _clientRc.width;
|
||||||
|
_scrollPos.x = newpos;
|
||||||
|
updateScrollbars();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case EditorActions.ScrollLineUp:
|
||||||
|
{
|
||||||
|
if (_firstVisibleLine > 0) {
|
||||||
|
_firstVisibleLine -= 3;
|
||||||
|
if (_firstVisibleLine < 0)
|
||||||
|
_firstVisibleLine = 0;
|
||||||
|
measureVisibleText();
|
||||||
|
updateScrollbars();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case EditorActions.ScrollPageUp:
|
||||||
|
{
|
||||||
|
int fullLines = _clientRc.height / _lineHeight;
|
||||||
|
if (_firstVisibleLine > 0) {
|
||||||
|
_firstVisibleLine -= fullLines * 3 / 4;
|
||||||
|
if (_firstVisibleLine < 0)
|
||||||
|
_firstVisibleLine = 0;
|
||||||
|
measureVisibleText();
|
||||||
|
updateScrollbars();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case EditorActions.ScrollLineDown:
|
||||||
|
{
|
||||||
|
int fullLines = _clientRc.height / _lineHeight;
|
||||||
|
if (_firstVisibleLine + fullLines < _content.length) {
|
||||||
|
_firstVisibleLine += 3;
|
||||||
|
if (_firstVisibleLine > _content.length - fullLines)
|
||||||
|
_firstVisibleLine = _content.length - fullLines;
|
||||||
|
if (_firstVisibleLine < 0)
|
||||||
|
_firstVisibleLine = 0;
|
||||||
|
measureVisibleText();
|
||||||
|
updateScrollbars();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case EditorActions.ScrollPageDown:
|
||||||
|
{
|
||||||
|
int fullLines = _clientRc.height / _lineHeight;
|
||||||
|
if (_firstVisibleLine + fullLines < _content.length) {
|
||||||
|
_firstVisibleLine += fullLines * 3 / 4;
|
||||||
|
if (_firstVisibleLine > _content.length - fullLines)
|
||||||
|
_firstVisibleLine = _content.length - fullLines;
|
||||||
|
if (_firstVisibleLine < 0)
|
||||||
|
_firstVisibleLine = 0;
|
||||||
|
measureVisibleText();
|
||||||
|
updateScrollbars();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case EditorActions.ZoomIn:
|
||||||
|
{
|
||||||
|
if (_minFontSize < _maxFontSize && _minFontSize > 10 && _maxFontSize > 10) {
|
||||||
|
int currentFontSize = fontSize;
|
||||||
|
int newFontSize = currentFontSize * 110 / 100;
|
||||||
|
if (currentFontSize != newFontSize && newFontSize <= _maxFontSize) {
|
||||||
|
fontSize = cast(ushort)newFontSize;
|
||||||
|
updateFontProps();
|
||||||
|
measureVisibleText();
|
||||||
|
updateScrollbars();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case EditorActions.ZoomOut:
|
||||||
|
{
|
||||||
|
if (_minFontSize < _maxFontSize && _minFontSize > 10 && _maxFontSize > 10) {
|
||||||
|
int currentFontSize = fontSize;
|
||||||
|
int newFontSize = currentFontSize * 100 / 110;
|
||||||
|
if (currentFontSize != newFontSize && newFontSize >= _minFontSize) {
|
||||||
|
fontSize = cast(ushort)newFontSize;
|
||||||
|
updateFontProps();
|
||||||
|
measureVisibleText();
|
||||||
|
updateScrollbars();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue