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.";
|
||||
}
|
||||
editBox.text = text;
|
||||
editBox.minFontSize(12).maxFontSize(75);
|
||||
editors.addChild(createEditorSettingsControl(editBox));
|
||||
editors.addChild(editBox);
|
||||
|
||||
editors.addChild(new TextWidget(null, "EditBox: additional view for the same content (split view testing)"d));
|
||||
EditBox editBox2 = new EditBox("editbox2", ""d);
|
||||
editBox2.content = editBox.content; // view the same content as first editbox
|
||||
editBox2.minFontSize(12).maxFontSize(75);
|
||||
editors.addChild(editBox2);
|
||||
editors.layoutHeight(FILL_PARENT).layoutWidth(FILL_PARENT);
|
||||
|
||||
|
|
|
@ -36,6 +36,9 @@ class Action {
|
|||
protected UIString _label;
|
||||
protected string _iconId;
|
||||
protected Accelerator[] _accelerators;
|
||||
this(int id) {
|
||||
_id = id;
|
||||
}
|
||||
this(int id, string labelResourceId, string iconResourceId = null) {
|
||||
_id = id;
|
||||
_label = labelResourceId;
|
||||
|
|
|
@ -274,6 +274,16 @@ class EditableContent {
|
|||
|
||||
protected UndoBuffer _undoBuffer;
|
||||
|
||||
protected bool _readOnly;
|
||||
|
||||
@property bool readOnly() {
|
||||
return _readOnly;
|
||||
}
|
||||
|
||||
@property void readOnly(bool readOnly) {
|
||||
_readOnly = readOnly;
|
||||
}
|
||||
|
||||
/// listeners for edit operations
|
||||
Signal!EditableContentListener contentChangeListeners;
|
||||
|
||||
|
@ -417,7 +427,10 @@ class EditableContent {
|
|||
}
|
||||
}
|
||||
|
||||
/// edit content
|
||||
bool performOperation(EditOperation op, Object source) {
|
||||
if (_readOnly)
|
||||
throw new Exception("content is readonly");
|
||||
if (op.action == EditAction.Replace) {
|
||||
TextRange rangeBefore = op.range;
|
||||
dstring[] oldcontent = rangeText(rangeBefore);
|
||||
|
@ -456,6 +469,8 @@ class EditableContent {
|
|||
bool undo() {
|
||||
if (!hasUndo)
|
||||
return false;
|
||||
if (_readOnly)
|
||||
throw new Exception("content is readonly");
|
||||
EditOperation op = _undoBuffer.undo();
|
||||
TextRange rangeBefore = op.newRange;
|
||||
dstring[] oldcontent = op.content;
|
||||
|
@ -470,6 +485,8 @@ class EditableContent {
|
|||
bool redo() {
|
||||
if (!hasUndo)
|
||||
return false;
|
||||
if (_readOnly)
|
||||
throw new Exception("content is readonly");
|
||||
EditOperation op = _undoBuffer.redo();
|
||||
TextRange rangeBefore = op.range;
|
||||
dstring[] oldcontent = op.oldContent;
|
||||
|
@ -580,6 +597,27 @@ enum EditorActions {
|
|||
|
||||
/// Select whole content (usually, Ctrl+A)
|
||||
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
|
||||
|
@ -593,6 +631,9 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
|||
protected int _spaceWidth;
|
||||
protected int _tabSize = 4;
|
||||
|
||||
protected int _minFontSize = -1; // disable zooming
|
||||
protected int _maxFontSize = -1; // disable zooming
|
||||
|
||||
protected bool _wantTabs = true;
|
||||
protected bool _useSpacesForTabs = false;
|
||||
|
||||
|
@ -684,7 +725,7 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
|||
|
||||
/// readonly flag (when true, user cannot change content of editor)
|
||||
@property bool readOnly() {
|
||||
return !enabled;
|
||||
return !enabled || _content.readOnly;
|
||||
}
|
||||
|
||||
/// sets readonly flag
|
||||
|
@ -756,6 +797,8 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
|||
_content = content;
|
||||
_ownContent = false;
|
||||
_content.contentChangeListeners.connect(this);
|
||||
if (_content.readOnly)
|
||||
enabled = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1348,6 +1391,22 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
|||
if (event.action == MouseAction.FocusIn) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1568,6 +1627,21 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
|||
_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() {
|
||||
Point sz;
|
||||
FontRef font = font();
|
||||
|
@ -1606,16 +1680,36 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
|||
/// handle scroll event
|
||||
override bool onScrollEvent(AbstractSlider source, ScrollEvent event) {
|
||||
if (source.id.equal("hscrollbar")) {
|
||||
if (_scrollPos.x != event.position) {
|
||||
_scrollPos.x = event.position;
|
||||
invalidate();
|
||||
if (event.action == ScrollAction.SliderMoved || event.action == ScrollAction.SliderReleased) {
|
||||
if (_scrollPos.x != event.position) {
|
||||
_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;
|
||||
} else if (source.id.equal("vscrollbar")) {
|
||||
if (_firstVisibleLine != event.position) {
|
||||
_firstVisibleLine = event.position;
|
||||
measureVisibleText();
|
||||
invalidate();
|
||||
if (event.action == ScrollAction.SliderMoved || event.action == ScrollAction.SliderReleased) {
|
||||
if (_firstVisibleLine != event.position) {
|
||||
_firstVisibleLine = event.position;
|
||||
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;
|
||||
}
|
||||
|
@ -1803,6 +1897,115 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
|||
return true;
|
||||
}
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue