Mercurial > projects > mde
comparison mde/gui/gui.d @ 27:0aa621b3e070
Some GUI work, plus a small fix in the paths module.
Implemented GUI code to load windows from file with a basic widget and draw.
Fixed a bug in mde.resource.paths.mdeDirectory.makeMTReader when called with readOrder == PRIORITY.HIGH_ONLY.
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Fri, 04 Apr 2008 17:07:38 +0100 |
parents | |
children | b5fadd8d930b |
comparison
equal
deleted
inserted
replaced
26:611f7b9063c6 | 27:0aa621b3e070 |
---|---|
1 /* LICENSE BLOCK | |
2 Part of mde: a Modular D game-oriented Engine | |
3 Copyright © 2007-2008 Diggory Hardy | |
4 | |
5 This program is free software: you can redistribute it and/or modify it under the terms | |
6 of the GNU General Public License as published by the Free Software Foundation, either | |
7 version 2 of the License, or (at your option) any later version. | |
8 | |
9 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; | |
10 without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
11 See the GNU General Public License for more details. | |
12 | |
13 You should have received a copy of the GNU General Public License | |
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
15 | |
16 /// Base GUI module. | |
17 module mde.gui.gui; | |
18 | |
19 import mde.gui.Widget; | |
20 import mde.gui.exception; | |
21 | |
22 import mt = mde.mergetag.DataSet; | |
23 import mt = mde.mergetag.exception; | |
24 import mde.mergetag.Reader; | |
25 | |
26 import mde.resource.paths; | |
27 import mde.scheduler.InitFunctions; | |
28 | |
29 import tango.scrapple.text.convert.parseTo : parseTo; | |
30 import tango.scrapple.text.convert.parseFrom : parseFrom; | |
31 | |
32 private Logger logger; | |
33 static this () { | |
34 logger = Log.getLogger ("mde.gui.gui"); | |
35 | |
36 init.addFunc (&GUI.load); | |
37 } | |
38 | |
39 struct GUI { | |
40 static: | |
41 private const fileName = "gui"; | |
42 void load() { | |
43 if (!confDir.exists (fileName)) { | |
44 logger.error ("Unable to load GUI: no config file!"); | |
45 return; // not a fatal error (so long as the game can run without a GUI!) | |
46 } | |
47 | |
48 IReader reader; | |
49 try { | |
50 reader = confDir.makeMTReader (fileName, PRIORITY.HIGH_ONLY); | |
51 reader.dataSecCreator = delegate mt.IDataSection(mt.ID) { | |
52 return new Window; | |
53 }; | |
54 reader.read; | |
55 } catch (mt.MTException e) { | |
56 logger.error ("Loading GUI aborted:"); | |
57 logger.error (e.msg); | |
58 | |
59 return; | |
60 } | |
61 | |
62 // get list | |
63 windows.length = reader.dataset.sec.length; // pre-allocate | |
64 windows.length = 0; | |
65 foreach (sec; reader.dataset.sec) { | |
66 Window w = cast(Window) sec; | |
67 if (w !is null) { // extra safety | |
68 windows ~= w; | |
69 try { | |
70 w.finalise(); | |
71 } catch (WindowLoadException e) { | |
72 logger.error ("Window failed to load: " ~ e.msg); | |
73 } | |
74 | |
75 gl.addDrawCallback (&w.draw); | |
76 } | |
77 } | |
78 } | |
79 | |
80 private: | |
81 Window[] windows; | |
82 } | |
83 | |
84 package: // Nothing else here is for external use. | |
85 | |
86 /** GUI Window class | |
87 * | |
88 * A window class instance does two things: (1) specify a region of the screen upon which the window | |
89 * and its associated widgets are drawn, and (2) load, save, and generally manage all its widgets. | |
90 * | |
91 * Let the window load a table of widget data, of type int[][widgetID]. Each widget will, when | |
92 * created, be given its int[] of data, which this() must confirm is valid (or throw). | |
93 */ | |
94 class Window : mt.IDataSection | |
95 { | |
96 alias int widgetID; // Widget ID type. Each ID is unique under this window. Type is int since this is the widget data type. | |
97 private int[][widgetID] widgetData; // Data for all widgets under this window. | |
98 private Widget[widgetID] widgets; // List of all widgets under this window (created on demand). | |
99 | |
100 Widget widget; // The primary widget in this window. | |
101 int x,y; // Window position | |
102 int w,h; // Window size (calculated from Widgets) | |
103 | |
104 const BORDER_WIDTH = 5; // Temporary way to handle window decorations | |
105 | |
106 | |
107 // Call after loading is finished to setup the window and confirm that it's valid. | |
108 void finalise () { | |
109 // Create the widget, throwing on error: | |
110 widget = getWidget (0); // primary widget always has ID 0. | |
111 widget.getSize (w,h); // Find the initial size | |
112 w += BORDER_WIDTH * 2; // Adjust for border | |
113 h += BORDER_WIDTH * 2; | |
114 } | |
115 | |
116 Widget getWidget (widgetID i) { | |
117 // See if it's already been created: | |
118 Widget* p = i in widgets; | |
119 if (p !is null) return *p; // yes | |
120 else { // no | |
121 int[]* d = i in widgetData; | |
122 if (d is null) throw new WindowLoadException ("Widget not found"); | |
123 | |
124 // Throws WidgetDataException (a WindowLoadException) if bad data: | |
125 Widget w = createWidget (*d); | |
126 widgets[i] = w; | |
127 return w; | |
128 } | |
129 } | |
130 | |
131 void draw () { | |
132 //BEGIN Window border/back | |
133 gl.setColor (0.0f, 0.0f, 0.5f); | |
134 gl.drawBox (x,x+w, y,y+h); | |
135 //END Window border/back | |
136 | |
137 // Tell the widget to draw itself: | |
138 widget.draw(x + BORDER_WIDTH, y + BORDER_WIDTH); | |
139 } | |
140 | |
141 //BEGIN Mergetag code | |
142 void addTag (char[] tp, mt.ID id, char[] dt) { | |
143 if (tp == "int[][int]") { | |
144 if (id == "widgetData") { | |
145 widgetData = cast(int[][widgetID]) parseTo!(int[][int]) (dt); | |
146 } | |
147 } else if (tp == "int") { | |
148 if (id == "x") { | |
149 x = parseTo!(int) (dt); | |
150 } else if (id == "y") { | |
151 y = parseTo!(int) (dt); | |
152 } | |
153 } | |
154 } | |
155 void writeAll (ItemDelg dlg) { | |
156 } | |
157 //END Mergetag code | |
158 } |