Mercurial > projects > mde
view mde/gui/widget/layout.d @ 34:6b4116e6355c
Work on the Gui: some of the framework for drag & drop. Also made Window an IWidget.
Implemented getWidget(x,y) to find the widget under this location for IWidgets (but not Gui).
Made Window an IWidget and made it work a little more similarly to widgets.
Implemented callbacks on the Gui for mouse events (enabling drag & drop, etc.).
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Fri, 02 May 2008 16:03:52 +0100 |
parents | 316b0230a849 |
children | 052df9b2fe07 |
line wrap: on
line source
/* LICENSE BLOCK Part of mde: a Modular D game-oriented Engine Copyright © 2007-2008 Diggory Hardy This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ /// Gui layout widgets. module mde.gui.widget.layout; import mde.gui.widget.Widget; import mde.gui.exception : WidgetDataException; /// Encapsulates a grid of Widgets class GridWidget : Widget { this (IWindow wind, IWidget, int[] data) { // Get grid size if (data.length < 2) throw new WidgetDataException; rows = data[0]; cols = data[1]; window = wind; // Get all sub-widgets // Check: correct data length and rows*cols >= 0 (know data.length - 2 >= 0). if (data.length != 2 + rows * cols) throw new WidgetDataException; subWidgets.length = rows*cols; foreach (i, inout subWidget; subWidgets) { subWidget = window.makeWidget (data[i+2], this); } getMinimumSize (w,h); // Calculate the size (current size is not saved) } // Calculates from all rows and columns of widgets. void getMinimumSize (out int w, out int h) { if (rows*cols == 0) { // special case w = h = 0; return; } // Find the sizes of all subWidgets int[] widgetW = new int[subWidgets.length]; // dimensions int[] widgetH = new int[subWidgets.length]; foreach (i,widget; subWidgets) widget.getCurrentSize (widgetW[i],widgetH[i]); // Find row heights and column widths (non cumulative) rowH.length = rows; colW.length = cols; //WARNING: code reliant on these being initialised to zero for (uint i = 0; i < subWidgets.length; ++i) { uint n = i / cols; // row if (rowH[n] < widgetH[i]) rowH[n] = widgetH[i]; n = i % cols; // column if (colW[n] < widgetW[i]) colW[n] = widgetW[i]; } // rowY / colX rowY.length = rows; colX.length = cols; int spacing = window.renderer.layoutSpacing; int cum = 0; foreach (i, x; rowH) { rowY[i] = cum; cum += x + spacing; } h = cum - spacing; // total height cum = 0; foreach (i, x; colW) { colX[i] = cum; cum += x + spacing; } w = cum - spacing; // total width } void setPosition (int x, int y) { this.x = x; this.y = y; foreach (i,widget; subWidgets) widget.setPosition (x + colX[i % cols], y + rowY[i / cols]); } // Find the relevant widget. IWidget getWidget (int cx, int cy) { if (rows*cols == 0) return this; // special case int lx = cx - x, ly = cy - y; // use coords relative to this widget // Find the column int i = cols - 1; // starting from right... while (lx < colX[i]) { // decrement while left of this column if (i == 0) return this; // left of first column --i; } // now (lx >= colX[i]) if (lx >= colX[i] + colW[i]) return this; // between columns // Find the row; int j = rows - 1; while (ly < rowY[j]) { if (j == 0) return this; --j; } if (ly >= rowY[j] + rowH[j]) return this; // Now we know it's in widget (i,j)'s cell (but the widget may not take up the whole cell) lx -= colX[i]; ly -= rowY[j]; IWidget widg = subWidgets[i + j*cols]; widg.getCurrentSize (i,j); if (lx < i && ly < j) return widg.getWidget (cx, cy); } void draw () { super.draw (); foreach (widget; subWidgets) widget.draw (); } protected: int rows, cols; // number of cells in grid int[] rowH; // row height (highest widget in the row) int[] colW; // column width (widest widget) int[] rowY; // cumulative rowH[i-1] + border and padding int[] colX; // cumulative colW[i-1] + border and padding IWidget[] subWidgets; // all widgets in the grid (by row): /* SubWidget order: [ 0 1 ] * [ 2 3 ] */ }