mirror of https://github.com/buggins/dlangui.git
edit line
This commit is contained in:
parent
f7045cac6a
commit
d1a794dcb2
|
@ -77,6 +77,7 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
hlayout.addChild((new ImageWidget()).drawableId("btn_check").padding(Rect(5,5,5,5)).alignment(Align.Center));
|
hlayout.addChild((new ImageWidget()).drawableId("btn_check").padding(Rect(5,5,5,5)).alignment(Align.Center));
|
||||||
hlayout.addChild((new TextWidget()).text("in horizontal layout"));
|
hlayout.addChild((new TextWidget()).text("in horizontal layout"));
|
||||||
hlayout.addChild((new ImageWidget()).drawableId("exit").padding(Rect(5,5,5,5)).alignment(Align.Center));
|
hlayout.addChild((new ImageWidget()).drawableId("exit").padding(Rect(5,5,5,5)).alignment(Align.Center));
|
||||||
|
hlayout.addChild((new EditLine("editline", "Some text to edit"d)));
|
||||||
//hlayout.addChild((new Button()).text(">>")); //.textColor(0x40FF4000)
|
//hlayout.addChild((new Button()).text(">>")); //.textColor(0x40FF4000)
|
||||||
hlayout.backgroundColor = 0x8080C0;
|
hlayout.backgroundColor = 0x8080C0;
|
||||||
layout.addChild(hlayout);
|
layout.addChild(hlayout);
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/* //device/apps/common/assets/res/any/drawable/editbox_background.xml
|
||||||
|
**
|
||||||
|
** Copyright 2006, The Android Open Source Project
|
||||||
|
**
|
||||||
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
** you may not use this file except in compliance with the License.
|
||||||
|
** You may obtain a copy of the License at
|
||||||
|
**
|
||||||
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
**
|
||||||
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
** See the License for the specific language governing permissions and
|
||||||
|
** limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_focused="true" android:drawable="@drawable/editbox_background_focus_yellow" />
|
||||||
|
<item android:drawable="@drawable/editbox_background_normal" />
|
||||||
|
</selector>
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
|
@ -59,5 +59,6 @@ public import dlangui.widgets.layouts;
|
||||||
public import dlangui.widgets.lists;
|
public import dlangui.widgets.lists;
|
||||||
public import dlangui.widgets.tabs;
|
public import dlangui.widgets.tabs;
|
||||||
public import dlangui.widgets.menu;
|
public import dlangui.widgets.menu;
|
||||||
|
public import dlangui.widgets.editors;
|
||||||
public import dlangui.graphics.fonts;
|
public import dlangui.graphics.fonts;
|
||||||
public import dlangui.core.i18n;
|
public import dlangui.core.i18n;
|
||||||
|
|
|
@ -91,12 +91,6 @@ class TextWidget : Widget {
|
||||||
measuredContent(parentWidth, parentHeight, sz.x, sz.y);
|
measuredContent(parentWidth, parentHeight, sz.x, sz.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onClick() {
|
|
||||||
// override it
|
|
||||||
Log.d("Button.onClick ", id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
override void onDraw(DrawBuf buf) {
|
override void onDraw(DrawBuf buf) {
|
||||||
if (visibility != Visibility.Visible)
|
if (visibility != Visibility.Visible)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -23,6 +23,66 @@ module dlangui.widgets.editors;
|
||||||
import dlangui.widgets.widget;
|
import dlangui.widgets.widget;
|
||||||
import dlangui.core.signals;
|
import dlangui.core.signals;
|
||||||
|
|
||||||
|
immutable dchar EOL = '\n';
|
||||||
|
|
||||||
|
/// split dstring by delimiters
|
||||||
|
dstring[] splitDString(dstring source, dchar delimiter = EOL) {
|
||||||
|
int start = 0;
|
||||||
|
dstring[] res;
|
||||||
|
for (int i = 0; i <= source.length; i++) {
|
||||||
|
if (i == source.length || source[i] == delimiter) {
|
||||||
|
if (i >= start) {
|
||||||
|
dstring line = i > start ? cast(dstring)(source[start .. i].dup) : ""d;
|
||||||
|
res ~= line;
|
||||||
|
}
|
||||||
|
start = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// text content position
|
||||||
|
struct TextPosition {
|
||||||
|
/// line number, zero based
|
||||||
|
int line;
|
||||||
|
/// character position in line (0 == before first character)
|
||||||
|
int pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// text content range
|
||||||
|
struct TextRange {
|
||||||
|
TextPosition start;
|
||||||
|
TextPosition end;
|
||||||
|
/// returns true if range is empty
|
||||||
|
@property bool empty() {
|
||||||
|
if (start.line > end.line)
|
||||||
|
return true;
|
||||||
|
if (start.line < end.line)
|
||||||
|
return false;
|
||||||
|
return (start.pos >= end.pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// action performed with editable contents
|
||||||
|
enum EditAction {
|
||||||
|
/// insert content into specified position (range.start)
|
||||||
|
Insert,
|
||||||
|
/// delete content in range
|
||||||
|
Delete,
|
||||||
|
/// replace range content with new content
|
||||||
|
Replace
|
||||||
|
}
|
||||||
|
|
||||||
|
/// edit operation details for EditableContent
|
||||||
|
class EditOperation {
|
||||||
|
/// action performed
|
||||||
|
EditAction action;
|
||||||
|
/// range
|
||||||
|
TextRange range;
|
||||||
|
/// new content for range (if required for this action)
|
||||||
|
dstring[] content;
|
||||||
|
}
|
||||||
|
|
||||||
/// editable plain text (multiline)
|
/// editable plain text (multiline)
|
||||||
class EditableContent {
|
class EditableContent {
|
||||||
this(bool multiline) {
|
this(bool multiline) {
|
||||||
|
@ -30,23 +90,26 @@ class EditableContent {
|
||||||
_lines.length = 1; // initial state: single empty line
|
_lines.length = 1; // initial state: single empty line
|
||||||
}
|
}
|
||||||
protected bool _multiline;
|
protected bool _multiline;
|
||||||
protected dchar[][] _lines;
|
protected dstring[] _lines;
|
||||||
/// returns all lines concatenated delimited by '\n'
|
/// returns all lines concatenated delimited by '\n'
|
||||||
@property dstring text() {
|
@property dstring text() {
|
||||||
if (_lines.length == 0)
|
if (_lines.length == 0)
|
||||||
return "";
|
return "";
|
||||||
|
if (_lines.length == 1)
|
||||||
|
return _lines[0];
|
||||||
|
// concat lines
|
||||||
dchar[] buf;
|
dchar[] buf;
|
||||||
foreach(item;_lines) {
|
foreach(item;_lines) {
|
||||||
if (buf.length)
|
if (buf.length)
|
||||||
buf ~= '\n';
|
buf ~= EOL;
|
||||||
buf ~= item;
|
buf ~= item;
|
||||||
}
|
}
|
||||||
return cast(dstring)buf;
|
return cast(dstring)buf;
|
||||||
}
|
}
|
||||||
|
/// replace whole text with another content
|
||||||
@property EditableContent text(dstring newContent) {
|
@property EditableContent text(dstring newContent) {
|
||||||
_lines.length = 0;
|
_lines.length = 0;
|
||||||
// TODO: split into lines
|
_lines = splitDString(newContent);
|
||||||
_lines ~= newContent.dup;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/// returns line text
|
/// returns line text
|
||||||
|
@ -56,30 +119,58 @@ class EditableContent {
|
||||||
}
|
}
|
||||||
/// returns line text by index
|
/// returns line text by index
|
||||||
dstring line(int index) {
|
dstring line(int index) {
|
||||||
return _lines[index].dup;
|
return _lines[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// single line editor
|
/// single line editor
|
||||||
class EditLine : Widget {
|
class EditLine : Widget {
|
||||||
EditableContent _content;
|
EditableContent _content;
|
||||||
this(string ID) {
|
this(string ID, dstring initialContent = null) {
|
||||||
super(ID);
|
super(ID);
|
||||||
_content = new EditableContent(false);
|
_content = new EditableContent(false);
|
||||||
|
styleId = "EDIT_LINE";
|
||||||
|
focusable = true;
|
||||||
|
text = initialContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get widget text
|
/// get widget text
|
||||||
override @property dstring text() { return _content.text; }
|
override @property dstring text() { return _content.text; }
|
||||||
|
|
||||||
/// set text
|
/// set text
|
||||||
override @property Widget text(dstring s) {
|
override @property Widget text(dstring s) {
|
||||||
_content.text = s;
|
_content.text = s;
|
||||||
requestLayout();
|
requestLayout();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// set text
|
/// set text
|
||||||
override @property Widget text(ref UIString s) {
|
override @property Widget text(ref UIString s) {
|
||||||
_content.text = s;
|
_content.text = s;
|
||||||
requestLayout();
|
requestLayout();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// measure
|
||||||
|
override void measure(int parentWidth, int parentHeight) {
|
||||||
|
FontRef font = font();
|
||||||
|
Point sz = font.textSize(text);
|
||||||
|
measuredContent(parentWidth, parentHeight, sz.x, sz.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
override void onDraw(DrawBuf buf) {
|
||||||
|
if (visibility != Visibility.Visible)
|
||||||
|
return;
|
||||||
|
super.onDraw(buf);
|
||||||
|
Rect rc = _pos;
|
||||||
|
applyMargins(rc);
|
||||||
|
auto saver = ClipRectSaver(buf, rc);
|
||||||
|
applyPadding(rc);
|
||||||
|
FontRef font = font();
|
||||||
|
dstring txt = text;
|
||||||
|
Point sz = font.textSize(txt);
|
||||||
|
applyAlign(rc, sz);
|
||||||
|
font.drawText(buf, rc.left, rc.top, txt, textColor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -646,8 +646,8 @@ Theme createDefaultTheme() {
|
||||||
res.createSubstyle("BUTTON_LABEL").layoutWidth(FILL_PARENT).alignment(Align.Left|Align.VCenter);
|
res.createSubstyle("BUTTON_LABEL").layoutWidth(FILL_PARENT).alignment(Align.Left|Align.VCenter);
|
||||||
res.createSubstyle("BUTTON_ICON").alignment(Align.Center);
|
res.createSubstyle("BUTTON_ICON").alignment(Align.Center);
|
||||||
res.createSubstyle("TEXT").margins(Rect(2,2,2,2)).padding(Rect(1,1,1,1));
|
res.createSubstyle("TEXT").margins(Rect(2,2,2,2)).padding(Rect(1,1,1,1));
|
||||||
res.createSubstyle("HSPACER").layoutWidth(FILL_PARENT).layoutWeight(100);
|
res.createSubstyle("HSPACER").layoutWidth(FILL_PARENT).minWidth(5).layoutWeight(100);
|
||||||
res.createSubstyle("VSPACER").layoutHeight(FILL_PARENT).layoutWeight(100);
|
res.createSubstyle("VSPACER").layoutHeight(FILL_PARENT).minHeight(5).layoutWeight(100);
|
||||||
//button.createState(State.Enabled | State.Focused, State.Focused).backgroundImageId("btn_default_small_normal_disable_focused");
|
//button.createState(State.Enabled | State.Focused, State.Focused).backgroundImageId("btn_default_small_normal_disable_focused");
|
||||||
//button.createState(State.Enabled, 0).backgroundImageId("btn_default_small_normal_disable");
|
//button.createState(State.Enabled, 0).backgroundImageId("btn_default_small_normal_disable");
|
||||||
//button.createState(State.Pressed, State.Pressed).backgroundImageId("btn_default_small_pressed");
|
//button.createState(State.Pressed, State.Pressed).backgroundImageId("btn_default_small_pressed");
|
||||||
|
@ -713,6 +713,8 @@ Theme createDefaultTheme() {
|
||||||
//listItem.createState(State.Selected, State.Selected).backgroundColor(0xC04040FF).textColor(0x000000);
|
//listItem.createState(State.Selected, State.Selected).backgroundColor(0xC04040FF).textColor(0x000000);
|
||||||
//listItem.createState(State.Enabled, 0).textColor(0x80000000); // half transparent text for disabled item
|
//listItem.createState(State.Enabled, 0).textColor(0x80000000); // half transparent text for disabled item
|
||||||
|
|
||||||
|
Style editLine = res.createSubstyle("EDIT_LINE").backgroundImageId("editbox_background").padding(Rect(4,2,4,2));
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue