Jamoma API  0.6.0.a19
j.textslider.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxExternals
4  *
5  * @brief j.textslider : A slider displaying text and value
6  *
7  * @details Inspired by a GUI widget from radiaL by jhno
8  *
9  * @authors Trond Lossius, Nils Peters
10  *
11  * @copyright © 2008 by Trond Lossius @n
12  * This code is licensed under the terms of the "New BSD License" @n
13  * http://creativecommons.org/licenses/BSD/
14  */
15 
16 
17 #include "ext.h"
18 #include "ext_obex.h"
19 #include "ext_user.h"
20 #include "ext_common.h"
21 #include "jpatcher_api.h" // jpatcher_api.h must come before z_dsp.h (in Jamoma.h)
22 #include "jgraphics.h"
23 #include "JamomaForMax.h"
24 #include "TTFoundation.h"
25 
26 // Constants
27 const double kPollIntervalDefault = 150;
28 const double kPollIntervalMinimum = 50;
29 const double kPollIntervalMaximum = 5000;
30 const double kHeightDefault = 13;
31 const double kHeightMinimum = 1;
32 const double kHeightMaximum = 400;
33 const double kWidthDefault = 80;
34 const double kWidthMinimum = 1;
35 const double kWidthMaximum = 1200;
36 const double kOrientationVectical = 1;
37 const double kOrientationHorizontal = 0;
38 const double kMinimumChangeForRedraw = 0.00001;
39 
40 // Instance definition
41 typedef struct _textslider{
42  t_jbox box;
43  char attrDefeat; // disable the textslider
44 
45  t_jrgba attrBgColor; ///< Background color
46  t_jrgba attrFgColor; ///< Forground color
47  t_jrgba attrBorderColor; ///< Border color
48  t_jrgba attrTextColor; ///< Text color
49  t_jrgba attrKnobColor; ///< Knob color
50 
51  float attrValue; ///< The slider value
52  float attrValueUnclipped; ///< The slider value, unclipped
53  float attrRange[2]; ///< ATTRIBUTE: low, high
54  float attrRangeDelta; /// attrRange[1] - attrRange[0]
55  float attrTextOffset[2]; // horizontal & vertical offset for text display
56  float anchorValue; ///< Used for mouse dragging
57  float attrDefaultValue; // default value is used when click+CTRL
58 
59  // TODO: Display a list instead of just one symbol.
60  // Eventually: Implement "prepend text" and "append text" attributes
61  t_symbol *attrText; ///< The text displayed by the slider
62  t_symbol *attrUnit; ///< The unit which is displayed together with the number
63  t_symbol *attrTracking; ///< Set mouse drag mode
64  long attrClickJump; ///< Jump to new value onj mouse click
65  long attrShowValue; /// permits showing the value for hovering and mousediting
66  double mousePositionY; ///< Used to redraw position mouse after dragging
67  bool mouseDown; ///< Flag indicating mouse status
68  bool mouseOver; ///< Flag indicating mouse status
69  void *outlet; ///< Outlet
70 } t_textslider;
71 
72 
73 // prototypes
74 void* textslider_new(t_symbol *s, long argc, t_atom *argv);
75 void textslider_free(t_textslider *x);
76 t_max_err textslider_notify(t_textslider *x, t_symbol *s, t_symbol *msg, void *sender, void *data);
77 void textslider_assist(t_textslider *x, void *b, long m, long a, char *s);
78 void textslider_updatestringvalue(t_textslider *x);
79 void textslider_bang(t_textslider *x);
80 void textslider_int(t_textslider *x, long value);
81 void textslider_float(t_textslider *x, double value);
82 void textslider_set(t_textslider *x, double value);
83 t_max_err textslider_getRange(t_textslider *x, void *attr, long *argc, t_atom **argv);
84 t_max_err textslider_setRange(t_textslider *x, void *attr, long argc, t_atom *argv);
85 t_max_err textslider_getTextOffset(t_textslider *x, void *attr, long *argc, t_atom **argv);
86 t_max_err textslider_setTextOffset(t_textslider *x, void *attr, long argc, t_atom *argv);
87 t_max_err textslider_get_text(t_textslider *x, void *attr, long *argc, t_atom **argv);
88 t_max_err textslider_set_text(t_textslider *x, void *attr, long argc, t_atom *argv);
89 t_max_err textslider_get_unit(t_textslider *x, void *attr, long *argc, t_atom **argv);
90 t_max_err textslider_set_unit(t_textslider *x, void *attr, long argc, t_atom *argv);
91 void textslider_mousedown(t_textslider *x, t_object *patcherview, t_pt px, long modifiers);
92 void textslider_mousedragdelta(t_textslider *x, t_object *patcherview, t_pt pt, long modifiers);
93 void textslider_mouseup(t_textslider *x, t_object *patcherview);
94 void textslider_mouseenter(t_textslider *x, t_object *patcherview, t_pt pt, long modifiers);
95 void textslider_mouseleave(t_textslider *x, t_object *patcherview, t_pt pt, long modifiers);
96 void textslider_paint(t_textslider *x, t_object *view);
97 void* textslider_oksize(t_textslider *x, t_rect *newrect);
98 void textslider_mousedoubleclick(t_textslider *x, t_object *patcherview, t_pt pt, long modifiers);
99 
100 
101 
102 
103 // globals
104 static t_class* s_textslider_class;
105 
106 
107 // implementation
108 #if 0
109 #pragma mark -
110 #pragma mark Class Definition
111 #endif 0
112 
113 int JAMOMA_EXPORT_MAXOBJ main(void)
114 {
115  long flags;
116  t_class *c;
117 
118  common_symbols_init();
119 
120  c = class_new("j.textslider",
121  (method)textslider_new,
122  (method)textslider_free,
123  sizeof(t_textslider),
124  (method)NULL,
125  A_GIMME,
126  0L);
127 
128  flags = JBOX_TEXTFIELD;
129  jbox_initclass(c, flags);
130  c->c_flags |= CLASS_FLAG_NEWDICTIONARY; // to specify dictionary constructor
131 
132  class_addmethod(c, (method)textslider_bang, "bang", 0);
133  class_addmethod(c, (method)textslider_int, "int", A_LONG, 0);
134  class_addmethod(c, (method)textslider_float, "float", A_FLOAT, 0);
135  class_addmethod(c, (method)textslider_set, "set", A_FLOAT, 0);
136  class_addmethod(c, (method)textslider_paint, "paint", A_CANT, 0);
137  class_addmethod(c, (method)textslider_oksize, "oksize", A_CANT, 0);
138  class_addmethod(c, (method)textslider_mousedown, "mousedown", A_CANT, 0);
139  class_addmethod(c, (method)textslider_mousedragdelta, "mousedragdelta", A_CANT, 0);
140  class_addmethod(c, (method)textslider_mouseup, "mouseup", A_CANT, 0);
141  class_addmethod(c, (method)textslider_mouseenter, "mouseenter", A_CANT, 0);
142  class_addmethod(c, (method)textslider_mouseleave, "mouseleave", A_CANT, 0);
143  class_addmethod(c, (method)textslider_notify, "notify", A_CANT, 0);
144  class_addmethod(c, (method)textslider_assist, "assist", A_CANT, 0);
145  class_addmethod(c, (method) textslider_mousedoubleclick, "mousedoubleclick",A_CANT, 0);
146 
147  CLASS_ATTR_DEFAULT(c, "patching_rect", 0, "0. 0. 160. 20.");
148  CLASS_ATTR_MIN(c, "patching_size", 0, "1. 1.");
149 
150  CLASS_ATTR_DEFAULT(c, "fontname", 0, JAMOMA_DEFAULT_FONT);
151  CLASS_ATTR_DEFAULT(c, "fontsize", 0, "10");
152 
153  CLASS_STICKY_ATTR(c, "category", 0, "Color");
154 
155  CLASS_ATTR_RGBA(c, "bgcolor", 0, t_textslider, attrBgColor);
156  CLASS_ATTR_DEFAULTNAME_SAVE_PAINT(c, "bgcolor", 0, "0.8 0.8 0.8 0.7");
157  CLASS_ATTR_STYLE(c, "bgcolor", 0, "rgba");
158  CLASS_ATTR_LABEL(c, "bgcolor", 0, "Background Color");
159 
160  CLASS_ATTR_RGBA(c, "fgcolor", 0, t_textslider, attrFgColor);
161  CLASS_ATTR_DEFAULTNAME_SAVE_PAINT(c, "fgcolor", 0, "0.95 0.95 0.95 1.0");
162  CLASS_ATTR_STYLE(c, "fgcolor", 0, "rgba");
163  CLASS_ATTR_LABEL(c, "fgcolor", 0, "Foreground Color");
164 
165  CLASS_ATTR_RGBA(c, "bordercolor", 0, t_textslider, attrBorderColor);
166  CLASS_ATTR_DEFAULTNAME_SAVE_PAINT(c, "bordercolor", 0, "0.5 0.5 0.5 1.0");
167  CLASS_ATTR_STYLE(c, "bordercolor", 0, "rgba");
168  CLASS_ATTR_LABEL(c, "bordercolor", 0, "Border Color");
169 
170  CLASS_ATTR_RGBA(c, "textcolor", 0, t_textslider, attrTextColor);
171  CLASS_ATTR_DEFAULTNAME_SAVE_PAINT(c, "textcolor", 0, "0.0 0.0 0.0 1.0");
172  CLASS_ATTR_STYLE(c, "textcolor", 0, "rgba");
173  CLASS_ATTR_LABEL(c, "textcolor", 0, "Text Color");
174 
175  CLASS_ATTR_RGBA(c, "knobcolor", 0, t_textslider, attrKnobColor);
176  CLASS_ATTR_DEFAULTNAME_SAVE_PAINT(c, "knobcolor", 0, "0.7 0.7 0.7 1.0");
177  CLASS_ATTR_STYLE(c, "knobcolor", 0, "rgba");
178  CLASS_ATTR_LABEL(c, "knobcolor", 0, "Knob Color");
179 
180  CLASS_STICKY_ATTR_CLEAR(c, "category");
181 
182  CLASS_STICKY_ATTR(c, "category", 0, "Jamoma");
183 
184  CLASS_ATTR_FLOAT_ARRAY(c, "range", 0, t_textslider, attrRange, 2);
185  CLASS_ATTR_LABEL(c, "range", 0, "Range");
186  CLASS_ATTR_DEFAULT(c, "range", 0, "0.0 1.0");
187  CLASS_ATTR_SAVE(c, "range", 0);
188  CLASS_ATTR_ACCESSORS(c, "range", textslider_getRange, textslider_setRange);
189 
190  CLASS_ATTR_FLOAT_ARRAY(c, "textpos", 0, t_textslider, attrTextOffset, 2);
191  CLASS_ATTR_LABEL(c, "textpos", 0, "Text position");
192  CLASS_ATTR_DEFAULT(c, "textpos", 0, "10.0 4.0");
193  CLASS_ATTR_SAVE(c, "textpos", 0);
194  CLASS_ATTR_ACCESSORS(c, "textpos", textslider_getTextOffset, textslider_setTextOffset);
195 
196  CLASS_ATTR_SYM(c, "text", 0, t_textslider, attrText);
197  CLASS_ATTR_LABEL(c, "text", 0, "Displayed Text");
198  CLASS_ATTR_DEFAULT(c, "text", 0, "textslider");
199  CLASS_ATTR_SAVE(c, "text", 0);
200  CLASS_ATTR_ACCESSORS(c, "text", textslider_get_text, textslider_set_text);
201 
202  CLASS_ATTR_SYM(c, "unit", 0, t_textslider, attrUnit);
203  CLASS_ATTR_LABEL(c, "unit", 0, "Displayed Unit");
204  CLASS_ATTR_DEFAULT(c, "unit", 0, "");
205  CLASS_ATTR_SAVE(c, "unit", 0);
206  CLASS_ATTR_ACCESSORS(c, "unit", textslider_get_unit, textslider_set_unit);
207 
208  CLASS_ATTR_SYM(c, "tracking", 0, t_textslider, attrTracking);
209  CLASS_ATTR_LABEL(c, "tracking", 0, "Mouse Tracking");
210  CLASS_ATTR_DEFAULT(c, "tracking", 0, "horizontal");
211  CLASS_ATTR_SAVE(c, "tracking", 0);
212  CLASS_ATTR_ENUM(c, "tracking", 0, "horizontal vertical both");
213 
214  CLASS_ATTR_LONG(c, "clickjump", 0, t_textslider, attrClickJump);
215  CLASS_ATTR_LABEL(c, "clickjump", 0, "Jump to Value on Mouse Down");
216  CLASS_ATTR_DEFAULT(c, "clickjump", 0, "1");
217  CLASS_ATTR_SAVE(c, "clickjump", 0);
218  CLASS_ATTR_STYLE(c, "clickjump", 0, "onoff");
219 
220  CLASS_ATTR_LONG(c, "showvalue", 0, t_textslider, attrShowValue);
221  CLASS_ATTR_LABEL(c, "showvalue", 0, "Shows Value while editing & hovering");
222  CLASS_ATTR_STYLE(c, "showvalue", 0, "onoff");
223  CLASS_ATTR_DEFAULT(c, "showvalue", 0, "1");
224  CLASS_ATTR_SAVE(c, "showvalue", 0);
225 
226  CLASS_ATTR_FLOAT(c, "defaultvalue", 0, t_textslider, attrDefaultValue);
227  CLASS_ATTR_LABEL(c, "defaultvalue", 0, "Default value");
228  CLASS_ATTR_DEFAULT(c, "defaultvalue", 0, "0.0");
229  CLASS_ATTR_SAVE(c, "defaultvalue", 0);
230 
231  CLASS_STICKY_ATTR_CLEAR(c, "category");
232 
233  class_register(CLASS_BOX, c);
234  s_textslider_class = c;
235  return 0;
236 }
237 
238 
239 #if 0
240 #pragma mark -
241 #pragma mark Life Cycle
242 #endif 0
243 
244 
245 void *textslider_new(t_symbol *s, long argc, t_atom *argv)
246 {
247  t_textslider *x = NULL;
248  t_dictionary *d=NULL;
249  long flags;
250 
251  if (!(d=object_dictionaryarg(argc,argv)))
252  return NULL;
253 
254  if (x = (t_textslider *)object_alloc(s_textslider_class)) {
255  flags = 0
256  | JBOX_DRAWFIRSTIN // 0
257  | JBOX_NODRAWBOX // 1
258  | JBOX_DRAWINLAST // 2
259  // | JBOX_TRANSPARENT // 3
260  // | JBOX_NOGROW // 4
261  // | JBOX_GROWY // 5
262  | JBOX_GROWBOTH // 6
263  // | JBOX_IGNORELOCKCLICK // 7
264  // | JBOX_HILITE // 8
265  | JBOX_BACKGROUND // 9
266  // | JBOX_NOFLOATINSPECTOR // 10
267  | JBOX_TEXTFIELD // 11
268  | JBOX_MOUSEDRAGDELTA // 12
269  // | JBOX_COLOR // 13
270  // | JBOX_BINBUF // 14
271  // | JBOX_DRAWIOLOCKED // 15
272  // | JBOX_DRAWBACKGROUND // 16
273  // | JBOX_NOINSPECTFIRSTIN // 17
274  // | JBOX_DEFAULTNAMES // 18
275  // | JBOX_FIXWIDTH // 19
276  ;
277 
278  jbox_new(&x->box, flags, argc, argv);
279  x->box.b_firstin = (t_object *)x;
280 
281  x->outlet = outlet_new(x, 0);
282 
283  attr_dictionary_process(x,d);
284  jbox_ready((t_jbox *)x);
285 
286  return x;
287  }
288  else
289  return NULL;
290 }
291 
292 
293 void textslider_free(t_textslider *x)
294 {
295  jbox_free((t_jbox *)x);
296 }
297 
298 
299 #if 0
300 #pragma mark -
301 #pragma mark Methods
302 #endif 0
303 
304 
305 t_max_err textslider_notify(t_textslider *x, t_symbol *s, t_symbol *msg, void *sender, void *data)
306 {
307  t_object *textfield;
308  t_symbol *attrname;
309 
310  if (msg == _sym_modified)
311  jbox_redraw(&x->box);
312  else if ((msg == _sym_attr_modified) && (sender == x)) {
313  attrname = (t_symbol *)object_method((t_object *)data, gensym("getname"));
314 
315  textfield = jbox_get_textfield((t_object*) x);
316  if (textfield)
317  textfield_set_textcolor(textfield, &x->attrTextColor);
318 
319  if (attrname == gensym("text"))
320  object_method(textfield, gensym("settext"), x->attrText->s_name);
321 
322  if (attrname == gensym("textpos"))
323  textfield_set_textmargins(textfield, x->attrTextOffset[0], x->attrTextOffset[1], 2.0, 2.0);
324 
325  if ((x->mouseDown) && (x->attrShowValue))
326  textslider_updatestringvalue(x);
327 
328  jbox_redraw(&x->box);
329  }
330  return jbox_notify((t_jbox*)x, s, msg, sender, data);
331 }
332 
333 
334 // Method for Assistance Messages
335 void textslider_assist(t_textslider *x, void *b, long msg, long arg, char *dst)
336 {
337  if (msg==1) // Inlet
338  strcpy(dst, "Input");
339  else if (msg==2) { // Outlets
340  switch (arg) {
341  case 0: strcpy(dst, "Output"); break;
342  //case 1: strcpy(dst, "Attribute Stuff"); break;
343  }
344  }
345 }
346 
347 void textslider_updatestringvalue(t_textslider *x)
348 {
349  //TODO: do we need to declate two strings? Can this be done better?
350  char str[16];
351  char str2[16];
352  t_object* textfield = jbox_get_textfield((t_object*) x);
353 
354  if (textfield) {
355  snprintf(str, 16, "%.3f", x->attrValueUnclipped);
356  if (x->attrUnit && x->attrUnit != _sym_nothing)
357  snprintf(str2, 16, "%s %s", str, x->attrUnit->s_name);
358  else
359  snprintf(str2, 16, "%s", str);
360  object_method(textfield, gensym("settext"), str2);
361  }
362 
363  jbox_redraw(&x->box);
364 }
365 
366 // Method: bang - output current value
367 void textslider_bang(t_textslider *x)
368 {
369  // jbox_redraw((t_jbox*)x); I don't think it's necsessary to redraw here...
370  outlet_float(x->outlet, x->attrValueUnclipped);
371 }
372 
373 
374 // Method: int - converted to float
375 void textslider_int(t_textslider *x, long value)
376 {
377  textslider_float(x,(double)value);
378 }
379 
380 
381 // Method: float - update value, redraw and output
382 void textslider_float(t_textslider *x, double value)
383 {
384  x->attrValueUnclipped = value;
385  outlet_float(x->outlet, x->attrValueUnclipped);
386  x->attrValue = TTClip<float>(value, x->attrRange[0], x->attrRange[1]);
387  if ((x->attrShowValue) && (x->mouseOver))
388  textslider_updatestringvalue(x);
389  else
390  jbox_redraw((t_jbox*)x);
391 }
392 
393 
394 // Method: set - update and redraw, but no output
395 void textslider_set(t_textslider *x, double value)
396 {
397  x->attrValueUnclipped = value;
398  x->attrValue = value;
399  TTLimit(x->attrValue, x->attrRange[0], x->attrRange[1]);
400 
401  if ((x->attrShowValue) && (x->mouseOver))
402  textslider_updatestringvalue(x);
403  else
404  jbox_redraw((t_jbox*)x);
405 }
406 
407 
408 #if 0
409 #pragma mark -
410 #pragma mark Attributes
411 #endif 0
412 
413 t_max_err textslider_getRange(t_textslider *x, void *attr, long *argc, t_atom **argv)
414 {
415  *argc = 2;
416 
417  //sysmem_ptrsize(*argv)
418  // FIXME: This checks if we have memory passed in, good, but how do we know if it is enough memory for 2 atoms? [TAP]
419  if (!(*argv)) // otherwise use memory passed in
420  *argv = (t_atom *)sysmem_newptr(sizeof(t_atom) * 2);
421 
422  atom_setfloat(*argv, x->attrRange[0]);
423  atom_setfloat(*argv+1, x->attrRange[1]);
424 
425  return MAX_ERR_NONE;
426 }
427 
428 
429 t_max_err textslider_setRange(t_textslider *x, void *attr, long argc, t_atom *argv)
430 {
431  if (argc)
432  x->attrRange[0] = atom_getfloat(argv+0);
433  if (argc > 1) {
434  if (atom_getfloat(argv+1) >= atom_getfloat(argv+0))
435  x->attrRange[1] = atom_getfloat(argv+1);
436  else {
437  x->attrRange[1] = atom_getfloat(argv+0);
438  x->attrRange[0] = atom_getfloat(argv+1);
439  }
440  x->attrRangeDelta = x->attrRange[1] - x->attrRange[0];
441  }
442  jbox_redraw((t_jbox*)x);
443 
444  return MAX_ERR_NONE;
445 }
446 
447 
448 t_max_err textslider_getTextOffset(t_textslider *x, void *attr, long *argc, t_atom **argv)
449 {
450 
451  *argc = 2;
452 
453  //sysmem_ptrsize(*argv)
454  // FIXME: This checks if we have memory passed in, good, but how do we know if it is enough memory for 2 atoms? [TAP]
455  if (!(*argv)) // otherwise use memory passed in
456  *argv = (t_atom *)sysmem_newptr(sizeof(t_atom) * 2);
457 
458  atom_setfloat(*argv, x->attrTextOffset[0]);
459  atom_setfloat(*argv+1, x->attrTextOffset[1]);
460 
461  return MAX_ERR_NONE;
462 }
463 
464 
465 t_max_err textslider_setTextOffset(t_textslider *x, void *attr, long argc, t_atom *argv)
466 {
467  if (argc)
468  x->attrTextOffset[0] = atom_getfloat(argv+0);
469  if (argc > 1)
470  x->attrTextOffset[1] = atom_getfloat(argv+1);
471 
472  jbox_redraw((t_jbox*)x);
473  return MAX_ERR_NONE;
474 }
475 
476 
477 t_max_err textslider_get_text(t_textslider *x, void *attr, long *argc, t_atom **argv)
478 {
479  *argc = 1;
480  if (!(*argv)) // otherwise use memory passed in
481  *argv = (t_atom *)sysmem_newptr(sizeof(t_atom));
482  atom_setsym(*argv, x->attrText);
483  return MAX_ERR_NONE;
484 }
485 
486 
487 t_max_err textslider_set_text(t_textslider *x, void *attr, long argc, t_atom *argv)
488 {
489  if (argc && argv)
490  x->attrText = atom_getsym(argv);
491  else
492  x->attrText = _sym_nothing;
493 
494  jbox_redraw((t_jbox*)x);
495  return MAX_ERR_NONE;
496 }
497 
498 
499 t_max_err textslider_get_unit(t_textslider *x, void *attr, long *argc, t_atom **argv)
500 {
501  *argc = 1;
502  if (!(*argv)) // otherwise use memory passed in
503  *argv = (t_atom *)sysmem_newptr(sizeof(t_atom));
504  atom_setsym(*argv, x->attrUnit);
505  return MAX_ERR_NONE;
506 }
507 
508 
509 t_max_err textslider_set_unit(t_textslider *x, void *attr, long argc, t_atom *argv)
510 {
511  if (argc && argv)
512  x->attrUnit = atom_getsym(argv);
513  else
514  x->attrUnit = _sym_nothing;
515 
516  //jbox_redraw((t_jbox*)x); not necessary here I think
517 
518  return MAX_ERR_NONE;
519 }
520 
521 
522 #if 0
523 #pragma mark -
524 #pragma mark User Interface
525 #endif 0
526 
527 
528 void textslider_mousedoubleclick(t_textslider *x, t_object *patcherview, t_pt pt, long modifiers)
529 {
530  if (modifiers & eControlKey) {
531  textslider_float(x, x->attrDefaultValue); // CTRL+doubleclick sets the slider to the default value
532  x->anchorValue = x->attrDefaultValue;
533  }
534 }
535 
536 
537 
538 void textslider_mousedown(t_textslider *x, t_object *patcherview, t_pt px, long modifiers)
539 {
540  t_rect rect;
541  double delta;
542 
543  x->mouseDown = 1;
544  // Get rect position and prepare for the mouse to show up properly affter dragging
545  jbox_get_rect_for_view((t_object *)x, patcherview, &rect);
546  x->mousePositionY = rect.y + px.y;
547 
548  // Jump to new value on mouse down?
549  if (x->attrClickJump) {
550  delta = px.x-1.; // substract for borders
551  TTLimit(delta ,0., rect.width-3.);
552  delta = delta/(rect.width-2.)*(x->attrRangeDelta) + x->attrRange[0];
553  if (modifiers & eCommandKey)
554  textslider_float(x, long(delta)); //when command-key pressed, jump to the nearest integer-value
555  else
556  textslider_float(x, delta); // otherwise jump to a float value
557  }
558  x->anchorValue = x->attrValue;
559  jbox_set_mousedragdelta((t_object *)x, 1);
560 }
561 
562 
563 // mousedragdelta sends the amount the mouse moved in t_pt
564 void textslider_mousedragdelta(t_textslider *x, t_object *patcherview, t_pt pt, long modifiers)
565 {
566  t_rect rect;
567  float delta;
568  double factor;
569 
570  jbox_get_rect_for_view((t_object *)x, patcherview, &rect);
571  factor = rect.width-2; // factor determines how much precision (vs. immediacy) you have when dragging the knob
572 
573  if (modifiers & eCommandKey)
574  factor = factor*0.8;
575  else if (modifiers & eShiftKey)
576  factor = factor*50.;
577 
578  factor = factor / (x->attrRangeDelta);
579 
580  if (x->attrTracking==gensym("horizontal"))
581  delta = pt.x;
582  else if (x->attrTracking==gensym("vertical"))
583  delta = -pt.y;
584  else if (x->attrTracking==gensym("both")) {
585  if (fabs(pt.x)>fabs(pt.y))
586  delta = pt.x;
587  else
588  delta = -pt.y;
589  }
590  x->anchorValue = x->anchorValue + (delta/factor);
591  TTLimit(x->anchorValue,x->attrRange[0], x->attrRange[1]);
592  // TODO: Add numdecimalplaces attribute
593 
594  if (modifiers & eCommandKey)
595  textslider_float(x, long(x->anchorValue)); //a change in integer-steps
596  else
597  textslider_float(x, x->anchorValue);
598  //textslider_updatestringvalue(x); this is done now in the flaot method
599 }
600 
601 
602 void textslider_mouseup(t_textslider *x, t_object *patcherview)
603 {
604  t_rect rect;
605 
606  x->mouseDown = 0;
607 
608  // Mouse show up again at current slider value
609  jbox_get_rect_for_view((t_object *)x, patcherview, &rect);
610  jmouse_setposition_view(patcherview,
611  rect.x+((x->attrValue - x->attrRange[0])/(x->attrRangeDelta))*(rect.width-2)+1,
612  x->mousePositionY);
613  jbox_redraw(&x->box);
614 }
615 
616 
617 // Display value while hoverring
618 void textslider_mouseenter(t_textslider *x, t_object *patcherview, t_pt pt, long modifiers)
619 {
620  x->mouseOver = 1;
621  if (x->attrShowValue)
622  textslider_updatestringvalue(x);
623 }
624 
625 
626 void textslider_mouseleave(t_textslider *x, t_object *patcherview, t_pt pt, long modifiers)
627 {
628  t_object* textfield = jbox_get_textfield((t_object*) x);
629 
630  if (textfield)
631  object_method(textfield, gensym("settext"), x->attrText->s_name);
632  x->mouseOver = 0;
633  jbox_redraw(&x->box);
634 }
635 
636 
637 void *textslider_oksize(t_textslider *x, t_rect *newrect)
638 {
639  t_object *textfield = NULL;
640 
641  TTClip(newrect->width, kWidthMinimum, kWidthMaximum);
642  TTClip(newrect->height, kHeightMinimum, kHeightMaximum);
643 
644  // We do textfield configuration here because the margins are dependent upon the dimensions
645  // Textfield is used for displaying the slider name
646  textfield = jbox_get_textfield((t_object*) x);
647  textfield_set_noactivate(textfield, 1);
648  textfield_set_readonly(textfield, 1);
649  textfield_set_editonclick(textfield, 0);
650  textfield_set_wordwrap(textfield, 0);
651  textfield_set_useellipsis(textfield, 1);
652  textfield_set_textcolor(textfield, &x->attrTextColor);
653  textfield_set_textmargins(textfield, x->attrTextOffset[0], x->attrTextOffset[1], 2.0, 2.0);
654  // changed by NP: was: textfield_set_textmargins(textfield, 10.0, 4.0, 2.0, 2.0);
655  return (void*)1;
656 }
657 
658 
659 void textslider_paint(t_textslider *x, t_object *view)
660 {
661  t_rect rect;
662  t_jgraphics* g;
663  double value;
664 
665  if (x->attrRange[0] == x->attrRange[1])
666  value = 0.5;
667  else {
668  value = (x->attrValue - x->attrRange[0])/x->attrRangeDelta;
669  TTLimit(value, 0.0, 1.0);
670  }
671  double position;
672 
673  g = (t_jgraphics*) patcherview_get_jgraphics(view); // obtain graphics context
674  jbox_get_rect_for_view((t_object *)x, view, &rect); // this is the box rectangle -- but we draw relative to 0 0, and thus only care about width & height
675  position = ((rect.width-3)*value)+1; // -5: one pixels for each border and -1 for counting to N-1
676 
677  // Draw passive part of slider
678 
679  // Draw Background
680  jgraphics_set_source_jrgba(g,&x->attrBgColor);
681  jgraphics_rectangle(g, 0., 0., rect.width, rect.height);
682  jgraphics_fill(g);
683 
684  // Draw frame
685  jgraphics_rectangle(g, 0., 0., rect.width, rect.height);
686  jgraphics_set_source_jrgba(g, &x->attrBorderColor);
687  jgraphics_set_line_width(g, 2.0);
688  jgraphics_stroke(g);
689 
690  if (value > 0.)
691  {
692  // Draw active part of slider
693  jgraphics_set_source_jrgba(g, &x->attrFgColor);
694  jgraphics_rectangle_fill_fast(g, 1.0 ,1.0, position, rect.height-2.0);
695 
696  // Draw slider knob
697  jgraphics_set_source_jrgba(g, &x->attrKnobColor);
698  jgraphics_line_draw_fast(g, position, 1.0, position, rect.height-2.0, 2.0);
699  }
700 
701 }
Various utilities for interfacing with Max that are not specific to JamomaModular as such...
int JAMOMA_EXPORT_MAXOBJ main(void)
Set up this class as a Max external the first time an object of this kind is instantiated.