123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 |
- /*
- * gui_meas.c - GUI, measurements
- *
- * Written 2009, 2010 by Werner Almesberger
- * Copyright 2009, 2010 by Werner Almesberger
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
- #include "util.h"
- #include "coord.h"
- #include "meas.h"
- #include "inst.h"
- #include "gui_canvas.h"
- #include "gui_tool.h"
- #include "gui_meas.h"
- static struct inst *meas_inst; /* point from which we're dragging */
- static enum {
- min_to_next_or_max,
- max_to_min,
- next_to_min,
- } mode;
- /* ----- measurement type characteristics ---------------------------------- */
- static struct meas_dsc {
- lt_op_type lt;
- enum meas_type type;
- } *meas_dsc;
- static struct meas_dsc meas_dsc_xy = {
- .lt = lt_xy,
- .type = mt_xy_next,
- };
- static struct meas_dsc meas_dsc_x = {
- .lt = lt_x,
- .type = mt_x_next,
- };
- static struct meas_dsc meas_dsc_y = {
- .lt = lt_y,
- .type = mt_y_next,
- };
- /* ----- min/next/max tester ----------------------------------------------- */
- static int is_min(lt_op_type lt, const struct inst *inst)
- {
- const struct sample *min;
- min = meas_find_min(lt, active_pkg->samples[inst->vec->n], NULL);
- return coord_eq(inst->u.vec.end, min->pos);
- }
- static int is_next(lt_op_type lt,
- const struct inst *inst, const struct inst *ref)
- {
- const struct sample *next;
- next = meas_find_next(lt, active_pkg->samples[inst->vec->n],
- ref->u.vec.end, NULL);
- return coord_eq(inst->u.vec.end, next->pos);
- }
- static int is_max(lt_op_type lt, const struct inst *inst)
- {
- const struct sample *max;
- max = meas_find_max(lt, active_pkg->samples[inst->vec->n], NULL);
- return coord_eq(inst->u.vec.end, max->pos);
- }
- static int is_a_next(lt_op_type lt, struct inst *inst)
- {
- struct inst *a;
- const struct sample *min, *next;
- for (a = insts_ip_vec(); a; a = a->next) {
- min = meas_find_min(lt, active_pkg->samples[a->vec->n], NULL);
- next = meas_find_next(lt, active_pkg->samples[inst->vec->n],
- min->pos, NULL);
- if (coord_eq(next->pos, inst->u.vec.end))
- return 1;
- }
- return 0;
- }
- #if 0
- static int is_min_of_next(lt_op_type lt,
- const struct inst *inst, const struct inst *ref)
- {
- struct coord min, next;
- min = meas_find_min(lt, inst->vec->samples);
- next = meas_find_next(lt, ref->vec->samples, min);
- return coord_eq(next, ref->u.vec.end);
- }
- #endif
- /* ----- picker functions -------------------------------------------------- */
- static int meas_pick_vec_a(struct inst *inst, void *ctx)
- {
- struct vec *vec = inst->vec;
- if (!active_pkg->samples[vec->n])
- return 0;
- if (is_min(meas_dsc->lt, inst)) {
- mode = min_to_next_or_max;
- return 1;
- }
- if (is_max(meas_dsc->lt, inst)) {
- mode = max_to_min;
- return 1;
- }
- if (is_a_next(meas_dsc->lt, inst)) {
- mode = next_to_min;
- return 1;
- }
- return 0;
- }
- static int meas_pick_vec_b(struct inst *inst, void *ctx)
- {
- struct vec *vec = inst->vec;
- struct inst *a = ctx;
- if (!active_pkg->samples[vec->n])
- return 0;
- switch (mode) {
- case min_to_next_or_max:
- if (is_max(meas_dsc->lt, inst))
- return 1;
- if (is_next(meas_dsc->lt, inst, a))
- return 1;
- return 0;
- case max_to_min:
- return is_min(meas_dsc->lt, inst);
- case next_to_min:
- if (!is_min(meas_dsc->lt, inst))
- return 0;
- return is_next(meas_dsc->lt, a, inst);
- // return is_min_of_next(meas_dsc->lt, inst, a);
- default:
- abort();
- }
- }
- /* ----- highlighting ------------------------------------------------------ */
- static void meas_highlight_a(void)
- {
- inst_highlight_vecs(meas_pick_vec_a, NULL);
- }
- static void meas_highlight_b(void)
- {
- inst_highlight_vecs(meas_pick_vec_b, meas_inst);
- }
- /* ----- meas -------------------------------------------------------------- */
- struct pix_buf *draw_move_meas(struct inst *inst, struct coord pos, int i)
- {
- return draw_move_line_common(inst, inst->u.meas.end, pos,
- inst->obj->u.meas.inverted ? 1-i : i);
- }
- /* ----- tool selection ---------------------------------------------------- */
- static void tool_selected_meas(void)
- {
- highlight = meas_highlight_a;
- redraw();
- }
- static void tool_selected_meas_xy(void)
- {
- meas_dsc = &meas_dsc_xy;
- tool_selected_meas();
- }
- static void tool_selected_meas_x(void)
- {
- meas_dsc = &meas_dsc_x;
- tool_selected_meas();
- }
- static void tool_selected_meas_y(void)
- {
- meas_dsc = &meas_dsc_y;
- tool_selected_meas();
- }
- static void tool_deselected_meas(void)
- {
- highlight = NULL;
- redraw();
- }
- /* ----- find start point (new measurement) -------------------------------- */
- static int is_highlighted(struct inst *inst, void *user)
- {
- return inst->u.vec.highlighted;
- }
- static struct inst *find_point_meas_new(struct coord pos)
- {
- return inst_find_vec(pos, is_highlighted, NULL);
- }
- /* ----- begin dragging new measurement ------------------------------------ */
- static void begin_drag_new_meas(struct inst *inst)
- {
- highlight = meas_highlight_b;
- meas_inst = inst;
- if (is_min(meas_dsc->lt, inst))
- mode = min_to_next_or_max;
- else if (is_max(meas_dsc->lt, inst))
- mode = max_to_min;
- else
- mode = next_to_min;
- redraw();
- }
- /* ----- end dragging new measurement -------------------------------------- */
- static int end_new_meas(struct inst *from, struct inst *to)
- {
- struct obj *obj;
- struct meas *meas;
- meas_inst = NULL;
- highlight = NULL;
- if (from == to)
- return 0;
- /* it's safe to pass "from" here, but we may change it later */
- obj = new_obj_unconnected(ot_meas, from);
- connect_obj(frames, obj);
- meas = &obj->u.meas;
- meas->label = NULL;
- switch (mode) {
- case min_to_next_or_max:
- if (!is_max(meas_dsc->lt, to)) {
- meas->type = meas_dsc->type;
- } else {
- meas->type = meas_dsc->type+3;
- }
- obj->base = from->vec;
- meas->high = to->vec;
- break;
- case next_to_min:
- meas->type = meas_dsc->type;
- obj->base = to->vec;
- meas->high = from->vec;
- break;
- case max_to_min:
- meas->type = meas_dsc->type+3;
- obj->base = to->vec;
- meas->high = from->vec;
- break;
- default:
- abort();
- }
- meas->inverted =
- mode == min_to_next_or_max && is_min(meas_dsc->lt, to) ? 0 :
- meas_dsc->lt(from->u.vec.end, to->u.vec.end) !=
- (mode == min_to_next_or_max);
- meas->offset = NULL;
- meas_dsc = NULL;
- /* we don't support qualifiers through the GUI yet */
- meas->low_qual = NULL;
- meas->high_qual = NULL;
- return 1;
- }
- static void cancel_drag_new_meas(void)
- {
- meas_inst = NULL;
- highlight = NULL;
- redraw();
- }
- /* ----- begin dragging existing measurement ------------------------------- */
- /*
- * We didn't record which instance provided the vector we're using here, so we
- * have to search for it now.
- */
- static struct inst *vec_at(const struct vec *vec, struct coord pos)
- {
- struct inst *inst;
- const struct sample *s;
- for (inst = insts_ip_vec(); inst; inst = inst->next)
- if (inst->vec == vec)
- for (s = active_pkg->samples[vec->n]; s; s = s->next)
- if (coord_eq(s->pos, pos))
- return inst;
- abort();
- }
- void begin_drag_move_meas(struct inst *inst, int i)
- {
- const struct meas *meas = &inst->obj->u.meas;
- struct coord a, b;
- switch (meas->type) {
- case mt_xy_next:
- case mt_xy_max:
- meas_dsc = &meas_dsc_xy;
- break;
- case mt_x_next:
- case mt_x_max:
- meas_dsc = &meas_dsc_x;
- break;
- case mt_y_next:
- case mt_y_max:
- meas_dsc = &meas_dsc_y;
- break;
- default:
- abort();
- }
- highlight = meas_highlight_b;
- /*
- * We're setting up the same conditions as after picking the first
- * point when making a new measurement. Thus, we set meas_inst to the
- * vector to the endpoint we're not moving.
- */
- a = inst->base;
- b = inst->u.meas.end;
- if (inst->obj->u.meas.inverted)
- SWAP(a, b);
- switch (i) {
- case 0:
- mode = meas->type < 3 ? next_to_min : max_to_min;
- meas_inst = vec_at(inst->obj->u.meas.high, b);
- break;
- case 1:
- mode = min_to_next_or_max;
- meas_inst = vec_at(inst->obj->base, a);
- break;
- default:
- abort();
- }
- // redraw();
- }
- /* ----- find end point (existing measurement) ----------------------------- */
- struct inst *find_point_meas_move(struct inst *inst, struct coord pos)
- {
- return inst_find_vec(pos, is_highlighted, NULL);
- }
- /* ----- end dragging existing measurements -------------------------------- */
- void end_drag_move_meas(void)
- {
- highlight = NULL;
- redraw();
- }
- void do_move_to_meas(struct inst *inst, struct inst *to, int i)
- {
- struct meas *meas = &inst->obj->u.meas;
- switch (i) {
- case 0:
- inst->obj->base = inst_get_vec(to);
- break;
- case 1:
- meas->high = inst_get_vec(to);
- if (is_max(meas_dsc->lt, to))
- meas->type = (meas->type % 3)+3;
- else
- meas->type = (meas->type % 3);
- break;
- default:
- abort();
- }
- }
- /* ----- operations -------------------------------------------------------- */
- struct tool_ops tool_meas_ops = {
- .tool_selected = tool_selected_meas_xy,
- .tool_deselected= tool_deselected_meas,
- .find_point = find_point_meas_new,
- .begin_drag_new = begin_drag_new_meas,
- .drag_new = drag_new_line,
- .end_new = end_new_meas,
- .cancel_drag_new= cancel_drag_new_meas,
- };
- struct tool_ops tool_meas_ops_x = {
- .tool_selected = tool_selected_meas_x,
- .tool_deselected= tool_deselected_meas,
- .find_point = find_point_meas_new,
- .begin_drag_new = begin_drag_new_meas,
- .drag_new = drag_new_line,
- .end_new = end_new_meas,
- .cancel_drag_new= cancel_drag_new_meas,
- };
- struct tool_ops tool_meas_ops_y = {
- .tool_selected = tool_selected_meas_y,
- .tool_deselected= tool_deselected_meas,
- .find_point = find_point_meas_new,
- .begin_drag_new = begin_drag_new_meas,
- .drag_new = drag_new_line,
- .end_new = end_new_meas,
- .cancel_drag_new= cancel_drag_new_meas,
- };
|