mirror of https://github.com/buggins/dlangui.git
editors enhancements
This commit is contained in:
parent
9fb9a451d4
commit
117d4ce33e
|
@ -7,6 +7,27 @@ import std.conv;
|
|||
|
||||
mixin APP_ENTRY_POINT;
|
||||
|
||||
Widget createEditorSettingsControl(EditWidgetBase editor) {
|
||||
HorizontalLayout res = new HorizontalLayout("editor_options");
|
||||
res.addChild((new CheckBox("wantTabs", "wantTabs"d)).checked(editor.wantTabs).addOnCheckChangeListener(delegate(Widget, bool checked) { editor.wantTabs = checked; return true;}));
|
||||
res.addChild((new CheckBox("useSpacesForTabs", "useSpacesForTabs"d)).checked(editor.useSpacesForTabs).addOnCheckChangeListener(delegate(Widget, bool checked) { editor.useSpacesForTabs = checked; return true;}));
|
||||
res.addChild((new CheckBox("fixedFont", "fixedFont"d)).checked(editor.fontFamily == FontFamily.MonoSpace).addOnCheckChangeListener(delegate(Widget, bool checked) {
|
||||
if (checked)
|
||||
editor.fontFamily(FontFamily.MonoSpace).fontFace("Courier New");
|
||||
else
|
||||
editor.fontFamily(FontFamily.SansSerif).fontFace("Arial");
|
||||
return true;
|
||||
}));
|
||||
res.addChild((new CheckBox("tabSize", "Tab size 8"d)).checked(editor.tabSize == 8).addOnCheckChangeListener(delegate(Widget, bool checked) {
|
||||
if (checked)
|
||||
editor.tabSize(8);
|
||||
else
|
||||
editor.tabSize(4);
|
||||
return true;
|
||||
}));
|
||||
return res;
|
||||
}
|
||||
|
||||
/// entry point for dlangui based application
|
||||
extern (C) int UIAppMain(string[] args) {
|
||||
// resource directory search paths
|
||||
|
@ -140,31 +161,36 @@ extern (C) int UIAppMain(string[] args) {
|
|||
tabs.addTab((new TextWidget()).id("tab4").textColor(0x00802000).text("Tab 4 contents some long string"), "Tab 4"d);
|
||||
tabs.addTab((new TextWidget()).id("tab5").textColor(0x00802000).text("Tab 5 contents"), "Tab 5"d);
|
||||
|
||||
//==========================================================================
|
||||
// create Editors test tab
|
||||
|
||||
VerticalLayout editors = new VerticalLayout("editors");
|
||||
|
||||
editors.addChild(new TextWidget(null, "EditLine(Single line editor)"d));
|
||||
// EditLine sample
|
||||
editors.addChild(new TextWidget(null, "EditLine: Single line editor"d));
|
||||
EditLine editLine = new EditLine("editline1", "Single line editor sample text");
|
||||
editors.addChild(createEditorSettingsControl(editLine));
|
||||
editors.addChild(editLine);
|
||||
editors.addChild(new TextWidget(null, "EditBox(Multiline editor)"d));
|
||||
|
||||
EditBox editBox = new EditBox("editbox1", "Some text\nSecond line\nYet another line"d);
|
||||
// EditBox sample
|
||||
editors.addChild(new TextWidget(null, "EditBox: Multiline editor"d));
|
||||
|
||||
EditBox editBox = new EditBox("editbox1", "Some text\nSecond line\nYet another line\n\n\tforeach(s;lines);\n\t\twriteln(s);\n"d);
|
||||
editBox.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
|
||||
dstring text = editBox.text;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
text ~= "\n Line ";
|
||||
text ~= to!dstring(i + 3);
|
||||
text ~= to!dstring(i + 5);
|
||||
text ~= " Some long long line. Blah blah blah.";
|
||||
for (int j = 0; j <= i % 4; j++)
|
||||
text ~= " The quick brown fox jumps over the lazy dog.";
|
||||
text ~= "End of line ";
|
||||
text ~= to!dstring(i + 3);
|
||||
}
|
||||
editBox.text = text;
|
||||
editors.addChild(createEditorSettingsControl(editBox));
|
||||
editors.addChild(editBox);
|
||||
|
||||
tabs.addTab(editors, "EditBox"d);
|
||||
tabs.addTab(editors, "Editors"d);
|
||||
|
||||
//==========================================================================
|
||||
|
||||
tabs.selectTab("tab1");
|
||||
|
||||
|
|
|
@ -739,12 +739,8 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
|||
|
||||
protected void updateFontProps() {
|
||||
FontRef font = font();
|
||||
_fixedFont = false;
|
||||
_spaceWidth = font.textSize(" "d).x;
|
||||
int mwidth = font.textSize("M"d).x;
|
||||
int iwidth = font.textSize("i"d).x;
|
||||
if (mwidth == iwidth)
|
||||
_fixedFont = true;
|
||||
_fixedFont = font.isFixed;
|
||||
_spaceWidth = font.spaceWidth;
|
||||
_lineHeight = font.height;
|
||||
}
|
||||
|
||||
|
@ -1149,6 +1145,14 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
|
|||
}
|
||||
}
|
||||
|
||||
/// map key to action
|
||||
override protected Action findKeyAction(uint keyCode, uint flags) {
|
||||
// don't handle tabs when disabled
|
||||
if (keyCode == KeyCode.TAB && (flags == 0 || flags == KeyFlag.Shift) && !_wantTabs)
|
||||
return null;
|
||||
return super.findKeyAction(keyCode, flags);
|
||||
}
|
||||
|
||||
/// handle keys
|
||||
override bool onKeyEvent(KeyEvent event) {
|
||||
//
|
||||
|
@ -1267,7 +1271,7 @@ class EditLine : EditWidgetBase {
|
|||
//Point sz = font.textSize(text);
|
||||
_measuredText = text;
|
||||
_measuredTextWidths.length = _measuredText.length;
|
||||
int charsMeasured = font.measureText(_measuredText, _measuredTextWidths, int.max);
|
||||
int charsMeasured = font.measureText(_measuredText, _measuredTextWidths, int.max, tabSize);
|
||||
_measuredTextSize.x = charsMeasured > 0 ? _measuredTextWidths[charsMeasured - 1]: 0;
|
||||
_measuredTextSize.y = font.height;
|
||||
return _measuredTextSize;
|
||||
|
@ -1354,7 +1358,7 @@ class EditLine : EditWidgetBase {
|
|||
dstring txt = text;
|
||||
Point sz = font.textSize(txt);
|
||||
//applyAlign(rc, sz);
|
||||
font.drawText(buf, rc.left - _scrollPos.x, rc.top + sz.y / 10, txt, textColor);
|
||||
font.drawText(buf, rc.left - _scrollPos.x, rc.top + sz.y / 10, txt, textColor, tabSize);
|
||||
if (focused) {
|
||||
// draw caret
|
||||
Rect caretRc = textPosToClient(_caretPos);
|
||||
|
@ -1419,7 +1423,7 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
|||
for (int i = 0; i < _numVisibleLines; i++) {
|
||||
_visibleLines[i] = _content[_firstVisibleLine + i];
|
||||
_visibleLinesMeasurement[i].length = _visibleLines[i].length;
|
||||
int charsMeasured = font.measureText(_visibleLines[i], _visibleLinesMeasurement[i], int.max);
|
||||
int charsMeasured = font.measureText(_visibleLines[i], _visibleLinesMeasurement[i], int.max, tabSize);
|
||||
_visibleLinesWidths[i] = charsMeasured > 0 ? _visibleLinesMeasurement[i][charsMeasured - 1] : 0;
|
||||
if (sz.x < _visibleLinesWidths[i])
|
||||
sz.x = _visibleLinesWidths[i]; // width - max from visible lines
|
||||
|
@ -1698,8 +1702,9 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
|||
|
||||
/// override to custom highlight of line background
|
||||
protected void drawLineBackground(DrawBuf buf, int lineIndex, Rect lineRect, Rect visibleRect) {
|
||||
if (lineIndex & 1)
|
||||
buf.fillRect(visibleRect, 0xF4808080);
|
||||
// highlight odd lines
|
||||
//if ((lineIndex & 1))
|
||||
// buf.fillRect(visibleRect, 0xF4808080);
|
||||
|
||||
if (!_selectionRange.empty && _selectionRange.start.line <= lineIndex && _selectionRange.end.line >= lineIndex) {
|
||||
// line inside selection
|
||||
|
@ -1716,7 +1721,8 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
|||
}
|
||||
}
|
||||
|
||||
if (lineIndex == _caretPos.line) {
|
||||
// frame around current line
|
||||
if (lineIndex == _caretPos.line && _selectionRange.singleLine && _selectionRange.start.line == _caretPos.line) {
|
||||
buf.drawFrame(visibleRect, 0xA0808080, Rect(1,1,1,1));
|
||||
}
|
||||
}
|
||||
|
@ -1747,7 +1753,7 @@ class EditBox : EditWidgetBase, OnScrollHandler {
|
|||
visibleRect.right = _clientRc.right;
|
||||
drawLineBackground(buf, _firstVisibleLine + i, lineRect, visibleRect);
|
||||
if (txt.length > 0) {
|
||||
font.drawText(buf, rc.left - _scrollPos.x, rc.top + i * _lineHeight, txt, textColor);
|
||||
font.drawText(buf, rc.left - _scrollPos.x, rc.top + i * _lineHeight, txt, textColor, tabSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -714,13 +714,13 @@ Theme createDefaultTheme() {
|
|||
//listItem.createState(State.Enabled, 0).textColor(0x80000000); // half transparent text for disabled item
|
||||
|
||||
Style editLine = res.createSubstyle("EDIT_LINE").backgroundImageId("editbox_background").padding(Rect(5,6,5,6)).margins(Rect(2,2,2,2)).minWidth(40);
|
||||
editLine.fontFace("Courier New").fontFamily(FontFamily.MonoSpace);
|
||||
editLine.fontFace("Arial").fontFamily(FontFamily.SansSerif).fontSize(16);
|
||||
Style editBox = res.createSubstyle("EDIT_BOX").backgroundImageId("editbox_background").padding(Rect(5,6,5,6)).margins(Rect(2,2,2,2)).minWidth(100).minHeight(60);
|
||||
editBox.fontFace("Courier New").fontFamily(FontFamily.MonoSpace);
|
||||
editBox.fontFace("Courier New").fontFamily(FontFamily.MonoSpace).fontSize(16);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
shared static ~this() {
|
||||
currentTheme = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,7 +216,11 @@ class Widget {
|
|||
/// get margins (between widget bounds and its background)
|
||||
@property Rect margins() const { return style.margins; }
|
||||
/// set margins for widget - override one from style
|
||||
@property Widget margins(Rect rc) { ownStyle.margins = rc; return this; }
|
||||
@property Widget margins(Rect rc) {
|
||||
ownStyle.margins = rc;
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
/// get padding (between background bounds and content of widget)
|
||||
@property Rect padding() const {
|
||||
// get max padding from style padding and background drawable padding
|
||||
|
@ -236,39 +240,75 @@ class Widget {
|
|||
return p;
|
||||
}
|
||||
/// set padding for widget - override one from style
|
||||
@property Widget padding(Rect rc) { ownStyle.padding = rc; return this; }
|
||||
@property Widget padding(Rect rc) {
|
||||
ownStyle.padding = rc;
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
/// returns background color
|
||||
@property uint backgroundColor() const { return stateStyle.backgroundColor; }
|
||||
/// set background color for widget - override one from style
|
||||
@property Widget backgroundColor(uint color) { ownStyle.backgroundColor = color; return this; }
|
||||
@property Widget backgroundColor(uint color) {
|
||||
ownStyle.backgroundColor = color;
|
||||
invalidate();
|
||||
return this;
|
||||
}
|
||||
/// get text color (ARGB 32 bit value)
|
||||
@property uint textColor() const { return stateStyle.textColor; }
|
||||
/// set text color (ARGB 32 bit value)
|
||||
@property Widget textColor(uint value) { ownStyle.textColor = value; return this; }
|
||||
@property Widget textColor(uint value) {
|
||||
ownStyle.textColor = value;
|
||||
invalidate();
|
||||
return this;
|
||||
}
|
||||
/// returns font face
|
||||
@property string fontFace() const { return stateStyle.fontFace; }
|
||||
/// set font face for widget - override one from style
|
||||
@property Widget fontFace(string face) { ownStyle.fontFace = face; return this; }
|
||||
@property Widget fontFace(string face) {
|
||||
ownStyle.fontFace = face;
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
/// returns font style (italic/normal)
|
||||
@property bool fontItalic() const { return stateStyle.fontItalic; }
|
||||
/// set font style (italic/normal) for widget - override one from style
|
||||
@property Widget fontItalic(bool italic) { ownStyle.fontStyle = italic ? FONT_STYLE_ITALIC : FONT_STYLE_NORMAL; return this; }
|
||||
@property Widget fontItalic(bool italic) {
|
||||
ownStyle.fontStyle = italic ? FONT_STYLE_ITALIC : FONT_STYLE_NORMAL;
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
/// returns font weight
|
||||
@property ushort fontWeight() const { return stateStyle.fontWeight; }
|
||||
/// set font weight for widget - override one from style
|
||||
@property Widget fontWeight(ushort weight) { ownStyle.fontWeight = weight; return this; }
|
||||
@property Widget fontWeight(ushort weight) {
|
||||
ownStyle.fontWeight = weight;
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
/// returns font size in pixels
|
||||
@property ushort fontSize() const { return stateStyle.fontSize; }
|
||||
/// set font size for widget - override one from style
|
||||
@property Widget fontSize(ushort size) { ownStyle.fontSize = size; return this; }
|
||||
@property Widget fontSize(ushort size) {
|
||||
ownStyle.fontSize = size;
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
/// returns font family
|
||||
@property FontFamily fontFamily() const { return stateStyle.fontFamily; }
|
||||
/// set font family for widget - override one from style
|
||||
@property Widget fontFamily(FontFamily family) { ownStyle.fontFamily = family; return this; }
|
||||
@property Widget fontFamily(FontFamily family) {
|
||||
ownStyle.fontFamily = family;
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
/// returns alignment (combined vertical and horizontal)
|
||||
@property ubyte alignment() const { return style.alignment; }
|
||||
/// sets alignment (combined vertical and horizontal)
|
||||
@property Widget alignment(ubyte value) { ownStyle.alignment = value; return this; }
|
||||
@property Widget alignment(ubyte value) {
|
||||
ownStyle.alignment = value;
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
/// returns horizontal alignment
|
||||
@property Align valign() { return cast(Align)(alignment & Align.VCenter); }
|
||||
/// returns vertical alignment
|
||||
|
@ -468,10 +508,16 @@ class Widget {
|
|||
return res;
|
||||
}
|
||||
|
||||
/// map key to action
|
||||
protected Action findKeyAction(uint keyCode, uint flags) {
|
||||
Action action = _acceleratorMap.findByKey(keyCode, flags);
|
||||
return action;
|
||||
}
|
||||
|
||||
/// 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));
|
||||
Action action = findKeyAction(event.keyCode, event.flags & (KeyFlag.Shift | KeyFlag.Alt | KeyFlag.Control));
|
||||
if (action !is null) {
|
||||
return handleAction(action);
|
||||
}
|
||||
|
@ -559,6 +605,24 @@ class Widget {
|
|||
/// focus state change event listener (bool delegate(Widget, bool))
|
||||
Signal!OnFocusHandler onFocusChangeListener;
|
||||
|
||||
/// helper function to add onCheckChangeListener in method chain
|
||||
Widget addOnClickListener(bool delegate(Widget) listener) {
|
||||
onClickListener.connect(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// helper function to add onCheckChangeListener in method chain
|
||||
Widget addOnCheckChangeListener(bool delegate(Widget, bool) listener) {
|
||||
onCheckChangeListener.connect(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// helper function to add onFocusChangeListener in method chain
|
||||
Widget addOnFocusChangeListener(bool delegate(Widget, bool) listener) {
|
||||
onFocusChangeListener.connect(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
// =======================================================
|
||||
// Layout and measurement methods
|
||||
|
||||
|
|
Loading…
Reference in New Issue