editors enhancements

This commit is contained in:
Vadim Lopatin 2014-04-24 13:58:10 +04:00
parent 9fb9a451d4
commit 117d4ce33e
4 changed files with 131 additions and 35 deletions

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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