julian+alberto classlib merges for 3.4 (10125, 10130, 10133)
[supercollider.git] / common / build / SCClassLibrary / Common / GUI / GUI.sc
blob170d6e6f06d7fc6c6e971284c8849b31bc8c7e0f
1 /**
2  *      Factory abstraction for all GUI related core classes.
3  *      Each GUI kit is described by a scheme that maps class names
4  *      to actual classes.
5  *
6  *      See the help file for details. The default
7  *      scheme is cocoa.
8  *
9  *      Changelog:
10  *              - jrh added makeGUI
11  *              - sciss added add, set, get, use, useID
12  *
13  *      @version        0.16, 10-Apr-07
14  */
15 GUI {
16         classvar <scheme, <schemes, <skin, <skins;
18         *new { arg key; ^scheme.perform( key )}
20         *makeGUI { arg key, args, properties;
21                 var meth, class;
22                 class = scheme.at(key);
23                 if(properties.notNil) {
24                         meth = class.class.findMethod(\new);
25                         if(meth.notNil) {
26                                 meth.argNames.drop(args.size).do { |key| args = args ++ properties[key] }
27                         }
28                 };
29                 meth.argNames.postln;
30                 args.postln;
31                 ^class.new(*args)
32         }
34         *initClass {
35                 skins = (
36                         default: (
37                                 fontSpecs:      ["Helvetica", 10],
38                                 fontColor:      Color.black,
39                                 background:     Color(0.8, 0.85, 0.7, 0.5),
40                                 foreground:     Color.grey(0.95),
41                                 onColor:                Color(0.5, 1, 0.5),
42                                 offColor:               Color.clear,
43                                 gap:                    0 @ 0,
44                                 margin:                 2@2,
45                                 buttonHeight:   16
46                         )
47                 );
49                 skin            = skins.default;
50                 schemes = IdentityDictionary.new;
51         }
53         /**
54          *      Makes Cocoa (Mac OS X GUI) the current scheme
55          *      and returns it. Subsequent GUI object calls
56          *      to GUI are delegated to cocoa.
57          *
58          *      @return the current (cocoa) scheme
59          */
60         *cocoa {
61                 ^this.fromID( \cocoa );
62         }
64         /**
65          *      Makes Swing (Java GUI) the current scheme
66          *      and returns it. Subsequent GUI object calls
67          *      to GUI are delegated to swing.
68          *
69          *      @return the current (swing) scheme
70          */
71         *swing {
72                 ^this.fromID( \swing );
73         }
75         /**
76          *      Changes the current scheme and returns it.
77          *
78          *      @param  id              (Symbol) the identifier of the scheme to
79          *                                      use, such as returned by calling
80          *                                      aScheme.id
81          *      @return the new current scheme
82          */
83         *fromID { arg id;
84                 var newScheme = schemes[ id.asSymbol ];
85                 if( newScheme.notNil, {
86                         scheme = newScheme;
87                 }, {
88                         ("GUI.fromID : The GUI scheme '" ++ id ++ "' is not installed\n" ++
89                          "The current scheme is still '" ++ if( scheme.notNil, { scheme.id }) ++ "'!").warn;
90                 });
91                 ^scheme;
92         }
94         /**
95          *      Returns the current scheme. This
96          *      is useful for objects that, upon instantiation,
97          *      wish to store the then-current scheme, so as
98          *      to be able to consistently use the same scheme
99          *      in future method calls.
100          *
101          *      Note: the caller shouldn't make any assumptions about
102          *      the nature (the class) of the returned object, so that
103          *      the actual implementation (an Event) may change in the future.
104          *
105          *      @return the current scheme
106          */
107         *current {
108                 ^scheme;
109         }
111         /**
112          *      Returns the scheme for a given identifier.
113          *      Does not switch the current scheme.
114          *
115          *      @param  id              (Symbol) the identifier of the scheme to
116          *                                      retrieve, such as returned by calling
117          *                                      aScheme.id
118          *      @return the scheme for the given id or nil
119          */
120         *get { arg id;
121                 ^schemes[ id.asSymbol ];
122         }
124         /**
125          *      Changes the current scheme.
126          *
127          *      @param  aScheme the scheme to use as current scheme
128          */
129         *set { arg aScheme;
130                 scheme = aScheme;
131         }
133         /**
134          *      Executes a function body, temporarily
135          *      setting the current GUI scheme. This is usefull inside
136          *      view's action functions in order to make this function
137          *      use the GUI scheme that was originally used for the
138          *      view of the action, even if the scheme has been switched meanwhile.
139          *
140          *      @param  scheme  the scheme to use during the function execution
141          *      @param  func            (Function) a body to execute
142          *      @return the result of the function
143          */
144         *use { arg aScheme, func;
145                 var recent      = scheme;
146                 scheme          = aScheme;
147                 ^func.protect({ scheme = recent });
148         }
150         /**
151          *      Same as 'use' but using a scheme's id as first argument
152          *
153          *      @param  id      the id of the scheme to use during the function execution
154          *      @param  func            (Function) a body to execute
155          *      @return the result of the function
156          */
157         *useID { arg id, func;
158                 ^this.use( schemes[ id.asSymbol ], func );
159         }
161         /**
162          *      Registers a new scheme. This is typically called
163          *      by external libraries in their startup procedure.
164          *      If a scheme with the same identifier (scheme.id)
165          *      exists, it is overwritten.
166          *
167          *      @param  aScheme the scheme to add
168          */
169         *add { arg aScheme;
170                 schemes.put( aScheme.id, aScheme );
171                 if( scheme.isNil, {                             // first registration = first default kit
172                         scheme = aScheme;
173                 }, {
174                         scheme = schemes[ scheme.id ];  // in case we are updating an existing scheme
175                 });
176         }
178         /**
179          *      All method calls are mapped to the current
180          *      scheme, so that for example GUI.button can be used
181          *      and is delegated to the button association of the
182          *      current scheme.
183          */
184         *doesNotUnderstand { arg selector ... args;
185                 ^scheme.performList( selector, args );
186         }
188         /**
189          *      Add skins : GUI.skins.put(skinName,( fontSpecs: etc.  )  )
190          *      then set that as default here.
191          *  Note that if you wanted to do this in an *initClass that the scheme and GUI must be initialized
192          * and the scheme must be created in CocoaGUI.initClass (class varies on platform) so you cannot
193          * explicitly init that class by name since it varies across platforms.  so you can't really setSkin
194          * in an initClass. Your initClass method could do StartUp.add { GUI.setSkin(...) };
195          */
196         *setSkin { arg skinName;
197                 skin = skins[skinName];
198                 scheme.font.new(*GUI.skin.fontSpecs).setDefault;
199         }