20 #include "ext_common.h"
21 #include "jpatcher_api.h"
22 #include "jgraphics.h"
24 #include "TTFoundation.h"
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;
41 typedef struct _textslider{
47 t_jrgba attrBorderColor;
48 t_jrgba attrTextColor;
49 t_jrgba attrKnobColor;
52 float attrValueUnclipped;
55 float attrTextOffset[2];
57 float attrDefaultValue;
63 t_symbol *attrTracking;
66 double mousePositionY;
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);
104 static t_class* s_textslider_class;
110 #pragma mark Class Definition
113 int JAMOMA_EXPORT_MAXOBJ
main(
void)
118 common_symbols_init();
120 c = class_new(
"j.textslider",
121 (method)textslider_new,
122 (method)textslider_free,
123 sizeof(t_textslider),
128 flags = JBOX_TEXTFIELD;
129 jbox_initclass(c, flags);
130 c->c_flags |= CLASS_FLAG_NEWDICTIONARY;
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);
147 CLASS_ATTR_DEFAULT(c,
"patching_rect", 0,
"0. 0. 160. 20.");
148 CLASS_ATTR_MIN(c,
"patching_size", 0,
"1. 1.");
150 CLASS_ATTR_DEFAULT(c,
"fontname", 0, JAMOMA_DEFAULT_FONT);
151 CLASS_ATTR_DEFAULT(c,
"fontsize", 0,
"10");
153 CLASS_STICKY_ATTR(c,
"category", 0,
"Color");
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");
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");
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");
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");
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");
180 CLASS_STICKY_ATTR_CLEAR(c,
"category");
182 CLASS_STICKY_ATTR(c,
"category", 0,
"Jamoma");
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);
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);
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);
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);
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");
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");
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);
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);
231 CLASS_STICKY_ATTR_CLEAR(c,
"category");
233 class_register(CLASS_BOX, c);
234 s_textslider_class = c;
241 #pragma mark Life Cycle
245 void *textslider_new(t_symbol *s,
long argc, t_atom *argv)
247 t_textslider *x = NULL;
248 t_dictionary *d=NULL;
251 if (!(d=object_dictionaryarg(argc,argv)))
254 if (x = (t_textslider *)object_alloc(s_textslider_class)) {
268 | JBOX_MOUSEDRAGDELTA
278 jbox_new(&x->box, flags, argc, argv);
279 x->box.b_firstin = (t_object *)x;
281 x->outlet = outlet_new(x, 0);
283 attr_dictionary_process(x,d);
284 jbox_ready((t_jbox *)x);
293 void textslider_free(t_textslider *x)
295 jbox_free((t_jbox *)x);
305 t_max_err textslider_notify(t_textslider *x, t_symbol *s, t_symbol *msg,
void *sender,
void *data)
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"));
315 textfield = jbox_get_textfield((t_object*) x);
317 textfield_set_textcolor(textfield, &x->attrTextColor);
319 if (attrname == gensym(
"text"))
320 object_method(textfield, gensym(
"settext"), x->attrText->s_name);
322 if (attrname == gensym(
"textpos"))
323 textfield_set_textmargins(textfield, x->attrTextOffset[0], x->attrTextOffset[1], 2.0, 2.0);
325 if ((x->mouseDown) && (x->attrShowValue))
326 textslider_updatestringvalue(x);
328 jbox_redraw(&x->box);
330 return jbox_notify((t_jbox*)x, s, msg, sender, data);
335 void textslider_assist(t_textslider *x,
void *b,
long msg,
long arg,
char *dst)
338 strcpy(dst,
"Input");
341 case 0: strcpy(dst,
"Output");
break;
347 void textslider_updatestringvalue(t_textslider *x)
352 t_object* textfield = jbox_get_textfield((t_object*) x);
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);
359 snprintf(str2, 16,
"%s", str);
360 object_method(textfield, gensym(
"settext"), str2);
363 jbox_redraw(&x->box);
367 void textslider_bang(t_textslider *x)
370 outlet_float(x->outlet, x->attrValueUnclipped);
375 void textslider_int(t_textslider *x,
long value)
377 textslider_float(x,(
double)value);
382 void textslider_float(t_textslider *x,
double value)
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);
390 jbox_redraw((t_jbox*)x);
395 void textslider_set(t_textslider *x,
double value)
397 x->attrValueUnclipped = value;
398 x->attrValue = value;
399 TTLimit(x->attrValue, x->attrRange[0], x->attrRange[1]);
401 if ((x->attrShowValue) && (x->mouseOver))
402 textslider_updatestringvalue(x);
404 jbox_redraw((t_jbox*)x);
410 #pragma mark Attributes
413 t_max_err textslider_getRange(t_textslider *x,
void *attr,
long *argc, t_atom **argv)
420 *argv = (t_atom *)sysmem_newptr(
sizeof(t_atom) * 2);
422 atom_setfloat(*argv, x->attrRange[0]);
423 atom_setfloat(*argv+1, x->attrRange[1]);
429 t_max_err textslider_setRange(t_textslider *x,
void *attr,
long argc, t_atom *argv)
432 x->attrRange[0] = atom_getfloat(argv+0);
434 if (atom_getfloat(argv+1) >= atom_getfloat(argv+0))
435 x->attrRange[1] = atom_getfloat(argv+1);
437 x->attrRange[1] = atom_getfloat(argv+0);
438 x->attrRange[0] = atom_getfloat(argv+1);
440 x->attrRangeDelta = x->attrRange[1] - x->attrRange[0];
442 jbox_redraw((t_jbox*)x);
448 t_max_err textslider_getTextOffset(t_textslider *x,
void *attr,
long *argc, t_atom **argv)
456 *argv = (t_atom *)sysmem_newptr(
sizeof(t_atom) * 2);
458 atom_setfloat(*argv, x->attrTextOffset[0]);
459 atom_setfloat(*argv+1, x->attrTextOffset[1]);
465 t_max_err textslider_setTextOffset(t_textslider *x,
void *attr,
long argc, t_atom *argv)
468 x->attrTextOffset[0] = atom_getfloat(argv+0);
470 x->attrTextOffset[1] = atom_getfloat(argv+1);
472 jbox_redraw((t_jbox*)x);
477 t_max_err textslider_get_text(t_textslider *x,
void *attr,
long *argc, t_atom **argv)
481 *argv = (t_atom *)sysmem_newptr(
sizeof(t_atom));
482 atom_setsym(*argv, x->attrText);
487 t_max_err textslider_set_text(t_textslider *x,
void *attr,
long argc, t_atom *argv)
490 x->attrText = atom_getsym(argv);
492 x->attrText = _sym_nothing;
494 jbox_redraw((t_jbox*)x);
499 t_max_err textslider_get_unit(t_textslider *x,
void *attr,
long *argc, t_atom **argv)
503 *argv = (t_atom *)sysmem_newptr(
sizeof(t_atom));
504 atom_setsym(*argv, x->attrUnit);
509 t_max_err textslider_set_unit(t_textslider *x,
void *attr,
long argc, t_atom *argv)
512 x->attrUnit = atom_getsym(argv);
514 x->attrUnit = _sym_nothing;
524 #pragma mark User Interface
528 void textslider_mousedoubleclick(t_textslider *x, t_object *patcherview, t_pt pt,
long modifiers)
530 if (modifiers & eControlKey) {
531 textslider_float(x, x->attrDefaultValue);
532 x->anchorValue = x->attrDefaultValue;
538 void textslider_mousedown(t_textslider *x, t_object *patcherview, t_pt px,
long modifiers)
545 jbox_get_rect_for_view((t_object *)x, patcherview, &rect);
546 x->mousePositionY = rect.y + px.y;
549 if (x->attrClickJump) {
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));
556 textslider_float(x, delta);
558 x->anchorValue = x->attrValue;
559 jbox_set_mousedragdelta((t_object *)x, 1);
564 void textslider_mousedragdelta(t_textslider *x, t_object *patcherview, t_pt pt,
long modifiers)
570 jbox_get_rect_for_view((t_object *)x, patcherview, &rect);
571 factor = rect.width-2;
573 if (modifiers & eCommandKey)
575 else if (modifiers & eShiftKey)
578 factor = factor / (x->attrRangeDelta);
580 if (x->attrTracking==gensym(
"horizontal"))
582 else if (x->attrTracking==gensym(
"vertical"))
584 else if (x->attrTracking==gensym(
"both")) {
585 if (fabs(pt.x)>fabs(pt.y))
590 x->anchorValue = x->anchorValue + (delta/factor);
591 TTLimit(x->anchorValue,x->attrRange[0], x->attrRange[1]);
594 if (modifiers & eCommandKey)
595 textslider_float(x,
long(x->anchorValue));
597 textslider_float(x, x->anchorValue);
602 void textslider_mouseup(t_textslider *x, t_object *patcherview)
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,
613 jbox_redraw(&x->box);
618 void textslider_mouseenter(t_textslider *x, t_object *patcherview, t_pt pt,
long modifiers)
621 if (x->attrShowValue)
622 textslider_updatestringvalue(x);
626 void textslider_mouseleave(t_textslider *x, t_object *patcherview, t_pt pt,
long modifiers)
628 t_object* textfield = jbox_get_textfield((t_object*) x);
631 object_method(textfield, gensym(
"settext"), x->attrText->s_name);
633 jbox_redraw(&x->box);
637 void *textslider_oksize(t_textslider *x, t_rect *newrect)
639 t_object *textfield = NULL;
641 TTClip(newrect->width, kWidthMinimum, kWidthMaximum);
642 TTClip(newrect->height, kHeightMinimum, kHeightMaximum);
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);
659 void textslider_paint(t_textslider *x, t_object *view)
665 if (x->attrRange[0] == x->attrRange[1])
668 value = (x->attrValue - x->attrRange[0])/x->attrRangeDelta;
669 TTLimit(value, 0.0, 1.0);
673 g = (t_jgraphics*) patcherview_get_jgraphics(view);
674 jbox_get_rect_for_view((t_object *)x, view, &rect);
675 position = ((rect.width-3)*value)+1;
680 jgraphics_set_source_jrgba(g,&x->attrBgColor);
681 jgraphics_rectangle(g, 0., 0., rect.width, rect.height);
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);
693 jgraphics_set_source_jrgba(g, &x->attrFgColor);
694 jgraphics_rectangle_fill_fast(g, 1.0 ,1.0, position, rect.height-2.0);
697 jgraphics_set_source_jrgba(g, &x->attrKnobColor);
698 jgraphics_line_draw_fast(g, position, 1.0, position, rect.height-2.0, 2.0);
int JAMOMA_EXPORT_MAXOBJ main(void)
Set up this class as a Max external the first time an object of this kind is instantiated.