From 595e1fc7d6d2c98453562e166caea3e6cd742842 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Wed, 5 Mar 2014 16:47:54 +0400 Subject: [PATCH] simple text widget --- dlanguilib.visualdproj | 1 + examples/example1/winmain.d | 4 +- src/dlangui/graphics/drawbuf.d | 14 +++ src/dlangui/graphics/fonts.d | 15 ++- src/dlangui/platforms/common/platform.d | 2 + src/dlangui/platforms/windows/winapp.d | 17 ++- src/dlangui/widgets/styles.d | 12 ++ src/dlangui/widgets/widget.d | 144 +++++++++++++++++------- 8 files changed, 160 insertions(+), 49 deletions(-) create mode 100644 src/dlangui/widgets/styles.d diff --git a/dlanguilib.visualdproj b/dlanguilib.visualdproj index 3422d465..27a18257 100644 --- a/dlanguilib.visualdproj +++ b/dlanguilib.visualdproj @@ -271,6 +271,7 @@ + diff --git a/examples/example1/winmain.d b/examples/example1/winmain.d index 498213ee..a220f71e 100644 --- a/examples/example1/winmain.d +++ b/examples/example1/winmain.d @@ -55,7 +55,9 @@ extern (C) int UIAppMain(string[] args) { Log.e("Sample error #", 22); Window window = Platform.instance().createWindow("My Window", null); - Widget myWidget = new TestWidget(); + Widget myWidget = new TextWidget(); + myWidget.text = "Some strange text string. 1234567890"; + myWidget.alignment = Align.Center; window.mainWidget = myWidget; window.show(); window.windowCaption = "New Window Caption"; diff --git a/src/dlangui/graphics/drawbuf.d b/src/dlangui/graphics/drawbuf.d index 6bb4a94f..bd06c61b 100644 --- a/src/dlangui/graphics/drawbuf.d +++ b/src/dlangui/graphics/drawbuf.d @@ -104,6 +104,20 @@ class DrawBuf : RefCountedObject { alias DrawBufRef = Ref!DrawBuf; +/// RAII setting/restoring of clip rectangle +struct ClipRectSaver { + DrawBuf _buf; + Rect _oldClipRect; + this(DrawBuf buf, Rect newClipRect) { + _buf = buf; + _oldClipRect = buf.clipRect; + buf.clipRect = newClipRect; + } + ~this() { + _buf.clipRect = _oldClipRect; + } +} + class ColorDrawBufBase : DrawBuf { int _dx; int _dy; diff --git a/src/dlangui/graphics/fonts.d b/src/dlangui/graphics/fonts.d index 3730595b..2893ad50 100644 --- a/src/dlangui/graphics/fonts.d +++ b/src/dlangui/graphics/fonts.d @@ -4,7 +4,7 @@ public import dlangui.core.types; public import dlangui.core.logger; import std.algorithm; -enum FontFamily : int { +enum FontFamily : ubyte { SansSerif, Serif, Fantasy, @@ -12,6 +12,11 @@ enum FontFamily : int { MonoSpace } +enum FontWeight : int { + Normal = 400, + Bold = 800 +} + struct Glyph { ubyte blackBoxX; ///< 0: width of glyph @@ -94,6 +99,14 @@ class Font : RefCountedObject { abstract @property bool isNull(); // measure text string, return accumulated widths[] (distance to end of n-th character), returns number of measured chars. abstract int measureText(const dchar[] text, ref int[] widths, int maxWidth); + // measure text string as single line, returns width and height + Point textSize(const dchar[] text, int maxWidth = 3000) { + int[] widths = new int[text.length + 1]; + int charsMeasured = measureText(text, widths, maxWidth); + if (charsMeasured < 1) + return Point(0,0); + return Point(widths[charsMeasured - 1], height); + } // draw text string to buffer abstract void drawText(DrawBuf buf, int x, int y, const dchar[] text, uint color); abstract Glyph * getCharGlyph(dchar ch); diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d index 78347ff8..6588ebe9 100644 --- a/src/dlangui/platforms/common/platform.d +++ b/src/dlangui/platforms/common/platform.d @@ -21,6 +21,8 @@ public class Window { abstract public @property string windowCaption(); abstract public @property void windowCaption(string caption); public void onResize(int width, int height) { + if (_dx == width && _dy == height) + return; _dx = width; _dy = height; if (_mainWidget !is null) { diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d index 471af750..41b2f674 100644 --- a/src/dlangui/platforms/windows/winapp.d +++ b/src/dlangui/platforms/windows/winapp.d @@ -46,14 +46,14 @@ class Win32Window : Window { cast(void*)this); // creation parameters } Win32ColorDrawBuf getDrawBuf() { - RECT rect; - GetClientRect(_hwnd, &rect); - int dx = rect.right - rect.left; - int dy = rect.bottom - rect.top; + //RECT rect; + //GetClientRect(_hwnd, &rect); + //int dx = rect.right - rect.left; + //int dy = rect.bottom - rect.top; if (_drawbuf is null) - _drawbuf = new Win32ColorDrawBuf(dx, dy); + _drawbuf = new Win32ColorDrawBuf(_dx, _dy); else - _drawbuf.resize(dx, dy); + _drawbuf.resize(_dx, _dy); return _drawbuf; } override void show() { @@ -230,12 +230,17 @@ LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) int dy = rect.bottom - rect.top; //window.onResize(pos.cx, pos.cy); window.onResize(dx, dy); + UpdateWindow(hwnd); } return 0; case WM_ERASEBKGND: return 1; case WM_PAINT: { + GetClientRect(hwnd, &rect); + int dx = rect.right - rect.left; + int dy = rect.bottom - rect.top; + window.onResize(dx, dy); hdc = BeginPaint(hwnd, &ps); Win32ColorDrawBuf buf = window.getDrawBuf(); buf.fill(0x808080); diff --git a/src/dlangui/widgets/styles.d b/src/dlangui/widgets/styles.d new file mode 100644 index 00000000..8f929105 --- /dev/null +++ b/src/dlangui/widgets/styles.d @@ -0,0 +1,12 @@ +module dlangui.widgets.styles; + +enum Align : ubyte { + Unspecified = 0, + Left = 1, + Right = 2, + HCenter = Left | Right, + Top = 4, + Bottom = 8, + VCenter = Top | Bottom, + Center = VCenter | HCenter +} diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index c3de1ad8..2db1f3a4 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -1,39 +1,41 @@ module dlangui.widgets.widget; -import dlangui.core.types; -import dlangui.graphics.drawbuf; +public import dlangui.core.types; +public import dlangui.widgets.styles; +public import dlangui.graphics.drawbuf; +public import dlangui.graphics.fonts; import dlangui.platforms.common.platform; -public class Widget { - Rect _pos; - Rect _margins; - Rect _padding; - int _measuredWidth; - int _measuredHeight; - bool _needLayout; - bool _needDraw; - Widget _parent; - Window _window; +class Widget { + protected Rect _pos; + protected Rect _margins; + protected Rect _padding; + protected int _measuredWidth; + protected int _measuredHeight; + protected bool _needLayout; + protected bool _needDraw; + protected Widget _parent; + protected Window _window; - uint _backgroundColor = 0xC0C0C0; + protected uint _backgroundColor = 0xC0C0C0; - public this() { + this() { _needLayout = true; _needDraw = true; } - public @property Rect margins() { return _margins; } - public @property void margins(Rect rc) { _margins = rc; } - public @property Rect padding() { return _padding; } - public @property void padding(Rect rc) { _padding = rc; } - public @property uint backgroundColor() { return _backgroundColor; } - public @property void backgroundColor(uint color) { _backgroundColor = color; } - public @property bool needLayout() { return _needLayout; } - public @property bool needDraw() { return _needDraw; } - public @property int childCount() { return 0; } - public Widget child(int index) { return null; } - public @property Widget parent() { return _parent; } - public @property void parent(Widget parent) { _parent = parent; } - public @property Window window() { + @property Rect margins() { return _margins; } + @property void margins(Rect rc) { _margins = rc; } + @property Rect padding() { return _padding; } + @property void padding(Rect rc) { _padding = rc; } + @property uint backgroundColor() { return _backgroundColor; } + @property void backgroundColor(uint color) { _backgroundColor = color; } + @property bool needLayout() { return _needLayout; } + @property bool needDraw() { return _needDraw; } + @property int childCount() { return 0; } + Widget child(int index) { return null; } + @property Widget parent() { return _parent; } + @property void parent(Widget parent) { _parent = parent; } + @property Window window() { Widget p = this; while (p !is null) { if (p._window !is null) @@ -42,37 +44,97 @@ public class Widget { } return null; } - public @property void window(Window window) { _window = window; } - public @property measuredWidth() { return _measuredWidth; } - public @property measuredHeight() { return _measuredHeight; } - public void measure(int width, int height) { - _measuredWidth = _measuredHeight = 0; - } - public void layout(Rect rc) { - _pos = rc; - } - public @property int width() { return _pos.width; } - public @property int height() { return _pos.height; } - public void applyMargins(ref Rect rc) { + @property void window(Window window) { _window = window; } + @property measuredWidth() { return _measuredWidth; } + @property measuredHeight() { return _measuredHeight; } + @property int width() { return _pos.width; } + @property int height() { return _pos.height; } + void applyMargins(ref Rect rc) { Rect m = margins; rc.left += m.left; rc.top += m.top; rc.bottom -= m.bottom; rc.right -= m.right; } - public void applyPadding(ref Rect rc) { + void applyPadding(ref Rect rc) { Rect m = padding; rc.left += m.left; rc.top += m.top; rc.bottom -= m.bottom; rc.right -= m.right; } - public void onDraw(DrawBuf buf) { + void measure(int width, int height) { + _measuredWidth = _measuredHeight = 0; + } + void layout(Rect rc) { + _pos = rc; + _needLayout = false; + } + void onDraw(DrawBuf buf) { Rect rc = _pos; applyMargins(rc); buf.fillRect(_pos, _backgroundColor); applyPadding(rc); buf.fillRect(rc.left + rc.width / 2, rc.top, rc.left + rc.width / 2 + 2, rc.bottom, 0xFF8000); buf.fillRect(rc.left, rc.top + rc.height / 2, rc.right, rc.top + rc.height / 2 + 2, 0xFF80FF); + _needDraw = false; + } + ref FontRef getFont() { + return FontManager.instance.getFont(24, FontWeight.Normal, false, FontFamily.SansSerif, "Arial"); + } + @property dstring text() { return ""; } + @property void text(dstring s) { } + protected uint _textColor = 0x000000; + @property uint textColor() { return _textColor; } + @property void textColor(uint value) { _textColor = value; } + protected ubyte _alignment = Align.Left | Align.Top; + @property ubyte alignment() { return _alignment; } + @property Align valign() { return cast(Align)(_alignment & Align.VCenter); } + @property Align halign() { return cast(Align)(_alignment & Align.HCenter); } + @property void alignment(ubyte value) { _alignment = value; } + void applyAlign(ref Rect rc, Point sz) { + if (valign == Align.Bottom) { + rc.top = rc.bottom - sz.y; + } else if (valign == Align.VCenter) { + int dy = (rc.height - sz.y) / 2; + rc.top += dy; + rc.bottom = rc.top + sz.y; + } else { + rc.bottom = rc.top + sz.y; + } + if (halign == Align.Right) { + rc.left = rc.right - sz.x; + } else if (halign == Align.HCenter) { + int dx = (rc.width - sz.x) / 2; + rc.left += dx; + rc.right = rc.left + sz.x; + } else { + rc.right = rc.left + sz.x; + } + } +} + +class TextWidget : Widget { + protected dstring _text; + override @property dstring text() { return _text; } + override @property void text(dstring s) { _text = s; } + override void measure(int width, int height) { + _measuredWidth = _measuredHeight = 0; + } + override void layout(Rect rc) { + _pos = rc; + _needLayout = false; + } + override void onDraw(DrawBuf buf) { + super.onDraw(buf); + Rect rc = _pos; + applyMargins(rc); + buf.fillRect(_pos, _backgroundColor); + applyPadding(rc); + ClipRectSaver(buf, rc); + FontRef font = getFont(); + Point sz = font.textSize(text); + applyAlign(rc, sz); + font.drawText(buf, rc.left, rc.top, text, textColor); } }