Mercurial > projects > mde
comparison mde/gui/WidgetManager.d @ 85:56c0ddd90193
Intermediate commit (not stable). Changes to init system.
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Thu, 11 Sep 2008 11:33:51 +0100 |
parents | e0f1ec7fe73a |
children | 79d816b3e2d2 |
comparison
equal
deleted
inserted
replaced
84:e0f1ec7fe73a | 85:56c0ddd90193 |
---|---|
27 | 27 |
28 // For adding the input event callbacks and requesting redraws: | 28 // For adding the input event callbacks and requesting redraws: |
29 import imde = mde.imde; | 29 import imde = mde.imde; |
30 import mde.input.Input; | 30 import mde.input.Input; |
31 import mde.scheduler.Scheduler; | 31 import mde.scheduler.Scheduler; |
32 import mde.setup.Screen; | |
32 | 33 |
33 import tango.core.sync.Mutex; | 34 import tango.core.sync.Mutex; |
34 import tango.util.log.Log : Log, Logger; | 35 import tango.util.log.Log : Log, Logger; |
35 | 36 |
36 private Logger logger; | 37 private Logger logger; |
37 static this () { | 38 static this () { |
38 logger = Log.getLogger ("mde.gui.WidgetManager"); | 39 logger = Log.getLogger ("mde.gui.WidgetManager"); |
39 | |
40 gui = new WidgetManager ("gui"); | |
41 } | 40 } |
42 | |
43 WidgetManager gui; | |
44 | |
45 | 41 |
46 /************************************************************************************************* | 42 /************************************************************************************************* |
47 * The widget manager. | 43 * The widget manager. |
48 * | 44 * |
49 * This is responsible for loading and saving an entire gui (although more than one may exist), | 45 * This is responsible for loading and saving an entire gui (although more than one may exist), |
52 * Currently mouse coordinates are passed to widgets untranslated. It may make sense to translate | 48 * Currently mouse coordinates are passed to widgets untranslated. It may make sense to translate |
53 * them and possibly drop events for some uses, such as if the gui is drawn to a texture. | 49 * them and possibly drop events for some uses, such as if the gui is drawn to a texture. |
54 * | 50 * |
55 * Aside from the IWidgetManager methods, this class should be thread-safe. | 51 * Aside from the IWidgetManager methods, this class should be thread-safe. |
56 *************************************************************************************************/ | 52 *************************************************************************************************/ |
57 class WidgetManager : WidgetLoader { | 53 class WidgetManager : WidgetLoader, Screen.Drawable { |
58 /** Construct a new widget manager. | 54 /** Construct a new widget manager. |
59 * | 55 * |
60 * params: | 56 * params: |
61 * fileName = Name of file specifying the gui, excluding path and extension. | 57 * fileName = Name of file specifying the gui, excluding path and extension. |
62 */ | 58 */ |
63 this (char[] file) { | 59 this (char[] file) { |
64 super(file); | 60 super(file); |
61 | |
62 Screen.addDrawable (this); | |
65 } | 63 } |
66 | 64 |
67 // NOTE - temporarily here to allow CTOR to run safely during static this | 65 // NOTE - temporarily here to allow CTOR to run safely during static this |
68 // called during init | 66 // called during init |
69 void init () { | 67 void init () { |
68 // Doesn't need a lock - cannot conflict with other class functions. | |
70 // Events we want to know about: | 69 // Events we want to know about: |
71 imde.input.addMouseClickCallback(&clickEvent); | 70 imde.input.addMouseClickCallback(&clickEvent); |
72 imde.input.addMouseMotionCallback(&motionEvent); | 71 imde.input.addMouseMotionCallback(&motionEvent); |
73 } | 72 } |
74 | 73 |
75 | 74 |
76 /** Draw the gui. */ | 75 /** Draw the gui. */ |
77 void draw() { | 76 void draw() { |
77 debug logger.trace ("drawing; w,h = {},{}",w,h); | |
78 synchronized(mutex) | 78 synchronized(mutex) |
79 child.draw; | 79 if (child) |
80 child.draw; | |
80 } | 81 } |
81 | 82 |
82 | 83 |
83 /** For mouse click events. | 84 /** For mouse click events. |
84 * | 85 * |
86 void clickEvent (ushort cx, ushort cy, ubyte b, bool state) { | 87 void clickEvent (ushort cx, ushort cy, ubyte b, bool state) { |
87 debug scope (failure) | 88 debug scope (failure) |
88 logger.warn ("clickEvent: failed!"); | 89 logger.warn ("clickEvent: failed!"); |
89 mutex.lock; | 90 mutex.lock; |
90 scope(exit) mutex.unlock; | 91 scope(exit) mutex.unlock; |
92 if (child is null) return; | |
91 | 93 |
92 // NOTE: buttons receive the up-event even when drag-callbacks are in place. | 94 // NOTE: buttons receive the up-event even when drag-callbacks are in place. |
93 foreach (dg; clickCallbacks) | 95 foreach (dg; clickCallbacks) |
94 // See IWidgetManager.addClickCallback's documentation: | 96 // See IWidgetManager.addClickCallback's documentation: |
95 if (dg (cast(wdabs)cx, cast(wdabs)cy, b, state)) return; | 97 if (dg (cast(wdabs)cx, cast(wdabs)cy, b, state)) return; |
96 | 98 |
97 // NOTE: do we need to test if the click was on the gui (and thus child)? | 99 // NOTE: do we need to test if the click was on the gui (and thus child)? |
100 // FIXME: yes, unless we can guarantee this! | |
98 IChildWidget widg = child.getWidget (cast(wdabs)cx,cast(wdabs)cy); | 101 IChildWidget widg = child.getWidget (cast(wdabs)cx,cast(wdabs)cy); |
99 if (widg !is null) | 102 if (widg !is null) |
100 widg.clickEvent (cast(wdabs)cx,cast(wdabs)cy,b,state); | 103 widg.clickEvent (cast(wdabs)cx,cast(wdabs)cy,b,state); |
101 /+ FIXME: remove | |
102 foreach (i,w; windows) { | |
103 IWidget widg = w.getWidget (cast(wdabs)cx,cast(wdabs)cy); | |
104 if (widg !is null) { | |
105 // Bring to front | |
106 windows = w ~ windows[0..i] ~ windows[i+1..$]; | |
107 | |
108 widg.clickEvent (cast(wdabs)cx,cast(wdabs)cy,b,state); | |
109 requestRedraw; // in case we've only moved to front | |
110 return; // only pass to first window | |
111 } | |
112 }+/ | |
113 } | 104 } |
114 | 105 |
115 /** For mouse motion events. | 106 /** For mouse motion events. |
116 * | 107 * |
117 * Sends the event on to all motion callbacks. */ | 108 * Sends the event on to all motion callbacks. */ |
124 foreach (dg; motionCallbacks) | 115 foreach (dg; motionCallbacks) |
125 dg (cast(wdabs)cx, cast(wdabs)cy); | 116 dg (cast(wdabs)cx, cast(wdabs)cy); |
126 } | 117 } |
127 | 118 |
128 | 119 |
129 void setSize (int x, int y) { | 120 void sizeEvent (int nw, int nh) { // Drawable function |
130 mutex.lock; | 121 mutex.lock; |
131 scope(exit) mutex.unlock; | 122 scope(exit) mutex.unlock; |
132 | 123 |
133 w = cast(wdim) x; | 124 w = cast(wdim) nw; |
134 h = cast(wdim) y; | 125 h = cast(wdim) nh; |
135 | 126 |
136 if (child is null) | 127 debug logger.trace ("Resize to: {},{}", nw, nh); |
137 return; // May not have been created before this is first run. | 128 if (w < mw || h < mh) |
129 logger.warn ("Minimal dimensions ({},{}) not met: ({},{}), but I cannot resize myself!",mw,mh,w,h); | |
130 | |
131 if (!child) return; // if not created yet. | |
138 child.setWidth (w, -1); | 132 child.setWidth (w, -1); |
139 child.setHeight (h, -1); | 133 child.setHeight (h, -1); |
140 child.setPosition (0,0); | 134 child.setPosition (0,0); |
141 } | 135 } |
142 | 136 |
163 motionCallbacks.remove(frame); | 157 motionCallbacks.remove(frame); |
164 } | 158 } |
165 //END IWidgetManager methods | 159 //END IWidgetManager methods |
166 | 160 |
167 protected: | 161 protected: |
168 /* Second stage of widget loading. */ | 162 /* Second stage of widget loading. |
163 * Note: sizeEvent should be called with window size before this. */ | |
169 void createRootWidget () { | 164 void createRootWidget () { |
170 // The renderer needs to be created on the first load, but not after this. | 165 // The renderer needs to be created on the first load, but not after this. |
171 if (rend is null) | 166 if (rend is null) |
172 rend = createRenderer (rendName); | 167 rend = createRenderer (rendName); |
173 | 168 |
174 child = makeWidget ("root"); | 169 child = makeWidget ("root"); |
170 | |
171 mw = child.minWidth; | |
172 mh = child.minHeight; | |
173 | |
174 if (w < mw || h < mh) | |
175 logger.warn ("Minimal dimensions ({},{}) not met: ({},{}), but I cannot resize myself!",mw,mh,w,h); | |
175 | 176 |
176 child.setWidth (w, -1); | 177 child.setWidth (w, -1); |
177 child.setHeight (h, -1); | 178 child.setHeight (h, -1); |
178 child.setPosition (0,0); | 179 child.setPosition (0,0); |
179 } | 180 } |
182 // callbacks indexed by their frame pointers: | 183 // callbacks indexed by their frame pointers: |
183 bool delegate(wdabs cx, wdabs cy, ubyte b, bool state) [void*] clickCallbacks; | 184 bool delegate(wdabs cx, wdabs cy, ubyte b, bool state) [void*] clickCallbacks; |
184 void delegate(wdabs cx, wdabs cy) [void*] motionCallbacks; | 185 void delegate(wdabs cx, wdabs cy) [void*] motionCallbacks; |
185 IRenderer rend; | 186 IRenderer rend; |
186 wdim w,h; // area available to the widgets | 187 wdim w,h; // area available to the widgets |
188 wdim mw,mh; // minimal area available to the widgets | |
187 } | 189 } |
188 | 190 |
189 | 191 |
190 import mde.gui.exception; | 192 import mde.gui.exception; |
191 import mde.gui.widget.Ifaces; | 193 import mde.gui.widget.Ifaces; |
209 * fileName = Name of file specifying the gui, excluding path and extension. | 211 * fileName = Name of file specifying the gui, excluding path and extension. |
210 */ | 212 */ |
211 protected this (char[] file) { | 213 protected this (char[] file) { |
212 mutex = new Mutex; // Used on functions intended to be called from outside the gui package. | 214 mutex = new Mutex; // Used on functions intended to be called from outside the gui package. |
213 fileName = file; | 215 fileName = file; |
214 } | |
215 ~this () { | |
216 save; | |
217 } | 216 } |
218 | 217 |
219 /* Load the widgets' data from the file specified to the CTOR. | 218 /* Load the widgets' data from the file specified to the CTOR. |
220 * | 219 * |
221 * params: | 220 * params: |
378 } | 377 } |
379 | 378 |
380 | 379 |
381 /** Create a widget by ID. */ | 380 /** Create a widget by ID. */ |
382 IChildWidget makeWidget (widgetID id, IParentWidget parent = null) { | 381 IChildWidget makeWidget (widgetID id, IParentWidget parent = null) { |
383 debug logger.trace ("Creating widget \""~id~'"'); | 382 debug (mdeWidgets) logger.trace ("Creating widget \""~id~'"'); |
384 return createWidget (this, curData[id], parent); | 383 return createWidget (this, curData[id], parent); |
385 } | 384 } |
386 | 385 |
387 /** For making changes. */ | 386 /** For making changes. */ |
388 void setData (widgetID id, WidgetData d) { | 387 void setData (widgetID id, WidgetData d) { |