WMColorComponents.Mod 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. MODULE WMColorComponents; (** AUTHOR "FN"; PURPOSE "Color Tools GUI"; *)
  2. IMPORT
  3. Strings, KernelLog, Raster, Texts, TextUtilities, XML,
  4. WMStandardComponents, WMGraphics, WMGraphicUtilities, WMComponents, WMRectangles,
  5. WMEditors, WMWindowManager, WMProperties, WMDropTarget, WMPopups, WMEvents;
  6. TYPE
  7. ChangeHandler = PROCEDURE {DELEGATE};
  8. ColorChangeHandler = PROCEDURE {DELEGATE} (sender, color : ANY);
  9. Color* = OBJECT
  10. VAR value* : WMGraphics.Color
  11. END Color;
  12. ColorDropTarget = OBJECT(WMDropTarget.DropTarget)
  13. VAR setColor : ColorChangeHandler;
  14. PROCEDURE & Init*(cch : ColorChangeHandler);
  15. BEGIN
  16. setColor := cch
  17. END Init;
  18. PROCEDURE GetInterface*(type : LONGINT) : WMDropTarget.DropInterface;
  19. VAR cdi : ColorDropInterface;
  20. BEGIN
  21. IF type = WMDropTarget.TypeInt32 THEN
  22. NEW(cdi, setColor); RETURN cdi
  23. ELSE
  24. RETURN NIL
  25. END
  26. END GetInterface;
  27. END ColorDropTarget;
  28. ColorDropInterface = OBJECT(WMDropTarget.DropInt32)
  29. VAR setColor : ColorChangeHandler;
  30. PROCEDURE & Init*(cch : ColorChangeHandler);
  31. BEGIN
  32. setColor := cch
  33. END Init;
  34. PROCEDURE Set*(i : LONGINT);
  35. VAR c : Color;
  36. BEGIN
  37. NEW(c); c.value := i; setColor(SELF, c)
  38. END Set;
  39. END ColorDropInterface;
  40. (** a controlled input-filed for numeric inputs *)
  41. NumberInput* = OBJECT(WMComponents.VisualComponent)
  42. VAR
  43. input : WMEditors.Editor;
  44. buttons : WMStandardComponents.Panel;
  45. caption -: WMStandardComponents.Label;
  46. min-, max-, value- : WMProperties.Int32Property;
  47. changeHandler : ChangeHandler;
  48. PROCEDURE & Init*;
  49. VAR plus, minus : WMStandardComponents.Button;
  50. BEGIN
  51. Init^;
  52. SetNameAsString(StrNumberInput);
  53. SetGenerator("WMColorComponents.GenNumberInput");
  54. (* properties *)
  55. NEW(min, NIL, Strings.NewString("Min"), Strings.NewString("Minimal value")); properties.Add(min);
  56. NEW(max, NIL, Strings.NewString("Max"), Strings.NewString("Maximal value")); properties.Add(max);
  57. NEW(value, NIL, Strings.NewString("Value"), Strings.NewString("Model")); properties.Add(value);
  58. (* bounds *)
  59. bounds.SetHeight(21);
  60. (* caption *)
  61. NEW(caption); caption.alignment.Set(WMComponents.AlignLeft); AddInternalComponent(caption);
  62. caption.bounds.SetWidth(10); caption.fillColor.Set(0FFFFFFFFH);
  63. (* input field *)
  64. NEW(input); input.multiLine.Set(FALSE); input.bounds.SetWidth(30); input.alignment.Set(WMComponents.AlignLeft);
  65. input.tv.showBorder.Set(TRUE); AddInternalComponent(input);
  66. input.tv.textAlignV.Set(WMGraphics.AlignCenter);
  67. input.text.onTextChanged.Add(ValueChanged);
  68. (* buttons *)
  69. NEW(buttons); buttons.bounds.SetWidth(20); buttons.alignment.Set(WMComponents.AlignLeft); AddInternalComponent(buttons);
  70. (* plus *)
  71. NEW(plus); plus.bounds.SetHeight(10); plus.SetCaption("+"); plus.useBgBitmaps.Set(FALSE); plus.alignment.Set(WMComponents.AlignTop);
  72. plus.onClick.Add(Increment); plus.isRepeating.Set(TRUE); buttons.AddInternalComponent(plus);
  73. (* minus *)
  74. NEW(minus); minus.bounds.SetHeight(10); minus.SetCaption("-"); minus.useBgBitmaps.Set(FALSE); minus.alignment.Set(WMComponents.AlignTop);
  75. minus.onClick.Add(Decrement); minus.isRepeating.Set(TRUE); buttons.AddInternalComponent(minus);
  76. END Init;
  77. (* update input editor *)
  78. PROCEDURE RecacheProperties*;
  79. VAR buf : ARRAY 128 OF CHAR;
  80. BEGIN
  81. Strings.IntToStr(value.Get(), buf); input.SetAsString(buf)
  82. END RecacheProperties;
  83. PROCEDURE PropertyChanged*(sender, prop : ANY);
  84. BEGIN
  85. IF prop = value THEN
  86. RecacheProperties
  87. ELSE
  88. PropertyChanged^(sender, prop)
  89. END
  90. END PropertyChanged;
  91. PROCEDURE Increment(sender, data : ANY);
  92. BEGIN
  93. IF value.Get() < max.Get() THEN
  94. value.Set(value.Get() + 1); PropertyChanged(SELF, value); changeHandler()
  95. END
  96. END Increment;
  97. PROCEDURE Decrement(sender, data : ANY);
  98. BEGIN
  99. IF value.Get() > min.Get() THEN
  100. value.Set(value.Get() - 1); PropertyChanged(SELF, value); changeHandler()
  101. END
  102. END Decrement;
  103. (* called if user modifies the input-field *)
  104. PROCEDURE ValueChanged(sender, data : ANY);
  105. VAR buf : ARRAY 128 OF CHAR; new : LONGINT;
  106. BEGIN
  107. input.GetAsString(buf);
  108. IF ~IsNumber(buf) THEN
  109. RecacheProperties
  110. ELSE
  111. Strings.StrToInt(buf, new);
  112. IF (new # value.Get()) THEN
  113. IF (new >= min.Get()) & (new <= max.Get()) THEN
  114. value.Set(new);
  115. changeHandler()
  116. ELSE
  117. RecacheProperties
  118. END
  119. END
  120. END
  121. END ValueChanged;
  122. END NumberInput;
  123. (** gui-component to specify a color in red-green-blue-transparency *)
  124. NumericColorChooser* = OBJECT(WMStandardComponents.Panel)
  125. VAR r, g, b, t : NumberInput; (* red, green, blue, transparency *)
  126. colorChangeHandler : ColorChangeHandler; (* to be called when color has been changed from inside this object *)
  127. PROCEDURE & Init*;
  128. BEGIN
  129. Init^;
  130. SetNameAsString(StrNumericColorChooser);
  131. SetGenerator("WMColorComponents.GenNumericColorChooser");
  132. (* red *)
  133. NEW(r); r.alignment.Set(WMComponents.AlignTop); AddInternalComponent(r);
  134. r.caption.SetCaption("R"); r.min.Set(0); r.max.Set(255); r.changeHandler := NumberInputChanged;
  135. (* green *)
  136. NEW(g); g.alignment.Set(WMComponents.AlignTop); AddInternalComponent(g);
  137. g.caption.SetCaption("G"); g.min.Set(0); g.max.Set(255); g.changeHandler := NumberInputChanged;
  138. (* blue *)
  139. NEW(b); b.alignment.Set(WMComponents.AlignTop); AddInternalComponent(b);
  140. b.caption.SetCaption("B"); b.min.Set(0); b.max.Set(255); b.changeHandler := NumberInputChanged;
  141. (* transparency *)
  142. NEW(t); t.alignment.Set(WMComponents.AlignTop); AddInternalComponent(t);
  143. t.caption.SetCaption("T"); t.min.Set(0); t.max.Set(255); t.changeHandler := NumberInputChanged;
  144. (* handler *)
  145. colorChangeHandler := DefaultColorChangeHandler
  146. END Init;
  147. PROCEDURE SetColor*(sender, color : ANY);
  148. VAR c : LONGINT;
  149. BEGIN
  150. IF color IS Color THEN
  151. c := color(Color).value;
  152. t.value.Set(c MOD 256); c := c DIV 256;
  153. b.value.Set(c MOD 256); c := c DIV 256;
  154. g.value.Set(c MOD 256); c := c DIV 256;
  155. r.value.Set(c MOD 256);
  156. END
  157. END SetColor;
  158. PROCEDURE SetExternalColorChangeHandler*(cch : ColorChangeHandler);
  159. BEGIN
  160. colorChangeHandler := cch
  161. END SetExternalColorChangeHandler;
  162. PROCEDURE NumberInputChanged;
  163. VAR c : Color;
  164. BEGIN
  165. NEW(c); c.value := (256*256*256)*r.value.Get() + (256*256)*g.value.Get() + (256)*b.value.Get() + t.value.Get();
  166. colorChangeHandler(SELF, c)
  167. END NumberInputChanged;
  168. PROCEDURE DefaultColorChangeHandler(sender, color : ANY);
  169. END DefaultColorChangeHandler;
  170. END NumericColorChooser;
  171. (** saves a color-value temporarly, color can be dragged from and unto *)
  172. ColorPot *= OBJECT(WMStandardComponents.Panel)
  173. VAR dragPossible : BOOLEAN;
  174. colorChangeHandler : ColorChangeHandler;
  175. PROCEDURE & Init*;
  176. BEGIN
  177. Init^;
  178. SetNameAsString(StrColorPot);
  179. SetGenerator("WMColorComponents.GenColorPot");
  180. onStartDrag.Add(MyStartDrag); colorChangeHandler := DefaultColorChangeHandler
  181. END Init;
  182. (* draw a line around the panel *)
  183. PROCEDURE DrawBackground*(c : WMGraphics.Canvas);
  184. VAR rect : WMRectangles.Rectangle; h, w : LONGINT;
  185. BEGIN
  186. rect := GetClientRect(); w := rect.r DIV 2; h := rect.b DIV 2;
  187. (* background *)
  188. c.Fill(WMRectangles.MakeRect(0, 0, w, h), LONGINT(0AAAAAAFFH), WMGraphics.ModeCopy);
  189. c.Fill(WMRectangles.MakeRect(w, h, 2*w, 2*h), LONGINT(0AAAAAAFFH), WMGraphics.ModeCopy);
  190. (* current color *)
  191. DrawBackground^(c);
  192. (* frame *)
  193. WMGraphicUtilities.DrawRect(c, GetClientRect(), WMGraphics.Black, WMGraphics.ModeSrcOverDst)
  194. END DrawBackground;
  195. (* return a string with the hex representation of the current color. the string is lead by a '0' and terminated by a 'H' *)
  196. PROCEDURE GetHexValue(VAR hex: ARRAY OF CHAR);
  197. VAR buf : ARRAY 10 OF CHAR; i : LONGINT;
  198. BEGIN
  199. Strings.IntToHexStr(fillColor.Get(), 7, buf);
  200. hex[0] := '0';
  201. FOR i := 1 TO 8 DO hex[i] := buf[i-1] END;
  202. hex[9] := 0X;
  203. END GetHexValue;
  204. (* set current color for this pot. color will be displayed in GUI *)
  205. PROCEDURE SetColor*(sender, color : ANY);
  206. BEGIN
  207. IF color IS Color THEN
  208. fillColor.Set(color(Color).value)
  209. END
  210. END SetColor;
  211. (* default handler; just sets color *)
  212. PROCEDURE DefaultColorChangeHandler(sender, color : ANY);
  213. BEGIN
  214. SetColor(sender, color)
  215. END DefaultColorChangeHandler;
  216. (* overwrite default handler *)
  217. PROCEDURE SetExternalColorChangeHandler*(cch : ColorChangeHandler);
  218. BEGIN
  219. colorChangeHandler := cch
  220. END SetExternalColorChangeHandler;
  221. (* ----- mouse handlers ----------------------------------------- *)
  222. PROCEDURE PointerDown*(x, y : LONGINT; keys : SET);
  223. BEGIN
  224. ASSERT(IsCallFromSequencer());
  225. dragPossible := TRUE
  226. END PointerDown;
  227. PROCEDURE PointerUp*(x, y : LONGINT; keys : SET);
  228. BEGIN
  229. dragPossible := FALSE
  230. END PointerUp;
  231. PROCEDURE PointerMove*(x, y : LONGINT; keys : SET);
  232. BEGIN
  233. IF dragPossible THEN dragPossible := FALSE; AutoStartDrag() END
  234. END PointerMove;
  235. (* ----- drag and drop handlers ----------------------------------- *)
  236. (* called when a drag-operation has been started *)
  237. PROCEDURE MyStartDrag(sender, data : ANY);
  238. VAR img : WMGraphics.Image; c : WMGraphics.BufferCanvas; a : ANY;
  239. BEGIN
  240. NEW(img); Raster.Create(img, 15, 15, Raster.BGRA8888);
  241. NEW(c, img); c.Fill(WMRectangles.MakeRect(0, 0, 15, 15), fillColor.Get(), WMGraphics.ModeCopy);
  242. IF StartDrag(a, img, 0,0,DragArrived, NIL) THEN KernelLog.String("DraggingStarted"); KernelLog.Ln
  243. ELSE KernelLog.String("Drag could not be started"); KernelLog.Ln
  244. END
  245. END MyStartDrag;
  246. (* called when color dragged from here has been dropped elsewhere *)
  247. PROCEDURE DragArrived(sender, data : ANY);
  248. VAR di : WMWindowManager.DragInfo;
  249. dt : WMDropTarget.DropTarget;
  250. itf : WMDropTarget.DropInterface;
  251. text : Texts.Text;
  252. textPos : Texts.TextPosition;
  253. hex: ARRAY 10 OF CHAR;
  254. res : WORD;
  255. BEGIN
  256. IF (data # NIL) & (data IS WMWindowManager.DragInfo) THEN
  257. di := data(WMWindowManager.DragInfo);
  258. IF (di.data # NIL) & (di.data IS WMDropTarget.DropTarget) THEN
  259. dt := di.data(WMDropTarget.DropTarget)
  260. ELSE RETURN
  261. END
  262. ELSE RETURN
  263. END;
  264. (* drop text *)
  265. itf := dt.GetInterface(WMDropTarget.TypeText);
  266. IF itf # NIL THEN
  267. text := itf(WMDropTarget.DropText).text;
  268. textPos := itf(WMDropTarget.DropText).pos;
  269. IF (text # NIL) & (textPos # NIL) THEN
  270. text.AcquireWrite; GetHexValue (hex); TextUtilities.StrToText(text, textPos.GetPosition(), hex); text.ReleaseWrite;
  271. END;
  272. RETURN
  273. END;
  274. (* drop integer *)
  275. itf := dt.GetInterface(WMDropTarget.TypeInt32);
  276. IF itf # NIL THEN
  277. itf(WMDropTarget.DropInt32).Set(fillColor.Get());
  278. RETURN
  279. END;
  280. itf := dt.GetInterface(WMDropTarget.TypeString);
  281. IF itf # NIL THEN
  282. GetHexValue(hex); itf(WMDropTarget.DropString).Set(hex, res);
  283. RETURN;
  284. END;
  285. END DragArrived;
  286. (* called by MyDraggedDropped *)
  287. PROCEDURE DragDropped*(x, y : LONGINT; dragInfo : WMWindowManager.DragInfo);
  288. VAR dt : ColorDropTarget;
  289. BEGIN
  290. NEW(dt, colorChangeHandler); dragInfo.data := dt; ConfirmDrag(TRUE, dragInfo)
  291. END DragDropped;
  292. END ColorPot;
  293. (** gui-component to choose and manage colors; consisting of a color palette, a numeric color-input and temporary color-stores *)
  294. ColorChooser* = OBJECT(WMStandardComponents.Panel)
  295. VAR title -: WMStandardComponents.Label;
  296. customPots : WMStandardComponents.Panel;
  297. numericInputs : NumericColorChooser;
  298. palette : WMPopups.ColorSwatchPanel;
  299. showColor : ColorPot;
  300. onColorChosen : WMEvents.EventSource;
  301. color : WMGraphics.Color;
  302. PROCEDURE & Init*;
  303. VAR main, pnl : WMStandardComponents.Panel; pot : ColorPot;
  304. BEGIN
  305. Init^;
  306. SetNameAsString(StrColorChooser);
  307. SetGenerator("WMColorComponents.GenColorChooser");
  308. (* title *)
  309. NEW(title); title.bounds.SetHeight(20); title.alignment.Set(WMComponents.AlignTop);
  310. title.fillColor.Set(0CCCCCCFFH); title.SetCaption("ColorChooser"); AddInternalComponent(title);
  311. (* main panel *)
  312. NEW(main); main.bounds.SetWidth(190); main.alignment.Set(WMComponents.AlignLeft); AddInternalComponent(main);
  313. (* palette *)
  314. NEW(palette); palette.alignment.Set(WMComponents.AlignTop); palette.bearing.SetHeight(20); main.AddInternalComponent(palette);
  315. palette.ChosenColorProc := SetColor;
  316. (* custom pots for temporary color storage *)
  317. NEW(customPots); customPots.bounds.SetWidth(19); customPots.alignment.Set(WMComponents.AlignLeft); customPots.bearing.SetWidth(20);
  318. main.AddInternalComponent(customPots);
  319. NEW(pot); pot.bearing.SetHeight(2); pot.bounds.SetHeight(19); pot.alignment.Set(WMComponents.AlignTop); customPots.AddInternalComponent(pot);
  320. NEW(pot); pot.bearing.SetHeight(2); pot.bounds.SetHeight(19); pot.alignment.Set(WMComponents.AlignTop); customPots.AddInternalComponent(pot);
  321. NEW(pot); pot.bearing.SetHeight(2); pot.bounds.SetHeight(19); pot.alignment.Set(WMComponents.AlignTop); customPots.AddInternalComponent(pot);
  322. NEW(pot); pot.bearing.SetHeight(2); pot.bounds.SetHeight(19); pot.alignment.Set(WMComponents.AlignTop); customPots.AddInternalComponent(pot);
  323. (* show color button *)
  324. NEW(pnl); pnl.alignment.Set(WMComponents.AlignLeft); pnl.bounds.SetWidth(75); main.AddInternalComponent(pnl);
  325. NEW(showColor); showColor.bounds.SetHeight(82); showColor.bounds.SetHeight(82); showColor.alignment.Set(WMComponents.AlignTop);
  326. showColor.SetExternalColorChangeHandler(ShowColorChangeHandler);
  327. pnl.AddInternalComponent(showColor);
  328. (* numeric inputs *)
  329. NEW(numericInputs); numericInputs.alignment.Set(WMComponents.AlignRight); numericInputs.bounds.SetWidth(60); main.AddInternalComponent(numericInputs);
  330. numericInputs.SetExternalColorChangeHandler(SetColor2);
  331. (* views-registration *)
  332. NEW(onColorChosen, SELF, Strings.NewString("OnColorChosen"), Strings.NewString("Listeners are called if a new color has been chosen"), NIL);
  333. onColorChosen.Add(showColor.SetColor);
  334. onColorChosen.Add(numericInputs.SetColor);
  335. (* model initialization *)
  336. SetColor(000000FFH);
  337. END Init;
  338. PROCEDURE SetColor(color : WMGraphics.Color);
  339. VAR c : Color;
  340. BEGIN
  341. SELF.color := color;
  342. NEW(c); c.value := color;
  343. onColorChosen.Call(c)
  344. END SetColor;
  345. PROCEDURE SetColor2(sender, color : ANY);
  346. BEGIN
  347. IF color IS Color THEN
  348. SetColor(color(Color).value)
  349. END
  350. END SetColor2;
  351. (* plugin-handler for showColor *)
  352. PROCEDURE ShowColorChangeHandler(sender, color : ANY);
  353. BEGIN
  354. showColor.SetColor(sender, color);
  355. SetColor2(sender, color)
  356. END ShowColorChangeHandler;
  357. END ColorChooser;
  358. VAR
  359. StrNumberInput, StrNumericColorChooser, StrColorPot, StrColorChooser : Strings.String;
  360. (* ----- helpers --------------------------------------- *)
  361. PROCEDURE IsNumber(CONST str : ARRAY OF CHAR) : BOOLEAN;
  362. VAR i : LONGINT;
  363. BEGIN
  364. i := 0;
  365. WHILE str[i] # 0X DO
  366. IF (str[i] < '0') OR (str[i] > '9') THEN RETURN FALSE END;
  367. INC(i)
  368. END;
  369. RETURN TRUE
  370. END IsNumber;
  371. PROCEDURE InitStrings;
  372. BEGIN
  373. StrNumberInput := Strings.NewString("NumberInput");
  374. StrNumericColorChooser := Strings.NewString("NumericColorChooser");
  375. StrColorPot := Strings.NewString("ColorPot");
  376. StrColorChooser := Strings.NewString("ColorChooser");
  377. END InitStrings;
  378. PROCEDURE GenNumberInput*() : XML.Element;
  379. VAR numberInput :NumberInput;
  380. BEGIN
  381. NEW(numberInput); RETURN numberInput;
  382. END GenNumberInput;
  383. PROCEDURE GenNumericColorChooser*() : XML.Element;
  384. VAR numericColorChooser : NumericColorChooser;
  385. BEGIN
  386. NEW(numericColorChooser); RETURN numericColorChooser;
  387. END GenNumericColorChooser;
  388. PROCEDURE GenColorPot*() : XML.Element;
  389. VAR colorPot : ColorPot;
  390. BEGIN
  391. NEW(colorPot); RETURN colorPot;
  392. END GenColorPot;
  393. PROCEDURE GenColorChooser*() : XML.Element;
  394. VAR colorChooser : ColorChooser;
  395. BEGIN
  396. NEW(colorChooser); RETURN colorChooser;
  397. END GenColorChooser;
  398. BEGIN
  399. InitStrings;
  400. END WMColorComponents.