Properties.txt 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. MODULE Properties;
  2. (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 System/Mod/Properties.odc *)
  3. (* DO NOT EDIT *)
  4. IMPORT SYSTEM, Kernel, Math, Services, Fonts, Stores, Views, Controllers, Dialog;
  5. CONST
  6. (** StdProp.known/valid **)
  7. color* = 0; typeface* = 1; size* = 2; style* = 3; weight* = 4;
  8. (** SizeProp.known/valid **)
  9. width* = 0; height* = 1;
  10. (** PollVerbsMsg limitation **)
  11. maxVerbs* = 16;
  12. (** PollPickMsg.mark, PollPick mark **)
  13. noMark* = FALSE; mark* = TRUE;
  14. (** PollPickMsg.show, PollPick show **)
  15. hide* = FALSE; show* = TRUE;
  16. TYPE
  17. Property* = POINTER TO ABSTRACT RECORD
  18. next-: Property; (** property lists are sorted **) (* by TD address *)
  19. known*, readOnly*: SET; (** used for polling, ignored when setting properties **)
  20. valid*: SET
  21. END;
  22. StdProp* = POINTER TO RECORD (Property)
  23. color*: Dialog.Color;
  24. typeface*: Fonts.Typeface;
  25. size*: INTEGER;
  26. style*: RECORD val*, mask*: SET END;
  27. weight*: INTEGER
  28. END;
  29. SizeProp* = POINTER TO RECORD (Property)
  30. width*, height*: INTEGER
  31. END;
  32. (** property messages **)
  33. Message* = Views.PropMessage;
  34. PollMsg* = RECORD (Message)
  35. prop*: Property (** preset to NIL **)
  36. END;
  37. SetMsg* = RECORD (Message)
  38. old*, prop*: Property
  39. END;
  40. (** preferences **)
  41. Preference* = ABSTRACT RECORD (Message) END;
  42. ResizePref* = RECORD (Preference)
  43. fixed*: BOOLEAN; (** OUT, preset to FALSE **)
  44. horFitToPage*: BOOLEAN; (** OUT, preset to FALSE **)
  45. verFitToPage*: BOOLEAN; (** OUT, preset to FALSE **)
  46. horFitToWin*: BOOLEAN; (** OUT, preset to FALSE **)
  47. verFitToWin*: BOOLEAN; (** OUT, preset to FALSE **)
  48. END;
  49. SizePref* = RECORD (Preference)
  50. w*, h*: INTEGER; (** OUT, preset to caller's preference **)
  51. fixedW*, fixedH*: BOOLEAN (** IN **)
  52. END;
  53. BoundsPref* = RECORD (Preference)
  54. w*, h*: INTEGER (** OUT, preset to (Views.undefined, Views.undefined) **)
  55. END;
  56. FocusPref* = RECORD (Preference)
  57. atLocation*: BOOLEAN; (** IN **)
  58. x*, y*: INTEGER; (** IN, valid iff atLocation **)
  59. hotFocus*, setFocus*: BOOLEAN (** OUT, preset to (FALSE, FALSE) **)
  60. END;
  61. ControlPref* = RECORD (Preference)
  62. char*: CHAR; (** IN **)
  63. focus*: Views.View; (** IN **)
  64. getFocus*: BOOLEAN; (** OUT, valid if (v # focus), preset to ((char = [l]tab) & "FocusPref.setFocus") **)
  65. accepts*: BOOLEAN (** OUT, preset to ((v = focus) & (char # [l]tab)) **)
  66. END;
  67. TypePref* = RECORD (Preference)
  68. type*: Stores.TypeName; (** IN **)
  69. view*: Views.View (** OUT, preset to NIL **)
  70. END;
  71. (** verbs **)
  72. PollVerbMsg* = RECORD (Message)
  73. verb*: INTEGER; (** IN **)
  74. label*: ARRAY 64 OF CHAR; (** OUT, preset to "" **)
  75. disabled*, checked*: BOOLEAN (** OUT, preset to FALSE, FALSE **)
  76. END;
  77. DoVerbMsg* = RECORD (Message)
  78. verb*: INTEGER; (** IN **)
  79. frame*: Views.Frame (** IN **)
  80. END;
  81. (** controller messages **)
  82. CollectMsg* = RECORD (Controllers.Message)
  83. poll*: PollMsg (** OUT, preset to NIL **)
  84. END;
  85. EmitMsg* = RECORD (Controllers.RequestMessage)
  86. set*: SetMsg (** IN **)
  87. END;
  88. PollPickMsg* = RECORD (Controllers.TransferMessage)
  89. mark*: BOOLEAN; (** IN, request to mark pick target **)
  90. show*: BOOLEAN; (** IN, if mark then show/hide target mark **)
  91. dest*: Views.Frame (** OUT, preset to NIL, set if PickMsg is acceptable **)
  92. END;
  93. PickMsg* = RECORD (Controllers.TransferMessage)
  94. prop*: Property (** set to picked properties by destination **)
  95. END;
  96. VAR era-: INTEGER; (* estimator to cache standard properties of focus *)
  97. PROCEDURE ^ IntersectSelections* (a, aMask, b, bMask: SET; OUT c, cMask: SET; OUT equal: BOOLEAN);
  98. (** properties **)
  99. PROCEDURE (p: Property) IntersectWith* (q: Property; OUT equal: BOOLEAN), NEW, ABSTRACT;
  100. PROCEDURE (p: StdProp) IntersectWith* (q: Property; OUT equal: BOOLEAN);
  101. VAR valid: SET; c, m: SET; eq: BOOLEAN;
  102. BEGIN
  103. WITH q: StdProp DO
  104. valid := p.valid * q.valid; equal := TRUE;
  105. IF p.color.val # q.color.val THEN EXCL(valid, color) END;
  106. IF p.typeface # q.typeface THEN EXCL(valid, typeface) END;
  107. IF p.size # q.size THEN EXCL(valid, size) END;
  108. IntersectSelections(p.style.val, p.style.mask, q.style.val, q.style.mask, c, m, eq);
  109. IF m = {} THEN EXCL(valid, style)
  110. ELSIF (style IN valid) & ~eq THEN p.style.mask := m; equal := FALSE
  111. END;
  112. IF p.weight # q.weight THEN EXCL(valid, weight) END;
  113. IF p.valid # valid THEN p.valid := valid; equal := FALSE END
  114. END
  115. END IntersectWith;
  116. PROCEDURE (p: SizeProp) IntersectWith* (q: Property; OUT equal: BOOLEAN);
  117. VAR valid: SET;
  118. BEGIN
  119. WITH q: SizeProp DO
  120. valid := p.valid * q.valid; equal := TRUE;
  121. IF p.width # q.width THEN EXCL(valid, width) END;
  122. IF p.height # q.height THEN EXCL(valid, height) END;
  123. IF p.valid # valid THEN p.valid := valid; equal := FALSE END
  124. END
  125. END IntersectWith;
  126. (** property collection and emission **)
  127. PROCEDURE IncEra*;
  128. BEGIN
  129. INC(era)
  130. END IncEra;
  131. PROCEDURE CollectProp* (OUT prop: Property);
  132. VAR msg: CollectMsg;
  133. BEGIN
  134. msg.poll.prop := NIL;
  135. Controllers.Forward(msg);
  136. prop := msg.poll.prop
  137. END CollectProp;
  138. PROCEDURE CollectStdProp* (OUT prop: StdProp);
  139. (** post: prop # NIL, prop.style.val = prop.style.val * prop.style.mask **)
  140. VAR p: Property;
  141. BEGIN
  142. CollectProp(p);
  143. WHILE (p # NIL) & ~(p IS StdProp) DO p := p.next END;
  144. IF p # NIL THEN
  145. prop := p(StdProp); prop.next := NIL
  146. ELSE
  147. NEW(prop); prop.known := {}
  148. END;
  149. prop.valid := prop.valid * prop.known;
  150. prop.style.val := prop.style.val * prop.style.mask
  151. END CollectStdProp;
  152. PROCEDURE EmitProp* (old, prop: Property);
  153. VAR msg: EmitMsg;
  154. BEGIN
  155. IF prop # NIL THEN
  156. msg.set.old := old; msg.set.prop := prop;
  157. Controllers.Forward(msg)
  158. END
  159. END EmitProp;
  160. PROCEDURE PollPick* (x, y: INTEGER;
  161. source: Views.Frame; sourceX, sourceY: INTEGER;
  162. mark, show: BOOLEAN;
  163. OUT dest: Views.Frame; OUT destX, destY: INTEGER);
  164. VAR msg: PollPickMsg;
  165. BEGIN
  166. ASSERT(source # NIL, 20);
  167. msg.mark := mark; msg.show := show; msg.dest := NIL;
  168. Controllers.Transfer(x, y, source, sourceX, sourceY, msg);
  169. dest := msg.dest; destX := msg.x; destY := msg.y
  170. END PollPick;
  171. PROCEDURE Pick* (x, y: INTEGER; source: Views.Frame; sourceX, sourceY: INTEGER;
  172. OUT prop: Property);
  173. VAR msg: PickMsg;
  174. BEGIN
  175. ASSERT(source # NIL, 20);
  176. msg.prop := NIL;
  177. Controllers.Transfer(x, y, source, sourceX, sourceY, msg);
  178. prop := msg.prop
  179. END Pick;
  180. (** property list construction **)
  181. PROCEDURE Insert* (VAR list: Property; x: Property);
  182. VAR p, q: Property; ta: INTEGER;
  183. BEGIN
  184. ASSERT(x # NIL, 20); ASSERT(x.next = NIL, 21); ASSERT(x # list, 22);
  185. ASSERT(x.valid - x.known = {}, 23);
  186. IF list # NIL THEN
  187. ASSERT(list.valid - list.known = {}, 24);
  188. ASSERT(Services.TypeLevel(list) = 1, 25)
  189. END;
  190. ta := SYSTEM.TYP(x^);
  191. ASSERT(Services.TypeLevel(x) = 1, 26);
  192. p := list; q := NIL;
  193. WHILE (p # NIL) & (SYSTEM.TYP(p^) < ta) DO
  194. q := p; p := p.next
  195. END;
  196. IF (p # NIL) & (SYSTEM.TYP(p^) = ta) THEN x.next := p.next ELSE x.next := p END;
  197. IF q # NIL THEN q.next := x ELSE list := x END
  198. END Insert;
  199. PROCEDURE CopyOfList* (p: Property): Property;
  200. VAR q, r, s: Property; t: Kernel.Type;
  201. BEGIN
  202. q := NIL; s := NIL;
  203. WHILE p # NIL DO
  204. ASSERT(Services.TypeLevel(p) = 1, 20);
  205. t := Kernel.TypeOf(p); Kernel.NewObj(r, t); ASSERT(r # NIL, 23);
  206. SYSTEM.MOVE(p, r, t.size);
  207. r.next := NIL;
  208. IF q # NIL THEN q.next := r ELSE s := r END;
  209. q := r; p := p.next
  210. END;
  211. RETURN s
  212. END CopyOfList;
  213. PROCEDURE CopyOf* (p: Property): Property;
  214. VAR r: Property; t: Kernel.Type;
  215. BEGIN
  216. IF p # NIL THEN
  217. ASSERT(Services.TypeLevel(p) = 1, 20);
  218. t := Kernel.TypeOf(p); Kernel.NewObj(r, t); ASSERT(r # NIL, 23);
  219. SYSTEM.MOVE(p, r, t.size);
  220. r.next := NIL;
  221. END;
  222. RETURN r
  223. END CopyOf;
  224. PROCEDURE Merge* (VAR base, override: Property);
  225. VAR p, q, r, s: Property; tp, tr: INTEGER;
  226. BEGIN
  227. ASSERT((base # override) OR (base = NIL), 20);
  228. p := base; q := NIL; r := override; override := NIL;
  229. IF p # NIL THEN
  230. tp := SYSTEM.TYP(p^);
  231. ASSERT(Services.TypeLevel(p) = 1, 21)
  232. END;
  233. IF r # NIL THEN
  234. tr := SYSTEM.TYP(r^);
  235. ASSERT(Services.TypeLevel(r) = 1, 22)
  236. END;
  237. WHILE (p # NIL) & (r # NIL) DO
  238. ASSERT(p # r, 23);
  239. WHILE (p # NIL) & (tp < tr) DO
  240. q := p; p := p.next;
  241. IF p # NIL THEN tp := SYSTEM.TYP(p^) END
  242. END;
  243. IF p # NIL THEN
  244. IF tp = tr THEN
  245. s := p.next; p.next := NIL; p := s;
  246. IF p # NIL THEN tp := SYSTEM.TYP(p^) END
  247. ELSE
  248. END;
  249. s := r.next;
  250. IF q # NIL THEN q.next := r ELSE base := r END;
  251. q := r; r.next := p; r := s;
  252. IF r # NIL THEN tr := SYSTEM.TYP(r^) END
  253. END
  254. END;
  255. IF r # NIL THEN
  256. IF q # NIL THEN q.next := r ELSE base := r END
  257. END
  258. END Merge;
  259. PROCEDURE Intersect* (VAR list: Property; x: Property; OUT equal: BOOLEAN);
  260. VAR l, p, q, r, s: Property; plen, rlen, ta: INTEGER; filtered: BOOLEAN;
  261. BEGIN
  262. ASSERT((x # list) OR (list = NIL), 20);
  263. IF list # NIL THEN ASSERT(Services.TypeLevel(list) = 1, 21) END;
  264. IF x # NIL THEN ASSERT(Services.TypeLevel(x) = 1, 22) END;
  265. p := list; s := NIL; list := NIL; l := NIL; plen := 0;
  266. r := x; rlen := 0; filtered := FALSE;
  267. WHILE (p # NIL) & (r # NIL) DO
  268. q := p.next; p.next := NIL; INC(plen);
  269. ta := SYSTEM.TYP(p^);
  270. WHILE (r # NIL) & (SYSTEM.TYP(r^) < ta) DO
  271. r := r.next; INC(rlen)
  272. END;
  273. IF (r # NIL) & (SYSTEM.TYP(r^) = ta) THEN
  274. ASSERT(r # p, 23);
  275. IF l # NIL THEN s.next := p ELSE l := p END;
  276. s := p;
  277. p.known := p.known + r.known;
  278. p.IntersectWith(r, equal);
  279. filtered := filtered OR ~equal OR (p.valid # r.valid);
  280. r := r.next; INC(rlen)
  281. END;
  282. p := q
  283. END;
  284. list := l;
  285. equal := (p = NIL) & (r = NIL) & (plen = rlen) & ~filtered
  286. END Intersect;
  287. (** support for IntersectWith methods **)
  288. PROCEDURE IntersectSelections* (a, aMask, b, bMask: SET; OUT c, cMask: SET; OUT equal: BOOLEAN);
  289. BEGIN
  290. cMask := aMask * bMask - (a / b);
  291. c := a * cMask;
  292. equal := (aMask = bMask) & (bMask = cMask)
  293. END IntersectSelections;
  294. (** standard preferences protocols **)
  295. PROCEDURE PreferredSize* (v: Views.View; minW, maxW, minH, maxH, defW, defH: INTEGER;
  296. VAR w, h: INTEGER);
  297. VAR p: SizePref;
  298. BEGIN
  299. ASSERT(Views.undefined < minW, 20); ASSERT(minW < maxW, 21);
  300. ASSERT(Views.undefined < minH, 23); ASSERT(minH < maxH, 24);
  301. ASSERT(Views.undefined <= defW, 26);
  302. ASSERT(Views.undefined <= defH, 28);
  303. IF (w < Views.undefined) OR (w > maxW) THEN w := defW END;
  304. IF (h < Views.undefined) OR (h > maxH) THEN h := defH END;
  305. p.w := w; p.h := h; p.fixedW := FALSE; p.fixedH := FALSE;
  306. Views.HandlePropMsg(v, p); w := p.w; h := p.h;
  307. IF w = Views.undefined THEN w := defW END;
  308. IF h = Views.undefined THEN h := defH END;
  309. IF w < minW THEN w := minW ELSIF w > maxW THEN w := maxW END;
  310. IF h < minH THEN h := minH ELSIF h > maxH THEN h := maxH END
  311. END PreferredSize;
  312. (** common resizing constraints **)
  313. PROCEDURE ProportionalConstraint* (scaleW, scaleH: INTEGER; fixedW, fixedH: BOOLEAN; VAR w, h: INTEGER);
  314. (** pre: w > Views.undefined, h > Views.undefined **)
  315. (** post: (E s: s * scaleW = w, s * scaleH = h), |w * h - w' * h'| min! **)
  316. VAR area: REAL;
  317. BEGIN
  318. ASSERT(scaleW > Views.undefined, 22); ASSERT(scaleH > Views.undefined, 23);
  319. IF fixedH THEN
  320. ASSERT(~fixedW, 24);
  321. ASSERT(h > Views.undefined, 21);
  322. area := h; area := area * scaleW;
  323. w := SHORT(ENTIER(area / scaleH))
  324. ELSIF fixedW THEN
  325. ASSERT(w > Views.undefined, 20);
  326. area := w; area := area * scaleH;
  327. h := SHORT(ENTIER(area / scaleW))
  328. ELSE
  329. ASSERT(w > Views.undefined, 20); ASSERT(h > Views.undefined, 21);
  330. area := w; area := area * h;
  331. w := SHORT(ENTIER(Math.(*L*)Sqrt(area * scaleW / scaleH)));
  332. h := SHORT(ENTIER(Math.(*L*)Sqrt(area * scaleH / scaleW)))
  333. END
  334. END ProportionalConstraint;
  335. PROCEDURE GridConstraint* (gridX, gridY: INTEGER; VAR x, y: INTEGER);
  336. VAR dx, dy: INTEGER;
  337. BEGIN
  338. ASSERT(gridX > Views.undefined, 20);
  339. ASSERT(gridY > Views.undefined, 21);
  340. dx := x MOD gridX;
  341. IF dx < gridX DIV 2 THEN DEC(x, dx) ELSE INC(x, (-x) MOD gridX) END;
  342. dy := y MOD gridY;
  343. IF dy < gridY DIV 2 THEN DEC(y, dy) ELSE INC(y, (-y) MOD gridY) END
  344. END GridConstraint;
  345. PROCEDURE ThisType* (view: Views.View; type: Stores.TypeName): Views.View;
  346. VAR msg: TypePref;
  347. BEGIN
  348. msg.type := type; msg.view := NIL;
  349. Views.HandlePropMsg(view, msg);
  350. RETURN msg.view
  351. END ThisType;
  352. END Properties.