diff --git a/examples/tetris/src/main.d b/examples/tetris/src/main.d index e48c01c8..ec0f04fd 100644 --- a/examples/tetris/src/main.d +++ b/examples/tetris/src/main.d @@ -123,32 +123,110 @@ class SampleAnimationWidget : VerticalLayout { } } +struct FigureCell { + // horizontal offset + int dx; + // vertical offset + int dy; + this(int[2] v) { + dx = v[0]; + dy = v[1]; + } +} + +struct FigureShape { + // by cell index 0..3 + FigureCell[4] cells; + this(int[2] c1, int[2] c2, int[2] c3, int[2] c4) { + cells[0] = FigureCell(c1); + cells[1] = FigureCell(c2); + cells[2] = FigureCell(c3); + cells[3] = FigureCell(c4); + } +} + +struct Figure { + FigureShape[4] shapes; // by orientation + this(FigureShape[4] v) { + shapes = v; + } +} + +const Figure[1] FIGURES = [ + // FIGURE1 + // ## + // #### + // ## + Figure([FigureShape([0, 0], [1, 0], [1, 1], [0, -1]), + FigureShape([0, 0], [0, 1], [-1, -1],[1, 0]), + FigureShape([0, 0], [1, 0], [1, 1], [0, -1]), + FigureShape([0, 0], [0, 1], [-1, -1],[1, 0])]) +]; + class CupWidget : Widget { int _cols; int _rows; + int[] _cup; + + static const int RESERVED_ROWS = 4; // reserved for next figure + enum : int { + WALL = -1, + EMPTY = 0, + FIGURE1, + FIGURE2, + FIGURE3, + FIGURE4, + FIGURE5, + FIGURE6, + FIGURE7, + } + + static const uint[] _figureColors = [0xFF0000, 0xFFFF00, 0xFF00FF, 0x0000FF, 0x800000, 0x408000, 0x000080]; this() { super("CUP"); layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT).layoutWeight(3); backgroundColor = 0xC0808080; - padding(Rect(10, 10, 10, 10)); + padding(Rect(20, 20, 20, 20)); init(10, 15); + + setCell(1, 1, FIGURE1); + setCell(3, 3, FIGURE2); + setCell(4, 4, FIGURE3); + setCell(6, 4, FIGURE4); + setCell(7, 4, FIGURE5); + setCell(4, 5, FIGURE6); + setCell(4, 6, FIGURE7); } void init(int cols, int rows) { _cols = cols; _rows = rows; + _cup = new int[_cols * _rows]; + for (int i = 0; i < _cup.length; i++) + _cup[i] = EMPTY; + } + + int cell(int col, int row) { + if (col < 0 || row < 0 || col >= _cols || row >= _rows) + return WALL; + return _cup[row * _cols + col]; + } + + void setCell(int col, int row, int value) { + _cup[row * _cols + col] = value; + invalidate(); } Rect cellRect(Rect rc, int col, int row) { int dx = rc.width / _cols; - int dy = rc.height / _rows; + int dy = rc.height / (_rows + RESERVED_ROWS); int dd = dx; if (dd > dy) dd = dy; int x0 = rc.left + (rc.width - dd * _cols) / 2 + dd * col; - int y0 = rc.top + (rc.height - dd * _rows) / 2 + dd * row; + int y0 = rc.bottom - (rc.height - dd * (_rows + RESERVED_ROWS)) / 2 - dd * row - dd; return Rect(x0, y0, x0 + dd, y0 + dd); } @@ -160,11 +238,29 @@ class CupWidget : Widget { auto saver = ClipRectSaver(buf, rc, alpha); applyPadding(rc); + Rect topLeft = cellRect(rc, 0, _rows - 1); + Rect bottomRight = cellRect(rc, _cols - 1, 0); + + uint fcl = 0x80404080; + int fw = 2; + buf.fillRect(Rect(topLeft.left - 1 - fw, topLeft.top, topLeft.left - 1, bottomRight.bottom + 1 + fw), 0x000000); + buf.fillRect(Rect(bottomRight.right + 2, topLeft.top, bottomRight.right + 2 + fw, bottomRight.bottom + 2 + fw), 0x000000); + buf.fillRect(Rect(topLeft.left - 1 - fw, bottomRight.bottom + 2, bottomRight.right + 2 + fw, bottomRight.bottom + 2 + fw), 0x000000); + for (int row = 0; row < _rows; row++) { for (int col = 0; col < _cols; col++) { - Rect cell = cellRect(rc, col, row); - cell.shrink(1, 1); - buf.fillRect(cell, 0x800000FF); + int value = cell(col, row); + Rect cellRc = cellRect(rc, col, row); + + if (value == EMPTY) { + Point middle = cellRc.middle; + buf.fillRect(Rect(middle.x - 1, middle.y - 1, middle.x + 1, middle.y + 1), 0x404040); + } else { + uint cl = _figureColors[value - 1]; + cellRc.shrink(1, 1); + int w = cellRc.width / 5; + buf.drawFrame(cellRc, cl, Rect(w,w,w,w)); + } } } diff --git a/src/dlangui/core/types.d b/src/dlangui/core/types.d index 96ec7531..80033e12 100644 --- a/src/dlangui/core/types.d +++ b/src/dlangui/core/types.d @@ -69,6 +69,8 @@ struct Rect { @property int middlex() { return (left + right) / 2; } /// returns average of top, bottom @property int middley() { return (top + bottom) / 2; } + /// returns middle point + @property Point middle() { return Point(middlex, middley); } /// add offset to horizontal and vertical coordinates void offset(int dx, int dy) { left += dx; diff --git a/src/dlangui/dialogs/msgbox.d b/src/dlangui/dialogs/msgbox.d new file mode 100644 index 00000000..fe01eded --- /dev/null +++ b/src/dlangui/dialogs/msgbox.d @@ -0,0 +1,66 @@ +// Written in the D programming language. + +/** +This module contains common Dialog implementation. + + +Synopsis: + +---- +import dlangui.dialogs.msgbox; + +// show message box with single Ok button +window.showMessageBox(UIString("Dialog title"d), UIString("Some message"d)); + +// show message box with OK and CANCEL buttons, cancel by default, and handle its result +window.showMessageBox(UIString("Dialog title"d), UIString("Some message"d), [ACTION_OK, ACTION_CANCEL], 1, delegate(const Action a) { + if (a.id == StandardAction.Ok) + Log.d("OK pressed"); + else if (a.id == StandardAction.Cancel) + Log.d("CANCEL pressed"); + return true; +}); + +---- + +Copyright: Vadim Lopatin, 2014 +License: Boost License 1.0 +Authors: Vadim Lopatin, coolreader.org@gmail.com +*/ +module dlangui.dialogs.msgbox; + +import dlangui.core.i18n; +import dlangui.core.signals; +import dlangui.core.stdaction; +import dlangui.widgets.layouts; +import dlangui.widgets.controls; +import dlangui.platforms.common.platform; +import dlangui.dialogs.dialog; + +/// Message box +class MessageBox : Dialog { + protected UIString _message; + protected const(Action)[] _actions; + protected int _defaultButtonIndex; + this(UIString caption, UIString message, Window parentWindow = null, const(Action) [] buttons = [ACTION_OK], int defaultButtonIndex = 0, bool delegate(const Action result) handler = null) { + super(caption, parentWindow, DialogFlag.Modal); + _message = message; + _actions = buttons; + _defaultButtonIndex = defaultButtonIndex; + if (handler) { + onDialogResult = delegate (Dialog dlg, const Action action) { + handler(action); + }; + } + } + /// override to implement creation of dialog controls + override void init() { + TextWidget msg = new TextWidget("msg", _message); + backgroundColor(0xE0E0E0); + padding(Rect(10, 10, 10, 10)); + msg.padding(Rect(10, 10, 10, 10)); + addChild(msg); + addChild(createButtonsPanel(_actions, _defaultButtonIndex, 0)); + } + +}