Changeset 96:dbf332403c6e
- Timestamp:
- 11/06/08 08:16:39
(2 months ago)
- Author:
- Diggory Hardy <diggory.hardy@gmail.com>
- branch:
- default
- Message:
Improvements to FloatingAreaWidget?: positioning, passing click events and draw order.
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r95 |
r96 |
|
| 5 | 5 | <WidgetData|root={0:[0xC100,0,3,3],1:["square","blank","square","blank","content","blank","square","blank","square"]}> |
|---|
| 6 | 6 | <WidgetData|square={0:[0x1,6,6]}> |
|---|
| 7 | | <WidgetData|content={0:[0xC100,0,4,2],1:["floating","button","blank","blank","f2","opts","blank","blank"]}> |
|---|
| | 7 | <WidgetData|content={0:[0xC100,0,3,1],1:["floating","opts","blank"]}> |
|---|
| 8 | 8 | <WidgetData|button={0:[0x10,50,50]}> |
|---|
| 9 | 9 | <WidgetData|blank={0:[0x2]}> |
|---|
| … | … | |
| 15 | 15 | <WidgetData|optVal={0:[0x6030]}> |
|---|
| 16 | 16 | <WidgetData|optSep={0:[0x21, 0xff],1:["="]}> |
|---|
| 17 | | <WidgetData|floating={0:[0x8200,20,20],1:["text"]}> |
|---|
| 18 | | <WidgetData|f2={0:[0x8200,50,20],1:["button"]}> |
|---|
| 19 | | <WidgetData|text={0:[0x21,0xFF0000],1:["Floating text"]}> |
|---|
| | 17 | <WidgetData|floating={0:[0x8200],1:["text","button"]}> |
|---|
| | 18 | <WidgetData|text={0:[0x21,0xE0E000],1:["Floating text"]}> |
|---|
| 20 | 19 | {Basic} |
|---|
| 21 | 20 | <WidgetData|root={0:[0x21,0x90D970],1:["A string!"]}> |
|---|
| r85 |
r96 |
|
| 31 | 31 | Credits: |
|---|
| 32 | 32 | Me (Diggory Hardy) for just about everything in mde as of now. |
|---|
| | 33 | Someone (?) for the toDg function in mde.util . |
|---|
| 33 | 34 | |
|---|
| 34 | 35 | Also thanks to: |
|---|
| r94 |
r96 |
|
| 254 | 254 | // if here, no existing texture had the room for the glyph so create a new texture |
|---|
| 255 | 255 | // NOTE: check if using more than one texture impacts performance due to texture switching |
|---|
| 256 | | logger.info ("Creating a new font texture."); |
|---|
| | 256 | debug logger.trace ("Creating a new font texture."); |
|---|
| 257 | 257 | tex ~= TexPacker.create(); |
|---|
| 258 | 258 | assert (tex[$-1].addGlyph (ga), "Failed to fit glyph in a new texture but addGlyph didn't throw"); |
|---|
| r93 |
r96 |
|
| 102 | 102 | } |
|---|
| 103 | 103 | IChildWidget widg = child.getWidget (cast(wdabs)cx,cast(wdabs)cy); |
|---|
| | 104 | //debug logger.trace ("Click on {}", widg); |
|---|
| 104 | 105 | if (widg !is null) |
|---|
| 105 | 106 | widg.clickEvent (cast(wdabs)cx,cast(wdabs)cy,b,state); |
|---|
| r95 |
r96 |
|
| 34 | 34 | logger = Log.getLogger ("mde.gui.widget.Floating"); |
|---|
| 35 | 35 | } |
|---|
| 36 | | //FIXME - documentation |
|---|
| 37 | | |
|---|
| 38 | | /** GUI Window class |
|---|
| 39 | | * |
|---|
| 40 | | * A window class instance does two things: (1) specify a region of the screen upon which the window |
|---|
| 41 | | * and its associated widgets are drawn, and (2) load, save, and generally manage all its widgets. |
|---|
| 42 | | * |
|---|
| 43 | | * Let the window load a table of widget data, of type int[][widgetID]. Each widget will, when |
|---|
| 44 | | * created, be given its int[] of data, which this() must confirm is valid (or throw). |
|---|
| 45 | | */ |
|---|
| | 36 | |
|---|
| 46 | 37 | /** An area to contain floating widgets. |
|---|
| 47 | 38 | * |
|---|
| 48 | | * The position of each sub-widget is set from data, but not the size. |
|---|
| | 39 | * The position of each sub-widget is set from dimension data, but not the size. |
|---|
| 49 | 40 | * Rationale: parents' need to set subwidgets' positions when its position is set, so it needs to |
|---|
| 50 | | * know their positions. Size setting is still under work FIXME. |
|---|
| | 41 | * know their positions. |
|---|
| 51 | 42 | * |
|---|
| 52 | 43 | * Data: Each string item is interpreted as a subwidget widgetID. |
|---|
| … | … | |
| 57 | 48 | { |
|---|
| 58 | 49 | this (IWidgetManager mgr, widgetID id, WidgetData data) { |
|---|
| 59 | | subWidgets.length = data.strings.length; |
|---|
| 60 | | foreach (i,s; data.strings) |
|---|
| | 50 | if (data.ints.length != 1) |
|---|
| | 51 | throw new WidgetDataException (this); |
|---|
| | 52 | |
|---|
| | 53 | subWidgets.length = data.strings.length; // widgets created from string data |
|---|
| | 54 | sWOrder.length = subWidgets.length; |
|---|
| | 55 | foreach (i,s; data.strings) { |
|---|
| 61 | 56 | subWidgets[i] = mgr.makeWidget (s); |
|---|
| 62 | | foreach (w; subWidgets) |
|---|
| 63 | | w.finalize; |
|---|
| 64 | | sWCoords.length = subWidgets.length; |
|---|
| 65 | | |
|---|
| 66 | | if (data.ints.length != 1) { |
|---|
| 67 | | if (data.ints.length != 2*subWidgets.length + 1) { |
|---|
| 68 | | throw new WidgetDataException (this); |
|---|
| | 57 | sWOrder[i] = i; |
|---|
| | 58 | } |
|---|
| | 59 | |
|---|
| | 60 | sWCoords = mgr.dimData (id); |
|---|
| | 61 | if (sWCoords.length != subWidgets.length * 2) { |
|---|
| | 62 | // don't bother logging a warning; correct data will be saved anyway |
|---|
| | 63 | sWCoords.length = subWidgets.length * 2; // maybe some data kept |
|---|
| | 64 | } |
|---|
| | 65 | |
|---|
| | 66 | super (mgr, id, data); |
|---|
| | 67 | } |
|---|
| | 68 | |
|---|
| | 69 | bool saveChanges () { |
|---|
| | 70 | foreach (widget; subWidgets) |
|---|
| | 71 | widget.saveChanges (); |
|---|
| | 72 | |
|---|
| | 73 | mgr.setDimData (id, sWCoords); // save positions |
|---|
| | 74 | return true; |
|---|
| | 75 | } |
|---|
| | 76 | |
|---|
| | 77 | void setWidth (wdim nw, int) { |
|---|
| | 78 | w = nw; |
|---|
| | 79 | // check all floating widgets are visible |
|---|
| | 80 | foreach (i, widg; subWidgets) { |
|---|
| | 81 | wdim d; |
|---|
| | 82 | if (sWCoords[i] + (d = widg.width) > w) { |
|---|
| | 83 | if (d > w) |
|---|
| | 84 | sWCoords[i] = 0; |
|---|
| | 85 | else |
|---|
| | 86 | sWCoords[i] = w - d; |
|---|
| 69 | 87 | } |
|---|
| 70 | | foreach (i, ref c; sWCoords) { |
|---|
| 71 | | c.x = cast(wdim) data.ints[i + 1]; |
|---|
| 72 | | c.y = cast(wdim) data.ints[i + 1 + sWCoords.length]; |
|---|
| | 88 | } |
|---|
| | 89 | } |
|---|
| | 90 | void setHeight (wdim nh, int) { |
|---|
| | 91 | h = nh; |
|---|
| | 92 | foreach (i, widg; subWidgets) { |
|---|
| | 93 | wdim d; |
|---|
| | 94 | size_t n = i + subWidgets.length; |
|---|
| | 95 | if (sWCoords[n] + (d = widg.height) > h) { |
|---|
| | 96 | if (d > h) |
|---|
| | 97 | sWCoords[n] = 0; |
|---|
| | 98 | else |
|---|
| | 99 | sWCoords[n] = h - d; |
|---|
| 73 | 100 | } |
|---|
| 74 | | } |
|---|
| 75 | | |
|---|
| 76 | | super (mgr, id, data); |
|---|
| 77 | | |
|---|
| 78 | | foreach (w; subWidgets) { |
|---|
| 79 | | //FIXME: set default size |
|---|
| 80 | | w.setWidth (w.minWidth, -1); |
|---|
| 81 | | w.setHeight (w.minHeight, -1); |
|---|
| 82 | 101 | } |
|---|
| 83 | 102 | } |
|---|
| … | … | |
| 89 | 108 | super.setPosition (x,y); |
|---|
| 90 | 109 | |
|---|
| 91 | | foreach (i,c; sWCoords) |
|---|
| 92 | | subWidgets[i].setPosition (x+c.x, y+c.y); |
|---|
| | 110 | size_t n = subWidgets.length; |
|---|
| | 111 | foreach (i,widg; subWidgets) |
|---|
| | 112 | widg.setPosition (x+sWCoords[i], y+sWCoords[i+n]); |
|---|
| 93 | 113 | } |
|---|
| 94 | 114 | |
|---|
| … | … | |
| 98 | 118 | mgr.renderer.restrict (x,y, w,h); |
|---|
| 99 | 119 | |
|---|
| 100 | | foreach (w; subWidgets) |
|---|
| 101 | | w.draw; |
|---|
| | 120 | foreach (i; sWOrder) |
|---|
| | 121 | subWidgets[i].draw; |
|---|
| | 122 | } |
|---|
| | 123 | |
|---|
| | 124 | IChildWidget getWidget (wdim cx, wdim cy) { |
|---|
| | 125 | debug assert (cx >= x && cx < x + w && cy >= y && cy < y + h, "getWidget: not on widget (code error)"); |
|---|
| | 126 | |
|---|
| | 127 | size_t n = subWidgets.length; |
|---|
| | 128 | foreach_reverse (j,i; sWOrder) { |
|---|
| | 129 | wdim lx = cx - (x + sWCoords[i ]); |
|---|
| | 130 | wdim ly = cy - (y + sWCoords[i+n]); |
|---|
| | 131 | if (lx >= 0 && lx < subWidgets[i].width && |
|---|
| | 132 | ly >= 0 && ly < subWidgets[i].height) |
|---|
| | 133 | { |
|---|
| | 134 | sWOrder[j..$-1] = sWOrder[j+1..$].dup; |
|---|
| | 135 | sWOrder[$-1] = i; |
|---|
| | 136 | mgr.requestRedraw; |
|---|
| | 137 | return subWidgets[i]; |
|---|
| | 138 | } |
|---|
| | 139 | } |
|---|
| | 140 | return this; // no match |
|---|
| 102 | 141 | } |
|---|
| 103 | 142 | |
|---|
| 104 | 143 | protected: |
|---|
| 105 | | wdimPair[] sWCoords; // coords for subwidgets, relative to this widget |
|---|
| | 144 | wdim[] sWCoords; // coords for subwidgets, relative to this widget: [x1,x2,...,y1,y2,...] |
|---|
| | 145 | size_t[] sWOrder; // indexes for draw order (top widget at end of list) |
|---|
| 106 | 146 | |
|---|
| 107 | 147 | /+ |
|---|
| r95 |
r96 |
|
| 139 | 139 | * parameters) if the data has wrong length or is otherwise invalid. |
|---|
| 140 | 140 | * |
|---|
| 141 | | * A parent widget is responsible for setting the size of its children widgets, however it must |
|---|
| 142 | | * satisfy their minimal sizes as available from minWidth() and minHeight(). setWidth() and |
|---|
| 143 | | * setHeight() are called on all widgets after creation. |
|---|
| | 141 | * All widgets should set their own size in this() or finalize(), although some parents may set |
|---|
| | 142 | * child-widgets' size during their creation. Widgets may rely on setPosition() being called after |
|---|
| | 143 | * finalize(). |
|---|
| 144 | 144 | * |
|---|
| 145 | 145 | * Also see finalize(). |
|---|
| r95 |
r96 |
|
| 42 | 42 | this (IWidgetManager mgr, widgetID id, WidgetData data) { |
|---|
| 43 | 43 | adapter.getDimensions (mw, mh); |
|---|
| | 44 | w = mw; |
|---|
| | 45 | h = mh; |
|---|
| 44 | 46 | super (mgr, id, data); |
|---|
| 45 | 47 | } |
|---|
| r95 |
r96 |
|
| 209 | 209 | /** For pressable buttons. |
|---|
| 210 | 210 | * |
|---|
| 211 | | * Normally overriding classes implement this, draw and activated. */ |
|---|
| | 211 | * Overriding classes should implement this() (setting the size), draw() and activated(). */ |
|---|
| 212 | 212 | abstract class AButtonWidget : AWidget |
|---|
| 213 | 213 | { |
|---|