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 }