home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / hc / barbutto.sit / BarButton / card_4702.txt < prev    next >
Text File  |  1987-11-23  |  14KB  |  513 lines

  1. -- card: 4702 from stack: in
  2. -- bmap block id: 4446
  3. -- flags: 0000
  4. -- background id: 2619
  5. -- name: Card 5
  6. ----- HyperTalk script -----
  7. on opencard
  8.   get rect of card button id 1
  9.   BarButton 3,600,0,500
  10. end opencard
  11.  
  12.  
  13. -- part 1 (button)
  14. -- low flags: 00
  15. -- high flags: 0002
  16. -- rect: left=372 top=139 right=222 bottom=453
  17. -- title width / last selected line: 0
  18. -- icon id / first selected line: 0 / 0
  19. -- text alignment: 1
  20. -- font id: 0
  21. -- text size: 24
  22. -- style flags: 0
  23. -- line height: 32
  24. -- part name: 
  25. ----- HyperTalk script -----
  26. on mousedown
  27.   if the optionkey is down then put script of me into bkgnd field lowerpane
  28.   set cursor to 2
  29.   get the rect of me
  30.   BarButton 3,600,0
  31.   put the result into bkgnd field results
  32. end mousedown
  33.  
  34.  
  35.  
  36. -- part 2 (button)
  37. -- low flags: 00
  38. -- high flags: 8003
  39. -- rect: left=174 top=296 right=325 bottom=313
  40. -- title width / last selected line: 0
  41. -- icon id / first selected line: 0 / 0
  42. -- text alignment: 1
  43. -- font id: 0
  44. -- text size: 12
  45. -- style flags: 0
  46. -- line height: 16
  47. -- part name: Show Card's script
  48. ----- HyperTalk script -----
  49. on mouseUp
  50.   put the script of this card into bkgnd field lowerpane
  51. end mouseUp
  52.  
  53. on mousedown
  54.   if the optionkey is down then put script of me into bkgnd field lowerpane
  55. end mousedown
  56.  
  57.  
  58. -- part 8 (field)
  59. -- low flags: 80
  60. -- high flags: 0000
  61. -- rect: left=312 top=57 right=142 bottom=512
  62. -- title width / last selected line: 0
  63. -- icon id / first selected line: 0 / 0
  64. -- text alignment: 0
  65. -- font id: 3
  66. -- text size: 9
  67. -- style flags: 0
  68. -- line height: 12
  69. -- part name: 
  70.  
  71.  
  72. -- part contents for background part 10
  73. ----- text -----
  74. You can issue the "BarButton" command at any time; you're not limited to just when a user clicks in the button.  The fourth parameter is used when you wish to force an initial value without requiring that the user click in the button.  When you supply this fourth parameter, BarButton displays the initial value and immediately returns, without even looking at the mouse location.
  75.     Throughout this stack we have assigned initial values to the Bar buttons in the script of each card, in response to the "opencard" event.  You can easily look at an example of this by clicking on the button "Show Card's script".  Or you can simulate an opencard event by "blind typing" the "opencard" command.
  76.     In some circumstances you may wish to graph initial values using the fourth parameter, but not want the numeric value displayed.   A first parameter value less than zero tells BarButton to do this.  So instead of using values between 1 and 4, use the corresponding negatives between -1 and -4:
  77.     -1:  left to right, no numeric display
  78.     -2:  right to left, no numeric display
  79.     -3:  bottom to top, no numeric display
  80.     -4:  top to bottom, no numeric display
  81. The script of the first card in this stack has several examples of this technique.
  82.  
  83.  
  84.  
  85. -- part contents for background part 4
  86. ----- text -----
  87. 422
  88.  
  89. -- part contents for card part 8
  90. ----- text -----
  91.  
  92.  
  93. {BarButton adjusts the size of the bar contained within rect in first 4}
  94. {parameters.}
  95. UNIT Main;
  96.  
  97. INTERFACE
  98.  
  99. USES
  100. HyperXCMD;
  101.  
  102. PROCEDURE Main (ParamPtr : XCmdPtr);
  103.  
  104. IMPLEMENTATION
  105.  
  106. {-------------------------------------------------------------------------------}
  107. PROCEDURE BarButton (ParamPtr : XCmdPtr);
  108. FORWARD;
  109.  
  110. PROCEDURE Main;
  111. BEGIN
  112. BarButton(ParamPtr);
  113. END;
  114.  
  115. PROCEDURE BarButton;
  116.  
  117. CONST
  118. leftToRight = 1;
  119. rightToLeft = 2;
  120. bottomToTop = 3;
  121. topToBottom = 4;
  122.  
  123. VAR
  124. str : Str255;
  125. ButtonRect, DrawRect, BlankRect, ViewRect, TextRect : rect;
  126. InRect, newLoc, dummy, ShowValue, SuppressDisplay : boolean;
  127. spot, oldspot, TextPoint : point;
  128. direction, maximumValue, minimumValue, CurrentValue, InitialValue : integer;
  129. theInfo : FontInfo;
  130. TextHeight, TextWidth, ButtonHeight, ButtonWidth : integer;
  131. proportion : real;
  132.  
  133. {-------------------------------------------------------------------------------}
  134. PROCEDURE DoJsr (addr : ProcPtr);
  135. INLINE
  136. $205F, $4E90;
  137. { Jump subroutine to a procedure.   Pop address into A0, JSR (A0) }
  138.  
  139. {-------------------------------------------------------------------------------}
  140. PROCEDURE ZeroToPas (zeroStr : Ptr;
  141. VAR pasStr : Str255);
  142. {Fill the Pascal string with the contents of the zero-terminated}
  143. {   string.  You create the Pascal string and pass it in as a VAR }
  144. {   parameter.  Useful for converting the arguments of any XCMD to }
  145. {   Pascal strings.}
  146. BEGIN
  147. WITH paramPtr^ DO
  148. BEGIN
  149. inArgs[1] := ORD(zeroStr);
  150. inArgs[2] := ORD(@pasStr);
  151. request := xreqZeroToPas;
  152. DoJsr(entryPoint);
  153. END;
  154. END;
  155.  
  156. {-------------------------------------------------------------------------------}
  157. FUNCTION StrToNum (str : Str31) : LongInt;
  158. {  Convert a string of ASCII decimal digits to a signed long integer.}
  159. {   Negative sign is allowed.  }
  160. BEGIN
  161. WITH paramPtr^ DO
  162. BEGIN
  163. inArgs[1] := ORD(@str);
  164. request := xreqStrToNum;
  165. DoJsr(entryPoint);
  166. StrToNum := outArgs[1];
  167. END;
  168. END;
  169.  
  170. {-------------------------------------------------------------------------------}
  171. FUNCTION PasToZero (str : Str255) : Handle;
  172. {  Convert a Pascal string to a zero-terminated string.  Returns a handle}
  173. {   to a new zero-terminated string.  The caller must dispose the handle. }
  174. BEGIN
  175. WITH paramPtr^ DO
  176. BEGIN
  177. inArgs[1] := ORD(@str);
  178. request := xreqPasToZero;
  179. DoJsr(entryPoint);
  180. PasToZero := Handle(outArgs[1]);
  181. END;
  182. END;
  183.  
  184. {-------------------------------------------------------------------------------}
  185. FUNCTION EvalExpr (expr : Str255) : Handle;
  186. {  Evaluate a HyperCard expression and return the answer.  The answer is}
  187. {   a handle to a zero-terminated string. }
  188. BEGIN
  189. WITH paramPtr^ DO
  190. BEGIN
  191. inArgs[1] := ORD(@expr);
  192. request := xreqEvalExpr;
  193. DoJsr(entryPoint);
  194. EvalExpr := Handle(outArgs[1]);
  195. END;
  196. END;
  197.  
  198. {-------------------------------------------------------------------------------}
  199. FUNCTION NumToStr (num : LongInt) : Str31;
  200. {  Convert a signed long integer to a Pascal string.  }
  201. VAR
  202. str : Str31;
  203. BEGIN
  204. WITH paramPtr^ DO
  205. BEGIN
  206. inArgs[1] := num;
  207. inArgs[2] := ORD(@str);
  208. request := xreqNumToStr;
  209. DoJsr(entryPoint);
  210. NumToStr := str;
  211. END;
  212. END;
  213.  
  214. {-------------------------------------------------------------------------------}
  215. FUNCTION IntExpr (theString : str255) : integer;
  216. TYPE
  217. Ptr31 = ^str31;
  218. Hand31 = ^Ptr31;
  219.  
  220. VAR
  221. tempHand : handle;
  222. ShortStr : str31;
  223. ShortPtr : Ptr31;
  224. ShortHand : Hand31;
  225. NumLong : longint;
  226. LongStr : str255;
  227.  
  228. BEGIN
  229. tempHand := EvalExpr(theString);
  230. ZeroToPas(tempHand^, LongStr);
  231. ShortStr := LongStr;
  232. NumLong := StrToNum(ShortStr);
  233. IntExpr := loword(NumLong);
  234. DisposHandle(tempHand);
  235. END;
  236.  
  237. {-------------------------------------------------------------------------------}
  238. FUNCTION DePad (str : str255) : str255;
  239. VAR
  240. c : integer;
  241.  
  242. BEGIN
  243. FOR c := length(str) DOWNTO 1 DO
  244. IF ord(str[c]) = 32 THEN
  245. Delete(str, c, 1);
  246. DePad := str;
  247. END;
  248.  
  249. {-------------------------------------------------------------------------------}
  250. PROCEDURE DisplayValue;
  251. BEGIN
  252. IF ShowValue THEN
  253. BEGIN
  254. TextFont(systemfont);{Chicago}
  255. TextSize(12);
  256. str := Depad(StringOf(CurrentValue));
  257. CASE direction OF
  258. leftToRight, rightToLeft : 
  259. MoveTo(TextPoint.h, TextPoint.v);
  260. bottomToTop, topToBottom : 
  261. MoveTo(TextPoint.h - StringWidth(str) DIV 2, TextPoint.v);
  262. END;
  263. EraseRect(TextRect);
  264. DrawString(str);
  265. END;
  266. END;{DisplayValue}
  267.  
  268. {-------------------------------------------------------------------------------}
  269. PROCEDURE ComputeValue;
  270.  
  271. BEGIN
  272. WITH ViewRect DO
  273. CASE direction OF
  274. leftToRight : 
  275. proportion := (oldspot.h - left) * 1.0 / (right - left);
  276. rightToLeft : 
  277. proportion := (right - oldspot.h) * 1.0 / (right - left);
  278. bottomToTop : 
  279. proportion := (bottom - oldspot.v) * 1.0 / (bottom - top);
  280. topToBottom : 
  281. proportion := (oldspot.v - top) * 1.0 / (bottom - top);
  282. END;
  283.  
  284. IF proportion < 0 THEN
  285. proportion := 0;
  286. IF proportion > 1.0 THEN
  287. proportion := 1.0;
  288.  
  289. CurrentValue := round(proportion * (maximumValue - minimumValue) + minimumValue);
  290. DisplayValue;
  291. END;{ComputeValue}
  292.  
  293. {-------------------------------------------------------------------------------}
  294. BEGIN
  295. ButtonRect.left := IntExpr('item 1 of It');
  296. ButtonRect.top := IntExpr('item 2 of It');
  297. ButtonRect.right := IntExpr('item 3 of It');
  298. ButtonRect.bottom := IntExpr('item 4 of It');
  299. ButtonHeight := ButtonRect.bottom - ButtonRect.top;
  300. ButtonWidth := ButtonRect.right - ButtonRect.left;
  301.  
  302. ViewRect := ButtonRect;
  303. InsetRect(ViewRect, 1, 1);
  304. DrawRect := ViewRect;
  305. BlankRect := DrawRect;
  306.  
  307. WITH ButtonRect DO
  308. IF right - left > bottom - top THEN
  309. direction := leftToRight
  310. ELSE
  311. direction := bottomToTop;
  312. maximumValue := 100;
  313. minimumValue := 0;
  314. ShowValue := FALSE;
  315. SuppressDisplay := FALSE;
  316. InitialValue := -32767;{Hopefully no one will actually use that value!}
  317.  
  318. WITH ParamPtr^ DO
  319. BEGIN
  320. IF paramCount > 0 THEN
  321. BEGIN
  322. ZeroToPas(params[1]^, str);
  323. direction := StrToNum(str);
  324. IF (direction >= -4) AND (direction <= -1) THEN
  325. BEGIN
  326. SuppressDisplay := TRUE;
  327. direction := -direction;
  328. END;
  329. IF (direction < 1) OR (direction > 4) THEN
  330. direction := leftToRight;
  331. IF paramCount > 1 THEN
  332. BEGIN
  333. ZeroToPas(params[2]^, str);
  334. maximumValue := StrToNum(str);
  335. ShowValue := TRUE;
  336. IF paramCount > 2 THEN
  337. BEGIN
  338. ZeroToPas(params[3]^, str);
  339. minimumValue := StrToNum(str);
  340. IF minimumValue >= maximumValue THEN
  341. minimumValue := maximumValue + 10;
  342. IF paramCount > 3 THEN
  343. BEGIN
  344. ZeroToPas(params[4]^, str);
  345. InitialValue := StrToNum(str);
  346. END;{end of reading initial value}
  347. END;{end of reading third parameter}
  348. END;{end of reading second parameter}
  349. END;{end of reading first parameter}
  350. END;{with ParamPtr^}
  351. IF SuppressDisplay THEN
  352. ShowValue := FALSE;
  353.  
  354. IF InitialValue = -32767 THEN
  355. GetMouse(spot){Get current loc of mouse}
  356. ELSE
  357. BEGIN{force initial value of bar without mousedown}
  358. proportion := (InitialValue - minimumValue) * 1.0 / (maximumValue - minimumValue);
  359. IF proportion < 0 THEN
  360. proportion := 0;
  361. IF proportion > 1.0 THEN
  362. proportion := 1.0;
  363. CASE direction OF
  364. leftToRight : 
  365. spot.h := round(DrawRect.left + proportion * ButtonWidth);
  366. rightToLeft : 
  367. spot.h := round(DrawRect.right - proportion * ButtonWidth);
  368. bottomToTop : 
  369. spot.v := round(DrawRect.bottom - proportion * ButtonHeight);
  370. topToBottom : 
  371. spot.v := round(DrawRect.top + proportion * ButtonHeight);
  372. END;{end of case direction}
  373. END;{end of forcing initial value}
  374.  
  375. CASE direction OF
  376. leftToRight : 
  377. BEGIN
  378. DrawRect.right := spot.h;
  379. BlankRect.left := spot.h;
  380. END;
  381. rightToLeft : 
  382. BEGIN
  383. DrawRect.left := spot.h;
  384. BlankRect.right := spot.h;
  385. END;
  386. bottomToTop : 
  387. BEGIN
  388. DrawRect.top := spot.v;
  389. BlankRect.bottom := spot.v;
  390. END;
  391. topToBottom : 
  392. BEGIN
  393. DrawRect.bottom := spot.v;
  394. BlankRect.top := spot.v;
  395. END;
  396. END;{end of case direction}
  397.  
  398. IF ShowValue THEN{Set up stuff for ShowValue}
  399. BEGIN
  400. IF StringWidth(DePad(StringOf(maximumValue))) >= StringWidth(DePad(StringOf(minimumValue))) THEN
  401. TextWidth := StringWidth(DePad(StringOf(maximumValue)))
  402. ELSE
  403. TextWidth := StringWidth(DePad(StringOf(minimumValue)));
  404.  
  405. GetFontInfo(theInfo);
  406. TextHeight := theInfo.ascent;{numbers don't have descenders}
  407.  
  408. CASE direction OF
  409. leftToRight, rightToLeft : 
  410. BEGIN
  411. TextRect.top := ButtonRect.top + ButtonHeight DIV 2 - TextHeight DIV 2 - TextHeight DIV 4;
  412. TextRect.left := ButtonRect.right + 1;
  413. TextPoint.h := TextRect.left + TextHeight DIV 4;
  414. TextRect.bottom := TextRect.top + TextHeight + TextHeight DIV 2;
  415. TextPoint.v := TextRect.bottom - TextHeight DIV 4;
  416. END;
  417. bottomToTop, topToBottom : 
  418. BEGIN
  419. TextRect.top := ButtonRect.bottom + 2;
  420. TextPoint.h := ButtonRect.left + ButtonWidth DIV 2;
  421. TextRect.left := TextPoint.h - TextWidth DIV 2 - TextHeight DIV 4;
  422. TextRect.bottom := TextRect.top + TextHeight + TextHeight DIV 2 - 4;
  423. TextPoint.v := TextRect.bottom - TextHeight DIV 4;
  424. END;
  425. END;
  426. TextRect.right := TextRect.left + TextWidth + TextHeight DIV 2;
  427. END;{end setting up ShowValue stuff}
  428.  
  429. oldspot := spot;
  430. dummy := SectRect(ViewRect, DrawRect, DrawRect);
  431. PaintRect(DrawRect);
  432. dummy := SectRect(ViewRect, BlankRect, BlankRect);
  433. EraseRect(BlankRect);
  434. DrawRect := ViewRect;{now will be used for the redrawing}
  435. InsetRect(ButtonRect, -10, -10);
  436. IF InitialValue > -32767 THEN
  437. BEGIN{Display forced starting value}
  438. CurrentValue := InitialValue;
  439. DisplayValue;
  440. END
  441. ELSE
  442. BEGIN
  443. ComputeValue;{Display first real value if requested}
  444. REPEAT
  445. GetMouse(spot);
  446. InRect := PtInRect(spot, ButtonRect) AND Button;
  447. IF InRect THEN
  448. BEGIN
  449. newLoc := TRUE;{guilty unless proven innocent}
  450. CASE direction OF
  451.  
  452. leftToRight, rightToLeft : 
  453. BEGIN
  454. IF spot.h = oldspot.h THEN{no horizontal movement; don't redraw at all}
  455. newLoc := FALSE
  456. ELSE
  457. BEGIN
  458. IF spot.h > oldspot.h THEN{moving right}
  459. BEGIN
  460. DrawRect.right := spot.h;
  461. DrawRect.left := oldspot.h;
  462. END
  463. ELSE{moving left}
  464. BEGIN
  465. DrawRect.left := spot.h;
  466. DrawRect.right := oldspot.h;
  467. END;
  468. END;{end new horizontal loc}
  469. DrawRect.top := ViewRect.top;{restore top and bottom in case SectRect wiped them out with empty rect}
  470. DrawRect.bottom := ViewRect.bottom;
  471. END;{end horizontal case}
  472.  
  473. bottomToTop, topToBottom : 
  474. BEGIN
  475. IF spot.v = oldspot.v THEN{no vertical movement; don't redraw at all}
  476. newLoc := FALSE
  477. ELSE
  478. BEGIN
  479. IF spot.v > oldspot.v THEN{moving down}
  480. BEGIN
  481. DrawRect.bottom := spot.v;
  482. DrawRect.top := oldspot.v;
  483. END
  484. ELSE{moving up}
  485. BEGIN
  486. DrawRect.top := spot.v;
  487. DrawRect.bottom := oldspot.v;
  488. END;
  489. END;{end new vertical loc}
  490. DrawRect.left := ViewRect.left;{restore left and right in case SectRect wiped them out with empty rect}
  491. DrawRect.right := ViewRect.right;
  492. END;{end vertical case}
  493. END;{case block}
  494.  
  495. dummy := SectRect(ViewRect, DrawRect, DrawRect);
  496. IF newLoc THEN{Redraw if necessary}
  497. BEGIN
  498. InvertRect(DrawRect);
  499. IF ShowValue THEN
  500. ComputeValue;{Display current value if requested}
  501. END;
  502. oldspot := spot;{today becomes yesterday}
  503. END;{end InRect}
  504.  
  505. UNTIL NOT Button;{loop until mouseUp}
  506. ComputeValue;{Put result in "the Result" even if they don't want it displayed}
  507. END;{end of event loop for real values}
  508.  
  509. str := NumToStr(CurrentValue);
  510. paramPtr^.returnValue := PasToZero(str);
  511. END;{end BarButton}
  512.  
  513. END.