WMDesktopIcons.Mod 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. MODULE WMDesktopIcons; (** AUTHOR "staubesv"; PURPOSE "Programmable Desktop Icons"; *)
  2. IMPORT
  3. Modules, Commands, Options, Strings,
  4. WMWindowManager, Raster, WMRasterScale, WMRectangles, WMGraphics, WMGraphicUtilities,
  5. WMRestorable, WMMessages, WMComponents, WMProperties, WMStandardComponents,
  6. WMPopups, WMDialogs;
  7. CONST
  8. CmSetCommandString = 1;
  9. CmSetImageName = 2;
  10. CmSetCaption = 3;
  11. TYPE
  12. ContextMenuPar = OBJECT
  13. VAR
  14. mode : LONGINT;
  15. PROCEDURE &New*(mode : LONGINT);
  16. BEGIN
  17. SELF.mode := mode;
  18. END New;
  19. END ContextMenuPar;
  20. TYPE
  21. KillerMsg = OBJECT
  22. END KillerMsg;
  23. IconWindow = OBJECT(WMComponents.FormWindow);
  24. VAR
  25. dragging, resizing : BOOLEAN;
  26. lastX, lastY : LONGINT;
  27. iconComponent : IconComponent;
  28. contextMenu : WMPopups.Popup;
  29. PROCEDURE &New*(c : WMRestorable.Context; flags : SET);
  30. VAR configuration : WMRestorable.XmlElement; color : LONGINT; string : Strings.String;
  31. BEGIN
  32. IncCount;
  33. dragging := FALSE; resizing := FALSE;
  34. Init(120, 40, TRUE);
  35. manager := WMWindowManager.GetDefaultManager();
  36. NEW(iconComponent);
  37. iconComponent.alignment.Set(WMComponents.AlignClient);
  38. SetContent(iconComponent);
  39. SetTitle(StrWindowTitle);
  40. IF (c # NIL) THEN
  41. flags := {};
  42. configuration := WMRestorable.GetElement(c, "Configuration");
  43. IF configuration # NIL THEN
  44. WMRestorable.LoadStringPtr(configuration, "commandString", string); iconComponent.commandString.Set(string);
  45. WMRestorable.LoadStringPtr(configuration, "imageName", string); iconComponent.imageName.Set(string);
  46. WMRestorable.LoadStringPtr(configuration, "caption", string); iconComponent.caption.Set(string);
  47. WMRestorable.LoadLongint(configuration, "color", color); iconComponent.color.Set(color);
  48. END;
  49. WMRestorable.AddByContext(SELF, c);
  50. Resized(c.r - c.l, c.b - c.t);
  51. ELSE
  52. WMWindowManager.ExtAddWindow(SELF, 50, 50, flags)
  53. END;
  54. END New;
  55. PROCEDURE PointerDown*(x, y:LONGINT; keys:SET);
  56. BEGIN
  57. lastX := bounds.l+x; lastY:=bounds.t+y;
  58. IF keys = {0} THEN
  59. dragging := TRUE;
  60. ELSIF keys = {0,2} THEN
  61. dragging := FALSE;
  62. resizing := TRUE;
  63. ELSIF (keys = {1}) THEN
  64. ExecuteCommand;
  65. ELSIF keys = {2} THEN
  66. NEW(contextMenu);
  67. contextMenu.Add("Close", HandleContextMenuClose);
  68. contextMenu.AddParButton("Set Command", HandleContextMenu, cmSetCommandString);
  69. contextMenu.AddParButton("Set Image", HandleContextMenu, cmSetImageName);
  70. contextMenu.AddParButton("Set Caption", HandleContextMenu, cmSetCaption);
  71. contextMenu.Popup(bounds.l + x, bounds.t + y)
  72. END
  73. END PointerDown;
  74. PROCEDURE PointerMove*(x,y:LONGINT; keys:SET);
  75. VAR dx, dy : LONGINT; width, height : LONGINT;
  76. BEGIN
  77. IF dragging OR resizing THEN
  78. x := bounds.l + x; y := bounds.t + y; dx := x - lastX; dy := y - lastY;
  79. lastX := lastX + dx; lastY := lastY + dy;
  80. IF (dx # 0) OR (dy # 0) THEN
  81. IF dragging THEN
  82. manager.SetWindowPos(SELF, bounds.l + dx, bounds.t + dy);
  83. ELSE
  84. width := GetWidth();
  85. height := GetHeight();
  86. width := MAX(10, width + dx);
  87. height := MAX(10, height + dy);
  88. manager.SetWindowSize(SELF, width, height);
  89. END;
  90. END;
  91. END;
  92. END PointerMove;
  93. PROCEDURE PointerUp*(x, y:LONGINT; keys:SET);
  94. BEGIN
  95. dragging := FALSE;
  96. IF (keys # {0,2}) THEN
  97. IF resizing THEN
  98. resizing := FALSE;
  99. Resized(GetWidth(), GetHeight());
  100. END;
  101. END;
  102. END PointerUp;
  103. PROCEDURE ExecuteCommand;
  104. VAR cmdString : Strings.String; msg : ARRAY 128 OF CHAR; res : WORD;
  105. BEGIN
  106. cmdString := iconComponent.commandString.Get();
  107. IF (cmdString # NIL) THEN
  108. Commands.Call(cmdString^, {}, res, msg);
  109. END;
  110. END ExecuteCommand;
  111. PROCEDURE HandleContextMenu(sender, data : ANY);
  112. VAR string : ARRAY 256 OF CHAR; mode, res : LONGINT;
  113. BEGIN
  114. IF (data # NIL) & (data IS ContextMenuPar) THEN
  115. mode := data(ContextMenuPar).mode;
  116. IF (mode = CmSetCommandString) THEN
  117. res := WMDialogs.QueryString("Enter command string", string);
  118. IF (res = WMDialogs.ResOk) THEN
  119. iconComponent.commandString.Set(Strings.NewString(string));
  120. END;
  121. ELSIF (mode = CmSetImageName) THEN
  122. res := WMDialogs.QueryString("Enter image name", string);
  123. IF (res = WMDialogs.ResOk) THEN
  124. iconComponent.imageName.Set(Strings.NewString(string));
  125. END;
  126. ELSIF (mode = CmSetCaption) THEN
  127. res := WMDialogs.QueryString("Enter caption", string);
  128. IF (res = WMDialogs.ResOk) THEN
  129. iconComponent.caption.Set(Strings.NewString(string));
  130. END;
  131. END;
  132. END;
  133. END HandleContextMenu;
  134. PROCEDURE HandleContextMenuClose(sender, data : ANY);
  135. BEGIN
  136. Close;
  137. END HandleContextMenuClose;
  138. PROCEDURE Close*;
  139. BEGIN
  140. IF (contextMenu # NIL) THEN contextMenu.Close; END;
  141. Close^;
  142. DecCount;
  143. END Close;
  144. PROCEDURE Handle*(VAR x: WMMessages.Message);
  145. VAR configuration : WMRestorable.XmlElement;
  146. BEGIN
  147. IF (x.msgType = WMMessages.MsgExt) & (x.ext # NIL) THEN
  148. IF (x.ext IS KillerMsg) THEN Close
  149. ELSIF (x.ext IS WMRestorable.Storage) THEN
  150. NEW(configuration); configuration.SetName("Configuration");
  151. WMRestorable.StoreStringPtr(configuration, "commandString", iconComponent.commandString.Get());
  152. WMRestorable.StoreStringPtr(configuration, "imageName", iconComponent.imageName.Get());
  153. WMRestorable.StoreStringPtr(configuration, "caption", iconComponent.caption.Get());
  154. WMRestorable.StoreLongint(configuration, "color", iconComponent.color.Get());
  155. WMRestorable.StoreBoolean(configuration, "stayOnTop", WMWindowManager.FlagStayOnTop IN flags);
  156. WMRestorable.StoreBoolean(configuration, "navigation", WMWindowManager.FlagNavigation IN flags);
  157. x.ext(WMRestorable.Storage).Add("WMDesktopIcons", "WMDesktopIcons.Restore", SELF, configuration)
  158. ELSE Handle^(x)
  159. END
  160. ELSE Handle^(x)
  161. END
  162. END Handle;
  163. END IconWindow;
  164. TYPE
  165. IconComponent* = OBJECT(WMComponents.VisualComponent)
  166. VAR
  167. commandString- : WMProperties.StringProperty;
  168. imageName- : WMProperties.StringProperty;
  169. caption- : WMProperties.StringProperty;
  170. color- : WMProperties.Int32Property;
  171. border- : WMProperties.Int32Property;
  172. image : WMGraphics.Image;
  173. hover : BOOLEAN;
  174. borderI : LONGINT;
  175. PROCEDURE & Init*;
  176. BEGIN
  177. Init^;
  178. SetNameAsString(StrIconComponent);
  179. NEW(commandString, prototypeCommandString, NIL, NIL); properties.Add(commandString);
  180. NEW(imageName, prototypeImageName, NIL, NIL); properties.Add(imageName);
  181. NEW(color, prototypeColor, NIL, NIL); properties.Add(color);
  182. NEW(caption, prototypeCaption, NIL, NIL); properties.Add(caption);
  183. NEW(border, prototypeBorder, NIL, NIL); properties.Add(border);
  184. image := NIL; hover := FALSE;
  185. borderI := 0;
  186. END Init;
  187. PROCEDURE DrawBackground*(canvas : WMGraphics.Canvas);
  188. VAR captionStr : Strings.String; rect : WMRectangles.Rectangle;
  189. BEGIN
  190. DrawBackground^(canvas);
  191. IF hover THEN
  192. rect := GetClientRect();
  193. canvas.Fill(rect, SHORT(06060C0C0H), WMGraphics.ModeSrcOverDst);
  194. WMGraphicUtilities.DrawRect(canvas, rect, SHORT(06060C0C0H), WMGraphics.ModeSrcOverDst);
  195. END;
  196. canvas.SetColor(color.Get());
  197. IF image # NIL THEN
  198. canvas.DrawImage(borderI, borderI, image, WMGraphics.ModeSrcOverDst);
  199. ELSE
  200. WMGraphicUtilities.DrawRect(canvas, GetClientRect(), color.Get(), WMGraphics.ModeSrcOverDst);
  201. END;
  202. captionStr := caption.Get();
  203. IF (captionStr # NIL) THEN
  204. WMGraphics.DrawStringInRect(canvas, GetClientRect(), FALSE, WMGraphics.AlignCenter, WMGraphics.AlignCenter, captionStr^)
  205. END;
  206. END DrawBackground;
  207. PROCEDURE PointerMove*(x, y : LONGINT; keys : SET);
  208. BEGIN
  209. PointerMove^(x, y, keys);
  210. IF ~hover THEN hover := TRUE; Invalidate; END;
  211. END PointerMove;
  212. PROCEDURE PointerLeave*;
  213. BEGIN
  214. PointerLeave^;
  215. IF hover THEN hover := FALSE; Invalidate; END;
  216. END PointerLeave;
  217. PROCEDURE PropertyChanged*(sender, property: ANY);
  218. BEGIN
  219. IF (property = imageName) OR (property = border) THEN
  220. RecacheProperties;
  221. ELSIF (property = color) OR (property = caption) THEN
  222. Invalidate;
  223. ELSIF (property = bounds) THEN
  224. PropertyChanged^(sender, property);
  225. RecacheProperties;
  226. ELSE
  227. PropertyChanged^(sender, property);
  228. END
  229. END PropertyChanged;
  230. PROCEDURE RecacheProperties*;
  231. VAR
  232. string : Strings.String; resizedImage : WMGraphics.Image;
  233. imageWidth, imageHeight : LONGINT;
  234. BEGIN
  235. string := imageName.Get();
  236. IF (string # NIL) THEN
  237. image := WMGraphics.LoadImage(string^, TRUE);
  238. IF (bounds.GetWidth() - 2*border.Get() > 10) & (bounds.GetHeight() - 2*border.Get() > 10) THEN
  239. imageWidth := bounds.GetWidth() - 2*border.Get();
  240. imageHeight := bounds.GetHeight() - 2*border.Get();
  241. borderI := border.Get();
  242. ELSE
  243. imageWidth := bounds.GetWidth();
  244. imageHeight := bounds.GetHeight();
  245. borderI := 0;
  246. END;
  247. IF (image # NIL) & ((image.width # imageWidth) OR (image.height # imageHeight)) THEN
  248. NEW(resizedImage);
  249. Raster.Create(resizedImage, imageWidth, imageHeight, Raster.BGRA8888);
  250. WMRasterScale.Scale(
  251. image, WMRectangles.MakeRect(0, 0, image.width, image.height),
  252. resizedImage, WMRectangles.MakeRect(0, 0, resizedImage.width, resizedImage.height),
  253. WMRectangles.MakeRect(0, 0, resizedImage.width, resizedImage.height),
  254. WMRasterScale.ModeCopy, WMRasterScale.ScaleBilinear);
  255. image := resizedImage;
  256. END;
  257. ELSE
  258. image := NIL;
  259. END;
  260. Invalidate;
  261. END RecacheProperties;
  262. END IconComponent;
  263. VAR
  264. nofWindows : LONGINT;
  265. prototypeCommandString, prototypeImageName, prototypeCaption : WMProperties.StringProperty;
  266. prototypeColor, prototypeBorder : WMProperties.Int32Property;
  267. cmSetImageName, cmSetCommandString, cmSetCaption : ContextMenuPar;
  268. StrIconComponent, StrWindowTitle : Strings.String;
  269. PROCEDURE Open*(context : Commands.Context);
  270. VAR options : Options.Options; window: IconWindow; flags : SET;
  271. BEGIN
  272. NEW(options);
  273. options.Add("n", "navigation", Options.Flag);
  274. options.Add("s", "stayOnTop", Options.Flag);
  275. IF options.Parse(context.arg, context.error) THEN
  276. flags := {WMWindowManager.FlagHidden};
  277. IF options.GetFlag("navigation") THEN INCL(flags, WMWindowManager.FlagNavigation); END;
  278. IF options.GetFlag("stayOnTop") THEN INCL(flags, WMWindowManager.FlagStayOnTop); END;
  279. NEW(window, NIL, flags);
  280. END;
  281. END Open;
  282. PROCEDURE Restore*(context : WMRestorable.Context);
  283. VAR icon : IconWindow;
  284. BEGIN
  285. NEW(icon, context, {});
  286. END Restore;
  287. PROCEDURE IncCount;
  288. BEGIN {EXCLUSIVE}
  289. INC(nofWindows)
  290. END IncCount;
  291. PROCEDURE DecCount;
  292. BEGIN {EXCLUSIVE}
  293. DEC(nofWindows)
  294. END DecCount;
  295. PROCEDURE Cleanup;
  296. VAR die : KillerMsg;
  297. msg : WMMessages.Message;
  298. m : WMWindowManager.WindowManager;
  299. BEGIN {EXCLUSIVE}
  300. NEW(die);
  301. msg.ext := die;
  302. msg.msgType := WMMessages.MsgExt;
  303. m := WMWindowManager.GetDefaultManager();
  304. m.Broadcast(msg);
  305. AWAIT(nofWindows = 0);
  306. END Cleanup;
  307. BEGIN
  308. StrIconComponent := Strings.NewString("IconComponent");
  309. StrWindowTitle := Strings.NewString("DesktopIcon");
  310. NEW(cmSetCommandString, CmSetCommandString);
  311. NEW(cmSetImageName, CmSetImageName);
  312. NEW(cmSetCaption, CmSetCaption);
  313. Modules.InstallTermHandler(Cleanup);
  314. NEW(prototypeColor, NIL, WMStandardComponents.NewString("color"),
  315. WMStandardComponents.NewString("toggle icon border color"));
  316. prototypeColor.Set(WMGraphics.White);
  317. NEW(prototypeCommandString, NIL, WMStandardComponents.NewString("commandString"),
  318. WMStandardComponents.NewString("command to be executed when double-clicking the icon"));
  319. NEW(prototypeImageName, NIL, WMStandardComponents.NewString("imageName"),
  320. WMStandardComponents.NewString("name of icon image"));
  321. NEW(prototypeCaption, NIL, WMStandardComponents.NewString("caption"),
  322. WMStandardComponents.NewString("caption of the icon"));
  323. NEW(prototypeBorder, NIL, WMStandardComponents.NewString("border"),
  324. WMStandardComponents.NewString("border"));
  325. prototypeBorder.Set(5);
  326. END WMDesktopIcons.
  327. System.Free WMDesktopIcons~
  328. WMDesktopIcons.Open -n ~