gui_meas.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  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. #include "util.h"
  13. #include "coord.h"
  14. #include "meas.h"
  15. #include "inst.h"
  16. #include "gui_canvas.h"
  17. #include "gui_tool.h"
  18. #include "gui_meas.h"
  19. static struct inst *meas_inst; /* point from which we're dragging */
  20. static enum {
  21. min_to_next_or_max,
  22. max_to_min,
  23. next_to_min,
  24. } mode;
  25. /* ----- measurement type characteristics ---------------------------------- */
  26. static struct meas_dsc {
  27. lt_op_type lt;
  28. enum meas_type type;
  29. } *meas_dsc;
  30. static struct meas_dsc meas_dsc_xy = {
  31. .lt = lt_xy,
  32. .type = mt_xy_next,
  33. };
  34. static struct meas_dsc meas_dsc_x = {
  35. .lt = lt_x,
  36. .type = mt_x_next,
  37. };
  38. static struct meas_dsc meas_dsc_y = {
  39. .lt = lt_y,
  40. .type = mt_y_next,
  41. };
  42. /* ----- min/next/max tester ----------------------------------------------- */
  43. static int is_min(lt_op_type lt, const struct inst *inst)
  44. {
  45. const struct sample *min;
  46. min = meas_find_min(lt, active_pkg->samples[inst->vec->n], NULL);
  47. return coord_eq(inst->u.vec.end, min->pos);
  48. }
  49. static int is_next(lt_op_type lt,
  50. const struct inst *inst, const struct inst *ref)
  51. {
  52. const struct sample *next;
  53. next = meas_find_next(lt, active_pkg->samples[inst->vec->n],
  54. ref->u.vec.end, NULL);
  55. return coord_eq(inst->u.vec.end, next->pos);
  56. }
  57. static int is_max(lt_op_type lt, const struct inst *inst)
  58. {
  59. const struct sample *max;
  60. max = meas_find_max(lt, active_pkg->samples[inst->vec->n], NULL);
  61. return coord_eq(inst->u.vec.end, max->pos);
  62. }
  63. static int is_a_next(lt_op_type lt, struct inst *inst)
  64. {
  65. struct inst *a;
  66. const struct sample *min, *next;
  67. for (a = insts_ip_vec(); a; a = a->next) {
  68. min = meas_find_min(lt, active_pkg->samples[a->vec->n], NULL);
  69. next = meas_find_next(lt, active_pkg->samples[inst->vec->n],
  70. min->pos, NULL);
  71. if (coord_eq(next->pos, inst->u.vec.end))
  72. return 1;
  73. }
  74. return 0;
  75. }
  76. #if 0
  77. static int is_min_of_next(lt_op_type lt,
  78. const struct inst *inst, const struct inst *ref)
  79. {
  80. struct coord min, next;
  81. min = meas_find_min(lt, inst->vec->samples);
  82. next = meas_find_next(lt, ref->vec->samples, min);
  83. return coord_eq(next, ref->u.vec.end);
  84. }
  85. #endif
  86. /* ----- picker functions -------------------------------------------------- */
  87. static int meas_pick_vec_a(struct inst *inst, void *ctx)
  88. {
  89. struct vec *vec = inst->vec;
  90. if (!active_pkg->samples[vec->n])
  91. return 0;
  92. if (is_min(meas_dsc->lt, inst)) {
  93. mode = min_to_next_or_max;
  94. return 1;
  95. }
  96. if (is_max(meas_dsc->lt, inst)) {
  97. mode = max_to_min;
  98. return 1;
  99. }
  100. if (is_a_next(meas_dsc->lt, inst)) {
  101. mode = next_to_min;
  102. return 1;
  103. }
  104. return 0;
  105. }
  106. static int meas_pick_vec_b(struct inst *inst, void *ctx)
  107. {
  108. struct vec *vec = inst->vec;
  109. struct inst *a = ctx;
  110. if (!active_pkg->samples[vec->n])
  111. return 0;
  112. switch (mode) {
  113. case min_to_next_or_max:
  114. if (is_max(meas_dsc->lt, inst))
  115. return 1;
  116. if (is_next(meas_dsc->lt, inst, a))
  117. return 1;
  118. return 0;
  119. case max_to_min:
  120. return is_min(meas_dsc->lt, inst);
  121. case next_to_min:
  122. if (!is_min(meas_dsc->lt, inst))
  123. return 0;
  124. return is_next(meas_dsc->lt, a, inst);
  125. // return is_min_of_next(meas_dsc->lt, inst, a);
  126. default:
  127. abort();
  128. }
  129. }
  130. /* ----- highlighting ------------------------------------------------------ */
  131. static void meas_highlight_a(void)
  132. {
  133. inst_highlight_vecs(meas_pick_vec_a, NULL);
  134. }
  135. static void meas_highlight_b(void)
  136. {
  137. inst_highlight_vecs(meas_pick_vec_b, meas_inst);
  138. }
  139. /* ----- meas -------------------------------------------------------------- */
  140. struct pix_buf *draw_move_meas(struct inst *inst, struct coord pos, int i)
  141. {
  142. return draw_move_line_common(inst, inst->u.meas.end, pos,
  143. inst->obj->u.meas.inverted ? 1-i : i);
  144. }
  145. /* ----- tool selection ---------------------------------------------------- */
  146. static void tool_selected_meas(void)
  147. {
  148. highlight = meas_highlight_a;
  149. redraw();
  150. }
  151. static void tool_selected_meas_xy(void)
  152. {
  153. meas_dsc = &meas_dsc_xy;
  154. tool_selected_meas();
  155. }
  156. static void tool_selected_meas_x(void)
  157. {
  158. meas_dsc = &meas_dsc_x;
  159. tool_selected_meas();
  160. }
  161. static void tool_selected_meas_y(void)
  162. {
  163. meas_dsc = &meas_dsc_y;
  164. tool_selected_meas();
  165. }
  166. static void tool_deselected_meas(void)
  167. {
  168. highlight = NULL;
  169. redraw();
  170. }
  171. /* ----- find start point (new measurement) -------------------------------- */
  172. static int is_highlighted(struct inst *inst, void *user)
  173. {
  174. return inst->u.vec.highlighted;
  175. }
  176. static struct inst *find_point_meas_new(struct coord pos)
  177. {
  178. return inst_find_vec(pos, is_highlighted, NULL);
  179. }
  180. /* ----- begin dragging new measurement ------------------------------------ */
  181. static void begin_drag_new_meas(struct inst *inst)
  182. {
  183. highlight = meas_highlight_b;
  184. meas_inst = inst;
  185. if (is_min(meas_dsc->lt, inst))
  186. mode = min_to_next_or_max;
  187. else if (is_max(meas_dsc->lt, inst))
  188. mode = max_to_min;
  189. else
  190. mode = next_to_min;
  191. redraw();
  192. }
  193. /* ----- end dragging new measurement -------------------------------------- */
  194. static int end_new_meas(struct inst *from, struct inst *to)
  195. {
  196. struct obj *obj;
  197. struct meas *meas;
  198. meas_inst = NULL;
  199. highlight = NULL;
  200. if (from == to)
  201. return 0;
  202. /* it's safe to pass "from" here, but we may change it later */
  203. obj = new_obj_unconnected(ot_meas, from);
  204. connect_obj(frames, obj);
  205. meas = &obj->u.meas;
  206. meas->label = NULL;
  207. switch (mode) {
  208. case min_to_next_or_max:
  209. if (!is_max(meas_dsc->lt, to)) {
  210. meas->type = meas_dsc->type;
  211. } else {
  212. meas->type = meas_dsc->type+3;
  213. }
  214. obj->base = from->vec;
  215. meas->high = to->vec;
  216. break;
  217. case next_to_min:
  218. meas->type = meas_dsc->type;
  219. obj->base = to->vec;
  220. meas->high = from->vec;
  221. break;
  222. case max_to_min:
  223. meas->type = meas_dsc->type+3;
  224. obj->base = to->vec;
  225. meas->high = from->vec;
  226. break;
  227. default:
  228. abort();
  229. }
  230. meas->inverted =
  231. mode == min_to_next_or_max && is_min(meas_dsc->lt, to) ? 0 :
  232. meas_dsc->lt(from->u.vec.end, to->u.vec.end) !=
  233. (mode == min_to_next_or_max);
  234. meas->offset = NULL;
  235. meas_dsc = NULL;
  236. /* we don't support qualifiers through the GUI yet */
  237. meas->low_qual = NULL;
  238. meas->high_qual = NULL;
  239. return 1;
  240. }
  241. static void cancel_drag_new_meas(void)
  242. {
  243. meas_inst = NULL;
  244. highlight = NULL;
  245. redraw();
  246. }
  247. /* ----- begin dragging existing measurement ------------------------------- */
  248. /*
  249. * We didn't record which instance provided the vector we're using here, so we
  250. * have to search for it now.
  251. */
  252. static struct inst *vec_at(const struct vec *vec, struct coord pos)
  253. {
  254. struct inst *inst;
  255. const struct sample *s;
  256. for (inst = insts_ip_vec(); inst; inst = inst->next)
  257. if (inst->vec == vec)
  258. for (s = active_pkg->samples[vec->n]; s; s = s->next)
  259. if (coord_eq(s->pos, pos))
  260. return inst;
  261. abort();
  262. }
  263. void begin_drag_move_meas(struct inst *inst, int i)
  264. {
  265. const struct meas *meas = &inst->obj->u.meas;
  266. struct coord a, b;
  267. switch (meas->type) {
  268. case mt_xy_next:
  269. case mt_xy_max:
  270. meas_dsc = &meas_dsc_xy;
  271. break;
  272. case mt_x_next:
  273. case mt_x_max:
  274. meas_dsc = &meas_dsc_x;
  275. break;
  276. case mt_y_next:
  277. case mt_y_max:
  278. meas_dsc = &meas_dsc_y;
  279. break;
  280. default:
  281. abort();
  282. }
  283. highlight = meas_highlight_b;
  284. /*
  285. * We're setting up the same conditions as after picking the first
  286. * point when making a new measurement. Thus, we set meas_inst to the
  287. * vector to the endpoint we're not moving.
  288. */
  289. a = inst->base;
  290. b = inst->u.meas.end;
  291. if (inst->obj->u.meas.inverted)
  292. SWAP(a, b);
  293. switch (i) {
  294. case 0:
  295. mode = meas->type < 3 ? next_to_min : max_to_min;
  296. meas_inst = vec_at(inst->obj->u.meas.high, b);
  297. break;
  298. case 1:
  299. mode = min_to_next_or_max;
  300. meas_inst = vec_at(inst->obj->base, a);
  301. break;
  302. default:
  303. abort();
  304. }
  305. // redraw();
  306. }
  307. /* ----- find end point (existing measurement) ----------------------------- */
  308. struct inst *find_point_meas_move(struct inst *inst, struct coord pos)
  309. {
  310. return inst_find_vec(pos, is_highlighted, NULL);
  311. }
  312. /* ----- end dragging existing measurements -------------------------------- */
  313. void end_drag_move_meas(void)
  314. {
  315. highlight = NULL;
  316. redraw();
  317. }
  318. void do_move_to_meas(struct inst *inst, struct inst *to, int i)
  319. {
  320. struct meas *meas = &inst->obj->u.meas;
  321. switch (i) {
  322. case 0:
  323. inst->obj->base = inst_get_vec(to);
  324. break;
  325. case 1:
  326. meas->high = inst_get_vec(to);
  327. if (is_max(meas_dsc->lt, to))
  328. meas->type = (meas->type % 3)+3;
  329. else
  330. meas->type = (meas->type % 3);
  331. break;
  332. default:
  333. abort();
  334. }
  335. }
  336. /* ----- operations -------------------------------------------------------- */
  337. struct tool_ops tool_meas_ops = {
  338. .tool_selected = tool_selected_meas_xy,
  339. .tool_deselected= tool_deselected_meas,
  340. .find_point = find_point_meas_new,
  341. .begin_drag_new = begin_drag_new_meas,
  342. .drag_new = drag_new_line,
  343. .end_new = end_new_meas,
  344. .cancel_drag_new= cancel_drag_new_meas,
  345. };
  346. struct tool_ops tool_meas_ops_x = {
  347. .tool_selected = tool_selected_meas_x,
  348. .tool_deselected= tool_deselected_meas,
  349. .find_point = find_point_meas_new,
  350. .begin_drag_new = begin_drag_new_meas,
  351. .drag_new = drag_new_line,
  352. .end_new = end_new_meas,
  353. .cancel_drag_new= cancel_drag_new_meas,
  354. };
  355. struct tool_ops tool_meas_ops_y = {
  356. .tool_selected = tool_selected_meas_y,
  357. .tool_deselected= tool_deselected_meas,
  358. .find_point = find_point_meas_new,
  359. .begin_drag_new = begin_drag_new_meas,
  360. .drag_new = drag_new_line,
  361. .end_new = end_new_meas,
  362. .cancel_drag_new= cancel_drag_new_meas,
  363. };