WMNavigate.Mod 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986
  1. MODULE WMNavigate; (** AUTHOR "staubesv"; PURPOSE "Windows navigation"; *)
  2. IMPORT
  3. Modules, Kernel, Commands, Options, Locks, Strings, Raster, Plugins, Displays, KernelLog, Inputs, XML, WMMessages,
  4. WMRectangles, WMGraphics, WMGraphicUtilities, WMWindowManager, WMComponents, WMProperties, WMRestorable, Files, Dates;
  5. CONST
  6. (* TaskList.style *)
  7. Text* = 0;
  8. Icons* = 1;
  9. (* TaskList.menuLocation *)
  10. Left* = 0;
  11. Top* = 1;
  12. Right* = 2;
  13. Bottom* = 3;
  14. (* TaskList.layoutMode *)
  15. Fixed* = 0; (* don't change entry width & size *)
  16. Default* =1; (* don't change entry height, decrease entry width if required to fit layout.width *)
  17. ScaleUp*= 2; (* calculate default layout and then scale up to fit layout.width & layout.height *)
  18. ScaleUpWidthOnly* = 3; (* calculate default layout and then scale up to fit layout.width & layout.height *)
  19. ScaleUpHeightOnly* = 4; (* calculate default layout and then scale up to fit layout.width & layout.height *)
  20. Aspect* = 5; (* Try to find optimum entry width & height, nofColumns, nofRows that maintains the aspect ratio desiredEntryWidth : desiredEntryHeight *)
  21. ThumbnailWidth = 128;
  22. ThumbnailHeight = 92;
  23. (* Specifies how often the timestamp of the window manager is polled *)
  24. UpdateInterval = 100; (* milliseconds *)
  25. (* Maximum number of windows that can be managed by components inside this module *)
  26. MaxNofWindows = 100;
  27. MaxNavigationWindows = 10;
  28. (* Active objects state *)
  29. Running = 0;
  30. Terminating = 1;
  31. Terminated = 2;
  32. TYPE
  33. Layout = OBJECT
  34. VAR
  35. width, height : LONGINT; (* of overall space available *)
  36. entryWidth, entryHeight : LONGINT;
  37. (* entries in rightmost column are 'fixX + entryWidth' width and entries in last row are 'fixY + entryHeight' in height *)
  38. fixX, fixY : LONGINT;
  39. nofRows, nofColumns : LONGINT;
  40. nofEntries : LONGINT;
  41. (** Return position owning entry at x, y. Returns -1 if no entry owns the position *)
  42. PROCEDURE GetIndexOf(x, y : LONGINT) : LONGINT;
  43. VAR result, row, column : LONGINT;
  44. BEGIN
  45. result := -1;
  46. IF (nofEntries > 0) & (nofRows > 0) & (nofColumns > 0) THEN
  47. column := x DIV entryWidth;
  48. row := y DIV entryHeight;
  49. IF (column < nofColumns) & (row < nofRows) THEN
  50. result := row * nofColumns + column;
  51. IF (result >= nofEntries) THEN result := -1; END;
  52. END;
  53. END;
  54. RETURN result;
  55. END GetIndexOf;
  56. (** Return the bounding box of the item hit at position x, y *)
  57. PROCEDURE GetPositionOf(x, y : LONGINT) : WMRectangles.Rectangle;
  58. VAR rect : WMRectangles.Rectangle; row, column : LONGINT;
  59. BEGIN
  60. rect := WMRectangles.MakeRect(0, 0, 0, 0);
  61. IF (nofEntries > 0) & (nofRows > 0) & (nofColumns > 0) THEN
  62. column := x DIV entryWidth;
  63. row := y DIV entryHeight;
  64. IF (column < nofColumns) & (row < nofRows) THEN
  65. rect.l := column * entryWidth;
  66. rect.r := rect.l + entryWidth;
  67. rect.t := row * entryHeight;
  68. rect.b := rect.t + entryHeight;
  69. END;
  70. END;
  71. RETURN rect;
  72. END GetPositionOf;
  73. PROCEDURE Compute(nofEntries, width, height, desiredEntryWidth, desiredEntryHeight, mode : LONGINT);
  74. BEGIN
  75. ASSERT(nofEntries >= 0);
  76. ASSERT((width >= 0) & (height >= 0));
  77. ASSERT((desiredEntryWidth > 0) & (desiredEntryHeight > 0));
  78. ASSERT((mode = Fixed) OR (mode = Default) OR (mode = ScaleUp) OR (mode = ScaleUpWidthOnly) OR (mode = ScaleUpHeightOnly) OR (mode = Aspect));
  79. SELF.nofEntries := nofEntries;
  80. SELF.width := width; SELF.height := height;
  81. SELF.entryWidth := desiredEntryWidth; SELF.entryHeight := desiredEntryHeight;
  82. fixX := 0; fixY := 0;
  83. IF (mode # Aspect) THEN
  84. ComputeDefault;
  85. IF (mode = Fixed) THEN
  86. entryWidth := desiredEntryWidth;
  87. END;
  88. IF (mode = ScaleUp) OR (mode = ScaleUpWidthOnly) THEN
  89. IF (nofEntries < nofColumns) THEN
  90. nofColumns := nofEntries;
  91. IF (nofColumns = 0) THEN nofColumns := 1; END;
  92. END;
  93. entryWidth := width DIV nofColumns;
  94. fixX := width MOD nofColumns;
  95. END;
  96. IF (mode = ScaleUp) OR (mode = ScaleUpHeightOnly) THEN
  97. entryHeight := height DIV nofRows;
  98. fixY := height MOD nofRows;
  99. END;
  100. ELSE
  101. ComputeAspect;
  102. END;
  103. END Compute;
  104. (* Try to fit the entries of size (entryWidth,entryHeight) as good as possible into a number of columns and rows. Scale down entryWidth if necessary *)
  105. PROCEDURE ComputeDefault; (* private *)
  106. VAR nofEntriesPerRow, nofAvailableRows, nofRequiredRows : LONGINT;
  107. BEGIN
  108. nofEntriesPerRow := width DIV entryWidth;
  109. IF (nofEntriesPerRow = 0) THEN nofEntriesPerRow := 1; END;
  110. IF (nofEntries > 0) & (width > 0) & (height > 0) THEN
  111. IF (nofEntries * entryWidth > width) THEN
  112. nofAvailableRows := height DIV entryHeight;
  113. IF (nofAvailableRows = 0) THEN nofAvailableRows := 1; END;
  114. nofRequiredRows := (nofEntries + nofEntriesPerRow - 1) DIV nofEntriesPerRow;
  115. IF (nofAvailableRows > 1) THEN (* there is space for more than one row ... *)
  116. IF (nofRequiredRows <= nofAvailableRows) THEN (* place entries on multiple rows without decreasing entryWidth *)
  117. nofRows := nofRequiredRows;
  118. nofColumns := nofEntriesPerRow;
  119. ELSE (* place entries on multiple rows but also decrease entryWidth *)
  120. nofRows := nofAvailableRows;
  121. nofColumns := (nofEntries + nofRows - 1) DIV nofRows;
  122. entryWidth := width DIV nofColumns;
  123. END;
  124. ELSE (* there is only space for one row -> decrease entryWidth *)
  125. nofRows := 1;
  126. nofColumns := nofEntries;
  127. entryWidth := width DIV nofEntries;
  128. IF (entryWidth = 0) THEN entryWidth := 1; END;
  129. END;
  130. ELSE (* all entries fit on one row *)
  131. nofRows := 1;
  132. nofColumns := nofEntriesPerRow;
  133. END;
  134. ELSE (* all entries fit on one row *)
  135. nofRows := 1;
  136. nofColumns := nofEntriesPerRow;
  137. END;
  138. ASSERT((nofRows >= 1) & (nofColumns >= 0));
  139. ASSERT(entryWidth > 0); ASSERT(entryHeight > 0);
  140. END ComputeDefault;
  141. (* width, height of remaining area, nofEntries that still need to be placed *)
  142. PROCEDURE ComputeAspect;
  143. VAR entryRatio, areaRatio : REAL; eWidth, eHeight : LONGINT; doesFit : BOOLEAN;
  144. BEGIN
  145. entryRatio := entryWidth / entryHeight;
  146. areaRatio := width / height;
  147. doesFit := FALSE;
  148. IF (entryRatio >= areaRatio) THEN
  149. nofRows := 0;
  150. WHILE ~doesFit DO
  151. INC(nofRows);
  152. eHeight := height DIV nofRows;
  153. eWidth := ENTIER(eHeight / entryHeight * entryWidth);
  154. IF (eWidth = 0) THEN eWidth := 1; END;
  155. nofColumns := width DIV eWidth;
  156. IF (nofColumns = 0) THEN INC(nofColumns); END;
  157. doesFit := nofEntries <= nofRows * nofColumns;
  158. END;
  159. ELSE
  160. nofColumns := 0;
  161. WHILE ~doesFit DO
  162. INC(nofColumns);
  163. eWidth := width DIV nofColumns;
  164. eHeight := ENTIER(eWidth / entryWidth * entryHeight);
  165. IF (eHeight = 0) THEN eHeight := 1; END;
  166. nofRows := height DIV eHeight;
  167. IF (nofRows = 0) THEN INC(nofRows); END;
  168. doesFit := nofEntries <= nofRows * nofColumns;
  169. END;
  170. END;
  171. entryWidth := width DIV nofColumns;
  172. fixX := width MOD nofColumns;
  173. IF (entryWidth = 0) THEN entryWidth := 1; END;
  174. entryHeight := height DIV nofRows;
  175. fixY := height MOD nofRows;
  176. IF (entryHeight = 0) THEN entryHeight := 1; END;
  177. ASSERT((nofRows >= 1) & (nofColumns >= 0));
  178. ASSERT(entryWidth > 0); ASSERT(entryHeight > 0);
  179. END ComputeAspect;
  180. PROCEDURE Show;
  181. BEGIN
  182. KernelLog.String("--- Layout ---"); KernelLog.Ln;
  183. KernelLog.String("width: "); KernelLog.Int(width, 0);
  184. KernelLog.String(", height: "); KernelLog.Int(height, 0);
  185. KernelLog.Ln;
  186. KernelLog.String("nofEntries: "); KernelLog.Int(nofEntries, 0);
  187. KernelLog.Ln;
  188. KernelLog.String("nofRows: "); KernelLog.Int(nofRows, 0);
  189. KernelLog.String(", nofColumns: "); KernelLog.Int(nofColumns, 0);
  190. KernelLog.Ln;
  191. KernelLog.String("entryWidth: "); KernelLog.Int(entryWidth, 0);
  192. KernelLog.String(", entryHeight: "); KernelLog.Int(entryHeight, 0);
  193. KernelLog.Ln;
  194. KernelLog.String("fixX: "); KernelLog.Int(fixX, 0);
  195. KernelLog.String(", fixY: "); KernelLog.Int(fixY, 0);
  196. KernelLog.Ln;
  197. END Show;
  198. END Layout;
  199. TYPE
  200. DoCloseWindow = OBJECT
  201. VAR
  202. window : WMWindowManager.Window;
  203. PROCEDURE &Init(window : WMWindowManager.Window);
  204. BEGIN
  205. ASSERT(window # NIL);
  206. SELF.window := window;
  207. END Init;
  208. BEGIN {ACTIVE}
  209. window.Close;
  210. END DoCloseWindow;
  211. TYPE
  212. Info = RECORD
  213. nofWindows : LONGINT;
  214. windows : Windows;
  215. extImages : POINTER TO ARRAY OF WMGraphics.Image;
  216. focusIdx : LONGINT;
  217. wTimestamp : LONGINT;
  218. oTimestamp : LONGINT;
  219. END;
  220. TYPE
  221. (*
  222. StoreCommand*=PROCEDURE{DELEGATE}(sender, par: ANY);
  223. *)
  224. Base* = OBJECT(WMComponents.VisualComponent)
  225. VAR
  226. clDefault-, clSelected-, clMouseOver-, clSelectedMouseOver-,
  227. clTextDefault-, clTextSelected-, clTextMouseOver-, clTextSelectedMouseOver-,
  228. clIndicateHidden- : WMProperties.ColorProperty;
  229. borderWidth- : WMProperties.Int32Property;
  230. layoutMode- : WMProperties.Int32Property;
  231. itemWidth-, itemHeight- : WMProperties.Int32Property;
  232. info : Info;
  233. layout : Layout;
  234. lock : Locks.Lock; (* protects info, layout *)
  235. state : LONGINT;
  236. mouseOverIdx, lastMouseOverIdx : LONGINT;
  237. PROCEDURE &Init;
  238. BEGIN
  239. Init^;
  240. SetNameAsString(StrBase);
  241. NEW(clDefault, ProtoClDefault, NIL, NIL); properties.Add(clDefault);
  242. NEW(clSelected, ProtoClSelected, NIL, NIL); properties.Add(clSelected);
  243. NEW(clMouseOver, ProtoClMouseOver, NIL, NIL); properties.Add(clMouseOver);
  244. NEW(clSelectedMouseOver, ProtoClSelectedMouseOver, NIL, NIL); properties.Add(clSelectedMouseOver);
  245. NEW(clTextDefault, ProtoClTextDefault, NIL, NIL); properties.Add(clTextDefault);
  246. NEW(clTextSelected, ProtoClTextSelected, NIL, NIL); properties.Add(clTextSelected);
  247. NEW(clTextMouseOver, ProtoClTextMouseOver, NIL, NIL); properties.Add(clTextMouseOver);
  248. NEW(clTextSelectedMouseOver, ProtoClTextSelectedMouseOver, NIL, NIL); properties.Add(clTextSelectedMouseOver);
  249. NEW(clIndicateHidden, ProtoClIndicateHidden, NIL, NIL); properties.Add(clIndicateHidden);
  250. NEW(borderWidth, ProtoBorderWidth, NIL, NIL); properties.Add(borderWidth);
  251. NEW(layoutMode, ProtoLayoutMode, NIL, NIL); properties.Add(layoutMode);
  252. NEW(itemWidth, ProtoItemWidth, NIL, NIL); properties.Add(itemWidth);
  253. NEW(itemHeight, ProtoItemHeight, NIL, NIL); properties.Add(itemHeight);
  254. info.nofWindows := 0;
  255. Clear(info.windows);
  256. info.focusIdx := -1;
  257. info.wTimestamp := WMWindowManager.wTimestamp - 1;
  258. info.oTimestamp := WMWindowManager.oTimestamp - 1;
  259. NEW(layout);
  260. NEW(lock);
  261. state := Running;
  262. mouseOverIdx := -1; lastMouseOverIdx := -1;
  263. END Init;
  264. PROCEDURE PropertyChanged(sender, data : ANY);
  265. BEGIN
  266. IF (data = clDefault) OR (data = clSelected) OR (data = clMouseOver) OR (data = clSelectedMouseOver) OR
  267. (data = clTextDefault) OR (data = clTextSelected) OR (data = clTextMouseOver) OR (data = clTextSelectedMouseOver) OR
  268. (data = clIndicateHidden)
  269. THEN
  270. Invalidate;
  271. ELSIF (data = layoutMode) OR (data = itemWidth) OR (data = itemHeight) OR (data = borderWidth) THEN
  272. Invalidate;
  273. WMWindowManager.IncWTimestamp; (* force layout update *)
  274. ELSE
  275. PropertyChanged^(sender, data);
  276. END;
  277. END PropertyChanged;
  278. PROCEDURE PointerMove(x, y : LONGINT; keys : SET); (** PROTECTED *)
  279. BEGIN
  280. IF enabled.Get() THEN
  281. lock.Acquire;
  282. mouseOverIdx := layout.GetIndexOf(x, y);
  283. lock.Release;
  284. IF (mouseOverIdx # lastMouseOverIdx) THEN
  285. lastMouseOverIdx := mouseOverIdx;
  286. IF (mouseOverIdx >= 0) THEN
  287. Invalidate;
  288. END;
  289. END
  290. ELSE
  291. mouseOverIdx := -1; lastMouseOverIdx := -1;
  292. END;
  293. PointerMove^(x, y, keys)
  294. END PointerMove;
  295. PROCEDURE PointerLeave;
  296. BEGIN
  297. PointerLeave^;
  298. mouseOverIdx := -1; lastMouseOverIdx := -1;
  299. Invalidate
  300. END PointerLeave;
  301. PROCEDURE PointerDown(x, y:LONGINT; keys:SET);
  302. VAR index : LONGINT; window : WMWindowManager.Window;
  303. BEGIN
  304. IF (keys = {}) OR ~enabled.Get() THEN RETURN; END;
  305. IF (keys * {0, 2} # {}) THEN
  306. window := NIL;
  307. lock.Acquire;
  308. index := layout.GetIndexOf(x, y);
  309. IF (index >= 0) & (index < info.nofWindows) THEN
  310. window := info.windows[index];
  311. END;
  312. lock.Release;
  313. IF (window # NIL) THEN
  314. IF keys * {0} # {} THEN
  315. manager.SetIsVisible(window, TRUE);
  316. manager.SetFocus(window);
  317. manager.ToFront(window);
  318. ELSIF keys * {2} # {} THEN
  319. manager.SetIsVisible(window, ~window.isVisible);
  320. END;
  321. END;
  322. END;
  323. END PointerDown;
  324. PROCEDURE DrawInternal(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN; VAR extImage : WMGraphics.Image);
  325. VAR rect : WMRectangles.Rectangle;
  326. BEGIN
  327. ASSERT(lock.HasLock());
  328. ASSERT(window # NIL);
  329. rect := WMRectangles.MakeRect(x, y, x + width, y + height);
  330. IF mouseOver & hasFocus THEN
  331. canvas.Fill(rect, clSelectedMouseOver.Get(), WMGraphics.ModeSrcOverDst);
  332. ELSIF mouseOver THEN
  333. canvas.Fill(rect, clMouseOver.Get(), WMGraphics.ModeSrcOverDst);
  334. ELSIF hasFocus THEN
  335. canvas.Fill(rect, clSelected.Get(), WMGraphics.ModeSrcOverDst);
  336. ELSE
  337. canvas.Fill(rect, clDefault.Get(), WMGraphics.ModeSrcOverDst);
  338. END;
  339. WMGraphicUtilities.RectGlassShade(canvas, rect, borderWidth.Get(), hasFocus);
  340. END DrawInternal;
  341. PROCEDURE DrawBackground(canvas : WMGraphics.Canvas);
  342. VAR
  343. row, column, x, y : LONGINT;
  344. width, height : LONGINT;
  345. i : LONGINT;
  346. BEGIN
  347. DrawBackground^(canvas);
  348. lock.Acquire;
  349. IF (layout.nofEntries > 0) & (layout.width > 0) & (layout.height > 0) THEN
  350. row := 0; column := 0;
  351. FOR i := 0 TO info.nofWindows-1 DO
  352. x := column * layout.entryWidth;
  353. y := row * layout.entryHeight;
  354. width := layout.entryWidth;
  355. IF (column = layout.nofColumns - 1) THEN width := width + layout.fixX; END;
  356. height := layout.entryHeight;
  357. IF (row = layout.nofRows - 1) THEN height := height + layout.fixY; END;
  358. DrawInternal(canvas, x, y, width, height, info.windows[i], i = info.focusIdx, i = mouseOverIdx, info.extImages[i]);
  359. INC(column);
  360. IF (column >= layout.nofColumns) THEN
  361. column := 0;
  362. INC(row);
  363. END;
  364. END;
  365. END;
  366. lock.Release;
  367. END DrawBackground;
  368. END Base;
  369. CONST
  370. Border = 2;
  371. TitleHeight = 20;
  372. TYPE
  373. WindowOverview* = OBJECT(Base)
  374. VAR
  375. aux_canvas : WMGraphics.BufferCanvas;
  376. rect : WMRectangles.Rectangle;
  377. font : WMGraphics.Font;
  378. timer : Kernel.Timer;
  379. PROCEDURE CreateAuxCanvas(width, height : LONGINT; alpha : BOOLEAN) : WMGraphics.BufferCanvas;
  380. VAR canvas : WMGraphics.BufferCanvas; img : WMGraphics.Image;
  381. BEGIN
  382. rect := WMRectangles.MakeRect(0, 0, width, height);
  383. NEW(img);
  384. IF alpha THEN
  385. Raster.Create(img, width, height, Raster.BGRA8888);
  386. ELSE
  387. Raster.Create(img, width, height, WMWindowManager.format);
  388. END;
  389. NEW(canvas, img);
  390. RETURN canvas;
  391. END CreateAuxCanvas;
  392. PROCEDURE PropertyChanged(sender, data : ANY);
  393. BEGIN
  394. PropertyChanged^(sender, data);
  395. IF (data = bounds) THEN
  396. lock.Acquire;
  397. UpdateLayout;
  398. lock.Release;
  399. Invalidate;
  400. END;
  401. END PropertyChanged;
  402. PROCEDURE UpdateLayout;
  403. VAR border : LONGINT;
  404. BEGIN
  405. ASSERT(lock.HasLock());
  406. border := borderWidth.Get();
  407. layout.Compute(info.nofWindows, bounds.GetWidth(), bounds.GetHeight(), itemWidth.Get() , itemHeight.Get(), layoutMode.Get());
  408. IF (layout.entryWidth - 2*border > 0) & (layout.entryHeight - TitleHeight - border > 0) THEN
  409. aux_canvas := CreateAuxCanvas(layout.entryWidth - 2*border, layout.entryHeight - TitleHeight - border, FALSE);
  410. ELSE
  411. aux_canvas := NIL;
  412. END;
  413. END UpdateLayout;
  414. PROCEDURE &Init;
  415. BEGIN
  416. Init^;
  417. SetNameAsString(StrWindowOverview);
  418. SetGenerator("WMNavigate.GenOverview");
  419. layoutMode.Set(Aspect);
  420. borderWidth.Set(Border);
  421. itemWidth.Set(ThumbnailWidth + 2*Border);
  422. itemHeight.Set(ThumbnailHeight + TitleHeight + Border);
  423. takesFocus.Set(TRUE);
  424. font := WMGraphics.GetFont("Oberon", 8, {});
  425. aux_canvas := CreateAuxCanvas(ThumbnailWidth, ThumbnailHeight, FALSE);
  426. NEW(timer);
  427. END Init;
  428. PROCEDURE DrawInternal(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN; VAR extImage : WMGraphics.Image);
  429. VAR
  430. image : Raster.Image;
  431. title : Strings.String;
  432. sizeX, sizeY : LONGINT;
  433. imgX, imgY, imgWidth, imgHeight, winWidth, winHeight : LONGINT;
  434. t_width, t_height : LONGINT;
  435. scaleX, scaleY : REAL;
  436. canvasState : WMGraphics.CanvasState;
  437. BEGIN
  438. DrawInternal^(canvas, x, y, width, height, window, hasFocus, mouseOver, extImage);
  439. canvas.SetFont(font);
  440. t_width := width - 2*Border;
  441. t_height := height - 2*Border - TitleHeight;
  442. IF (aux_canvas # NIL) THEN (* aux_canvas is protected by lock *)
  443. aux_canvas.Fill(rect, fillColor.Get(), WMGraphics.ModeSrcOverDst);
  444. winWidth := window.GetWidth(); (* TODO: Not threadsafe *)
  445. winHeight := window.GetHeight();
  446. scaleX := t_width / winWidth;
  447. scaleY := t_height / winHeight;
  448. IF (scaleX <= scaleY) THEN
  449. imgWidth := t_width;
  450. imgHeight := ENTIER(winHeight * scaleX);
  451. imgX := 0;
  452. imgY := t_height - imgHeight;
  453. ELSE
  454. imgWidth := ENTIER(winWidth * scaleY);
  455. imgHeight := t_height;
  456. imgX := (t_width - imgWidth) DIV 2;
  457. imgY := 0;
  458. END;
  459. window.Draw(aux_canvas, imgWidth, imgHeight, WMGraphics.ScaleBilinear);
  460. image := aux_canvas.GetImage();
  461. canvas.SaveState(canvasState);
  462. canvas.SetClipRect(WMRectangles.MakeRect(x + Border + imgX, y + TitleHeight + imgY, x + Border + imgX + imgWidth, y + imgY + TitleHeight + imgHeight));
  463. canvas.DrawImage(x + Border + imgX, y + TitleHeight + imgY, image, WMGraphics.ModeSrcOverDst);
  464. canvas.RestoreState(canvasState);
  465. END;
  466. title := window.GetTitle();
  467. IF (title = NIL) THEN title := StrNoName; END;
  468. font.GetStringSize(title^, sizeX, sizeY);
  469. IF ~window.isVisible THEN
  470. canvas.SetColor(clIndicateHidden.Get());
  471. ELSIF (hasFocus OR mouseOver) THEN
  472. canvas.SetColor(WMGraphics.White);
  473. ELSE
  474. canvas.SetColor(WMGraphics.Black);
  475. END;
  476. canvas.DrawString(x + (width - sizeX) DIV 2, y + 15, title^);
  477. END DrawInternal;
  478. PROCEDURE Finalize;
  479. BEGIN
  480. Finalize^;
  481. state := Terminating; timer.Wakeup;
  482. BEGIN {EXCLUSIVE} AWAIT(state = Terminated); END;
  483. END Finalize;
  484. PROCEDURE Update;
  485. BEGIN
  486. IF (info.wTimestamp # WMWindowManager.wTimestamp) OR (info.oTimestamp # WMWindowManager.oTimestamp) THEN
  487. lock.Acquire;
  488. IF (info.wTimestamp # WMWindowManager.wTimestamp) THEN
  489. info.wTimestamp := WMWindowManager.wTimestamp;
  490. GetWindows(info.windows, info.nofWindows);
  491. IF (info.nofWindows > 0) THEN NEW(info.extImages, info.nofWindows); ELSE info.extImages := NIL; END;
  492. info.focusIdx := GetFocusOwnerIndex(info.windows, info.nofWindows);
  493. UpdateLayout;
  494. END;
  495. IF (info.oTimestamp # WMWindowManager.oTimestamp) THEN
  496. info.oTimestamp := WMWindowManager.oTimestamp;
  497. info.focusIdx := GetFocusOwnerIndex(info.windows, info.nofWindows);
  498. END;
  499. lock.Release;
  500. END;
  501. Invalidate;
  502. END Update;
  503. BEGIN {ACTIVE}
  504. LOOP
  505. IF (state # Running) THEN EXIT; END;
  506. Update;
  507. timer.Sleep(UpdateInterval);
  508. END;
  509. BEGIN {EXCLUSIVE} state := Terminated; END;
  510. END WindowOverview;
  511. TYPE
  512. TaskList* = OBJECT(Base)
  513. VAR
  514. style- : WMProperties.Int32Property; (* Text | Icons *)
  515. menuLocation- : WMProperties.Int32Property; (* Left | Top | Right | Bottom *)
  516. showThumbnails- : WMProperties.BooleanProperty;
  517. showNames- : WMProperties.BooleanProperty;
  518. viewport : WMWindowManager.ViewPort;
  519. dummyInfo : WMWindowManager.WindowInfo;
  520. lastKeys : SET;
  521. lastWindow : WMWindowManager.Window;
  522. msg: WMMessages.Message;
  523. PROCEDURE &Init;
  524. BEGIN
  525. Init^;
  526. SetNameAsString(StrTaskList);
  527. SetGenerator("WMNavigate.GenTaskList");
  528. NEW(style, ProtoTaskListStyle, NIL, NIL); properties.Add(style);
  529. NEW(menuLocation, ProtoTaskListMenuLocation, NIL, NIL); properties.Add(menuLocation);
  530. NEW(showThumbnails, ProtoTaskListShowThumbnails, NIL, NIL); properties.Add(showThumbnails);
  531. NEW(showNames, ProtoTaskListShowNames, NIL, NIL); showNames.Set(showWindowNames); properties.Add(showNames);
  532. CASE style.Get() OF
  533. | Text:
  534. itemWidth.Set(150); itemHeight.Set(20);
  535. layoutMode.Set(ScaleUp);
  536. | Icons:
  537. itemWidth.Set(40); itemHeight.Set(50);
  538. layoutMode.Set(Default); (*was Fixed*)
  539. ELSE
  540. itemWidth.Set(100); itemHeight.Set(50);
  541. END;
  542. viewport := WMWindowManager.GetDefaultView();
  543. WMWindowManager.ClearInfo(dummyInfo);
  544. lastKeys := {};
  545. lastWindow := NIL;
  546. END Init;
  547. PROCEDURE PropertyChanged(sender, data : ANY);
  548. BEGIN
  549. PropertyChanged^(sender, data);
  550. IF (data = menuLocation) THEN
  551. Invalidate;
  552. ELSIF (data = bounds) OR (data = style) THEN
  553. lock.Acquire;
  554. layout.Compute(info.nofWindows, bounds.GetWidth(), bounds.GetHeight(), itemWidth.Get(), itemHeight.Get(), layoutMode.Get());
  555. lock.Release;
  556. Invalidate;
  557. END;
  558. END PropertyChanged;
  559. PROCEDURE GoToWindow(window : WMWindowManager.Window; moveViewport : BOOLEAN);
  560. VAR rect : WMRectangles.Rectangle; px, py : LONGINT;
  561. BEGIN
  562. ASSERT(window # NIL);
  563. manager.lock.AcquireWrite;
  564. manager.SetIsVisible(window, TRUE);
  565. manager.SetFocus(window);
  566. manager.ToFront(window);
  567. IF (viewport # NIL) THEN
  568. rect := WMRectangles.MakeRect(ENTIER(viewport.range.l), ENTIER(viewport.range.t), ENTIER(viewport.range.r), ENTIER(viewport.range.b));
  569. IF ~WMRectangles.IsContained(rect, window.bounds) THEN
  570. IF (window.bounds.l < viewport.range.l) OR (window.bounds.t < viewport.range.t) OR
  571. ~WMRectangles.Intersect(rect, window.bounds)
  572. THEN
  573. IF (moveViewport) THEN (* re-position the viewport *)
  574. IF window.GetWidth() < (viewport.range.r - viewport.range.l) THEN
  575. px := window.bounds.l - ENTIER((viewport.range.r - viewport.range.l - window.GetWidth()) / 2);
  576. ELSE
  577. px := window.bounds.l - 20;
  578. END;
  579. IF window.GetHeight() < (viewport.range.b - viewport.range.t) THEN
  580. py := window.bounds.t - ENTIER((viewport.range.b - viewport.range.t - window.GetHeight()) / 2);
  581. ELSE
  582. py := window.bounds.t - 20;
  583. END;
  584. viewport.SetRange(px, py, viewport.range.r - viewport.range.l, viewport.range.b - viewport.range.t, TRUE);
  585. ELSE (* re-position the window *)
  586. IF window.GetWidth() < (viewport.range.r - viewport.range.l) THEN
  587. px := ENTIER(viewport.range.l + (viewport.range.r - viewport.range.l - window.GetWidth()) / 2);
  588. ELSE
  589. px := ENTIER(viewport.range.l) + 20;
  590. END;
  591. IF window.GetHeight() < (viewport.range.b - viewport.range.t) THEN
  592. py := ENTIER(viewport.range.t + (viewport.range.b - viewport.range.t - window.GetHeight()) / 2);
  593. ELSE
  594. py := ENTIER(viewport.range.t) + 20;
  595. END;
  596. manager.SetWindowPos(window, px, py);
  597. END;
  598. END;
  599. END;
  600. END;
  601. manager.lock.ReleaseWrite;
  602. END GoToWindow;
  603. PROCEDURE FocusLost;
  604. BEGIN
  605. FocusLost^;
  606. lastKeys := {};
  607. END FocusLost;
  608. PROCEDURE PointerDown(x, y:LONGINT; keys:SET);
  609. VAR
  610. index : LONGINT; window : WMWindowManager.Window;
  611. info2 : WMWindowManager.WindowInfo;
  612. gx, gy: LONGINT;
  613. menu : MenuWindow;
  614. type, index2 : LONGINT;
  615. infoKeys : SET;
  616. res : LONGINT;
  617. rect : WMRectangles.Rectangle;
  618. closeWindow : DoCloseWindow;
  619. same: BOOLEAN;
  620. BEGIN
  621. IF ~enabled.Get() THEN RETURN; END;
  622. lastKeys := keys;
  623. IF (keys * {0, 1, 2} # {}) THEN
  624. window := NIL;
  625. lock.Acquire;
  626. index := layout.GetIndexOf(x, y);
  627. IF (index >= 0) & (index < info.nofWindows) THEN
  628. window := info.windows[index];
  629. rect := layout.GetPositionOf(x, y);
  630. END;
  631. lock.Release;
  632. IF (window # NIL) THEN
  633. same := lastWindow = window;
  634. IF 0 IN keys THEN lastWindow := window; ELSE lastWindow := NIL; END;
  635. IF keys * {0,1} # {} THEN
  636. IF same & window.isVisible THEN
  637. manager.SetIsVisible(window, FALSE);
  638. ELSE
  639. GoToWindow(window, 0 IN keys);
  640. END;
  641. ELSIF keys * {2} # {} THEN
  642. IF (menuLocation.Get() = Top) THEN
  643. ToWMCoordinates(rect.l, rect.t + ShadowWidth, gx, gy);
  644. ELSE
  645. ToWMCoordinates(rect.l, rect.b, gx, gy);
  646. END;
  647. IF window.GetInfo(info2) THEN
  648. NEW(menu, gx, gy, 200, menuLocation.Get(), showThumbnails.Get(), window, info2);
  649. ELSE
  650. NEW(menu, gx, gy, 200, menuLocation.Get(), showThumbnails.Get(), window, dummyInfo);
  651. END;
  652. menu.GetSelection(type, index2, infoKeys);
  653. IF ~(2 IN infoKeys) THEN
  654. IF (type = Document) THEN
  655. IF (info2.handleDocumentInfo # NIL) THEN
  656. info2.handleDocumentInfo(info2.openDocuments[index2], FALSE, res);
  657. END;
  658. GoToWindow(window, 0 IN infoKeys);
  659. ELSIF (type = SystemCommand) THEN
  660. IF (index2 = SystemCommand_Close) THEN
  661. NEW(closeWindow, window);
  662. ELSIF (index2 = SystemCommand_Hide) THEN
  663. manager.SetIsVisible(window, ~window.isVisible);
  664. ELSIF (index2 = SystemCommand_StayOnTop) THEN
  665. manager.SetWindowFlag(window, WMWindowManager.FlagStayOnTop, ~(WMWindowManager.FlagStayOnTop IN window.flags));
  666. ELSIF (index2 = SystemCommand_StayOnBottom) THEN
  667. manager.SetWindowFlag(window, WMWindowManager.FlagStayOnBottom, ~(WMWindowManager.FlagStayOnBottom IN window.flags));
  668. ELSIF (index2 = SystemCommand_WindowShot) THEN
  669. WindowShot(window, windowShotScale);
  670. ELSIF (index2 = SystemCommand_StoreComponent) THEN
  671. StoreWindow(window);
  672. ELSIF (index2 = SystemCommand_StoreData) THEN
  673. msg.msgType := WMMessages.MsgSerialize;
  674. msg.msgSubType := WMMessages.MsgSubSerializeData;
  675. window.Handle(msg);
  676. ELSIF (index2 = SystemCommand_Frame) THEN
  677. manager.SetWindowFlag(window, WMWindowManager.FlagFrame, ~(WMWindowManager.FlagFrame IN window.flags));
  678. END;
  679. END;
  680. END;
  681. END;
  682. ELSE
  683. lastWindow := NIL;
  684. END;
  685. END;
  686. END PointerDown;
  687. PROCEDURE PointerUp(x, y : LONGINT; keys : SET);
  688. VAR window : WMWindowManager.Window; windowCloser : DoCloseWindow; index : LONGINT;
  689. BEGIN
  690. PointerUp^(x, y, keys);
  691. IF ~enabled.Get() THEN RETURN; END;
  692. IF (lastKeys * {0, 2} = {0, 2}) & ((keys = {0}) OR (keys = {2})) THEN
  693. window := NIL;
  694. lock.Acquire;
  695. index := layout.GetIndexOf(x, y);
  696. IF (index >= 0) & (index < info.nofWindows) THEN
  697. window := info.windows[index];
  698. END;
  699. lock.Release;
  700. IF (window # NIL) & (window = lastWindow) THEN
  701. NEW(windowCloser, window);
  702. END;
  703. END;
  704. lastKeys := keys;
  705. END PointerUp;
  706. PROCEDURE DrawInternalIcons(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN; VAR extImage : WMGraphics.Image);
  707. VAR
  708. image : WMGraphics.Image;
  709. imageRect, indicatorRect : WMRectangles.Rectangle;
  710. title : Strings.String;
  711. BEGIN
  712. CASE menuLocation.Get() OF
  713. |Top:
  714. imageRect := WMRectangles.MakeRect(x + Border, y + MenuSize, x + width - Border, y + height - Border);
  715. indicatorRect := WMRectangles.MakeRect(x + Border, y + Border, x + width - Border, y + MenuSize - Border);
  716. |Left:
  717. imageRect := WMRectangles.MakeRect(x + MenuSize, y + Border, x + width - Border, y + height - Border);
  718. indicatorRect := WMRectangles.MakeRect(x + Border, y + Border, x + MenuSize - Border, y + height - Border);
  719. |Right:
  720. imageRect := WMRectangles.MakeRect(x + Border, y + Border, x + width - MenuSize, y + height - Border);
  721. indicatorRect := WMRectangles.MakeRect(x + width - MenuSize + Border, y + Border, x + width - Border, y + height - Border);
  722. |Bottom:
  723. imageRect := WMRectangles.MakeRect(x + Border, y + Border, x + width - Border, y + height - MenuSize);
  724. indicatorRect := WMRectangles.MakeRect(x + Border, y + height - MenuSize + Border, x + width - Border, y + height - Border);
  725. END;
  726. IF (window.icon # NIL) THEN
  727. image := window.icon;
  728. ELSE
  729. IF (extImage = NIL) THEN extImage := GetWindowImage(window, 64, 64); END;
  730. image := extImage;
  731. END;
  732. IF (image # NIL) THEN
  733. canvas.ScaleImage(image,
  734. WMRectangles.MakeRect(0, 0, image.width, image.height),
  735. imageRect,
  736. WMGraphics.ModeSrcOverDst,
  737. WMGraphics.ScaleBilinear
  738. );
  739. IF ~window.isVisible THEN
  740. canvas.Fill(indicatorRect, clIndicateHidden.Get(), WMGraphics.ModeSrcOverDst);
  741. WMGraphicUtilities.ExtRectGlassShade(canvas, indicatorRect, {}, 1, FALSE);
  742. END;
  743. END;
  744. IF (window.icon = NIL) THEN
  745. title := window.GetTitle();
  746. IF (title = NIL) THEN title := StrNoName; END;
  747. IF ~window.isVisible THEN
  748. canvas.SetColor(WMGraphics.Yellow);
  749. ELSIF hasFocus & ~mouseOver THEN
  750. canvas.SetColor(WMGraphics.White);
  751. ELSE
  752. canvas.SetColor(WMGraphics.Black);
  753. END;
  754. canvas.DrawString(x + 4, y + height - 5, title^);
  755. ELSE
  756. IF showNames.Get() & window.isVisible & (window.info#NIL) THEN
  757. canvas.SetColor(WMGraphics.Black);
  758. canvas.DrawString(x+4, y + height-5, window.info.openDocuments[0].name); (* to do: show the ACTIVE window *)
  759. END;
  760. END;
  761. END DrawInternalIcons;
  762. PROCEDURE DrawInternalText(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN);
  763. VAR title : Strings.String;
  764. BEGIN
  765. title := window.GetTitle();
  766. IF (title = NIL) THEN title := StrNoName; END;
  767. IF ~window.isVisible THEN
  768. canvas.SetColor(clIndicateHidden.Get());
  769. ELSIF mouseOver & hasFocus THEN
  770. canvas.SetColor(clTextSelectedMouseOver.Get());
  771. ELSIF mouseOver THEN
  772. canvas.SetColor(clTextMouseOver.Get());
  773. ELSIF hasFocus THEN
  774. canvas.SetColor(clTextSelected.Get());
  775. ELSE
  776. canvas.SetColor(clTextDefault.Get());
  777. END;
  778. canvas.DrawString(x + 4, y + height - 5, title^);
  779. END DrawInternalText;
  780. PROCEDURE DrawInternal(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN; VAR extImage : WMGraphics.Image);
  781. BEGIN
  782. canvas.SetClipRect(WMRectangles.MakeRect(x, y, x + width, y + height));
  783. DrawInternal^(canvas, x, y, width, height, window, hasFocus, mouseOver, extImage);
  784. CASE style.Get() OF
  785. |Text: DrawInternalText(canvas, x, y, width, height, window, hasFocus, mouseOver);
  786. |Icons: DrawInternalIcons(canvas, x, y, width, height, window, hasFocus, mouseOver, extImage);
  787. ELSE
  788. END;
  789. END DrawInternal;
  790. PROCEDURE Finalize;
  791. BEGIN
  792. Finalize^;
  793. state := Terminating;
  794. WMWindowManager.IncOTimestamp; (* unblock active body WMWindowManager.AwaitChange *)
  795. BEGIN {EXCLUSIVE} AWAIT(state = Terminated); END;
  796. END Finalize;
  797. BEGIN {ACTIVE}
  798. LOOP
  799. IF (state # Running) THEN EXIT; END;
  800. WMWindowManager.AwaitChange(info.wTimestamp, info.oTimestamp);
  801. IF (state # Running) THEN EXIT; END;
  802. lock.Acquire;
  803. IF (info.wTimestamp # WMWindowManager.wTimestamp) THEN
  804. info.wTimestamp := WMWindowManager.wTimestamp;
  805. GetWindows(info.windows, info.nofWindows);
  806. IF (info.nofWindows > 0) THEN NEW(info.extImages, info.nofWindows); ELSE info.extImages := NIL; END;
  807. info.focusIdx := GetFocusOwnerIndex(info.windows, info.nofWindows);
  808. layout.Compute(info.nofWindows, bounds.GetWidth(), bounds.GetHeight(), itemWidth.Get(), itemHeight.Get(), layoutMode.Get());
  809. END;
  810. IF (info.oTimestamp # WMWindowManager.oTimestamp) THEN
  811. info.oTimestamp := WMWindowManager.oTimestamp;
  812. info.focusIdx := GetFocusOwnerIndex(info.windows, info.nofWindows);
  813. END;
  814. lock.Release;
  815. Invalidate;
  816. END;
  817. BEGIN {EXCLUSIVE} state := Terminated; END;
  818. END TaskList;
  819. CONST
  820. ShadowWidth = 5;
  821. LineHeight = 20;
  822. LeftBorder = 25;
  823. RightBorder = 5;
  824. NofSystemCommands = 8;
  825. SystemCommand = 99;
  826. SystemCommand_Close = 0;
  827. SystemCommand_Hide = 1;
  828. SystemCommand_StayOnTop = 2;
  829. SystemCommand_StayOnBottom = 3;
  830. SystemCommand_Frame = 4;
  831. SystemCommand_WindowShot = 5;
  832. SystemCommand_StoreComponent = 6;
  833. SystemCommand_StoreData = 7;
  834. Document = 1;
  835. TYPE
  836. InfoView = OBJECT(WMComponents.VisualComponent)
  837. VAR
  838. window : WMWindowManager.Window;
  839. info : WMWindowManager.WindowInfo;
  840. nofDocuments: LONGINT;
  841. documentOffset, commandOffset, imageOffset : LONGINT;
  842. owner : MenuWindow;
  843. menuLocation : LONGINT;
  844. showThumbnails : BOOLEAN;
  845. type, index : LONGINT;
  846. keys : SET;
  847. xt, yt : LONGINT;
  848. image : WMGraphics.Image;
  849. imgX, imgY : LONGINT;
  850. imageYes, imageNo : WMGraphics.Image;
  851. PROCEDURE &New(owner : MenuWindow; menuLocation : LONGINT; showThumbnails : BOOLEAN);
  852. BEGIN
  853. ASSERT(owner # NIL);
  854. SELF.owner := owner;
  855. SELF.menuLocation := menuLocation;
  856. SELF.showThumbnails := showThumbnails;
  857. Init; (* no super call since Init does not exist in this scope *)
  858. SetNameAsString(Strings.NewString("InfoView"));
  859. nofDocuments := 0;
  860. keys := {};
  861. xt := -1; yt := -1;
  862. imageYes := WMGraphics.LoadImage("Navigation.rep://Yes.png", TRUE);
  863. imageNo := WMGraphics.LoadImage("Navigation.rep://No.png", TRUE);
  864. END New;
  865. PROCEDURE SetInfo(window : WMWindowManager.Window; CONST info : WMWindowManager.WindowInfo);
  866. VAR
  867. vc : WMComponents.VisualComponent; ptr : ANY; i : LONGINT; aux_canvas : WMGraphics.BufferCanvas;
  868. height, imageWidth, imageHeight : LONGINT;
  869. BEGIN
  870. SELF.window := window;
  871. Acquire;
  872. SELF.info := info;
  873. nofDocuments := 0;
  874. FOR i := 0 TO LEN(info.openDocuments)-1 DO
  875. IF (info.openDocuments[i].name # "") THEN INC(nofDocuments); END;
  876. END;
  877. vc := NIL;
  878. IF (info.vc.generator # NIL) THEN
  879. ptr := info.vc.generator();
  880. IF (ptr # NIL) & (ptr IS WMComponents.VisualComponent) THEN
  881. vc := ptr (WMComponents.VisualComponent);
  882. END;
  883. END;
  884. Release;
  885. height := NofSystemCommands * LineHeight + LineHeight; (* incl. 1 separator line *)
  886. IF (nofDocuments > 0) THEN
  887. height := height + nofDocuments * LineHeight + LineHeight; (* incl. 1 separator line *)
  888. END;
  889. IF (vc # NIL) THEN
  890. vc.alignment.Set(WMComponents.AlignNone);
  891. vc.bounds.SetTop(height);
  892. vc.bounds.SetHeight(info.vc.height);
  893. height := height + ((info.vc.height + LineHeight - 1) DIV LineHeight) * LineHeight + RightBorder;
  894. vc.bounds.SetLeft(LeftBorder);
  895. vc.bounds.SetRight(bounds.GetWidth() - RightBorder);
  896. END;
  897. IF showThumbnails THEN
  898. imageWidth := bounds.GetWidth() - LeftBorder - RightBorder;
  899. imageHeight := ENTIER(3 * imageWidth / 4);
  900. NEW(image);
  901. Raster.Create(image, imageWidth, imageHeight, Raster.BGRA8888);
  902. NEW(aux_canvas, image);
  903. aux_canvas.Fill(WMRectangles.MakeRect(0, 0, imageWidth, imageHeight), WMGraphics.White, WMGraphics.ModeCopy);
  904. DrawIntoCanvas(window, aux_canvas, imageWidth, imageHeight, imgX, imgY);
  905. IF (menuLocation = Top) THEN
  906. imageOffset := RightBorder;
  907. ELSE
  908. imageOffset := height;
  909. END;
  910. height := height + ((imageHeight + LineHeight - 1) DIV LineHeight) * LineHeight + RightBorder;
  911. ELSE
  912. imageWidth := 0; imageHeight := 0;
  913. END;
  914. IF (vc # NIL) THEN
  915. IF (menuLocation = Top) THEN
  916. vc.bounds.SetTop(2*RightBorder + ((imageHeight + LineHeight - 1) DIV LineHeight) * LineHeight);
  917. vc.bounds.SetHeight(info.vc.height);
  918. END;
  919. AddContent(vc);
  920. END;
  921. bounds.SetHeight(height);
  922. IF (menuLocation = Top) THEN
  923. documentOffset := height - (NofSystemCommands + nofDocuments + 1) * LineHeight;
  924. commandOffset := height - NofSystemCommands * LineHeight;
  925. ELSE
  926. commandOffset := 0;
  927. documentOffset := (NofSystemCommands + 1) * LineHeight;
  928. END;
  929. Invalidate;
  930. END SetInfo;
  931. PROCEDURE PointerMove(x, y : LONGINT; keys : SET); (** PROTECTED *)
  932. BEGIN
  933. IF enabled.Get() THEN
  934. xt := x; yt := y;
  935. Invalidate;
  936. ELSE
  937. xt := -1; yt := -1;
  938. END;
  939. PointerMove^(x, y, keys)
  940. END PointerMove;
  941. PROCEDURE PointerLeave;
  942. BEGIN
  943. PointerLeave^;
  944. xt := -1; yt := -1;
  945. Invalidate
  946. END PointerLeave;
  947. PROCEDURE PointerDown(x, y:LONGINT; keys:SET);
  948. BEGIN
  949. IF enabled.Get() THEN
  950. SELF.keys := keys;
  951. type := -1;
  952. index := -1;
  953. IF (commandOffset <= y) & (y < commandOffset + NofSystemCommands * LineHeight) THEN
  954. type := SystemCommand;
  955. IF (y < commandOffset + LineHeight) THEN
  956. index := SystemCommand_Close;
  957. ELSIF (y < commandOffset + 2 * LineHeight) THEN
  958. index := SystemCommand_Hide;
  959. ELSIF (y < commandOffset + 3 * LineHeight) THEN
  960. index := SystemCommand_StayOnTop;
  961. ELSIF (y < commandOffset + 4 * LineHeight) THEN
  962. index := SystemCommand_StayOnBottom;
  963. ELSIF (y < commandOffset + 5 * LineHeight) THEN
  964. index := SystemCommand_Frame;
  965. ELSIF (y < commandOffset + 6 * LineHeight) THEN
  966. index := SystemCommand_WindowShot;
  967. ELSIF (WMWindowManager.FlagStorable IN window.flags) & (y < commandOffset + 7 * LineHeight) THEN
  968. index := SystemCommand_StoreComponent;
  969. ELSIF (WMWindowManager.FlagStorable IN window.flags) & (y < commandOffset + 8 * LineHeight) THEN
  970. index := SystemCommand_StoreData;END;
  971. ELSIF (documentOffset <= y) & (y < documentOffset + nofDocuments * LineHeight) THEN
  972. type := Document;
  973. index := (y - documentOffset) DIV LineHeight;
  974. END;
  975. END;
  976. owner.Close;
  977. END PointerDown;
  978. PROCEDURE Draw(canvas : WMGraphics.Canvas);
  979. VAR y : LONGINT;
  980. PROCEDURE IsHighlighted(y : LONGINT) : BOOLEAN;
  981. BEGIN
  982. RETURN (y <= yt) & (yt < y + LineHeight);
  983. END IsHighlighted;
  984. PROCEDURE DrawBg(y : LONGINT);
  985. BEGIN
  986. IF IsHighlighted(y) THEN
  987. canvas.Fill(WMRectangles.MakeRect(0, y, bounds.GetWidth(), y + LineHeight), LONGINT(060606A0H), WMGraphics.ModeSrcOverDst);
  988. canvas.SetColor(WMGraphics.White);
  989. ELSE
  990. canvas.SetColor(WMGraphics.Black);
  991. END;
  992. END DrawBg;
  993. PROCEDURE DrawDocuments(VAR y : LONGINT);
  994. VAR row : LONGINT;
  995. BEGIN
  996. FOR row := 1 TO nofDocuments DO
  997. DrawBg(y);
  998. IF info.openDocuments[row - 1].modified THEN
  999. canvas.SetColor(WMGraphics.Red);
  1000. ELSIF (info.openDocuments[row - 1].hasFocus) THEN
  1001. canvas.SetColor(00DA00FFH);
  1002. ELSIF IsHighlighted(y) THEN
  1003. canvas.SetColor(WMGraphics.White);
  1004. ELSE
  1005. canvas.SetColor(WMGraphics.Black);
  1006. END;
  1007. canvas.DrawString(LeftBorder, y + 16, info.openDocuments[row - 1].name);
  1008. INC(y, LineHeight);
  1009. END;
  1010. END DrawDocuments;
  1011. PROCEDURE DrawSystemCommands(VAR y : LONGINT);
  1012. BEGIN
  1013. canvas.SetColor(WMGraphics.Black);
  1014. DrawBg(y);
  1015. canvas.DrawString(LeftBorder, y + 16, "Close"); INC(y, LineHeight);
  1016. DrawBg(y);
  1017. DrawYesNo(y, window.isVisible);
  1018. canvas.DrawString(LeftBorder, y + 16, "Visible"); INC(y, LineHeight);
  1019. DrawBg(y);
  1020. DrawYesNo(y, WMWindowManager.FlagStayOnTop IN window.flags);
  1021. canvas.DrawString(LeftBorder, y + 16, "StayOnTop"); INC(y, LineHeight);
  1022. IF (NofSystemCommands > 3) THEN
  1023. DrawBg(y);
  1024. DrawYesNo(y, WMWindowManager.FlagStayOnBottom IN window.flags);
  1025. canvas.DrawString(LeftBorder, y + 16, "StayOnBottom"); INC(y, LineHeight);
  1026. END;
  1027. IF (NofSystemCommands > 4) THEN
  1028. DrawBg(y);
  1029. DrawYesNo(y, WMWindowManager.FlagFrame IN window.flags);
  1030. canvas.DrawString(LeftBorder, y + 16, "Frame"); INC(y, LineHeight);
  1031. END;
  1032. IF (NofSystemCommands > 5) THEN
  1033. DrawBg(y);
  1034. canvas.DrawString(LeftBorder, y + 16, "WindowShot"); INC(y, LineHeight);
  1035. END;
  1036. IF (*(window IS WMComponents.FormWindow) &*) (WMWindowManager.FlagStorable IN window.flags) & (NofSystemCommands > 6) THEN
  1037. DrawBg(y);
  1038. canvas.DrawString(LeftBorder, y + 16, "StoreComponent"); INC(y, LineHeight);
  1039. END;
  1040. IF (WMWindowManager.FlagStorable IN window.flags) & (NofSystemCommands > 7) THEN
  1041. DrawBg(y);
  1042. canvas.DrawString(LeftBorder, y + 16, "StoreData"); INC(y, LineHeight);
  1043. END;
  1044. END DrawSystemCommands;
  1045. PROCEDURE DrawLine(VAR y : LONGINT);
  1046. BEGIN
  1047. canvas.Line(LeftBorder, y + (LineHeight DIV 2), bounds.GetWidth(), y + (LineHeight DIV 2), LONGINT(0C0C0C0FFH), WMGraphics.ModeCopy);
  1048. INC(y, LineHeight);
  1049. END DrawLine;
  1050. PROCEDURE DrawImage(y : LONGINT);
  1051. VAR canvasState : WMGraphics.CanvasState;
  1052. BEGIN
  1053. canvas.SaveState(canvasState);
  1054. canvas.SetClipRect(WMRectangles.MakeRect(LeftBorder, y, bounds.GetWidth() - RightBorder, y + image.height));
  1055. canvas.DrawImage(LeftBorder + imgX, y + imgY, image, WMGraphics.ModeCopy);
  1056. WMGraphicUtilities.DrawRect(canvas,
  1057. WMRectangles.MakeRect(LeftBorder, y, bounds.GetWidth() - RightBorder, y + image.height),
  1058. LONGINT(0C0C0C0C0H), WMGraphics.ModeSrcOverDst
  1059. );
  1060. canvas.RestoreState(canvasState);
  1061. END DrawImage;
  1062. PROCEDURE DrawYesNo(y : LONGINT; value : BOOLEAN);
  1063. BEGIN
  1064. IF value & (imageYes # NIL) THEN
  1065. canvas.DrawImage(5, y + 6, imageYes, WMGraphics.ModeSrcOverDst);
  1066. ELSIF ~value & (imageNo # NIL) THEN
  1067. canvas.DrawImage(5, y + 6, imageNo, WMGraphics.ModeSrcOverDst);
  1068. END;
  1069. END DrawYesNo;
  1070. BEGIN
  1071. Draw^(canvas);
  1072. canvas.Fill(WMRectangles.MakeRect(0, 0, LeftBorder - 5, bounds.GetHeight()), LONGINT(0C0C0C0C0H), WMGraphics.ModeSrcOverDst);
  1073. IF (menuLocation = Top) THEN
  1074. IF (nofDocuments > 0) THEN
  1075. y := documentOffset - LineHeight;
  1076. DrawLine(y);
  1077. DrawDocuments(y);
  1078. END;
  1079. y := commandOffset - LineHeight;
  1080. DrawLine(y);
  1081. DrawSystemCommands(y);
  1082. ELSE
  1083. y := commandOffset;
  1084. DrawSystemCommands(y);
  1085. DrawLine(y);
  1086. IF (nofDocuments > 0) THEN
  1087. DrawDocuments(y);
  1088. DrawLine(y);
  1089. END;
  1090. END;
  1091. IF showThumbnails & (image # NIL)THEN
  1092. DrawImage(imageOffset);
  1093. END;
  1094. END Draw;
  1095. END InfoView;
  1096. TYPE
  1097. MenuWindow = OBJECT (WMComponents.FormWindow)
  1098. VAR
  1099. isClosed : BOOLEAN;
  1100. shadowRectB, shadowRectR, borderRect : WMRectangles.Rectangle;
  1101. infoView : InfoView;
  1102. info : WMWindowManager.WindowInfo;
  1103. close : BOOLEAN;
  1104. PROCEDURE GetSelection(VAR type, index : LONGINT; VAR keys : SET);
  1105. BEGIN {EXCLUSIVE}
  1106. AWAIT(close);
  1107. type := infoView.type;
  1108. index := infoView.index;
  1109. keys := infoView.keys;
  1110. END GetSelection;
  1111. PROCEDURE&New(
  1112. x, y, width, menuLocation : LONGINT;
  1113. showThumbnails : BOOLEAN;
  1114. window : WMWindowManager.Window; CONST info : WMWindowManager.WindowInfo
  1115. );
  1116. VAR height : LONGINT;
  1117. BEGIN
  1118. ASSERT((width > 0));
  1119. isClosed := FALSE;
  1120. SELF.info := info;
  1121. NEW(infoView, SELF, menuLocation, showThumbnails);
  1122. infoView.fillColor.Set(WMGraphics.White);
  1123. infoView.bounds.SetWidth(width);
  1124. infoView.SetInfo(window, info);
  1125. height := infoView.bounds.GetHeight();
  1126. Init(width+ ShadowWidth, infoView.bounds.GetHeight() + ShadowWidth, TRUE);
  1127. SetContent(infoView);
  1128. SetTitle(Strings.NewString("WMNavigateMenu"));
  1129. infoView.alignment.Set(WMComponents.AlignNone);
  1130. infoView.bounds.SetExtents(width, height);
  1131. borderRect := WMRectangles.MakeRect(0, 0, width, height);
  1132. shadowRectB := WMRectangles.MakeRect(ShadowWidth, height, width+ShadowWidth, height+ShadowWidth);
  1133. shadowRectR := WMRectangles.MakeRect(width, ShadowWidth, width+ShadowWidth, height);
  1134. IF (menuLocation = Top) THEN
  1135. y := y - (infoView.bounds.GetHeight() + ShadowWidth);
  1136. END;
  1137. manager := WMWindowManager.GetDefaultManager();
  1138. manager.Add(x, y, SELF, {WMWindowManager.FlagStayOnTop, WMWindowManager.FlagNavigation, WMWindowManager.FlagHidden});
  1139. manager.SetFocus(SELF);
  1140. END New;
  1141. PROCEDURE Draw(canvas : WMGraphics.Canvas; w, h, q : LONGINT); (** override *)
  1142. BEGIN
  1143. Draw^(canvas, w, h, q);
  1144. canvas.Fill(shadowRectB, 04FH, WMGraphics.ModeSrcOverDst);
  1145. canvas.Fill(shadowRectR, 04FH, WMGraphics.ModeSrcOverDst);
  1146. WMGraphicUtilities.DrawRect(canvas, borderRect, WMGraphics.Black, WMGraphics.ModeCopy);
  1147. END Draw;
  1148. PROCEDURE SetClosed;
  1149. BEGIN
  1150. BEGIN {EXCLUSIVE} close := TRUE; END;
  1151. END SetClosed;
  1152. PROCEDURE Close;
  1153. BEGIN
  1154. SetClosed;
  1155. Close^;
  1156. END Close;
  1157. PROCEDURE KeyEvent(ucs : LONGINT; flags : SET; keysym : LONGINT); (* override *)
  1158. BEGIN
  1159. IF ~(Inputs.Release IN flags) THEN
  1160. IF keysym = 0FF54H THEN (* Cursor Down *)
  1161. ELSIF keysym = 0FF52H THEN (* Cursor Up *)
  1162. ELSIF (keysym = Inputs.KsTab) OR (keysym = Inputs.KsReturn) THEN
  1163. ELSIF (keysym = Inputs.KsEscape) THEN
  1164. Close;
  1165. ELSE
  1166. END;
  1167. ELSE
  1168. END;
  1169. END KeyEvent;
  1170. PROCEDURE FocusLost;
  1171. BEGIN
  1172. FocusLost^;
  1173. Close;
  1174. END FocusLost;
  1175. END MenuWindow;
  1176. CONST
  1177. MenuSize = 10;
  1178. TYPE
  1179. Window = OBJECT(WMComponents.FormWindow)
  1180. VAR
  1181. myId : LONGINT;
  1182. PROCEDURE &New*(id : LONGINT; component : WMComponents.VisualComponent; x, y, width, height : LONGINT; alpha : BOOLEAN; flags : SET);
  1183. VAR title, nbr : ARRAY 32 OF CHAR;
  1184. BEGIN
  1185. ASSERT((component # NIL) & (width > 0) & (height > 0));
  1186. Init(width, height, alpha);
  1187. SELF.myId := id;
  1188. SetContent(component);
  1189. COPY("WMNavigate", title); Strings.IntToStr(id, nbr); Strings.Append(title, nbr);
  1190. SetTitle(Strings.NewString(title));
  1191. IF (WMWindowManager.FlagNavigation IN flags) THEN
  1192. WMWindowManager.ExtAddViewBoundWindow(SELF, x, y, NIL, flags);
  1193. ELSE
  1194. WMWindowManager.ExtAddWindow(SELF, x, y, flags);
  1195. END;
  1196. component.bounds.SetExtents(width, height);
  1197. pointerThreshold := 1;
  1198. END New;
  1199. PROCEDURE Close;
  1200. BEGIN
  1201. Close^;
  1202. windows[myId] := NIL;
  1203. END Close;
  1204. END Window;
  1205. TYPE
  1206. Windows = ARRAY MaxNofWindows OF WMWindowManager.Window;
  1207. VAR
  1208. windows : ARRAY MaxNavigationWindows OF Window;
  1209. manager : WMWindowManager.WindowManager;
  1210. viewport : WMWindowManager.ViewPort;
  1211. StrWindowOverview : Strings.String;
  1212. StrNoName : Strings.String;
  1213. StrBase: Strings.String;
  1214. StrTaskList: Strings.String;
  1215. StrOverview: Strings.String;
  1216. width, height : LONGINT;
  1217. windowShotScale*:REAL;
  1218. windowsAreHidden : BOOLEAN;
  1219. navigationIsHidden : BOOLEAN;
  1220. showWindowNames: BOOLEAN;
  1221. ProtoClDefault, ProtoClSelected, ProtoClMouseOver, ProtoClSelectedMouseOver,
  1222. ProtoClTextDefault, ProtoClTextSelected, ProtoClTextMouseOver, ProtoClTextSelectedMouseOver,
  1223. ProtoClIndicateHidden : WMProperties.ColorProperty;
  1224. ProtoBorderWidth : WMProperties.Int32Property;
  1225. ProtoTaskListStyle, ProtoTaskListMenuLocation : WMProperties.Int32Property;
  1226. ProtoTaskListShowThumbnails, ProtoTaskListShowNames : WMProperties.BooleanProperty;
  1227. ProtoItemWidth, ProtoItemHeight : WMProperties.Int32Property;
  1228. ProtoLayoutMode : WMProperties.Int32Property;
  1229. PROCEDURE GetWindowImage(window : WMWindowManager.Window; width, height : LONGINT) : WMGraphics.Image;
  1230. VAR image : WMGraphics.Image; canvas : WMGraphics.BufferCanvas; ignore : LONGINT;
  1231. BEGIN (* must hold window manager lock *)
  1232. ASSERT((window # NIL));
  1233. NEW(image);
  1234. Raster.Create(image, width, height, Raster.BGRA8888);
  1235. NEW(canvas, image);
  1236. DrawIntoCanvas(window, canvas, width, height, ignore, ignore);
  1237. RETURN image;
  1238. END GetWindowImage;
  1239. PROCEDURE GenerateName(prefix: Strings.String; VAR str: ARRAY OF CHAR);
  1240. VAR i,j:LONGINT; num: ARRAY 32 OF CHAR; title: Files.FileName; c:CHAR;
  1241. BEGIN
  1242. i:=0; j:=0;
  1243. IF prefix#NIL THEN
  1244. WHILE (i<LEN(prefix)) & (j<LEN(title)-1) DO
  1245. c:=prefix[i];
  1246. IF (c>="A")&(c<="Z") OR (c>="a")&(c<="z") OR(c>="0")&(c<="9") OR (c="_") OR (c=" ")THEN
  1247. IF c=" " THEN c:="_" END;
  1248. title[j]:=c; INC(i); INC(j);
  1249. ELSE
  1250. INC(i);
  1251. END;
  1252. END;
  1253. title[j]:=0X;
  1254. IF title="" THEN title:="ScreenShot" END;
  1255. ELSE title:="ScreenShot"
  1256. END;
  1257. COPY(title, str);
  1258. END GenerateName;
  1259. PROCEDURE WindowShot(window: WMWindowManager.Window; scale:REAL);
  1260. VAR str,fn: Files.FileName; w,h, res: LONGINT; startTime: Dates.DateTime;
  1261. img:WMGraphics.Image;
  1262. BEGIN
  1263. GenerateName(window.GetTitle(),fn);
  1264. IF fn="" THEN COPY("WindowShot",fn) END;
  1265. Strings.FormatDateTime("_yyyymmdd__hhnnss",Dates.Now(),str);
  1266. Strings.Concat(fn,str,fn);
  1267. Strings.Append(fn,".bmp");
  1268. (* TBD: scaled storing not yet implemented *)
  1269. IF window IS WMWindowManager.DoubleBufferWindow THEN
  1270. WMGraphics.StoreImage(window(WMWindowManager.DoubleBufferWindow).backImg, fn, res);
  1271. ELSIF window IS WMWindowManager.BufferWindow THEN
  1272. WMGraphics.StoreImage(window(WMWindowManager.BufferWindow).img, fn, res);
  1273. ELSE
  1274. NEW(img); Raster.Create(img, window.GetWidth(), window.GetHeight(),Raster.BGRA8888);
  1275. window.Draw(WMGraphics.GenCanvas(img), window.GetWidth(), window.GetHeight(), 0);
  1276. WMGraphics.StoreImage(img, fn, res);
  1277. END;
  1278. IF res=0 THEN
  1279. KernelLog.String("stored window shot as "); KernelLog.String(fn); KernelLog.Ln;
  1280. END;
  1281. END WindowShot;
  1282. PROCEDURE StoreWindow(window: WMWindowManager.Window); (*! o do: move this to WMComponents.Mod, or use WMRestorable.Mod *)
  1283. VAR fn0,fn: Files.FileName; s: ARRAY 6 OF CHAR; i, res: LONGINT; f:Files.File; w:Files.Writer;
  1284. xml:XML.Content; msg: WMMessages.Message;
  1285. BEGIN
  1286. IF (WMWindowManager.FlagStorable IN window.flags) THEN
  1287. GenerateName(window.GetTitle(),fn0);
  1288. IF window IS WMComponents.FormWindow THEN
  1289. Strings.Concat(fn0,".Cwd",fn); (* component window *)
  1290. f:=Files.Old(fn);
  1291. i:=0;
  1292. WHILE f#NIL DO
  1293. f:=NIL;
  1294. Strings.IntToStr(i,s);
  1295. COPY (fn0,fn);
  1296. Strings.Append(fn,"_");
  1297. Strings.Append(fn,s);
  1298. Strings.Append(fn,".Cwd");
  1299. f:=Files.Old(fn);
  1300. INC(i);
  1301. END;
  1302. (*? WMRestorable.StoreWindow*(window: WM.Window; CONST fileName: ARRAY OF CHAR);*)
  1303. f:=Files.New(fn);
  1304. IF f#NIL THEN
  1305. Files.OpenWriter(w,f,0);
  1306. w.String('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'); w.Ln;
  1307. window(WMComponents.FormWindow).ToXML().Write(w,NIL,0);
  1308. w.Update;
  1309. Files.Register(f);
  1310. KernelLog.String("WMNavigate.StoreWindow "); KernelLog.String(fn); KernelLog.Ln;
  1311. END;
  1312. ELSE (* try to serialize by sending a message*)
  1313. msg.msgType := WMMessages.MsgSerialize;
  1314. msg.msgSubType := WMMessages.MsgSubSerializeComponent;
  1315. window.Handle(msg);
  1316. (* IF (window.manager#NIL) & window.manager.SendMessage(window, msg) THEN END;*)
  1317. END;
  1318. END;
  1319. END StoreWindow;
  1320. PROCEDURE DrawIntoCanvas(window : WMWindowManager.Window; canvas : WMGraphics.BufferCanvas; width, height : LONGINT; VAR offsetX, offsetY : LONGINT);
  1321. VAR image : Raster.Image; winWidth, winHeight, imgWidth, imgHeight : LONGINT; scaleX, scaleY : REAL;
  1322. BEGIN (* must hold window manager lock *)
  1323. ASSERT((window # NIL) & (canvas # NIL));
  1324. image := canvas.GetImage();
  1325. canvas.Fill(WMRectangles.MakeRect(0, 0, image.width, image.height), 0, WMGraphics.ModeCopy);
  1326. winWidth := window.GetWidth(); (* TODO: Not threadsafe *)
  1327. winHeight := window.GetHeight();
  1328. scaleX := width / winWidth;
  1329. scaleY := height / winHeight;
  1330. IF (scaleX <= scaleY) THEN
  1331. imgWidth := width;
  1332. imgHeight := ENTIER(winHeight * scaleX);
  1333. offsetX := 0;
  1334. offsetY := height - imgHeight;
  1335. ELSE
  1336. imgWidth := ENTIER(winWidth * scaleY);
  1337. imgHeight := height;
  1338. offsetX := (width - imgWidth) DIV 2;
  1339. offsetY := 0;
  1340. END;
  1341. window.Draw(canvas, imgWidth, imgHeight, WMGraphics.ScaleBilinear);
  1342. END DrawIntoCanvas;
  1343. PROCEDURE Clear(VAR windows : Windows);
  1344. VAR i : LONGINT;
  1345. BEGIN
  1346. FOR i := 0 TO LEN(windows)-1 DO
  1347. windows[i] := NIL;
  1348. END;
  1349. END Clear;
  1350. PROCEDURE GetFocusOwnerIndex(CONST windows : Windows; nofWindows : LONGINT) : LONGINT; (* private *)
  1351. VAR index : LONGINT; focusOwner : WMWindowManager.Window;
  1352. BEGIN
  1353. focusOwner := manager.GetFocusOwner();
  1354. index := 0;
  1355. WHILE (index < nofWindows) & (windows[index] # focusOwner) DO INC(index); END;
  1356. IF (index >= LEN(windows)) THEN
  1357. index := -1;
  1358. END;
  1359. RETURN index;
  1360. END GetFocusOwnerIndex;
  1361. (** Postcondition: {(windows # NIL) & (0 <= nofWindows < MaxNofWindows) & (windows[i < nofWindows] # NIL)} *)
  1362. PROCEDURE GetWindows(VAR windows : Windows; VAR nofWindows : LONGINT);
  1363. VAR
  1364. window : WMWindowManager.Window;
  1365. PROCEDURE IsUserWindow(window : WMWindowManager.Window) : BOOLEAN;
  1366. BEGIN
  1367. ASSERT(window # NIL);
  1368. RETURN {WMWindowManager.FlagHidden, WMWindowManager.FlagDecorWindow} * window.flags = {};
  1369. END IsUserWindow;
  1370. PROCEDURE SortWindowsById(VAR windows : Windows);
  1371. VAR temp : WMWindowManager.Window; i, j : LONGINT;
  1372. BEGIN
  1373. (* for now bubble sort is sufficient *)
  1374. FOR i := 0 TO nofWindows-1 DO
  1375. FOR j := 0 TO nofWindows-2 DO
  1376. IF (windows[j].id > windows[j+1].id) THEN
  1377. temp := windows[j+1];
  1378. windows[j+1] := windows[j];
  1379. windows[j] := temp;
  1380. END;
  1381. END;
  1382. END;
  1383. END SortWindowsById;
  1384. BEGIN
  1385. ASSERT((manager # NIL));
  1386. (* clear all references *)
  1387. Clear(windows);
  1388. manager.lock.AcquireWrite;
  1389. nofWindows := 0;
  1390. window := manager.GetFirst();
  1391. WHILE (window # NIL) & (nofWindows < MaxNofWindows) DO
  1392. IF IsUserWindow(window) THEN
  1393. windows[nofWindows] := window;
  1394. INC(nofWindows);
  1395. END;
  1396. window := manager.GetNext(window);
  1397. END;
  1398. manager.lock.ReleaseWrite;
  1399. IF (nofWindows > 1) THEN SortWindowsById(windows); END;
  1400. END GetWindows;
  1401. PROCEDURE Open*(context : Commands.Context); (** [Options] id x y componentFile ~ *)
  1402. VAR
  1403. options : Options.Options;
  1404. id, x, y, w, h : LONGINT;
  1405. filename : ARRAY 256 OF CHAR;
  1406. content : XML.Content;
  1407. flags : SET;
  1408. BEGIN {EXCLUSIVE}
  1409. NEW(options);
  1410. options.Add("f", "frame", Options.Flag);
  1411. options.Add("s", "stayOnTop", Options.Flag);
  1412. options.Add("v", "viewport", Options.Flag);
  1413. options.Add("n", "names", Options.Flag);
  1414. IF options.Parse(context.arg, context.out) THEN
  1415. showWindowNames := options.GetFlag("names");
  1416. context.arg.SkipWhitespace; context.arg.Int(id, FALSE);
  1417. context.arg.SkipWhitespace; context.arg.Int(x, FALSE);
  1418. context.arg.SkipWhitespace; context.arg.Int(y, FALSE);
  1419. context.arg.SkipWhitespace; context.arg.String(filename);
  1420. IF (filename # "") THEN
  1421. IF (0 <= id) & (id < MaxNavigationWindows) THEN
  1422. IF (windows[id] = NIL) THEN
  1423. content := WMComponents.GetComponent(filename);
  1424. IF (content # NIL) THEN
  1425. IF (content IS WMComponents.VisualComponent) THEN
  1426. w := content(WMComponents.VisualComponent).bounds.GetWidth();
  1427. h := content(WMComponents.VisualComponent).bounds.GetHeight();
  1428. IF (w <= 0) THEN w := width; END;
  1429. IF (h <= 0) THEN h := height; END;
  1430. flags := {WMWindowManager.FlagHidden};
  1431. IF options.GetFlag("frame") THEN INCL(flags, WMWindowManager.FlagFrame); END;
  1432. IF options.GetFlag("stayOnTop") THEN INCL(flags, WMWindowManager.FlagStayOnTop); END;
  1433. IF options.GetFlag("viewport") THEN INCL(flags, WMWindowManager.FlagNavigation); END;
  1434. NEW(windows[id], id, content(WMComponents.VisualComponent), x, y, w, h, TRUE, flags);
  1435. WMWindowManager.IncWTimestamp;
  1436. windows[id].CSChanged;
  1437. ELSE
  1438. context.out.String("WMNavigate: Expected visual component"); context.out.Ln;
  1439. END;
  1440. ELSE
  1441. context.out.String("WMNavigate: Could not load component from file ");
  1442. context.out.String(filename); context.out.Ln;
  1443. END;
  1444. ELSE
  1445. context.out.String("WMNavigate: Window with id already open"); context.out.Ln;
  1446. END;
  1447. ELSE
  1448. context.out.String("WMNavigate: Invalid id parameter"); context.out.Ln;
  1449. END;
  1450. ELSE
  1451. context.out.String("WMNavigate.Open id x y width height componentFile ~"); context.out.Ln;
  1452. END;
  1453. END;
  1454. END Open;
  1455. PROCEDURE Close*(context : Commands.Context); (** id ~ *)
  1456. VAR id : LONGINT;
  1457. BEGIN {EXCLUSIVE}
  1458. IF context.arg.GetInteger(id, FALSE) & (0 <= id) & (id < MaxNavigationWindows) THEN
  1459. IF (windows[id] # NIL) THEN
  1460. windows[id].Close;
  1461. windows[id] := NIL;
  1462. ELSE
  1463. context.out.String("WMNavigate: Window with id is not open"); context.out.Ln;
  1464. END;
  1465. ELSE
  1466. context.out.String("WMNavigate: Invalid id parameter"); context.out.Ln;
  1467. END;
  1468. END Close;
  1469. PROCEDURE ToggleVisibility*(context : Commands.Context); (** id ~ *)
  1470. VAR id : LONGINT;
  1471. BEGIN {EXCLUSIVE}
  1472. IF context.arg.GetInteger(id, FALSE) & (0 <= id) & (id < MaxNavigationWindows) THEN
  1473. IF (windows[id] # NIL) THEN
  1474. manager.SetIsVisible(windows[id], ~windows[id].isVisible);
  1475. ELSE
  1476. context.out.String("WMNavigate: Window with id is not open"); context.out.Ln;
  1477. END;
  1478. ELSE
  1479. context.out.String("WMNavigate: Invalid id parameter"); context.out.Ln;
  1480. END;
  1481. END ToggleVisibility;
  1482. PROCEDURE HideNavigation*;
  1483. BEGIN {EXCLUSIVE}
  1484. SetIsVisibleNavigation(FALSE);
  1485. navigationIsHidden := TRUE;
  1486. END HideNavigation;
  1487. PROCEDURE RestoreNavigation*;
  1488. BEGIN {EXCLUSIVE}
  1489. SetIsVisibleNavigation(TRUE);
  1490. navigationIsHidden := FALSE;
  1491. END RestoreNavigation;
  1492. PROCEDURE ToggleNavigation*;
  1493. BEGIN {EXCLUSIVE}
  1494. navigationIsHidden := ~navigationIsHidden;
  1495. SetIsVisibleNavigation(~navigationIsHidden);
  1496. END ToggleNavigation;
  1497. PROCEDURE SetIsVisibleNavigation(isVisible : BOOLEAN);
  1498. VAR window : WMWindowManager.Window;
  1499. BEGIN
  1500. manager.lock.AcquireWrite;
  1501. window := manager.GetFirst();
  1502. WHILE (window # NIL) DO
  1503. IF (WMWindowManager.FlagNavigation IN window.flags) THEN
  1504. manager.SetIsVisible(window, isVisible);
  1505. END;
  1506. window := manager.GetNext(window);
  1507. END;
  1508. manager.lock.ReleaseWrite;
  1509. END SetIsVisibleNavigation;
  1510. PROCEDURE FocusToNext*;
  1511. BEGIN
  1512. SwitchFocus(FALSE);
  1513. END FocusToNext;
  1514. PROCEDURE FocusToPrevious*;
  1515. BEGIN
  1516. SwitchFocus(TRUE);
  1517. END FocusToPrevious;
  1518. PROCEDURE SwitchFocus(backwards : BOOLEAN);
  1519. VAR windows : Windows; nofWindows, focusIdx : LONGINT;
  1520. BEGIN {EXCLUSIVE}
  1521. GetWindows(windows, nofWindows);
  1522. IF (nofWindows >= 1) THEN
  1523. focusIdx := GetFocusOwnerIndex(windows, nofWindows);
  1524. IF (focusIdx >= 0) THEN
  1525. IF (nofWindows > 1) THEN
  1526. IF backwards THEN
  1527. IF focusIdx > 0 THEN
  1528. DEC(focusIdx);
  1529. ELSE
  1530. focusIdx := nofWindows - 1;
  1531. END;
  1532. ELSE
  1533. focusIdx := (focusIdx + 1) MOD nofWindows;
  1534. END;
  1535. END;
  1536. ELSE
  1537. focusIdx := 0; (* set focus to first user window *)
  1538. END;
  1539. IF (windows[focusIdx] = NIL) THEN RETURN (* can happen when no window has the focus initially *) END;
  1540. ASSERT((0 <= focusIdx) & (focusIdx < LEN(windows)));
  1541. manager.lock.AcquireWrite;
  1542. manager.ToFront(windows[focusIdx]);
  1543. manager.SetFocus(windows[focusIdx]);
  1544. manager.lock.ReleaseWrite;
  1545. END;
  1546. END SwitchFocus;
  1547. PROCEDURE HideAll*;
  1548. BEGIN {EXCLUSIVE}
  1549. SetIsVisible(FALSE);
  1550. windowsAreHidden := TRUE;
  1551. END HideAll;
  1552. PROCEDURE RestoreAll*;
  1553. BEGIN {EXCLUSIVE}
  1554. SetIsVisible(TRUE);
  1555. windowsAreHidden := FALSE;
  1556. END RestoreAll;
  1557. PROCEDURE ToggleAll*;
  1558. BEGIN {EXCLUSIVE}
  1559. windowsAreHidden := ~windowsAreHidden;
  1560. SetIsVisible(~windowsAreHidden);
  1561. END ToggleAll;
  1562. PROCEDURE SetIsVisible(isVisible : BOOLEAN);
  1563. VAR windows : Windows; nofWindows, i : LONGINT;
  1564. BEGIN
  1565. GetWindows(windows, nofWindows);
  1566. manager.lock.AcquireWrite;
  1567. FOR i := 0 TO nofWindows-1 DO
  1568. manager.SetIsVisible(windows[i], isVisible);
  1569. END;
  1570. manager.lock.ReleaseWrite;
  1571. END SetIsVisible;
  1572. (** Toggle minimized/fullscreen for the window that currently owns the focus *)
  1573. PROCEDURE ToggleFullscreen*;
  1574. VAR window : WMWindowManager.Window; newWidth, newHeight : LONGINT;
  1575. BEGIN {EXCLUSIVE}
  1576. manager.lock.AcquireWrite;
  1577. window := manager.GetFocusOwner();
  1578. IF (window # NIL) & (window.flags * {WMWindowManager.FlagNavigation, WMWindowManager.FlagHidden, WMWindowManager.FlagNoResizing} = {}) THEN
  1579. IF (window.GetWidth() = width) & (window.GetHeight() = height) THEN
  1580. manager.SetWindowPos(window, window.normalBounds.l, window.normalBounds.t);
  1581. newWidth := window.normalBounds.r - window.normalBounds.l;
  1582. newHeight := window.normalBounds.b - window.normalBounds.t;
  1583. SetIsVisibleNavigation(~navigationIsHidden);
  1584. ELSE
  1585. window.normalBounds := window.bounds;
  1586. manager.SetWindowPos(window, ENTIER(viewport.range.l), ENTIER(viewport.range.t));
  1587. newWidth := width;
  1588. newHeight := height;
  1589. SetIsVisibleNavigation(FALSE);
  1590. END;
  1591. manager.SetWindowSize(window, newWidth, newHeight);
  1592. (* potentially another thread has the sequencer lock of this window and might require the manager lock. Lock order: never take manager lock before sequencer lock *)
  1593. manager.lock.ReleaseWrite;
  1594. window.Resized(newWidth, newHeight);
  1595. ELSE
  1596. manager.lock.ReleaseWrite;
  1597. END;
  1598. END ToggleFullscreen;
  1599. PROCEDURE MoveWindow*(context : Commands.Context);
  1600. VAR options : Options.Options; window : WMWindowManager.Window; x, y : LONGINT;
  1601. BEGIN {EXCLUSIVE}
  1602. NEW(options);
  1603. options.Add("d", "display", Options.Flag);
  1604. IF options.Parse(context.arg, context.out) THEN
  1605. IF context.arg.GetInteger(x, FALSE) & context.arg.GetInteger(y, FALSE) THEN
  1606. IF options.GetFlag("display") THEN
  1607. x := x * width;
  1608. y := y * height;
  1609. END;
  1610. window := manager.GetFocusOwner();
  1611. IF (window IS WMComponents.FormWindow) THEN
  1612. manager.SetWindowPos(window, window.bounds.l + x, window.bounds.t + y);
  1613. END;
  1614. END;
  1615. END;
  1616. END MoveWindow;
  1617. (** Close the window that currently owns the focus *)
  1618. PROCEDURE CloseWindow*;
  1619. VAR window : WMWindowManager.Window; formWindow : WMComponents.FormWindow;
  1620. BEGIN {EXCLUSIVE}
  1621. window := manager.GetFocusOwner();
  1622. IF window IS WMComponents.FormWindow THEN
  1623. formWindow := window (WMComponents.FormWindow);
  1624. formWindow.Close;
  1625. END;
  1626. END CloseWindow;
  1627. (**
  1628. * Set the range of the default view port. Can be used for virtual desktops.
  1629. * Parameters:
  1630. * x, y : Position of viewport ovservable range (pixel)
  1631. * w, h : width and height of viewport observable range (pixel, set to display width/height if omitted)
  1632. * "s" : show transition to new range
  1633. * "d": interpret x, y, w and h parameters as multiples of display width/height
  1634. *)
  1635. PROCEDURE SetViewportRange*(context : Commands.Context); (** [options] [x y [w h]] ~ *)
  1636. VAR options : Options.Options; x, y, w, h : LONGINT;
  1637. BEGIN
  1638. NEW(options);
  1639. options.Add("s", "showTransition", Options.Flag);
  1640. options.Add("d", "display", Options.Flag);
  1641. IF options.Parse(context.arg, context.out) THEN
  1642. x := 0; y := 0; w := 0; h := 0;
  1643. context.arg.SkipWhitespace; context.arg.Int(x, FALSE);
  1644. context.arg.SkipWhitespace; context.arg.Int(y, FALSE);
  1645. context.arg.SkipWhitespace; context.arg.Int(w, FALSE);
  1646. context.arg.SkipWhitespace; context.arg.Int(h, FALSE);
  1647. IF options.GetFlag("display") THEN
  1648. x := x * width; w := w * width;
  1649. y := y * height; h := h * height;
  1650. END;
  1651. IF w = 0 THEN w := width; END;
  1652. IF h = 0 THEN h := height; END;
  1653. viewport.SetRange(x, y, w, h, options.GetFlag("showTransition"));
  1654. END;
  1655. END SetViewportRange;
  1656. PROCEDURE GenTaskList*() : XML.Element;
  1657. VAR t : TaskList;
  1658. BEGIN
  1659. NEW(t); RETURN t;
  1660. END GenTaskList;
  1661. PROCEDURE GenOverview*() : XML.Element;
  1662. VAR o : WindowOverview;
  1663. BEGIN
  1664. NEW(o); RETURN o;
  1665. END GenOverview;
  1666. PROCEDURE InitStrings;
  1667. BEGIN
  1668. StrWindowOverview := Strings.NewString("WindowOverview");
  1669. StrTaskList := Strings.NewString("TaskList");
  1670. StrNoName := Strings.NewString("NoName");
  1671. StrBase := Strings.NewString("Base");
  1672. StrOverview:=Strings.NewString("Overview");
  1673. END InitStrings;
  1674. PROCEDURE InitProtos;
  1675. BEGIN
  1676. NEW(ProtoClDefault, NIL, Strings.NewString("ClDefault"), Strings.NewString("Default color of item"));
  1677. ProtoClDefault.Set(0A0A0A0A0H);
  1678. NEW(ProtoClSelected, NIL, Strings.NewString("ClSelected"), Strings.NewString("Color of selected item"));
  1679. ProtoClSelected.Set(060606A0H);
  1680. NEW(ProtoClMouseOver, NIL, Strings.NewString("ClMouseOver"), Strings.NewString("Mouse over color of item"));
  1681. ProtoClMouseOver.Set(0D0D0D0A0H);
  1682. NEW(ProtoClSelectedMouseOver, NIL, Strings.NewString("ClSelectedMouseOver"), Strings.NewString("Mouse over color of selected item"));
  1683. ProtoClSelectedMouseOver.Set(0F0F0F0A0H);
  1684. NEW(ProtoClTextDefault, NIL, Strings.NewString("ClTextDefault"), Strings.NewString("Default text color"));
  1685. ProtoClTextDefault.Set(WMGraphics.White);
  1686. NEW(ProtoClTextSelected, NIL, Strings.NewString("ClTextSelected"), Strings.NewString("Text color of selected item"));
  1687. ProtoClTextSelected.Set(WMGraphics.White);
  1688. NEW(ProtoClTextMouseOver, NIL, Strings.NewString("ClTextMouseOver"), Strings.NewString("Text color of mouse over item"));
  1689. ProtoClTextMouseOver.Set(WMGraphics.White);
  1690. NEW(ProtoClTextSelectedMouseOver, NIL, Strings.NewString("ClTextSelectedMouseOver"), Strings.NewString("Text color of selected mouse over item"));
  1691. ProtoClTextSelectedMouseOver.Set(WMGraphics.White);
  1692. NEW(ProtoClIndicateHidden, NIL, Strings.NewString("ClIndicateHidden"), Strings.NewString("Color used to indicate hidden windows"));
  1693. ProtoClIndicateHidden.Set(WMGraphics.Yellow);
  1694. NEW(ProtoBorderWidth, NIL, Strings.NewString("BorderWidth"), Strings.NewString("Width of border"));
  1695. ProtoBorderWidth.Set(2);
  1696. NEW(ProtoTaskListStyle, NIL, Strings.NewString("Style"), Strings.NewString("Style of task representation"));
  1697. ProtoTaskListStyle.Set(Icons);
  1698. NEW(ProtoTaskListMenuLocation, NIL, Strings.NewString("MenuLocation"), Strings.NewString("Location of submenu relative to task list"));
  1699. ProtoTaskListMenuLocation.Set(Bottom);
  1700. NEW(ProtoTaskListShowThumbnails, NIL, Strings.NewString("ShowThumbnails"), Strings.NewString("Show window thumbnails?"));
  1701. ProtoTaskListShowThumbnails.Set(TRUE);
  1702. NEW(ProtoTaskListShowNames, NIL, Strings.NewString("ShowNames"), Strings.NewString("Show window names?"));
  1703. ProtoTaskListShowNames.Set(TRUE);
  1704. NEW(ProtoItemWidth, NIL, Strings.NewString("ItemWidth"), Strings.NewString("Width of task list item"));
  1705. NEW(ProtoItemHeight, NIL, Strings.NewString("ItemHeight"), Strings.NewString("Height of task list item"));
  1706. NEW(ProtoLayoutMode, NIL, Strings.NewString("LayoutMode"), Strings.NewString("Item layouting mode"));
  1707. END InitProtos;
  1708. PROCEDURE Init;
  1709. VAR plugin : Plugins.Plugin;
  1710. BEGIN
  1711. manager := WMWindowManager.GetDefaultManager();
  1712. viewport := WMWindowManager.GetDefaultView();
  1713. plugin := Displays.registry.Get("");
  1714. IF plugin # NIL THEN
  1715. width := plugin(Displays.Display).width;
  1716. height := plugin(Displays.Display).height;
  1717. ELSE
  1718. width := 1024;
  1719. height := 768;
  1720. END;
  1721. END Init;
  1722. PROCEDURE Cleanup;
  1723. VAR i : LONGINT;
  1724. BEGIN {EXCLUSIVE}
  1725. FOR i := 0 TO LEN(windows)-1 DO
  1726. IF (windows[i] # NIL) THEN windows[i].Close; END;
  1727. END;
  1728. END Cleanup;
  1729. BEGIN
  1730. Modules.InstallTermHandler(Cleanup);
  1731. Init;
  1732. InitStrings;
  1733. InitProtos;
  1734. windowsAreHidden := FALSE;
  1735. navigationIsHidden := FALSE;
  1736. windowShotScale:=1.0;
  1737. ASSERT(manager # NIL);
  1738. END WMNavigate.
  1739. WMNavigate.SetViewportRange 0 0 ~
  1740. WMNavigate.SetViewportRange "-1" 0 1 1 sd ~
  1741. WMNavigate.MoveWindow -1280 ~
  1742. Example: Four virtual desktops with overview, depended on display resolution
  1743. WMNavigate.SetViewportRange -sd -1 0 1 1 ~ (* left desktop *)
  1744. WMNavigate.SetViewportRange -sd 0 0 1 1 ~ (* standard desktop *)
  1745. WMNavigate.SetViewportRange -sd -1 -1 1 1 ~ (* left/up desktop *)
  1746. WMNavigate.SetViewportRange -sd 0 -1 1 1 ~ (* up desktop *)
  1747. WMNavigate.SetViewportRange -sd -1 -1 2 2 ~ (* all four desktops *)
  1748. WMNavigate.Open -vs 1 0 0 Navigation:TaskList ~
  1749. WMNavigate.Open -vs 2 20 600 Navigation:TaskList ~
  1750. WMNavigate.Open -fs 6 20 20 Navigation:WindowList ~
  1751. WMNavigate.Close 1 ~
  1752. WMNavigate.ToggleVisibility 1 ~
  1753. WMNavigate.HideNavigation ~
  1754. WMNavigate.RestoreNavigation ~
  1755. WMNavigate.ToggleNavigation ~
  1756. SystemTools.Free WMNavigate ~