inst.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424
  1. /*
  2. * inst.c - Instance structures
  3. *
  4. * Written 2009-2012, 2015 by Werner Almesberger
  5. * Copyright 2009-2012, 2015 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 <stdlib.h>
  13. #include <stdio.h>
  14. #include <math.h>
  15. #include "util.h"
  16. #include "error.h"
  17. #include "coord.h"
  18. #include "expr.h"
  19. #include "layer.h"
  20. #include "obj.h"
  21. #include "delete.h"
  22. #include "gui_util.h"
  23. #include "gui_status.h"
  24. #include "gui_canvas.h"
  25. #include "gui_tool.h"
  26. #include "gui_meas.h"
  27. #include "gui_inst.h"
  28. #include "gui_frame.h"
  29. #include "gui.h"
  30. #include "inst.h"
  31. struct inst *selected_inst = NULL;
  32. struct bbox active_frame_bbox;
  33. struct pkg *pkgs, *active_pkg, *curr_pkg;
  34. struct pkg *reachable_pkg = NULL;
  35. struct inst *frame_instantiating = NULL;
  36. static struct pkg *prev_pkgs, *prev_reachable_pkg;
  37. static unsigned long active_set = 0;
  38. static struct inst_ops vec_ops;
  39. static struct inst_ops frame_ops;
  40. static struct inst_ops meas_ops;
  41. #define IS_ACTIVE ((active_set & 1))
  42. /* ----- selective visibility ---------------------------------------------- */
  43. static int show(enum inst_prio prio)
  44. {
  45. switch (prio) {
  46. case ip_vec:
  47. case ip_frame:
  48. return show_stuff;
  49. case ip_meas:
  50. return show_meas;
  51. default:
  52. return 1;
  53. }
  54. }
  55. int bright(const struct inst *inst)
  56. {
  57. if (!show_bright)
  58. return 0;
  59. return inst->ops != &vec_ops && inst->ops != &frame_ops &&
  60. inst->ops != &meas_ops;
  61. }
  62. static int show_this(const struct inst *inst)
  63. {
  64. if (show_all)
  65. return 1;
  66. if (inst->ops == &frame_ops && inst->u.frame.ref == active_frame)
  67. return 1;
  68. if (!inst->outer)
  69. return active_frame == frames;
  70. return inst->outer->u.frame.ref == active_frame;
  71. }
  72. /* ----- selection of items not on the canvas ------------------------------ */
  73. static void *selected_outside = NULL;
  74. static void (*outside_deselect)(void *item);
  75. static void deselect_outside(void)
  76. {
  77. if (selected_outside && outside_deselect)
  78. outside_deselect(selected_outside);
  79. selected_outside = NULL;
  80. }
  81. void inst_select_outside(void *item, void (*deselect)(void *item))
  82. {
  83. if (item == selected_outside)
  84. return;
  85. deselect_outside();
  86. inst_deselect();
  87. selected_outside = item;
  88. outside_deselect = deselect;
  89. }
  90. /* ----- check connectedness ----------------------------------------------- */
  91. /*
  92. * After an instantiation failure, the instances can get out of sync with the
  93. * object tree, and attempts to select an item on the canvas can cause accesses
  94. * to objects that aren't there anymore. So we need to check if we can still
  95. * reach the corresponding object.
  96. *
  97. * Note: even this isn't bullet-proof. Theoretically, we may get a new object
  98. * in the old place. However, this probably doesn't do any serious damage.
  99. */
  100. static int inst_connected(const struct inst *inst)
  101. {
  102. const struct frame *frame;
  103. const struct vec *vec;
  104. const struct obj *obj;
  105. for (frame = frames; frame; frame = frame->next) {
  106. if (inst->ops == &vec_ops) {
  107. for (vec = frame->vecs; vec; vec = vec->next)
  108. if (vec == inst->vec)
  109. return 1;
  110. } else {
  111. for (obj = frame->objs; obj; obj = obj->next)
  112. if (obj == inst->obj)
  113. return 1;
  114. }
  115. }
  116. return 0;
  117. }
  118. /* ----- selection --------------------------------------------------------- */
  119. static void inst_select_inst(struct inst *inst)
  120. {
  121. selected_inst = inst;
  122. tool_selected_inst(inst);
  123. gui_frame_select_inst(inst);
  124. if (inst->ops->select)
  125. selected_inst->ops->select(inst);
  126. status_set_icon(get_icon_by_inst(inst));
  127. }
  128. /*
  129. * @@@ This logic is overly complicated and should be simplified. The general
  130. * idea was to avoid making unnecessary changes to the user's selections, but
  131. * that risk doesn't exist. Furthermore, the way activate_item is used, its
  132. * preconditions aren't met. It works anyway but it could be simpler as a
  133. * consequence.
  134. *
  135. * activate_item tries to activate the path through the frame references,
  136. * leading to a specific instance. It returns whether this is failed or whether
  137. * it may have been successful.
  138. *
  139. * The initial condition is that we want to activate an item on a frame
  140. * instance that's not active. Since the frame has been instantiated, there
  141. * must be a way to activate it. We just have to find out how.
  142. *
  143. * The first test eliminates the root frame. If we're at the root frame and
  144. * still haven't figured out what to do, something is wrong and we give up.
  145. *
  146. * The next test skips references that are already right. Since we know that
  147. * there must be at least one reference that leads elsewhere, and we haven't
  148. * found it yet, the recursion will tell us whether it can find it at all.
  149. *
  150. * Finally, if we've found a mismatch, we correct it. We then try to fix any
  151. * further mismatches. Since we've made progress, we return 1, even if the
  152. * other fixes should fail (or reach the root frame).
  153. *
  154. */
  155. static int activate_item(struct inst *inst)
  156. {
  157. if (!inst->outer)
  158. return 0;
  159. if (inst->outer->u.frame.ref->active_ref == inst->outer->obj)
  160. return activate_item(inst->outer);
  161. inst->outer->u.frame.ref->active_ref = inst->outer->obj;
  162. activate_item(inst->outer);
  163. return 1;
  164. }
  165. static int __inst_select(struct coord pos, int tries)
  166. {
  167. enum inst_prio prio;
  168. const struct inst *prev;
  169. struct inst *inst;
  170. struct inst *first = NULL; /* first active item */
  171. struct inst *next = NULL; /* active item after currently sel. */
  172. struct inst *any_first = NULL; /* first item, active or inactive */
  173. struct inst *any_same_frame = NULL; /* first item on active frame */
  174. struct frame *frame;
  175. int best_dist = 0; /* keep gcc happy */
  176. int select_next;
  177. int dist, i;
  178. if (!tries) {
  179. fprintf(stderr, "__inst_select: tries exhausted\n");
  180. return 0;
  181. }
  182. prev = selected_inst;
  183. deselect_outside();
  184. edit_nothing();
  185. if (selected_inst) {
  186. gui_frame_deselect_inst(selected_inst);
  187. tool_selected_inst(NULL);
  188. }
  189. inst_deselect();
  190. select_next = 0;
  191. FOR_INST_PRIOS_DOWN(prio) {
  192. if (!show(prio))
  193. continue;
  194. FOR_ALL_INSTS(i, prio, inst) {
  195. if (!show_this(inst))
  196. continue;
  197. if (!inst->ops->distance)
  198. continue;
  199. if (!inst_connected(inst))
  200. continue;
  201. dist = inst->ops->distance(inst, pos, draw_ctx.scale);
  202. if (dist >= 0) {
  203. if (!any_first)
  204. any_first = inst;
  205. if (!any_same_frame && inst->outer &&
  206. inst->outer->u.frame.ref == active_frame)
  207. any_same_frame = inst;
  208. if (!inst->active)
  209. continue;
  210. if (!first)
  211. first = inst;
  212. if (!next && select_next)
  213. next = inst;
  214. if (inst == prev)
  215. select_next = 1;
  216. if (!selected_inst || best_dist > dist) {
  217. selected_inst = inst;
  218. best_dist = dist;
  219. }
  220. }
  221. }
  222. }
  223. if (select_next) {
  224. selected_inst = next ? next : first;
  225. goto selected;
  226. }
  227. if (selected_inst)
  228. goto selected;
  229. /* give vectors a second chance */
  230. if (show_stuff) {
  231. FOR_ALL_INSTS(i, ip_vec, inst) {
  232. if (!inst->active)
  233. continue;
  234. if (!inst_connected(inst))
  235. continue;
  236. dist = gui_dist_vec_fallback(inst, pos, draw_ctx.scale);
  237. if (dist >= 0 && (!selected_inst || best_dist > dist)) {
  238. selected_inst = inst;
  239. best_dist = dist;
  240. }
  241. }
  242. if (selected_inst)
  243. goto selected;
  244. }
  245. if (!show_all)
  246. return 0;
  247. if (any_same_frame) {
  248. activate_item(any_same_frame);
  249. search_inst(any_same_frame);
  250. instantiate();
  251. change_world();
  252. return __inst_select(pos, tries-1);
  253. }
  254. if (any_first) {
  255. frame = any_first->outer ? any_first->outer->u.frame.ref : NULL;
  256. if (frame != active_frame) {
  257. select_frame(frame);
  258. return __inst_select(pos, tries-1);
  259. }
  260. }
  261. return 0;
  262. selected:
  263. inst_select_inst(selected_inst);
  264. return 1;
  265. }
  266. int inst_select(struct coord pos)
  267. {
  268. /*
  269. * We shouldn't need more than 2 tries to select any item, so 5 is more
  270. * than enough. This can still fail, but then it would for any number
  271. * of tries.
  272. */
  273. return __inst_select(pos, 5);
  274. }
  275. struct inst *inst_find_point(struct coord pos)
  276. {
  277. struct inst *inst, *found;
  278. int best_dist = 0; /* keep gcc happy */
  279. int dist, i;
  280. found = NULL;
  281. FOR_ALL_INSTS(i, ip_frame, inst) {
  282. if (!inst->u.frame.active)
  283. continue;
  284. dist = gui_dist_frame_eye(inst, pos, draw_ctx.scale);
  285. if (dist >= 0 && (!found || best_dist > dist)) {
  286. found = inst;
  287. best_dist = dist;
  288. }
  289. }
  290. if (found)
  291. return found;
  292. FOR_ALL_INSTS(i, ip_vec, inst) {
  293. if (!inst->active || !inst->ops->distance)
  294. continue;
  295. dist = inst->ops->distance(inst, pos, draw_ctx.scale);
  296. if (dist >= 0 && (!found || best_dist > dist)) {
  297. found = inst;
  298. best_dist = dist;
  299. }
  300. }
  301. return found;
  302. }
  303. int inst_find_point_selected(struct coord pos, struct inst **res)
  304. {
  305. struct vec **anchors[3];
  306. int n, best_i, i;
  307. struct inst *best = NULL;
  308. struct inst *inst;
  309. int d_min, d, j;
  310. assert(selected_inst);
  311. n = inst_anchors(selected_inst, anchors);
  312. for (i = 0; i != n; i++) {
  313. if (*anchors[i]) {
  314. FOR_ALL_INSTS(j, ip_vec, inst) {
  315. if (inst->vec != *anchors[i])
  316. continue;
  317. d = gui_dist_vec(inst, pos, draw_ctx.scale);
  318. if (d != -1 && (!best || d < d_min)) {
  319. best = inst;
  320. best_i = i;
  321. d_min = d;
  322. }
  323. }
  324. } else {
  325. FOR_ALL_INSTS(j, ip_frame, inst) {
  326. if (inst != selected_inst->outer)
  327. continue;
  328. d = gui_dist_frame(inst, pos, draw_ctx.scale);
  329. if (d != -1 && (!best || d < d_min)) {
  330. best = inst;
  331. best_i = i;
  332. d_min = d;
  333. }
  334. }
  335. }
  336. }
  337. if (!best)
  338. return -1;
  339. if (res)
  340. *res = best;
  341. return best_i;
  342. }
  343. struct coord inst_get_point(const struct inst *inst)
  344. {
  345. if (inst->ops == &vec_ops)
  346. return inst->u.vec.end;
  347. if (inst->ops == &frame_ops)
  348. return inst->base;
  349. abort();
  350. }
  351. struct vec *inst_get_vec(const struct inst *inst)
  352. {
  353. if (inst->ops == &vec_ops)
  354. return inst->vec;
  355. if (inst->ops == &frame_ops)
  356. return NULL;
  357. abort();
  358. }
  359. int inst_anchors(struct inst *inst, struct vec ***anchors)
  360. {
  361. if (inst->vec) {
  362. anchors[0] = &inst->vec->base;
  363. return 1;
  364. }
  365. return obj_anchors(inst->obj, anchors);
  366. }
  367. void inst_deselect(void)
  368. {
  369. if (selected_inst) {
  370. tool_selected_inst(NULL);
  371. gui_frame_deselect_inst(selected_inst);
  372. }
  373. deselect_outside();
  374. status_set_type_x(NULL, "");
  375. status_set_type_y(NULL, "");
  376. status_set_type_entry(NULL, "");
  377. status_set_name(NULL, "");
  378. status_set_x(NULL, "");
  379. status_set_y(NULL, "");
  380. status_set_r(NULL, "");
  381. status_set_angle(NULL, "");
  382. selected_inst = NULL;
  383. edit_nothing();
  384. refresh_pos();
  385. status_set_icon(NULL);
  386. }
  387. /* ----- select instance by vector/object ---------------------------------- */
  388. static void vec_edit(struct vec *vec);
  389. static void obj_edit(struct obj *obj);
  390. void inst_select_vec(struct vec *vec)
  391. {
  392. struct inst *inst;
  393. int i;
  394. if (vec->frame != active_frame)
  395. select_frame(vec->frame);
  396. FOR_ALL_INSTS(i, ip_vec, inst)
  397. if (inst->vec == vec && inst->active) {
  398. inst_deselect();
  399. inst_select_inst(inst);
  400. return;
  401. }
  402. vec_edit(vec);
  403. }
  404. void inst_select_obj(struct obj *obj)
  405. {
  406. enum inst_prio prio;
  407. struct inst *inst;
  408. int i;
  409. if (obj->frame != active_frame)
  410. select_frame(obj->frame);
  411. FOR_INST_PRIOS_DOWN(prio)
  412. FOR_ALL_INSTS(i, prio, inst)
  413. if (inst->obj && inst->obj == obj && inst->active)
  414. goto found;
  415. obj_edit(obj);
  416. return;
  417. found:
  418. inst_deselect();
  419. inst_select_inst(inst);
  420. }
  421. /* ----- common status reporting ------------------------------------------- */
  422. static void rect_status(struct coord a, struct coord b, unit_type width,
  423. int rounded)
  424. {
  425. const char *tip;
  426. struct coord d = sub_vec(b, a);
  427. double r;
  428. unit_type diag;
  429. status_set_xy(d);
  430. tip = "Angle of diagonal";
  431. if (!d.x && !d.y) {
  432. status_set_angle(tip, "a = 0 deg");
  433. } else {
  434. status_set_angle(tip, "a = %3.1f deg", theta(a, b));
  435. }
  436. if (d.x < 0)
  437. d.x = -d.x;
  438. if (d.y < 0)
  439. d.y = -d.y;
  440. diag = hypot(d.x, d.y);
  441. if (rounded) {
  442. /*
  443. * Only consider the part of the diagonal that is on the pad
  444. * surface.
  445. *
  446. * The circle: (x-r)^2+(y-r)^2 = r^2
  447. * The diagonal: x = t*cos(theta), y = t*sin(theta)
  448. *
  449. * t is the distance from the corner of the surrounding
  450. * rectangle to the half-circle:
  451. *
  452. * t = 2*r*(s+c-sqrt(2*s*c))
  453. *
  454. * With s = sin(theta) and c = cos(theta).
  455. *
  456. * Since d.x = diag*cos(theta), we don't need to calculate the
  457. * sinus and cosinus but can use d.x and d.y directly.
  458. */
  459. r = (d.x > d.y ? d.y : d.x)/2;
  460. diag -= 2*r*(d.x+d.y-sqrt(2*d.x*d.y))/diag;
  461. }
  462. set_with_units(status_set_r, "d = ", diag, "Length of diagonal");
  463. if (width != -1) {
  464. status_set_type_entry(NULL, "width =");
  465. set_with_units(status_set_name, "", width, "Line width");
  466. }
  467. }
  468. static void rect_status_sort(struct coord a, struct coord b, unit_type width,
  469. int rounded)
  470. {
  471. sort_coord(&a, &b);
  472. rect_status(a, b, width, rounded);
  473. }
  474. /* ----- helper functions for instance creation ---------------------------- */
  475. static void update_bbox(struct bbox *bbox, struct coord coord)
  476. {
  477. if (bbox->min.x > coord.x)
  478. bbox->min.x = coord.x;
  479. if (bbox->max.x < coord.x)
  480. bbox->max.x = coord.x;
  481. if (bbox->min.y > coord.y)
  482. bbox->min.y = coord.y;
  483. if (bbox->max.y < coord.y)
  484. bbox->max.y = coord.y;
  485. }
  486. static void propagate_bbox(const struct inst *inst)
  487. {
  488. struct inst *frame = frame_instantiating ?
  489. frame_instantiating : curr_pkg->insts[ip_frame];
  490. update_bbox(&frame->bbox, inst->bbox.min);
  491. update_bbox(&frame->bbox, inst->bbox.max);
  492. if (curr_pkg->bbox.min.x || curr_pkg->bbox.min.y ||
  493. curr_pkg->bbox.max.x || curr_pkg->bbox.max.y) {
  494. update_bbox(&curr_pkg->bbox, inst->bbox.min);
  495. update_bbox(&curr_pkg->bbox, inst->bbox.max);
  496. } else {
  497. curr_pkg->bbox = inst->bbox;
  498. }
  499. }
  500. static void grow_bbox_by_width(struct bbox *bbox, unit_type width)
  501. {
  502. bbox->min.x -= width/2;
  503. bbox->min.y -= width/2;
  504. bbox->max.x += width/2;
  505. bbox->max.y += width/2;
  506. }
  507. static int zero_sized(struct coord a, struct coord b, const char *fmt,
  508. const char *arg)
  509. {
  510. if (a.x == b.x && a.y == b.y) {
  511. fail(fmt, "zero-sized", arg);
  512. return 1;
  513. }
  514. if (a.x == b.x) {
  515. fail(fmt, "zero-width", arg);
  516. return 1;
  517. }
  518. if (a.y == b.y) {
  519. fail(fmt, "zero-height", arg);
  520. return 1;
  521. }
  522. return 0;
  523. }
  524. static struct inst *add_inst(const struct inst_ops *ops, enum inst_prio prio,
  525. struct coord base)
  526. {
  527. struct inst *inst;
  528. inst = alloc_type(struct inst);
  529. inst->ops = ops;
  530. inst->prio = prio;
  531. inst->vec = NULL;
  532. inst->obj = NULL;
  533. inst->base = inst->bbox.min = inst->bbox.max = base;
  534. inst->outer = frame_instantiating;
  535. inst->active = IS_ACTIVE;
  536. inst->next = NULL;
  537. *curr_pkg->next_inst[prio] = inst;
  538. curr_pkg->next_inst[prio] = &inst->next;
  539. return inst;
  540. }
  541. /* ----- vec --------------------------------------------------------------- */
  542. static int validate_vec_name(const char *s, void *ctx)
  543. {
  544. struct vec *vec = ctx;
  545. const struct vec *walk;
  546. if (!is_id(s))
  547. return 0;
  548. for (walk = vec->frame->vecs; walk; walk = walk->next)
  549. if (walk->name && !strcmp(walk->name, s))
  550. return 0;
  551. return 1;
  552. }
  553. static void vec_edit(struct vec *vec)
  554. {
  555. edit_x(&vec->x, "X distance");
  556. edit_y(&vec->y, "Y distance");
  557. edit_unique_null(&vec->name, validate_vec_name, vec, "Vector name");
  558. }
  559. static void vec_op_select(struct inst *self)
  560. {
  561. status_set_type_entry(NULL, "ref =");
  562. status_set_name("Vector reference (name)",
  563. "%s", self->vec->name ? self->vec->name : "");
  564. rect_status(self->base, self->u.vec.end, -1, 0);
  565. vec_edit(self->vec);
  566. }
  567. /*
  568. * @@@ The logic of gui_find_point_vec isn't great. Instead of selecting a
  569. * point and then filtering, we should filter the candidates, so that a point
  570. * that's close end eligible can win against one that's closer but not
  571. * eligible.
  572. */
  573. static struct inst *find_point_vec(struct inst *self, struct coord pos)
  574. {
  575. struct inst *inst;
  576. const struct vec *vec;
  577. inst = inst_find_point(pos);
  578. if (!inst)
  579. return NULL;
  580. if (inst->ops == &frame_ops)
  581. return inst;
  582. for (vec = inst->vec; vec; vec = vec->base)
  583. if (vec == self->vec)
  584. return NULL;
  585. return inst;
  586. }
  587. /*
  588. * When instantiating and when dumping, we assume that bases appear in the
  589. * frame->vecs list before vectors using them. A move may change this order.
  590. * We therefore have to sort the list after the move.
  591. *
  592. * Since the list is already ordered, cleaning it up is just O(n).
  593. */
  594. static void do_move_to_vec(struct inst *inst, struct inst *to, int i)
  595. {
  596. struct vec *to_vec = inst_get_vec(to);
  597. struct vec *vec = inst->vec;
  598. struct frame *frame = vec->frame;
  599. struct vec *v, **anchor, **walk;
  600. assert(!i);
  601. vec->base = to_vec;
  602. /*
  603. * Mark the vector that's being rebased and all vectors that
  604. * (recursively) depend on it.
  605. *
  606. * We're mainly interested in the range between the vector being moved
  607. * and the new base. If the vector follows the base, the list is
  608. * already in the correct order and nothing needs moving.
  609. */
  610. for (v = frame->vecs; v != vec; v = v->next)
  611. v->mark = 0;
  612. vec->mark = 1;
  613. for (v = vec->next; v && v != to_vec; v = v->next)
  614. v->mark = v->base ? v->base->mark : 0;
  615. if (!v)
  616. return;
  617. /*
  618. * All the marked vectors appearing on the list before the new base
  619. * are moved after the new base, preserving their order.
  620. *
  621. * Start at frame->vecs, not "vec", so that we move the the vector
  622. * being rebased as well.
  623. */
  624. anchor = &to_vec->next;
  625. walk = &frame->vecs;
  626. while (*walk != to_vec) {
  627. v = *walk;
  628. if (!v->mark) {
  629. walk = &v->next;
  630. } else {
  631. *walk = v->next;
  632. v->next = *anchor;
  633. *anchor = v;
  634. anchor = &v->next;
  635. }
  636. }
  637. }
  638. static struct inst_ops vec_ops = {
  639. .draw = gui_draw_vec,
  640. .hover = gui_hover_vec,
  641. .distance = gui_dist_vec,
  642. .select = vec_op_select,
  643. .find_point = find_point_vec,
  644. .draw_move = draw_move_vec,
  645. .do_move_to = do_move_to_vec,
  646. };
  647. int inst_vec(struct vec *vec, struct coord base)
  648. {
  649. struct inst *inst;
  650. inst = add_inst(&vec_ops, ip_vec, base);
  651. inst->vec = vec;
  652. inst->u.vec.end = vec->pos;
  653. find_inst(inst);
  654. update_bbox(&inst->bbox, vec->pos);
  655. propagate_bbox(inst);
  656. return 1;
  657. }
  658. /* ----- line -------------------------------------------------------------- */
  659. static void obj_line_edit(struct obj *obj)
  660. {
  661. edit_dist_expr(&obj->u.line.width, "Line width");
  662. }
  663. static void line_op_select(struct inst *self)
  664. {
  665. rect_status_sort(self->base, self->u.rect.end, self->u.rect.width, 0);
  666. obj_line_edit(self->obj);
  667. }
  668. static struct inst_ops line_ops = {
  669. .draw = gui_draw_line,
  670. .distance = gui_dist_line,
  671. .select = line_op_select,
  672. .draw_move = draw_move_line,
  673. };
  674. int inst_line(struct obj *obj, struct coord a, struct coord b, unit_type width)
  675. {
  676. struct inst *inst;
  677. inst = add_inst(&line_ops, ip_line, a);
  678. inst->obj = obj;
  679. inst->u.rect.end = b;
  680. inst->u.rect.width = width;
  681. find_inst(inst);
  682. update_bbox(&inst->bbox, b);
  683. grow_bbox_by_width(&inst->bbox, width);
  684. propagate_bbox(inst);
  685. return 1;
  686. }
  687. /* ----- rect -------------------------------------------------------------- */
  688. static void obj_rect_edit(struct obj *obj)
  689. {
  690. edit_dist_expr(&obj->u.rect.width, "Line width");
  691. }
  692. static void rect_op_select(struct inst *self)
  693. {
  694. rect_status_sort(self->base, self->u.rect.end, self->u.rect.width, 0);
  695. obj_rect_edit(self->obj);
  696. }
  697. static struct inst_ops rect_ops = {
  698. .draw = gui_draw_rect,
  699. .distance = gui_dist_rect,
  700. .select = rect_op_select,
  701. .draw_move = draw_move_rect,
  702. };
  703. int inst_rect(struct obj *obj, struct coord a, struct coord b, unit_type width)
  704. {
  705. struct inst *inst;
  706. inst = add_inst(&rect_ops, ip_rect, a);
  707. inst->obj = obj;
  708. inst->u.rect.end = b;
  709. inst->u.rect.width = width;
  710. find_inst(inst);
  711. update_bbox(&inst->bbox, b);
  712. grow_bbox_by_width(&inst->bbox, width);
  713. propagate_bbox(inst);
  714. return 1;
  715. }
  716. /* ----- pad / rpad -------------------------------------------------------- */
  717. static int validate_pad_name(const char *s, void *ctx)
  718. {
  719. char *tmp;
  720. status_begin_reporting();
  721. tmp = expand(s, NULL);
  722. if (!tmp)
  723. return 0;
  724. free(tmp);
  725. return 1;
  726. }
  727. static void obj_pad_edit(struct obj *obj)
  728. {
  729. edit_pad_type(&obj->u.pad.type);
  730. edit_name(&obj->u.pad.name, validate_pad_name, NULL,
  731. "Pad name (template)");
  732. }
  733. static void pad_op_select(struct inst *self)
  734. {
  735. status_set_type_entry(NULL, "label =");
  736. status_set_name("Pad name (actual)", "%s", self->u.pad.name);
  737. rect_status_sort(self->base, self->u.pad.other, -1, 0);
  738. obj_pad_edit(self->obj);
  739. }
  740. static struct inst_ops pad_ops = {
  741. .draw = gui_draw_pad,
  742. .distance = gui_dist_pad,
  743. .select = pad_op_select,
  744. .draw_move = draw_move_pad,
  745. };
  746. static void rpad_op_select(struct inst *self)
  747. {
  748. status_set_type_entry(NULL, "label =");
  749. status_set_name("Pad name (actual)", "%s", self->u.pad.name);
  750. rect_status_sort(self->base, self->u.pad.other, -1, 1);
  751. obj_pad_edit(self->obj);
  752. }
  753. static struct inst_ops rpad_ops = {
  754. .draw = gui_draw_rpad,
  755. .distance = gui_dist_pad, /* @@@ */
  756. .select = rpad_op_select,
  757. .draw_move = draw_move_rpad,
  758. };
  759. int inst_pad(struct obj *obj, const char *name, struct coord a, struct coord b)
  760. {
  761. struct inst *inst;
  762. if (zero_sized(a, b, "%s pad \"%s\"", name))
  763. return 0;
  764. inst = add_inst(obj->u.pad.rounded ? &rpad_ops : &pad_ops,
  765. obj->u.pad.type == pt_normal || obj->u.pad.type == pt_bare ||
  766. obj->u.pad.type == pt_trace ?
  767. ip_pad_copper : ip_pad_special, a);
  768. inst->obj = obj;
  769. inst->u.pad.name = stralloc(name);
  770. inst->u.pad.other = b;
  771. inst->u.pad.layers = pad_type_to_layers(obj->u.pad.type);
  772. find_inst(inst);
  773. update_bbox(&inst->bbox, b);
  774. propagate_bbox(inst);
  775. return 1;
  776. }
  777. /* ----- hole -------------------------------------------------------------- */
  778. static void hole_op_select(struct inst *self)
  779. {
  780. rect_status_sort(self->base, self->u.hole.other, -1, 1);
  781. }
  782. static struct inst_ops hole_ops = {
  783. .draw = gui_draw_hole,
  784. .distance = gui_dist_hole,
  785. .select = hole_op_select,
  786. .draw_move = draw_move_hole,
  787. };
  788. int inst_hole(struct obj *obj, struct coord a, struct coord b)
  789. {
  790. struct inst *inst;
  791. if (zero_sized(a, b, "%s hole", NULL))
  792. return 0;
  793. inst = add_inst(&hole_ops, ip_hole, a);
  794. inst->obj = obj;
  795. inst->u.hole.other = b;
  796. inst->u.hole.layers = mech_hole_layers();
  797. find_inst(inst);
  798. update_bbox(&inst->bbox, b);
  799. propagate_bbox(inst);
  800. return 1;
  801. }
  802. /* ----- arc --------------------------------------------------------------- */
  803. static void obj_arc_edit(struct obj *obj)
  804. {
  805. edit_dist_expr(&obj->u.arc.width, "Line width");
  806. }
  807. static void arc_op_select(struct inst *self)
  808. {
  809. status_set_xy(self->base);
  810. status_set_angle("Angle", "a = %3.1f deg",
  811. self->u.arc.a1 == self->u.arc.a2 ? 360 :
  812. self->u.arc.a2-self->u.arc.a1);
  813. set_with_units(status_set_r, "r = ", self->u.arc.r, "Radius");
  814. status_set_type_entry(NULL, "width =");
  815. set_with_units(status_set_name, "", self->u.arc.width, "Line width");
  816. obj_arc_edit(self->obj);
  817. }
  818. static struct inst_ops arc_ops = {
  819. .draw = gui_draw_arc,
  820. .distance = gui_dist_arc,
  821. .select = arc_op_select,
  822. .draw_move = draw_move_arc,
  823. .do_move_to = do_move_to_arc,
  824. };
  825. int inst_arc(struct obj *obj, struct coord center, struct coord start,
  826. struct coord end, unit_type width)
  827. {
  828. struct inst *inst;
  829. double r, a1, a2;
  830. a1 = theta(center, start);
  831. a2 = theta(center, end);
  832. inst = add_inst(&arc_ops,
  833. fmod(a1, 360) == fmod(a2, 360) ? ip_circ : ip_arc, center);
  834. inst->obj = obj;
  835. r = hypot(start.x-center.x, start.y-center.y);
  836. inst->u.arc.r = r;
  837. inst->u.arc.a1 = a1;
  838. inst->u.arc.a2 = a2;
  839. inst->u.arc.width = width;
  840. inst->bbox.min.x = center.x-r;
  841. inst->bbox.max.x = center.x+r;
  842. inst->bbox.min.y = center.y-r;
  843. inst->bbox.max.y = center.y+r;
  844. find_inst(inst);
  845. grow_bbox_by_width(&inst->bbox, width);
  846. propagate_bbox(inst);
  847. return 1;
  848. }
  849. /* ----- measurement ------------------------------------------------------- */
  850. static void obj_meas_edit(struct obj *obj)
  851. {
  852. edit_dist_expr(&obj->u.meas.offset, "Measurement line offset");
  853. }
  854. static void meas_op_select(struct inst *self)
  855. {
  856. rect_status_sort(self->base, self->u.meas.end, -1, 0);
  857. status_set_type_entry(NULL, "offset =");
  858. set_with_units(status_set_name, "", self->u.meas.offset,
  859. "Measurement line offset");
  860. obj_meas_edit(self->obj);
  861. }
  862. static struct inst_ops meas_ops = {
  863. .draw = gui_draw_meas,
  864. .distance = gui_dist_meas,
  865. .select = meas_op_select,
  866. .begin_drag_move= begin_drag_move_meas,
  867. .find_point = find_point_meas_move,
  868. .draw_move = draw_move_meas,
  869. .end_drag_move = end_drag_move_meas,
  870. .do_move_to = do_move_to_meas,
  871. };
  872. struct inst *find_meas_hint(const struct obj *obj)
  873. {
  874. struct inst *inst;
  875. for (inst = curr_pkg->insts[ip_meas]; inst; inst = inst->next)
  876. if (inst->obj == obj)
  877. break;
  878. return inst;
  879. }
  880. int inst_meas(struct obj *obj, struct coord from, struct coord to)
  881. {
  882. struct inst *inst;
  883. struct coord a1, b1;
  884. inst = find_meas_hint(obj);
  885. assert(inst);
  886. inst->base = from;
  887. inst->u.meas.end = to;
  888. inst->u.meas.valid = 1;
  889. /* @@@ we still need to consider the text size as well */
  890. update_bbox(&inst->bbox, from);
  891. update_bbox(&inst->bbox, to);
  892. project_meas(inst, &a1, &b1);
  893. update_bbox(&inst->bbox, a1);
  894. update_bbox(&inst->bbox, b1);
  895. propagate_bbox(inst);
  896. return 1;
  897. }
  898. void inst_meas_hint(struct obj *obj, unit_type offset)
  899. {
  900. static const struct coord zero = { 0, 0 };
  901. struct inst *inst;
  902. inst = find_meas_hint(obj);
  903. if (inst)
  904. return;
  905. inst = add_inst(&meas_ops, ip_meas, zero);
  906. inst->obj = obj;
  907. inst->u.meas.offset = offset;
  908. inst->u.meas.valid = 0;
  909. inst->active = 1; /* measurements are always active */
  910. }
  911. /* ----- direct editing of objects ----------------------------------------- */
  912. static void obj_edit(struct obj *obj)
  913. {
  914. switch (obj->type) {
  915. case ot_frame:
  916. break;
  917. case ot_line:
  918. obj_line_edit(obj);
  919. break;
  920. case ot_rect:
  921. obj_rect_edit(obj);
  922. break;
  923. case ot_arc:
  924. obj_arc_edit(obj);
  925. break;
  926. case ot_pad:
  927. obj_pad_edit(obj);
  928. break;
  929. case ot_meas:
  930. obj_meas_edit(obj);
  931. break;
  932. default:
  933. abort();
  934. }
  935. }
  936. /* ----- active instance --------------------------------------------------- */
  937. void inst_begin_active(int active)
  938. {
  939. active_set = (active_set << 1) | active;
  940. }
  941. void inst_end_active(void)
  942. {
  943. active_set >>= 1;
  944. }
  945. /* ----- frame ------------------------------------------------------------- */
  946. static void frame_op_select(struct inst *self)
  947. {
  948. rect_status(self->bbox.min, self->bbox.max, -1, 0);
  949. status_set_type_entry(NULL, "name =");
  950. status_set_name("Frame name", "%s", self->u.frame.ref->name);
  951. }
  952. static struct inst_ops frame_ops = {
  953. .draw = gui_draw_frame,
  954. .hover = gui_hover_frame,
  955. .distance = gui_dist_frame,
  956. .select = frame_op_select,
  957. .draw_move = draw_move_frame,
  958. };
  959. void inst_begin_frame(struct obj *obj, struct frame *frame,
  960. struct coord base, int active, int is_active_frame)
  961. {
  962. struct inst *inst;
  963. inst = add_inst(&frame_ops, ip_frame, base);
  964. inst->obj = obj;
  965. inst->u.frame.ref = frame;
  966. inst->u.frame.active = is_active_frame;
  967. inst->active = active;
  968. find_inst(inst);
  969. frame_instantiating = inst;
  970. }
  971. void inst_end_frame(const struct frame *frame)
  972. {
  973. struct inst *inst = frame_instantiating;
  974. frame_instantiating = frame_instantiating->outer;
  975. if (frame_instantiating)
  976. propagate_bbox(inst);
  977. if (inst->u.frame.active && frame == active_frame)
  978. active_frame_bbox = inst->bbox;
  979. }
  980. /* ----- package ----------------------------------------------------------- */
  981. void inst_select_pkg(const char *name, int active)
  982. {
  983. struct pkg **pkg;
  984. enum inst_prio prio;
  985. name = name ? unique(name) : NULL;
  986. for (pkg = &pkgs; *pkg; pkg = &(*pkg)->next)
  987. if ((*pkg)->name == name)
  988. break;
  989. if (!*pkg) {
  990. *pkg = zalloc_type(struct pkg);
  991. (*pkg)->name = name;
  992. FOR_INST_PRIOS_UP(prio)
  993. (*pkg)->next_inst[prio] = &(*pkg)->insts[prio];
  994. (*pkg)->samples =
  995. zalloc_size(sizeof(struct sample *)*n_samples);
  996. (*pkg)->n_samples = n_samples;
  997. }
  998. curr_pkg = *pkg;
  999. if (active && name)
  1000. reachable_pkg = curr_pkg;
  1001. }
  1002. /* ----- misc. ------------------------------------------------------------- */
  1003. struct bbox inst_get_bbox(const struct pkg *pkg)
  1004. {
  1005. if (pkg)
  1006. return pkg->bbox;
  1007. else
  1008. return pkgs->insts[ip_frame]->bbox;
  1009. }
  1010. static void cleanup_inst(enum inst_prio prio, const struct inst *inst)
  1011. {
  1012. switch (prio) {
  1013. case ip_pad_copper:
  1014. case ip_pad_special:
  1015. free(inst->u.pad.name);
  1016. break;
  1017. default:
  1018. break;
  1019. }
  1020. }
  1021. static void free_pkgs(struct pkg *pkg)
  1022. {
  1023. enum inst_prio prio;
  1024. struct pkg *next_pkg;
  1025. struct inst *inst, *next;
  1026. while (pkg) {
  1027. next_pkg = pkg->next;
  1028. FOR_INST_PRIOS_UP(prio)
  1029. for (inst = pkg->insts[prio]; inst; inst = next) {
  1030. next = inst->next;
  1031. cleanup_inst(prio, inst);
  1032. free(inst);
  1033. }
  1034. reset_samples(pkg->samples, pkg->n_samples);
  1035. free(pkg->samples);
  1036. free(pkg);
  1037. pkg = next_pkg;
  1038. }
  1039. }
  1040. void inst_start(void)
  1041. {
  1042. static struct bbox bbox_zero = { { 0, 0 }, { 0, 0 }};
  1043. active_frame_bbox = bbox_zero;
  1044. prev_pkgs = pkgs;
  1045. prev_reachable_pkg = reachable_pkg;
  1046. pkgs = NULL;
  1047. reachable_pkg = NULL;
  1048. inst_select_pkg(NULL, 0);
  1049. curr_pkg = pkgs;
  1050. frame_instantiating = NULL;
  1051. }
  1052. void inst_commit(void)
  1053. {
  1054. struct pkg *pkg;
  1055. if (active_pkg) {
  1056. for (pkg = pkgs; pkg && pkg->name != active_pkg->name;
  1057. pkg = pkg->next);
  1058. active_pkg = pkg;
  1059. }
  1060. if (!active_pkg)
  1061. active_pkg = pkgs->next;
  1062. free_pkgs(prev_pkgs);
  1063. }
  1064. void inst_revert(void)
  1065. {
  1066. free_pkgs(pkgs);
  1067. pkgs = prev_pkgs;
  1068. reachable_pkg = prev_reachable_pkg;
  1069. }
  1070. void inst_draw(void)
  1071. {
  1072. enum inst_prio prio;
  1073. struct inst *inst;
  1074. int i;
  1075. FOR_INST_PRIOS_UP(prio)
  1076. FOR_ALL_INSTS(i, prio, inst)
  1077. if (show_this(inst))
  1078. if (show(prio) && !inst->active &&
  1079. inst->ops->draw)
  1080. inst->ops->draw(inst);
  1081. FOR_INST_PRIOS_UP(prio)
  1082. FOR_ALL_INSTS(i, prio, inst)
  1083. if (show(prio) && prio != ip_frame && inst->active &&
  1084. inst != selected_inst && inst->ops->draw)
  1085. inst->ops->draw(inst);
  1086. if (show_stuff)
  1087. FOR_ALL_INSTS(i, ip_frame, inst)
  1088. if (inst->active && inst != selected_inst &&
  1089. inst->ops->draw)
  1090. inst->ops->draw(inst);
  1091. if (selected_inst && selected_inst->ops->draw)
  1092. selected_inst->ops->draw(selected_inst);
  1093. }
  1094. void inst_highlight_vecs(int (*pick)(struct inst *inst, void *user), void *user)
  1095. {
  1096. struct inst *inst;
  1097. int i;
  1098. FOR_ALL_INSTS(i, ip_vec, inst) {
  1099. inst->u.vec.highlighted = pick(inst, user);
  1100. if (inst->u.vec.highlighted)
  1101. gui_highlight_vec(inst);
  1102. }
  1103. }
  1104. struct inst *inst_find_vec(struct coord pos,
  1105. int (*pick)(struct inst *inst, void *user), void *user)
  1106. {
  1107. struct inst *inst, *found;
  1108. int best_dist = 0; /* keep gcc happy */
  1109. int dist, i;
  1110. found = NULL;
  1111. FOR_ALL_INSTS(i, ip_vec, inst) {
  1112. if (!inst->ops->distance)
  1113. continue;
  1114. dist = inst->ops->distance(inst, pos, draw_ctx.scale);
  1115. if (dist < 0 || (found && best_dist <= dist))
  1116. continue;
  1117. if (!pick(inst, user))
  1118. continue;
  1119. found = inst;
  1120. best_dist = dist;
  1121. }
  1122. return found;
  1123. }
  1124. struct inst *insts_ip_vec(void)
  1125. {
  1126. return active_pkg->insts[ip_vec];
  1127. }
  1128. struct pix_buf *inst_draw_move(struct inst *inst, struct coord pos, int i)
  1129. {
  1130. return inst->ops->draw_move(inst, pos, i);
  1131. }
  1132. int inst_do_move_to(struct inst *inst, struct inst *to, int i)
  1133. {
  1134. if (!inst->ops->do_move_to)
  1135. return 0;
  1136. inst->ops->do_move_to(inst, to, i);
  1137. return 1;
  1138. }
  1139. struct pix_buf *inst_hover(struct inst *inst)
  1140. {
  1141. if (!inst->ops->hover)
  1142. return NULL;
  1143. return inst->ops->hover(inst);
  1144. }
  1145. void inst_begin_drag_move(struct inst *inst, int i)
  1146. {
  1147. if (inst->ops->begin_drag_move)
  1148. inst->ops->begin_drag_move(inst, i);
  1149. }
  1150. void inst_delete(struct inst *inst)
  1151. {
  1152. if (inst->ops == &vec_ops)
  1153. delete_vec(inst->vec);
  1154. else
  1155. delete_obj(inst->obj);
  1156. }