1 /*
2  *                           0BSD
3  *
4  *                    BSD Zero Clause License
5  *
6  *  Copyright (c) 2019 Hermann Meyer
7  *
8  * Permission to use, copy, modify, and/or distribute this software for any
9  * purpose with or without fee is hereby granted.
10 
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  *
19  */
20 
21 #include "xadjustment.h"
22 #include "xadjustment_private.h"
23 
24 
add_adjustment(Widget_t * w,float std_value,float value,float min_value,float max_value,float step,CL_type type)25 Adjustment_t *add_adjustment(Widget_t *w, float std_value, float value,
26                 float min_value,float max_value, float step, CL_type type) {
27     Adjustment_t *adj = (Adjustment_t*)malloc(sizeof(Adjustment_t));
28     assert(adj);
29     adj->log_scale = 20.0;
30 
31     switch(type) {
32         case (CL_LOGSCALE) :
33         *(adj) = (Adjustment_t) {
34             .w           = w,
35             .std_value   = powf(10,(std_value/adj->log_scale)),
36             .value       = powf(10,(value/adj->log_scale)),
37             .min_value   = powf(10,(min_value/adj->log_scale)),
38             .max_value   = powf(10,(max_value/adj->log_scale)),
39             .step        = step,
40             .start_value = powf(10,(value/adj->log_scale)),
41             .scale       = 1.0,
42             .type        = type,
43             .log_scale   = adj->log_scale
44         };
45         break;
46         case (CL_LOGARITHMIC) :
47         *(adj) = (Adjustment_t) {
48             .w           = w,
49             .std_value   = log10(std_value),
50             .value       = log10(value),
51             .min_value   = log10(min_value),
52             .max_value   = log10(max_value),
53             .step        = step,
54             .start_value = log10(value),
55             .scale       = 1.0,
56             .type        = type,
57             .log_scale   = adj->log_scale
58         };
59         break;
60         default:
61         *(adj) = (Adjustment_t) {
62             .w           = w,
63             .std_value   = std_value,
64             .value       = value,
65             .min_value   = min_value,
66             .max_value   = max_value,
67             .step        = step,
68             .start_value = value,
69             .scale       = 1.0,
70             .type        = type,
71             .log_scale   = adj->log_scale
72         };
73         break;
74     }
75 
76     debug_print("Widget_t add adjustment\n");
77     return adj;
78 }
79 
set_adjustment(Adjustment_t * adj,float std_value,float value,float min_value,float max_value,float step,CL_type type)80 void set_adjustment(Adjustment_t *adj, float std_value, float value,
81                 float min_value,float max_value, float step, CL_type type) {
82     if (!adj) adj = (Adjustment_t*)malloc(sizeof(Adjustment_t));
83     assert(adj);
84 
85     switch(type) {
86         case (CL_LOGSCALE) :
87         *(adj) = (Adjustment_t) {
88             .w           = adj->w,
89             .std_value   = powf(10,(std_value/adj->log_scale)),
90             .value       = powf(10,(value/adj->log_scale)),
91             .min_value   = powf(10,(min_value/adj->log_scale)),
92             .max_value   = powf(10,(max_value/adj->log_scale)),
93             .step        = step,
94             .start_value = powf(10,(value/adj->log_scale)),
95             .scale       = 1.0,
96             .type        = type,
97             .log_scale   = adj->log_scale
98         };
99         break;
100         case (CL_LOGARITHMIC) :
101         *(adj) = (Adjustment_t) {
102             .w           = adj->w,
103             .std_value   = log10(std_value),
104             .value       = log10(value),
105             .min_value   = log10(min_value),
106             .max_value   = log10(max_value),
107             .step        = step,
108             .start_value = log10(value),
109             .scale       = 1.0,
110             .type        = type,
111             .log_scale   = adj->log_scale
112         };
113         break;
114         default:
115         *(adj) = (Adjustment_t) {
116             .w           = adj->w,
117             .std_value   = std_value,
118             .value       = value,
119             .min_value   = min_value,
120             .max_value   = max_value,
121             .step        = step,
122             .start_value = value,
123             .scale       = 1.0,
124             .type        = type,
125             .log_scale   = adj->log_scale
126         };
127         break;
128     }
129 
130     debug_print("Widget_t set adjustment\n");
131 }
132 
delete_adjustment(Adjustment_t * adj)133 void *delete_adjustment(Adjustment_t *adj) {
134     if(adj) {
135         free(adj);
136         debug_print("Widget_t delete adjustment\n");
137     }
138     return NULL;
139 }
140 
adj_set_state(Adjustment_t * adj,float state)141 void adj_set_state(Adjustment_t *adj, float state) {
142     if (!adj) return;
143     float nvalue = min(1.0,max(0.0,state));
144     float value = nvalue * (adj->max_value - adj->min_value) + adj->min_value;
145     check_value_changed(adj, &value);
146 }
147 
adj_get_state(Adjustment_t * adj)148 float adj_get_state(Adjustment_t *adj) {
149     if (!adj) return 0.0;
150     return (adj->value - adj->min_value) /
151        (adj->max_value - adj->min_value);
152 }
153 
adj_get_value(Adjustment_t * adj)154 float adj_get_value(Adjustment_t *adj) {
155     if (!adj) return 0.0;
156     if (adj->type == CL_LOGSCALE)
157         return log10(adj->value)*adj->log_scale;
158     else if (adj->type == CL_LOGARITHMIC)
159         return powf(10,adj->value);
160     return (adj->value);
161 }
162 
adj_set_value(Adjustment_t * adj,float v)163 void adj_set_value(Adjustment_t *adj, float v) {
164     if (!adj) return;
165     if (adj->type == CL_LOGSCALE)
166         v = powf(10,(v/adj->log_scale));
167     else if (adj->type == CL_LOGARITHMIC)
168         v = log10(v);
169     v = min(adj->max_value,max(adj->min_value, v));
170     check_value_changed(adj, &v);
171 }
172 
adj_set_start_value(void * w)173 void adj_set_start_value(void *w) {
174     Widget_t * wid = (Widget_t*)w;
175     if(wid->adj_x)wid->adj_x->start_value = wid->adj_x->value;
176     if(wid->adj_y)wid->adj_y->start_value = wid->adj_y->value;
177 }
178 
adj_set_scale(Adjustment_t * adj,float value)179 void adj_set_scale(Adjustment_t *adj, float value) {
180     adj->scale = value;
181 }
182 
adj_set_log_scale(Adjustment_t * adj,float value)183 void adj_set_log_scale(Adjustment_t *adj, float value) {
184     adj->log_scale = value;
185 }
186 
adj_set_motion_state(void * w,float x,float y)187 void adj_set_motion_state(void *w, float x, float y) {
188     Widget_t * wid = (Widget_t*)w;
189     if(wid->adj_x) {
190         float value= wid->adj_x->value;
191         switch(wid->adj_x->type) {
192             case (CL_LOGSCALE):
193             case (CL_LOGARITHMIC):
194             case (CL_CONTINUOS):
195             {
196                 float state = (wid->adj_x->start_value - wid->adj_x->min_value) /
197                     (wid->adj_x->max_value - wid->adj_x->min_value);
198                 float nsteps = wid->adj_x->step / (wid->adj_x->max_value - wid->adj_x->min_value);
199                 float nvalue = min(1.0,max(0.0,state + ((float)(x - wid->pos_x)*wid->adj_x->scale *nsteps)));
200                 float prevalue = nvalue * (wid->adj_x->max_value - wid->adj_x->min_value) + wid->adj_x->min_value;
201                 float mulscale = round(prevalue/wid->adj_x->step);
202                 value = min(wid->adj_x->max_value,max(wid->adj_x->min_value,mulscale*wid->adj_x->step));
203             }
204             break;
205             case (CL_VIEWPORTSLIDER):
206             {
207                 float state = (wid->adj_x->start_value - wid->adj_x->min_value) /
208                     (wid->adj_x->max_value - wid->adj_x->min_value);
209                 float nsteps = wid->adj_x->step / (wid->adj_x->max_value - wid->adj_x->min_value);
210                 float nvalue = min(1.0,max(0.0,state - ((float)(x - wid->pos_x)*wid->adj_x->scale *nsteps)));
211                 float prevalue = nvalue * (wid->adj_x->max_value - wid->adj_x->min_value) + wid->adj_x->min_value;
212                 float mulscale = round(prevalue/wid->adj_x->step);
213                 value = min(wid->adj_x->max_value,max(wid->adj_x->min_value,mulscale*wid->adj_x->step));
214             }
215             break;
216             case (CL_TOGGLE):
217                 // dont toggle on motion!
218                 // value = wid->adj_x->value ? 0.0 : 1.0;
219             break;
220             default:
221             break;
222         }
223         check_value_changed(wid->adj_x, &value);
224     }
225     if(wid->adj_y) {
226         float value = wid->adj_y->value;
227         switch(wid->adj_y->type) {
228             case (CL_LOGSCALE):
229             case (CL_LOGARITHMIC):
230             case (CL_CONTINUOS):
231             {
232                 float state = (wid->adj_y->start_value - wid->adj_y->min_value) /
233                     (wid->adj_y->max_value - wid->adj_y->min_value);
234                 float nsteps = wid->adj_y->step / (wid->adj_y->max_value - wid->adj_y->min_value);
235                 float nvalue = min(1.0,max(0.0,state + ((float)(wid->pos_y - y)*wid->adj_y->scale *nsteps)));
236                 float prevalue = nvalue * (wid->adj_y->max_value - wid->adj_y->min_value) + wid->adj_y->min_value;
237                 float mulscale = round(prevalue/wid->adj_y->step);
238                 value = min(wid->adj_y->max_value,max(wid->adj_y->min_value,mulscale*wid->adj_y->step));
239             }
240             break;
241             case (CL_VIEWPORTSLIDER):
242             {
243                 float state = (wid->adj_y->start_value - wid->adj_y->min_value) /
244                     (wid->adj_y->max_value - wid->adj_y->min_value);
245                 float nsteps = wid->adj_y->step / (wid->adj_y->max_value - wid->adj_y->min_value);
246                 float nvalue = min(1.0,max(0.0,state - ((float)(wid->pos_y - y)*wid->adj_y->scale *nsteps)));
247                 float prevalue = nvalue * (wid->adj_y->max_value - wid->adj_y->min_value) + wid->adj_y->min_value;
248                 float mulscale = round(prevalue/wid->adj_y->step);
249                 value = min(wid->adj_y->max_value,max(wid->adj_y->min_value,mulscale*wid->adj_y->step));
250             }
251             break;
252             case (CL_TOGGLE):
253                 // dont toggle on motion!
254                 // value = wid->adj_y->value ? 0.0 : 1.0;
255             break;
256             default:
257             break;
258         }
259         check_value_changed(wid->adj_y, &value);
260     }
261 }
262 
check_value_changed(Adjustment_t * adj,float * value)263 void check_value_changed(Adjustment_t *adj, float *value) {
264     debug_print("Adjustment_t check_value_changed %f\n", *(value));
265     if(fabs(*(value) - adj->value)>=0.00001) {
266         adj->value = *(value);
267         adj->w->func.adj_callback(adj->w, NULL);
268         adj->w->func.value_changed_callback(adj->w, value);
269     }
270 }
271