Root/gui_meas.c

Source at commit 103933acf59927d84df7f99d9580dfc0f45059c2 created 2 years 10 months ago.
By Werner Almesberger, fix a few whitespace issues in previous commit
1/*
2 * gui_meas.c - GUI, measurements
3 *
4 * Written 2009, 2010 by Werner Almesberger
5* Copyright 2009, 2010 by Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include "util.h"
15#include "coord.h"
16#include "meas.h"
17#include "inst.h"
18#include "gui_canvas.h"
19#include "gui_tool.h"
20#include "gui_meas.h"
21
22
23static struct inst *meas_inst; /* point from which we're dragging */
24
25static enum {
26    min_to_next_or_max,
27    max_to_min,
28    next_to_min,
29} mode;
30
31
32/* ----- measurement type characteristics ---------------------------------- */
33
34
35static struct meas_dsc {
36    lt_op_type lt;
37    enum meas_type type;
38} *meas_dsc;
39
40
41static struct meas_dsc meas_dsc_xy = {
42    .lt = lt_xy,
43    .type = mt_xy_next,
44};
45
46
47static struct meas_dsc meas_dsc_x = {
48    .lt = lt_x,
49    .type = mt_x_next,
50};
51
52
53static struct meas_dsc meas_dsc_y = {
54    .lt = lt_y,
55    .type = mt_y_next,
56};
57
58
59/* ----- min/next/max tester ----------------------------------------------- */
60
61
62static int is_min(lt_op_type lt, const struct inst *inst)
63{
64    const struct sample *min;
65
66    min = meas_find_min(lt, active_pkg->samples[inst->vec->n], NULL);
67    return coord_eq(inst->u.vec.end, min->pos);
68}
69
70
71static int is_next(lt_op_type lt,
72    const struct inst *inst, const struct inst *ref)
73{
74    const struct sample *next;
75
76    next = meas_find_next(lt, active_pkg->samples[inst->vec->n],
77        ref->u.vec.end, NULL);
78    return coord_eq(inst->u.vec.end, next->pos);
79}
80
81
82static int is_max(lt_op_type lt, const struct inst *inst)
83{
84    const struct sample *max;
85
86    max = meas_find_max(lt, active_pkg->samples[inst->vec->n], NULL);
87    return coord_eq(inst->u.vec.end, max->pos);
88}
89
90
91static int is_a_next(lt_op_type lt, struct inst *inst)
92{
93    struct inst *a;
94    const struct sample *min, *next;
95
96    for (a = insts_ip_vec(); a; a = a->next) {
97        min = meas_find_min(lt, active_pkg->samples[a->vec->n], NULL);
98        next = meas_find_next(lt, active_pkg->samples[inst->vec->n],
99            min->pos, NULL);
100        if (coord_eq(next->pos, inst->u.vec.end))
101            return 1;
102    }
103    return 0;
104}
105
106
107#if 0
108static int is_min_of_next(lt_op_type lt,
109    const struct inst *inst, const struct inst *ref)
110{
111    struct coord min, next;
112
113    min = meas_find_min(lt, inst->vec->samples);
114    next = meas_find_next(lt, ref->vec->samples, min);
115    return coord_eq(next, ref->u.vec.end);
116}
117#endif
118
119
120/* ----- picker functions -------------------------------------------------- */
121
122
123static int meas_pick_vec_a(struct inst *inst, void *ctx)
124{
125    struct vec *vec = inst->vec;
126
127    if (!active_pkg->samples[vec->n])
128        return 0;
129    if (is_min(meas_dsc->lt, inst)) {
130        mode = min_to_next_or_max;
131        return 1;
132    }
133    if (is_max(meas_dsc->lt, inst)) {
134        mode = max_to_min;
135        return 1;
136    }
137    if (is_a_next(meas_dsc->lt, inst)) {
138        mode = next_to_min;
139        return 1;
140    }
141    return 0;
142}
143
144
145static int meas_pick_vec_b(struct inst *inst, void *ctx)
146{
147    struct vec *vec = inst->vec;
148    struct inst *a = ctx;
149
150    if (!active_pkg->samples[vec->n])
151        return 0;
152    switch (mode) {
153    case min_to_next_or_max:
154        if (is_max(meas_dsc->lt, inst))
155            return 1;
156        if (is_next(meas_dsc->lt, inst, a))
157            return 1;
158        return 0;
159    case max_to_min:
160        return is_min(meas_dsc->lt, inst);
161    case next_to_min:
162        if (!is_min(meas_dsc->lt, inst))
163            return 0;
164        return is_next(meas_dsc->lt, a, inst);
165// return is_min_of_next(meas_dsc->lt, inst, a);
166    default:
167        abort();
168    }
169}
170
171
172/* ----- highlighting ------------------------------------------------------ */
173
174
175static void meas_highlight_a(void)
176{
177    inst_highlight_vecs(meas_pick_vec_a, NULL);
178}
179
180
181static void meas_highlight_b(void)
182{
183    inst_highlight_vecs(meas_pick_vec_b, meas_inst);
184}
185
186
187/* ----- meas -------------------------------------------------------------- */
188
189
190struct pix_buf *draw_move_meas(struct inst *inst, struct coord pos, int i)
191{
192    return draw_move_line_common(inst, inst->u.meas.end, pos,
193        inst->obj->u.meas.inverted ? 1-i : i);
194}
195
196
197/* ----- tool selection ---------------------------------------------------- */
198
199
200static void tool_selected_meas(void)
201{
202    highlight = meas_highlight_a;
203    redraw();
204}
205
206
207static void tool_selected_meas_xy(void)
208{
209    meas_dsc = &meas_dsc_xy;
210    tool_selected_meas();
211}
212
213
214static void tool_selected_meas_x(void)
215{
216    meas_dsc = &meas_dsc_x;
217    tool_selected_meas();
218}
219
220
221static void tool_selected_meas_y(void)
222{
223    meas_dsc = &meas_dsc_y;
224    tool_selected_meas();
225}
226
227
228static void tool_deselected_meas(void)
229{
230    highlight = NULL;
231    redraw();
232}
233
234
235/* ----- find start point (new measurement) -------------------------------- */
236
237
238static int is_highlighted(struct inst *inst, void *user)
239{
240    return inst->u.vec.highlighted;
241}
242
243
244static struct inst *find_point_meas_new(struct coord pos)
245{
246    return inst_find_vec(pos, is_highlighted, NULL);
247}
248
249
250/* ----- begin dragging new measurement ------------------------------------ */
251
252
253static void begin_drag_new_meas(struct inst *inst)
254{
255    highlight = meas_highlight_b;
256    meas_inst = inst;
257    if (is_min(meas_dsc->lt, inst))
258        mode = min_to_next_or_max;
259    else if (is_max(meas_dsc->lt, inst))
260        mode = max_to_min;
261    else
262        mode = next_to_min;
263    redraw();
264}
265
266
267/* ----- end dragging new measurement -------------------------------------- */
268
269
270static int end_new_meas(struct inst *from, struct inst *to)
271{
272    struct obj *obj;
273    struct meas *meas;
274
275    meas_inst = NULL;
276    highlight = NULL;
277    if (from == to)
278        return 0;
279    /* it's safe to pass "from" here, but we may change it later */
280    obj = new_obj_unconnected(ot_meas, from);
281    connect_obj(frames, obj);
282    meas = &obj->u.meas;
283    meas->label = NULL;
284    switch (mode) {
285    case min_to_next_or_max:
286        if (!is_max(meas_dsc->lt, to)) {
287            meas->type = meas_dsc->type;
288        } else {
289            meas->type = meas_dsc->type+3;
290        }
291        obj->base = from->vec;
292        meas->high = to->vec;
293        break;
294    case next_to_min:
295        meas->type = meas_dsc->type;
296        obj->base = to->vec;
297        meas->high = from->vec;
298        break;
299    case max_to_min:
300        meas->type = meas_dsc->type+3;
301        obj->base = to->vec;
302        meas->high = from->vec;
303        break;
304    default:
305        abort();
306    }
307    meas->inverted =
308        mode == min_to_next_or_max && is_min(meas_dsc->lt, to) ? 0 :
309        meas_dsc->lt(from->u.vec.end, to->u.vec.end) !=
310        (mode == min_to_next_or_max);
311    meas->offset = NULL;
312    meas_dsc = NULL;
313    /* we don't support qualifiers through the GUI yet */
314    meas->low_qual = NULL;
315    meas->high_qual = NULL;
316    return 1;
317}
318
319
320static void cancel_drag_new_meas(void)
321{
322    meas_inst = NULL;
323    highlight = NULL;
324    redraw();
325}
326
327
328/* ----- begin dragging existing measurement ------------------------------- */
329
330
331/*
332 * We didn't record which instance provided the vector we're using here, so we
333 * have to search for it now.
334 */
335
336static struct inst *vec_at(const struct vec *vec, struct coord pos)
337{
338    struct inst *inst;
339    const struct sample *s;
340
341    for (inst = insts_ip_vec(); inst; inst = inst->next)
342        if (inst->vec == vec)
343            for (s = active_pkg->samples[vec->n]; s; s = s->next)
344                if (coord_eq(s->pos, pos))
345                    return inst;
346    abort();
347}
348
349
350void begin_drag_move_meas(struct inst *inst, int i)
351{
352    const struct meas *meas = &inst->obj->u.meas;
353    struct coord a, b;
354
355    switch (meas->type) {
356    case mt_xy_next:
357    case mt_xy_max:
358        meas_dsc = &meas_dsc_xy;
359        break;
360    case mt_x_next:
361    case mt_x_max:
362        meas_dsc = &meas_dsc_x;
363        break;
364    case mt_y_next:
365    case mt_y_max:
366        meas_dsc = &meas_dsc_y;
367        break;
368    default:
369        abort();
370    }
371    highlight = meas_highlight_b;
372
373    /*
374     * We're setting up the same conditions as after picking the first
375     * point when making a new measurement. Thus, we set meas_inst to the
376     * vector to the endpoint we're not moving.
377     */
378    a = inst->base;
379    b = inst->u.meas.end;
380    if (inst->obj->u.meas.inverted)
381        SWAP(a, b);
382    switch (i) {
383    case 0:
384        mode = meas->type < 3 ? next_to_min : max_to_min;
385        meas_inst = vec_at(inst->obj->u.meas.high, b);
386        break;
387    case 1:
388        mode = min_to_next_or_max;
389        meas_inst = vec_at(inst->obj->base, a);
390        break;
391    default:
392        abort();
393    }
394// redraw();
395}
396
397
398/* ----- find end point (existing measurement) ----------------------------- */
399
400
401struct inst *find_point_meas_move(struct inst *inst, struct coord pos)
402{
403    return inst_find_vec(pos, is_highlighted, NULL);
404}
405
406
407/* ----- end dragging existing measurements -------------------------------- */
408
409
410void end_drag_move_meas(void)
411{
412    highlight = NULL;
413    redraw();
414}
415
416
417void do_move_to_meas(struct inst *inst, struct inst *to, int i)
418{
419    struct meas *meas = &inst->obj->u.meas;
420
421    switch (i) {
422    case 0:
423        inst->obj->base = inst_get_vec(to);
424        break;
425    case 1:
426        meas->high = inst_get_vec(to);
427        if (is_max(meas_dsc->lt, to))
428            meas->type = (meas->type % 3)+3;
429        else
430            meas->type = (meas->type % 3);
431        break;
432    default:
433        abort();
434    }
435}
436
437
438/* ----- operations -------------------------------------------------------- */
439
440
441struct tool_ops tool_meas_ops = {
442    .tool_selected = tool_selected_meas_xy,
443    .tool_deselected= tool_deselected_meas,
444    .find_point = find_point_meas_new,
445    .begin_drag_new = begin_drag_new_meas,
446    .drag_new = drag_new_line,
447    .end_new = end_new_meas,
448    .cancel_drag_new= cancel_drag_new_meas,
449};
450
451struct tool_ops tool_meas_ops_x = {
452    .tool_selected = tool_selected_meas_x,
453    .tool_deselected= tool_deselected_meas,
454    .find_point = find_point_meas_new,
455    .begin_drag_new = begin_drag_new_meas,
456    .drag_new = drag_new_line,
457    .end_new = end_new_meas,
458    .cancel_drag_new= cancel_drag_new_meas,
459};
460
461
462struct tool_ops tool_meas_ops_y = {
463    .tool_selected = tool_selected_meas_y,
464    .tool_deselected= tool_deselected_meas,
465    .find_point = find_point_meas_new,
466    .begin_drag_new = begin_drag_new_meas,
467    .drag_new = drag_new_line,
468    .end_new = end_new_meas,
469    .cancel_drag_new= cancel_drag_new_meas,
470};
471

Archive Download this file

Branches:
master



interactive