clean up indentation and spacing
[supercollider.git] / SCClassLibrary / Common / GUI / Grid.sc
bloba67754b461cfd4a4b39b32ac5b90014a55c117bd
3 DrawGrid {
5         var <bounds,<>x,<>y;
6         var <>opacity=0.7,<>smoothing=false,<>linePattern;
7         var pen;
9         *new { |bounds,horzGrid,vertGrid|
10                 ^super.new.init(bounds, horzGrid, vertGrid)
11         }
12         *test { arg horzGrid,vertGrid,bounds;
13                 var w,grid;
14                 bounds = bounds ?? {Rect(0,0,500,400)};
15                 grid = DrawGrid(bounds,horzGrid,vertGrid);
16                 w = Window("Grid",bounds).front;
17                 UserView(w,bounds ?? {w.bounds.moveTo(0,0)})
18                         .resize_(5)
19                         .drawFunc_({ arg v;
20                                 grid.bounds = v.bounds;
21                                 grid.draw
22                         })
23                         .background_(Color.white)
24                 ^grid
25         }
27         init { arg bounds,h,v;
28                 var w;
29                 pen = GUI.pen;
30                 x = DrawGridX(h);
31                 y = DrawGridY(v);
32                 this.bounds = bounds;
33                 this.font = Font( Font.defaultSansFace, 9 );
34                 this.fontColor = Color.grey(0.3);
35                 this.gridColors = [Color.grey(0.7),Color.grey(0.7)];
36         }
37         bounds_ { arg b;
38                 bounds = b;
39                 x.bounds = b;
40                 y.bounds = b;
41         }
42         draw {
43                 pen.push;
44                         pen.alpha = opacity;
45                         pen.smoothing = smoothing;
46                         if(linePattern.notNil) {Pen.lineDash_(linePattern)};
47                         x.commands.do({ arg cmd; pen.perform(cmd) });
48                         y.commands.do({ arg cmd; pen.perform(cmd) });
49                 pen.pop;
50         }
51         font_ { arg f;
52                 x.font = f;
53                 y.font = f;
54         }
55         fontColor_ { arg c;
56                 x.fontColor = c;
57                 y.fontColor = c;
58         }
59         gridColors_ { arg colors;
60                 x.gridColor = colors[0];
61                 y.gridColor = colors[1];
62         }
63         horzGrid_ { arg g;
64                 x.grid = g;
65         }
66         vertGrid_ { arg g;
67                 y.grid = g;
68         }
69         copy {
70                 ^DrawGrid(bounds,x.grid,y.grid).x_(x.copy).y_(y.copy).opacity_(opacity).smoothing_(smoothing).linePattern_(linePattern)
71         }
72         clearCache {
73                 x.clearCache;
74                 y.clearCache;
75         }
79 DrawGridX {
81         var <grid,<>range,<>bounds;
82         var <>font,<>fontColor,<>gridColor,<>labelOffset;
83         var commands,cacheKey;
85         *new { arg grid;
86                 ^super.newCopyArgs(grid.asGrid).init
87         }
89         init {
90                 range = [grid.spec.minval, grid.spec.maxval];
91                 labelOffset = 4 @ -10;
92         }
93         grid_ { arg g;
94                 grid = g.asGrid;
95                 range = [grid.spec.minval, grid.spec.maxval];
96                 this.clearCache;
97         }
98         setZoom { arg min,max;
99                 range = [min,max];
100         }
101         commands {
102                 var p;
103                 if(cacheKey != [range,bounds],{ commands = nil });
104                 ^commands ?? {
105                         cacheKey = [range,bounds];
106                         commands = [];
107                         p = grid.getParams(range[0],range[1],bounds.left,bounds.right);
108                         p['lines'].do { arg val;
109                                 // value, [color]
110                                 var x;
111                                 val = val.asArray;
112                                 x = val[0].linlin(range[0],range[1],bounds.left,bounds.right);
113                                 commands = commands.add( ['strokeColor_',val[1] ? gridColor] );
114                                 commands = commands.add( ['line', Point( x, bounds.top), Point(x,bounds.bottom) ] );
115                                 commands = commands.add( ['stroke' ] );
116                         };
117                         if(bounds.width >= 12   ,{
118                                 commands = commands.add(['font_',font ] );
119                                 commands = commands.add(['color_',fontColor ] );
120                                 p['labels'].do { arg val;
121                                         var x;
122                                         // value, label, [color, font]
123                                         if(val[2].notNil,{
124                                                 commands = commands.add( ['color_',val[2] ] );
125                                         });
126                                         if(val[3].notNil,{
127                                                 commands = commands.add( ['font_',val[3] ] );
128                                         });
129                                         x = val[0].linlin(range[0],range[1],bounds.left,bounds.right);
130                                         commands = commands.add( ['stringAtPoint', val[1].asString, Point(x, bounds.bottom) + labelOffset ] );
131                                 }
132                         });
133                         commands
134                 }
135         }
136         clearCache { cacheKey = nil; }
137         copy { ^super.copy.clearCache }
141 DrawGridY : DrawGridX {
143         init {
144                 range = [grid.spec.minval, grid.spec.maxval];
145                 labelOffset = 4 @ 4;
146         }
147         commands {
148                 var p;
149                 if(cacheKey != [range,bounds],{ commands = nil });
150                 ^commands ?? {
151                         commands = [];
153                         p = grid.getParams(range[0],range[1],bounds.top,bounds.bottom);
154                         p['lines'].do { arg val;
155                                 // value, [color]
156                                 var y;
157                                 val = val.asArray;
158                                 y = val[0].linlin(range[0],range[1],bounds.bottom,bounds.top);
159                                 commands = commands.add( ['strokeColor_',val[1] ? gridColor] );
160                                 commands = commands.add( ['line', Point( bounds.left,y), Point(bounds.right,y) ] );
161                                 commands = commands.add( ['stroke' ] );
162                         };
163                         if(bounds.height >= 20  ,{
164                                 commands = commands.add(['font_',font ] );
165                                 commands = commands.add(['color_',fontColor ] );
166                                 p['labels'].do { arg val,i;
167                                         var y;
168                                         y = val[0].linlin(range[0],range[1],bounds.bottom,bounds.top);
169                                         if(val[2].notNil,{
170                                                 commands = commands.add( ['color_',val[2] ] );
171                                         });
172                                         if(val[3].notNil,{
173                                                 commands = commands.add( ['font_',val[3] ] );
174                                         });
175                                         commands = commands.add( ['stringAtPoint', val[1].asString, Point(bounds.left, y) + labelOffset ] );
176                                 }
177                         });
178                         commands
179                 }
180         }
184 // DrawGridRadial : DrawGridX {}
187 GridLines {
189         var <>spec;
191         *new { arg spec;
192                 ^super.newCopyArgs(spec.asSpec)
193         }
195         asGrid { ^this }
196         niceNum { arg val,round;
197                 // http://books.google.de/books?id=fvA7zLEFWZgC&pg=PA61&lpg=PA61
198                 var exp,f,nf,rf;
199                 exp = floor(log10(val));
200                 f = val / 10.pow(exp);
201                 rf = 10.pow(exp);
202                 if(round,{
203                         if(f < 1.5,{
204                                 ^rf *  1.0
205                         });
206                         if(f < 3.0,{
207                                 ^rf *  2.0
208                         });
209                         if( f < 7.0,{
210                                 ^rf *  5.0
211                         });
212                         ^rf *  10.0
213                 },{
214                         if(f <= 1.0,{
215                                 ^rf *  1.0;
216                         });
217                         if(f <= 2,{
218                                 ^rf *  2.0
219                         });
220                         if(f <= 5,{
221                                 ^rf *  5.0;
222                         });
223                         ^rf *  10.0
224                 });
225         }
226         ideals { arg min,max,ntick=5;
227                 var nfrac,d,graphmin,graphmax,range,x;
228                 range = this.niceNum(max - min,false);
229                 d = this.niceNum(range / (ntick - 1),true);
230                 graphmin = floor(min / d) * d;
231                 graphmax = ceil(max / d) * d;
232                 nfrac = max( floor(log10(d)).neg, 0 );
233                 ^[graphmin,graphmax,nfrac,d];
234         }
235         looseRange { arg min,max,ntick=5;
236                 ^this.ideals(min,max).at( [ 0,1] )
237         }
238         getParams { |valueMin,valueMax,pixelMin,pixelMax,numTicks|
239                 var lines,p,pixRange;
240                 var nfrac,d,graphmin,graphmax,range;
241                 pixRange = pixelMax - pixelMin;
242                 if(numTicks.isNil,{
243                         numTicks = (pixRange / 64);
244                         numTicks = numTicks.max(3).round(1);
245                 });
246                 # graphmin,graphmax,nfrac,d = this.ideals(valueMin,valueMax,numTicks);
247                 lines = [];
248                 if(d != inf,{
249                         forBy(graphmin,graphmax + (0.5*d),d,{ arg tick;
250                                 if(tick.inclusivelyBetween(valueMin,valueMax),{
251                                         lines = lines.add( tick );
252                                 })
253                         });
254                 });
255                 p = ();
256                 p['lines'] = lines;
257                 if(pixRange / numTicks > 9) {
258                         p['labels'] = lines.collect({ arg val; [val, this.formatLabel(val,nfrac) ] });
259                 };
260                 ^p
261         }
262         formatLabel { arg val, numDecimalPlaces;
263                 ^val.round( (10**numDecimalPlaces).reciprocal).asString + (spec.units?"")
264         }
268 BlankGridLines : GridLines {
270         getParams {
271                 ^()
272         }
276 + Nil {
277         asGrid { ^BlankGridLines.new }