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 }