Mercurial > projects > mde
comparison mde/gui/content/Content.d @ 101:71f0f1f83620
Some path adjustments for windows (untested) and fonts. All types of option can be edited.
paths: support for getting the full path for a font when just the file name is entered, in order to unify usage on windows and linux.
paths: Used getSpecialPath for some windows paths; needs testing.
Content: Moved line-editing code to abstract ValueContent class and added some conversion functions, so that any type of ValueContent can be edited as text.
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Sun, 16 Nov 2008 17:03:47 +0000 |
parents | 0ea4a3e651ae |
children | 42e241e7be3e |
comparison
equal
deleted
inserted
replaced
100:0ea4a3e651ae | 101:71f0f1f83620 |
---|---|
89 | 89 |
90 void name (char[] n, char[] d = null) { | 90 void name (char[] n, char[] d = null) { |
91 name_ = n; | 91 name_ = n; |
92 desc_ = d; | 92 desc_ = d; |
93 } | 93 } |
94 protected: | 94 |
95 /// Get the text. | |
96 char[] toString (uint i) { | |
97 return (i == 0) ? sv | |
98 : (i == 1) ? name_ | |
99 : (i == 2) ? desc_ | |
100 : null; | |
101 } | |
102 | |
103 /** Acts on a keystroke and returns the new value. | |
104 * | |
105 * Supports one-line editing: left/right, home/end, backspace/delete. */ | |
106 char[] keyStroke (ushort sym, char[] i) { | |
107 debug assert (i.length, "TextContent.keyStroke: no value (??)"); // impossible? | |
108 char k = *i; | |
109 if (k > 0x20) { | |
110 if (k == 0x7f) { // delete | |
111 size_t p = pos; | |
112 if (p < sv.length) ++p; | |
113 while (p < sv.length && (sv[p] & 0x80) && !(sv[p] & 0x40)) | |
114 ++p; | |
115 sv = sv[0..pos] ~ sv[p..$]; | |
116 } else { // insert character | |
117 char[] tail = sv[pos..$]; | |
118 sv.length = sv.length + i.length; | |
119 size_t npos = pos+i.length; | |
120 if (tail) sv[npos..$] = tail.dup; // cannot assign with overlapping ranges | |
121 sv[pos..npos] = i; | |
122 pos = npos; | |
123 } | |
124 } else { // use sym; many keys output 0 | |
125 if (sym == SDLK_BACKSPACE) { // backspace; k == 0x8 | |
126 char[] tail = sv[pos..$]; | |
127 if (pos) --pos; | |
128 while (pos && (sv[pos] & 0x80) && !(sv[pos] & 0x40)) | |
129 --pos; | |
130 sv = sv[0..pos] ~ tail; | |
131 } else if (sym == SDLK_LEFT) { | |
132 if (pos) --pos; | |
133 while (pos && (sv[pos] & 0x80) && !(sv[pos] & 0x40)) | |
134 --pos; | |
135 } else if (sym == SDLK_RIGHT) { | |
136 if (pos < sv.length) ++pos; | |
137 while (pos < sv.length && (sv[pos] & 0x80) && !(sv[pos] & 0x40)) | |
138 ++pos; | |
139 } else if (sym == SDLK_HOME || sym == SDLK_UP) { | |
140 pos = 0; | |
141 } else if (sym == SDLK_END || sym == SDLK_DOWN) { | |
142 pos = sv.length; | |
143 } else | |
144 debug logger.trace ("Symbol: {}", sym); | |
145 } | |
146 return sv; | |
147 } | |
148 | |
149 size_t getEditIndex () { | |
150 size_t i = 0; | |
151 for (size_t p = 0; p < pos; ++p) | |
152 if (!(sv[p] & 0x80) || sv[p] & 0x40) | |
153 ++i; | |
154 return i; | |
155 } | |
156 | |
157 /// Call at the end of an edit to convert sv to v and call callbacks | |
158 void endEdit (); | |
159 protected: | |
160 char[] sv; // string of value; updated on assignment for displaying and editing | |
161 size_t pos; // editing position; used by keyStroke | |
162 char[] symb; | |
95 char[] name_, desc_;// name and description, loaded by lookup.Translation | 163 char[] name_, desc_;// name and description, loaded by lookup.Translation |
96 } | 164 } |
97 | 165 |
98 template VContentN(T) { | 166 template VContentN(T) { |
99 static if (is(T == bool)) { | 167 static if (is(T == bool)) { |
111 class BoolContent : ValueContent | 179 class BoolContent : ValueContent |
112 { | 180 { |
113 /** Create a content with _symbol name symbol. */ | 181 /** Create a content with _symbol name symbol. */ |
114 this (char[] symbol, bool val = false) { | 182 this (char[] symbol, bool val = false) { |
115 symb = symbol; | 183 symb = symbol; |
116 v = val; | 184 assignNoCB (val); |
117 } | 185 } |
118 | 186 |
119 /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ | 187 /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ |
120 BoolContent addChangeCb (void delegate (char[] symbol,bool value) cb) { | 188 BoolContent addChangeCb (void delegate (char[] symbol,bool value) cb) { |
121 cngCb ~= cb; | 189 cngCb ~= cb; |
122 return this; | 190 return this; |
123 } | 191 } |
124 | 192 |
125 /// Get the text. | 193 void assignNoCB (bool val) { |
126 char[] toString (uint i) { | 194 v = val; |
127 return (i == 0) ? v ? "true" : "false" | 195 sv = v ? "true" : "false"; |
128 : (i == 1) ? name_ | 196 } |
129 : (i == 2) ? desc_ | |
130 : null; | |
131 } | |
132 | |
133 void opAssign (bool val) { | 197 void opAssign (bool val) { |
134 v = val; | 198 assignNoCB (val); |
135 foreach (cb; cngCb) | 199 foreach (cb; cngCb) |
136 cb(symb, val); | 200 cb(symb, val); |
137 } | 201 } |
138 bool opCall () { | 202 bool opCall () { |
139 return v; | 203 return v; |
140 } | 204 } |
141 alias opCall opCast; | 205 alias opCall opCast; |
142 | 206 |
143 bool v; //FIXME: should be protected but Options needs to set without calling callbacks | 207 void endEdit () { |
144 protected: | 208 v = sv && (sv[0] == 't' || sv[0] == 'T' || sv[0] == '1'); |
145 char[] symb; | 209 foreach (cb; cngCb) |
210 cb(symb, v); | |
211 } | |
212 | |
213 protected: | |
214 bool v; | |
146 void delegate (char[],bool)[] cngCb; // change callbacks | 215 void delegate (char[],bool)[] cngCb; // change callbacks |
147 } | 216 } |
148 | 217 |
149 /** Text content. */ | 218 /** Text content. */ |
150 class TextContent : ValueContent | 219 class TextContent : ValueContent |
151 { | 220 { |
152 this (char[] symbol, char[] val = null) { | 221 this (char[] symbol, char[] val = null) { |
153 symb = symbol; | 222 symb = symbol; |
154 v = val; | 223 v = val; |
155 pos = v.length; | |
156 } | 224 } |
157 | 225 |
158 /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ | 226 /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ |
159 TextContent addChangeCb (void delegate (char[] symbol,char[] value) cb) { | 227 TextContent addChangeCb (void delegate (char[] symbol,char[] value) cb) { |
160 cngCb ~= cb; | 228 cngCb ~= cb; |
161 return this; | 229 return this; |
162 } | 230 } |
163 | 231 |
164 /// Get the text. | 232 void assignNoCB (char[] val) { |
165 char[] toString (uint i) { | 233 v = val; |
166 return (i == 0) ? v | 234 } |
167 : (i == 1) ? name_ | |
168 : (i == 2) ? desc_ | |
169 : null; | |
170 } | |
171 | |
172 void opAssign (char[] val) { | 235 void opAssign (char[] val) { |
173 v = val; | 236 v = val; |
174 foreach (cb; cngCb) | 237 foreach (cb; cngCb) |
175 cb(symb, val); | 238 cb(symb, val); |
176 } | 239 } |
177 char[] opCall () { | 240 char[] opCall () { |
178 return v; | 241 return v; |
179 } | 242 } |
180 alias opCall opCast; | 243 alias opCall opCast; |
181 | 244 |
182 /** Acts on a keystroke and returns the new value. | |
183 * | |
184 * Supports one-line editing: left/right, home/end, backspace/delete. */ | |
185 char[] keyStroke (ushort sym, char[] i) { | |
186 debug assert (i.length, "TextContent.keyStroke: no value (??)"); // impossible? | |
187 char k = *i; | |
188 if (k > 0x20) { | |
189 if (k == 0x7f) { // delete | |
190 size_t p = pos; | |
191 if (p < v.length) ++p; | |
192 while (p < v.length && (v[p] & 0x80) && !(v[p] & 0x40)) | |
193 ++p; | |
194 v = v[0..pos] ~ v[p..$]; | |
195 } else { // insert character | |
196 char[] tail = v[pos..$]; | |
197 v.length = v.length + i.length; | |
198 size_t npos = pos+i.length; | |
199 if (tail) v[npos..$] = tail.dup; // cannot assign with overlapping ranges | |
200 v[pos..npos] = i; | |
201 pos = npos; | |
202 } | |
203 } else { // use sym; many keys output 0 | |
204 if (sym == SDLK_BACKSPACE) { // backspace; k == 0x8 | |
205 char[] tail = v[pos..$]; | |
206 if (pos) --pos; | |
207 while (pos && (v[pos] & 0x80) && !(v[pos] & 0x40)) | |
208 --pos; | |
209 v = v[0..pos] ~ tail; | |
210 } else if (sym == SDLK_LEFT) { | |
211 if (pos) --pos; | |
212 while (pos && (v[pos] & 0x80) && !(v[pos] & 0x40)) | |
213 --pos; | |
214 } else if (sym == SDLK_RIGHT) { | |
215 if (pos < v.length) ++pos; | |
216 while (pos < v.length && (v[pos] & 0x80) && !(v[pos] & 0x40)) | |
217 ++pos; | |
218 } else if (sym == SDLK_HOME || sym == SDLK_UP) { | |
219 pos = 0; | |
220 } else if (sym == SDLK_END || sym == SDLK_DOWN) { | |
221 pos = v.length; | |
222 } else | |
223 debug logger.trace ("Symbol: {}", sym); | |
224 } | |
225 return v; | |
226 } | |
227 | |
228 size_t getEditIndex () { | |
229 size_t i = 0; | |
230 for (size_t p = 0; p < pos; ++p) | |
231 if (!(v[p] & 0x80) || v[p] & 0x40) | |
232 ++i; | |
233 return i; | |
234 } | |
235 | |
236 /// Gives all callbacks the modified value | |
237 void endEdit () { | 245 void endEdit () { |
238 foreach (cb; cngCb) | 246 foreach (cb; cngCb) |
239 cb(symb, v); | 247 cb(symb, v); |
240 } | 248 } |
241 | 249 |
242 char[] v; | 250 protected: |
243 protected: | 251 alias sv v; // don't need separate v and sv in this case |
244 char[] symb; | |
245 size_t pos; // editing position; used by keyStroke | |
246 void delegate (char[],char[])[] cngCb; | 252 void delegate (char[],char[])[] cngCb; |
247 } | 253 } |
248 | 254 |
249 /** Integer content. */ | 255 /** Integer content. */ |
250 class IntContent : ValueContent | 256 class IntContent : ValueContent |
251 { | 257 { |
252 /** Create a content with _symbol name symbol. */ | 258 /** Create a content with _symbol name symbol. */ |
253 this (char[] symbol, int val = 0) { | 259 this (char[] symbol, int val = 0) { |
254 symb = symbol; | 260 symb = symbol; |
255 v = val; | 261 assignNoCB (val); |
256 } | 262 } |
257 | 263 |
258 /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ | 264 /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ |
259 IntContent addChangeCb (void delegate (char[] symbol,int value) cb) { | 265 IntContent addChangeCb (void delegate (char[] symbol,int value) cb) { |
260 cngCb ~= cb; | 266 cngCb ~= cb; |
261 return this; | 267 return this; |
262 } | 268 } |
263 | 269 |
264 /// Get the text. | 270 void assignNoCB (int val) { |
265 char[] toString (uint i) { | 271 v = val; |
266 return (i == 0) ? Int.toString (v) | 272 sv = Int.toString (v); |
267 : (i == 1) ? name_ | 273 } |
268 : (i == 2) ? desc_ | |
269 : null; | |
270 } | |
271 | |
272 void opAssign (int val) { | 274 void opAssign (int val) { |
273 v = val; | 275 assignNoCB (val); |
274 foreach (cb; cngCb) | 276 foreach (cb; cngCb) |
275 cb(symb, val); | 277 cb(symb, val); |
276 } | 278 } |
277 int opCall () { | 279 int opCall () { |
278 return v; | 280 return v; |
279 } | 281 } |
280 alias opCall opCast; | 282 alias opCall opCast; |
281 | 283 |
284 void endEdit () { | |
285 v = Int.toInt (sv); | |
286 foreach (cb; cngCb) | |
287 cb(symb, v); | |
288 } | |
289 | |
290 protected: | |
282 int v; | 291 int v; |
283 protected: | |
284 char[] symb; | |
285 void delegate (char[],int)[] cngCb; | 292 void delegate (char[],int)[] cngCb; |
286 } | 293 } |
287 | 294 |
288 /** Double content. */ | 295 /** Double content. */ |
289 class DoubleContent : ValueContent | 296 class DoubleContent : ValueContent |
290 { | 297 { |
291 /** Create a content with _symbol name symbol. */ | 298 /** Create a content with _symbol name symbol. */ |
292 this (char[] symbol, double val = 0) { | 299 this (char[] symbol, double val = 0) { |
293 symb = symbol; | 300 symb = symbol; |
294 v = val; | 301 assignNoCB (val); |
295 } | 302 } |
296 | 303 |
297 /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ | 304 /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ |
298 DoubleContent addChangeCb (void delegate (char[] symbol,double value) cb) { | 305 DoubleContent addChangeCb (void delegate (char[] symbol,double value) cb) { |
299 cngCb ~= cb; | 306 cngCb ~= cb; |
300 return this; | 307 return this; |
301 } | 308 } |
302 | 309 |
303 /// Get the text. | 310 void assignNoCB (double val) { |
304 char[] toString (uint i) { | 311 v = val; |
305 return (i == 0) ? Float.toString (v) | 312 sv = Float.toString (v); |
306 : (i == 1) ? name_ | 313 } |
307 : (i == 2) ? desc_ | |
308 : null; | |
309 } | |
310 | |
311 void opAssign (double val) { | 314 void opAssign (double val) { |
312 v = val; | 315 assignNoCB (val); |
313 foreach (cb; cngCb) | 316 foreach (cb; cngCb) |
314 cb(symb, val); | 317 cb(symb, val); |
315 } | 318 } |
316 double opCall () { | 319 double opCall () { |
317 return v; | 320 return v; |
318 } | 321 } |
319 alias opCall opCast; | 322 alias opCall opCast; |
320 | 323 |
324 void endEdit () { | |
325 v = Float.toFloat (sv); | |
326 foreach (cb; cngCb) | |
327 cb(symb, v); | |
328 } | |
329 | |
330 protected: | |
321 double v; | 331 double v; |
322 protected: | |
323 char[] symb; | |
324 void delegate (char[],double)[] cngCb; | 332 void delegate (char[],double)[] cngCb; |
325 } | 333 } |