Refactoring of rec process "~" in faustexp.ml.
[Faustine.git] / interpretor / faust-0.9.47mr3 / architecture / iPhone / CocoaUI.h
1 /************************************************************************
2
3 IMPORTANT NOTE : this file contains two clearly delimited sections :
4 the ARCHITECTURE section (in two parts) and the USER section. Each section
5 is governed by its own copyright and license. Please check individually
6 each section for license and copyright information.
7 *************************************************************************/
8
9 /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
10
11 /************************************************************************
12 FAUST Architecture File
13 Copyright (C) 2004-2011 GRAME, Centre National de Creation Musicale
14 ---------------------------------------------------------------------
15 This Architecture section is free software; you can redistribute it
16 and/or modify it under the terms of the GNU Lesser General Public
17 License as published by the Free Software Foundation; either version 3
18 of the License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU Lesser General Public License for more details.
24
25 You should have received a copy of the GNU Lesser General Public License
26 along with this program; If not, see <http://www.gnu.org/licenses/>.
27
28 EXCEPTION : As a special exception, you may create a larger work
29 that contains this FAUST architecture section and distribute
30 that work under terms of your choice, so long as this FAUST
31 architecture section is not modified.
32
33
34 ************************************************************************
35 ************************************************************************/
36
37 #import <UIKit/UIKit.h>
38 #import "iPhoneViewController.h"
39
40 #include "misc.h"
41
42 #include <list>
43 #include <map>
44
45 using namespace std;
46
47 /******************************************************************************
48 *******************************************************************************
49
50 GRAPHIC USER INTERFACE (v2)
51 abstract interfaces
52
53 *******************************************************************************
54 *******************************************************************************/
55
56 //typedef void (*uiCallback)(float val, void* data);
57
58 //=================
59 // COCOA part
60 //=================
61
62 class UI;
63
64 @interface uiItem : NSObject
65 {
66 UI* fGUI;
67 float* fZone;
68 float fCache;
69 }
70
71 - (id)initWithValues:(UI*)ui:(float*)zone;
72 - (void)modifyZone:(float)v;
73 - (float)cache;
74 - (void)reflectZone;
75
76 @end
77
78 /**
79 * Graphic User Interface : abstract definition
80 */
81
82 class UI
83 {
84 typedef list<uiItem*> clist;
85 typedef map<float*, clist*> zmap;
86
87 protected:
88
89 static list<UI*> fGuiList;
90 zmap fZoneMap;
91 bool fStopped;
92
93 public:
94
95 UI() : fStopped(false)
96 {
97 fGuiList.push_back(this);
98 }
99
100 virtual ~UI()
101 {
102 // suppression de this dans fGuiList
103 }
104
105 // -- registerZone(z,c) : zone management
106
107 void registerZone(float* z, uiItem* c)
108 {
109 if (fZoneMap.find(z) == fZoneMap.end()) {
110 fZoneMap[z] = new clist();
111 }
112 fZoneMap[z]->push_back(c);
113 }
114
115 // -- saveState(filename) : save the value of every zone to a file
116
117 void saveState(const char* filename)
118 {
119 ofstream f(filename);
120
121 if (!f.is_open()) {
122 } else {
123 for (zmap::iterator i = fZoneMap.begin(); i != fZoneMap.end(); i++) {
124 f << *(i->first) << ' ';
125 }
126 }
127
128 f << endl;
129 f.close();
130 }
131
132 // -- recallState(filename) : load the value of every zone from a file
133
134 void recallState(const char* filename)
135 {
136 ifstream f(filename);
137 if (f.good()) {
138 for (zmap::iterator i = fZoneMap.begin(); i != fZoneMap.end(); i++) {
139 f >> *(i->first);
140 }
141 }
142 f.close();
143 updateAllZones();
144 }
145
146 void updateAllZones();
147
148 void updateZone(float* z);
149
150 static void updateAllGuis()
151 {
152 list<UI*>::iterator g;
153 for (g = fGuiList.begin(); g != fGuiList.end(); g++) {
154 (*g)->updateAllZones();
155 }
156 }
157
158 // -- active widgets
159
160 virtual void addButton(const char* label, float* zone) = 0;
161 virtual void addToggleButton(const char* label, float* zone) = 0;
162 virtual void addCheckButton(const char* label, float* zone) = 0;
163 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
164 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
165 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0;
166
167 // -- passive widgets
168
169 virtual void addNumDisplay(const char* label, float* zone, int precision) = 0;
170 virtual void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max) = 0;
171 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0;
172 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0;
173
174 //void addCallback(float* zone, uiCallback foo, void* data);
175
176 // -- widget's layouts
177
178 virtual void openFrameBox(const char* label) = 0;
179 virtual void openTabBox(const char* label) = 0;
180 virtual void openHorizontalBox(const char* label) = 0;
181 virtual void openVerticalBox(const char* label) = 0;
182
183 // -- extra widget's layouts
184
185 virtual void openDialogBox(const char* label, float* zone) = 0;
186 virtual void openEventBox(const char* label) = 0;
187 virtual void openHandleBox(const char* label) = 0;
188 virtual void openExpanderBox(const char* label, float* zone) = 0;
189
190 virtual void closeBox() = 0;
191
192 virtual void show() {};
193 virtual void run() {};
194
195 void stop() { fStopped = true; }
196 bool stopped() { return fStopped; }
197
198 virtual void declare(float* zone, const char* key, const char* value) {}
199 };
200
201 /**
202 * Update all user items reflecting zone z
203 */
204
205 void UI::updateZone(float* z)
206 {
207 float v = *z;
208 clist* l = fZoneMap[z];
209
210 for (clist::iterator c = l->begin(); c != l->end(); c++) {
211 if ([(*c) cache] != v) [(*c) reflectZone];
212 }
213 }
214
215 /**
216 * Update all user items not up to date
217 */
218
219 inline void UI::updateAllZones()
220 {
221 for (zmap::iterator m = fZoneMap.begin(); m != fZoneMap.end(); m++) {
222 float* z = m->first;
223 clist* l = m->second;
224 float v = *z;
225 for (clist::iterator c = l->begin(); c != l->end(); c++) {
226 if ([(*c) cache] != v) [(*c) reflectZone];
227 }
228 }
229 }
230
231 /*
232 inline void UI::addCallback(float* zone, uiCallback foo, void* data)
233 {
234 new uiCallbackItem(this, zone, foo, data);
235 };
236 */
237
238 #define WIDGET_SLICE 50.f
239 #define OFFSET_Y 80.f
240
241 #define SCREEN_WIDTH 320
242 #define SCREEN_HEIGHT 480
243
244 @implementation uiItem
245
246 - (id)initWithValues:(UI*)ui:(float*)zone
247 {
248 fGUI = ui;
249 fZone = zone;
250 fCache = -123456.654321;
251 ui->registerZone(zone, self);
252 return self;
253 }
254
255 - (void)modifyZone:(float)v
256 {
257 fCache = v;
258
259 if (*fZone != v) {
260 *fZone = v;
261 fGUI->updateZone(fZone);
262 }
263 }
264
265 - (float)cache
266 {
267 return fCache;
268 }
269
270 // To implement in subclasses
271
272 - (void)reflectZone
273 {}
274
275 @end
276
277 // -------------------------- Slider -----------------------------------
278
279 @interface uiSlider : uiItem
280 {
281 UISlider* fSlider;
282 UITextField* fTextField;
283 }
284
285 - (void)changed:(UISlider*)sender;
286 - (void)reflectZone;
287 - (id)initWithValues:(int)index:(UI*)ui:(iPhoneViewController*)controler:(const char*)label:(float*)zone:(float)init:(float)min:(float)max:(float)step;
288
289 @end
290
291 @implementation uiSlider
292
293 - (id)initWithValues:(int)index:(UI*)ui:(iPhoneViewController*)controler:(const char*)name:(float*)zone:(float)init:(float)min:(float)max:(float)step
294 {
295 if (self = [super initWithValues:ui:zone]) {
296
297 CGRect labelFrame = CGRectMake(0.0, OFFSET_Y + WIDGET_SLICE * index - 5.f, 130.0, 30.0);
298 UILabel *label = [[UILabel alloc] initWithFrame:labelFrame];
299 [label setFont:[UIFont boldSystemFontOfSize:12]];
300 label.textAlignment = UITextAlignmentCenter;
301 [label setText:[[NSString alloc] initWithCString:name encoding:NSASCIIStringEncoding]];
302 label.textColor = [UIColor blackColor ];
303 label.backgroundColor = [UIColor lightGrayColor];
304 [controler.view addSubview:label];
305
306 CGRect frame = CGRectMake(130.0f, OFFSET_Y + WIDGET_SLICE * index, 110.0f, 7.0f);
307 fSlider = [[UISlider alloc] initWithFrame:frame];
308 [fSlider addTarget:self action:@selector(changed:)forControlEvents:UIControlEventValueChanged];
309 fSlider.minimumValue = min;
310 fSlider.maximumValue = max;
311 fSlider.continuous = YES;
312 fSlider.value = init;
313 [controler.view addSubview:fSlider];
314
315 CGRect textFieldFrame = CGRectMake(250.0, OFFSET_Y + WIDGET_SLICE * index, 60.0, 20.0);
316 fTextField = [[UITextField alloc] initWithFrame:textFieldFrame];
317 [fTextField setBorderStyle:UITextBorderStyleLine];
318 fTextField.textAlignment = UITextAlignmentCenter;
319 [fTextField setEnabled:NO];
320 [fTextField setTextColor:[UIColor blackColor]];
321 [fTextField setFont:[UIFont systemFontOfSize:14]];
322 [fTextField setPlaceholder:[NSString stringWithFormat:@"%1.2f", init]];
323 [fTextField setBackgroundColor:[UIColor whiteColor]];
324 [fTextField setAdjustsFontSizeToFitWidth:YES];
325 fTextField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
326 [controler.view addSubview:fTextField];
327 }
328 return self;
329 }
330
331 - (void)changed:(UISlider*)sender
332 {
333 [self modifyZone:sender.value];
334 [fTextField setPlaceholder:[NSString stringWithFormat:@"%1.2f", sender.value]];
335 }
336
337 - (void)reflectZone;
338 {
339 float v = *fZone;
340 fCache = v;
341 fSlider.value = v;
342 [fTextField setPlaceholder:[NSString stringWithFormat:@"%1.2f", v]];
343 }
344
345 - (void)dealloc
346 {
347 [fSlider release];
348 [fTextField release];
349 [super dealloc];
350 }
351
352 @end
353
354 // --------------------------- Press button ---------------------------
355
356 #define kStdButtonWidth 100.0
357 #define kStdButtonHeight 40.0
358
359 @interface uiButton : uiItem
360 {
361 UIButton* fButton;
362 }
363
364 - (void)pressed:(UIButton*)sender;
365 - (void)released:(UIButton*)sender;
366 - (void)reflectZone;
367 - (id)initWithValues:(int)index:(UI*)ui:(iPhoneViewController*)controler:(const char*)label:(float*)zone;
368
369 @end
370
371 @implementation uiButton
372
373 - (id)initWithValues:(int)index:(UI*)ui:(iPhoneViewController*)controler:(const char*)name:(float*)zone
374 {
375 if (self = [super initWithValues:ui:zone]) {
376 fButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
377 fButton.frame = CGRectMake(SCREEN_WIDTH/2 - kStdButtonWidth/2, OFFSET_Y + WIDGET_SLICE * index - 5.f, kStdButtonWidth, kStdButtonHeight);
378 [fButton setTitle:[[NSString alloc] initWithCString:name encoding:NSASCIIStringEncoding] forState:UIControlStateNormal];
379 fButton.backgroundColor = [UIColor clearColor];
380 [fButton addTarget:self action:@selector(pressed:) forControlEvents:UIControlEventTouchDown];
381 [fButton addTarget:self action:@selector(released:) forControlEvents:UIControlEventTouchUpInside];
382 [controler.view addSubview:fButton];
383 }
384 return self;
385 }
386
387 - (void)pressed:(UIButton*)sender
388 {
389 [self modifyZone:1.0f];
390 }
391
392 - (void)released:(UIButton*)sender
393 {
394 [self modifyZone:0.0f];
395 }
396
397 - (void)reflectZone
398 {
399 float v = *fZone;
400 fCache = v;
401 //if (v > 0.0) gtk_button_pressed(fButton); else gtk_button_released(fButton);
402 }
403
404 - (void)dealloc
405 {
406 [fButton release];
407 [super dealloc];
408 }
409
410 @end
411
412 // ------------------------------ Num Entry -----------------------------------
413
414 @interface uiNumEntry : uiItem
415 {
416 UITextField* fTextField;
417 }
418
419 - (id)initWithValues:(int)index:(UI*)ui:(iPhoneViewController*)controler:(const char*)label:(float*)zone:(float)init:(float)min:(float)max:(float)step;
420
421 @end
422
423 @implementation uiNumEntry
424
425 - (id)initWithValues:(int)index:(UI*)ui:(iPhoneViewController*)controler:(const char*)label:(float*)zone:(float)init:(float)min:(float)max:(float)step
426 {
427 if (self = [super initWithValues:ui:zone]) {
428 CGRect textFieldFrame = CGRectMake(SCREEN_WIDTH/2 - kStdButtonWidth/2, OFFSET_Y + WIDGET_SLICE * index - 5.f, kStdButtonWidth, kStdButtonHeight);
429 fTextField = [[UITextField alloc] initWithFrame:textFieldFrame];
430 [fTextField setTextColor:[UIColor blackColor]];
431 [fTextField setFont:[UIFont systemFontOfSize:14]];
432 [fTextField setPlaceholder:@"<enter text>"];
433 [fTextField setBackgroundColor:[UIColor whiteColor]];
434 fTextField.keyboardType = UIKeyboardTypeDefault;
435
436 [controler.view addSubview:fTextField];
437 }
438 return self;
439 }
440
441 - (void)dealloc
442 {
443 [fTextField release];
444 [super dealloc];
445 }
446
447 @end
448
449
450 class CocoaUI : public UI
451 {
452
453 private:
454
455 UIWindow* fWindow;
456 iPhoneViewController* fViewController;
457 MY_Meta* fMetadata;
458
459 list <uiItem*> fWidgetList;
460
461 void insert(const char* label, uiItem* widget)
462 {
463 fWidgetList.push_back(widget);
464 [fViewController.view setContentSize:CGSizeMake(320, WIDGET_SLICE * fWidgetList.size() + 100.f)];
465 }
466
467 public:
468
469 // -- Labels and metadata
470
471 // virtual void declare (float* zone, const char* key, const char* value);
472 // virtual int checkLabelOptions (GtkWidget* widget, const string& fullLabel, string& simplifiedLabel);
473 // virtual void checkForTooltip (float* zone, GtkWidget* widget);
474
475 // -- layout groups
476
477 CocoaUI(UIWindow* window, iPhoneViewController* viewController, MY_Meta* metadata)
478 {
479 fViewController = viewController;
480 fWindow = window;
481 fMetadata = metadata;
482
483 CGRect titleFrame = CGRectMake(0.0, 0.0f, 320.0, 75.0);
484 UIView *titleView = [[UIView alloc] initWithFrame:titleFrame];
485 titleView.backgroundColor = [UIColor brownColor];
486 [fViewController.view addSubview:titleView];
487
488 if (fMetadata->find("name") != fMetadata->end()) {
489 const char* name = (*fMetadata->find("name")).second;
490 CGRect labelFrame = CGRectMake(0.0, 20.0f, 320.0, 30.0);
491 UILabel *label = [[UILabel alloc] initWithFrame:labelFrame];
492 [label setFont:[UIFont boldSystemFontOfSize:18]];
493 label.textAlignment = UITextAlignmentCenter;
494 [label setText:[[NSString alloc] initWithCString:name encoding:NSASCIIStringEncoding]];
495 label.textColor = [UIColor blackColor ];
496 label.backgroundColor = [UIColor brownColor];
497 [fViewController.view addSubview:label];
498 }
499
500 if (fMetadata->find("author") != fMetadata->end()) {
501 const char* name = (*fMetadata->find("author")).second;
502 CGRect labelFrame = CGRectMake(0.0, 45.0f, 320.0, 30.0);
503 UILabel *label = [[UILabel alloc] initWithFrame:labelFrame];
504 [label setFont:[UIFont boldSystemFontOfSize:14]];
505 label.textAlignment = UITextAlignmentCenter;
506 [label setText:[[NSString alloc] initWithCString:name encoding:NSASCIIStringEncoding]];
507 label.textColor = [UIColor blackColor ];
508 label.backgroundColor = [UIColor brownColor];
509 [fViewController.view addSubview:label];
510 }
511
512 [window addSubview:viewController.view];
513 [window makeKeyAndVisible];
514 }
515
516 ~CocoaUI()
517 {
518 [fViewController release];
519 [fWindow release];
520 }
521
522 virtual void openFrameBox(const char* label)
523 {}
524 virtual void openTabBox(const char* label = "")
525 {}
526 virtual void openHorizontalBox(const char* label = "")
527 {}
528 virtual void openVerticalBox(const char* label = "")
529 {}
530
531 // -- extra widget's layouts
532
533 virtual void openDialogBox(const char* label, float* zone)
534 {}
535 virtual void openEventBox(const char* label = "")
536 {}
537 virtual void openHandleBox(const char* label = "")
538 {}
539 virtual void openExpanderBox(const char* label, float* zone)
540 {}
541
542 virtual void closeBox()
543 {}
544
545 //virtual void adjustStack(int n);
546
547 // -- active widgets
548
549 virtual void addButton(const char* label, float* zone)
550 {
551 uiItem* item = [[uiButton alloc] initWithValues:fWidgetList.size():this:fViewController:label:zone];
552 insert(label, item);
553 }
554 virtual void addToggleButton(const char* label, float* zone)
555 {}
556 virtual void addCheckButton(const char* label, float* zone)
557 {}
558 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
559 {
560 uiItem* item = [[uiSlider alloc] initWithValues:fWidgetList.size():this:fViewController:label:zone:init:min:max:step];
561 insert(label, item);
562 }
563 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
564 {
565 uiItem* item = [[uiSlider alloc] initWithValues:fWidgetList.size():this:fViewController:label:zone:init:min:max:step];
566 insert(label, item);
567 }
568 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
569 {
570 uiItem* item = [[uiNumEntry alloc] initWithValues:fWidgetList.size():this:fViewController:label:zone:init:min:max:step];
571 insert(label, item);
572 }
573
574 // -- passive display widgets
575
576 virtual void addNumDisplay(const char* label, float* zone, int precision)
577 {}
578 virtual void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max)
579 {}
580 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max)
581 {}
582 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max)
583 {}
584
585 virtual void show()
586 {}
587 virtual void run()
588 {}
589
590 virtual void declare(float* zone, const char* key, const char* value)
591 {}
592
593 };
594
595
596 // global static fields
597
598 list<UI*> UI::fGuiList;
599
600 /*
601 bool GTKUI::fInitialized = false;
602 map<float*, float> GTKUI::fGuiSize;
603 map<float*, string> GTKUI::fTooltip;
604 */