WMNavigate.Mod 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974
  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. PROCEDURE &Init;
  523. BEGIN
  524. Init^;
  525. SetNameAsString(StrTaskList);
  526. SetGenerator("WMNavigate.GenTaskList");
  527. NEW(style, ProtoTaskListStyle, NIL, NIL); properties.Add(style);
  528. NEW(menuLocation, ProtoTaskListMenuLocation, NIL, NIL); properties.Add(menuLocation);
  529. NEW(showThumbnails, ProtoTaskListShowThumbnails, NIL, NIL); properties.Add(showThumbnails);
  530. NEW(showNames, ProtoTaskListShowNames, NIL, NIL); showNames.Set(showWindowNames); properties.Add(showNames);
  531. CASE style.Get() OF
  532. | Text:
  533. itemWidth.Set(150); itemHeight.Set(20);
  534. layoutMode.Set(ScaleUp);
  535. | Icons:
  536. itemWidth.Set(40); itemHeight.Set(50);
  537. layoutMode.Set(Default); (*was Fixed*)
  538. ELSE
  539. itemWidth.Set(100); itemHeight.Set(50);
  540. END;
  541. viewport := WMWindowManager.GetDefaultView();
  542. WMWindowManager.ClearInfo(dummyInfo);
  543. lastKeys := {};
  544. lastWindow := NIL;
  545. END Init;
  546. PROCEDURE PropertyChanged(sender, data : ANY);
  547. BEGIN
  548. PropertyChanged^(sender, data);
  549. IF (data = menuLocation) THEN
  550. Invalidate;
  551. ELSIF (data = bounds) OR (data = style) THEN
  552. lock.Acquire;
  553. layout.Compute(info.nofWindows, bounds.GetWidth(), bounds.GetHeight(), itemWidth.Get(), itemHeight.Get(), layoutMode.Get());
  554. lock.Release;
  555. Invalidate;
  556. END;
  557. END PropertyChanged;
  558. PROCEDURE GoToWindow(window : WMWindowManager.Window; moveViewport : BOOLEAN);
  559. VAR rect : WMRectangles.Rectangle; px, py : LONGINT;
  560. BEGIN
  561. ASSERT(window # NIL);
  562. manager.lock.AcquireWrite;
  563. manager.SetIsVisible(window, TRUE);
  564. manager.SetFocus(window);
  565. manager.ToFront(window);
  566. IF (viewport # NIL) THEN
  567. rect := WMRectangles.MakeRect(ENTIER(viewport.range.l), ENTIER(viewport.range.t), ENTIER(viewport.range.r), ENTIER(viewport.range.b));
  568. IF ~WMRectangles.IsContained(rect, window.bounds) THEN
  569. IF (window.bounds.l < viewport.range.l) OR (window.bounds.t < viewport.range.t) OR
  570. ~WMRectangles.Intersect(rect, window.bounds)
  571. THEN
  572. IF (moveViewport) THEN (* re-position the viewport *)
  573. IF window.GetWidth() < (viewport.range.r - viewport.range.l) THEN
  574. px := window.bounds.l - ENTIER((viewport.range.r - viewport.range.l - window.GetWidth()) / 2);
  575. ELSE
  576. px := window.bounds.l - 20;
  577. END;
  578. IF window.GetHeight() < (viewport.range.b - viewport.range.t) THEN
  579. py := window.bounds.t - ENTIER((viewport.range.b - viewport.range.t - window.GetHeight()) / 2);
  580. ELSE
  581. py := window.bounds.t - 20;
  582. END;
  583. viewport.SetRange(px, py, viewport.range.r - viewport.range.l, viewport.range.b - viewport.range.t, TRUE);
  584. ELSE (* re-position the window *)
  585. IF window.GetWidth() < (viewport.range.r - viewport.range.l) THEN
  586. px := ENTIER(viewport.range.l + (viewport.range.r - viewport.range.l - window.GetWidth()) / 2);
  587. ELSE
  588. px := ENTIER(viewport.range.l) + 20;
  589. END;
  590. IF window.GetHeight() < (viewport.range.b - viewport.range.t) THEN
  591. py := ENTIER(viewport.range.t + (viewport.range.b - viewport.range.t - window.GetHeight()) / 2);
  592. ELSE
  593. py := ENTIER(viewport.range.t) + 20;
  594. END;
  595. manager.SetWindowPos(window, px, py);
  596. END;
  597. END;
  598. END;
  599. END;
  600. manager.lock.ReleaseWrite;
  601. END GoToWindow;
  602. PROCEDURE FocusLost;
  603. BEGIN
  604. FocusLost^;
  605. lastKeys := {};
  606. END FocusLost;
  607. PROCEDURE PointerDown(x, y:LONGINT; keys:SET);
  608. VAR
  609. index : LONGINT; window : WMWindowManager.Window;
  610. info2 : WMWindowManager.WindowInfo;
  611. gx, gy: LONGINT;
  612. menu : MenuWindow;
  613. type, index2 : LONGINT;
  614. infoKeys : SET;
  615. res : LONGINT;
  616. rect : WMRectangles.Rectangle;
  617. closeWindow : DoCloseWindow;
  618. same: BOOLEAN;
  619. BEGIN
  620. IF ~enabled.Get() THEN RETURN; END;
  621. lastKeys := keys;
  622. IF (keys * {0, 1, 2} # {}) THEN
  623. window := NIL;
  624. lock.Acquire;
  625. index := layout.GetIndexOf(x, y);
  626. IF (index >= 0) & (index < info.nofWindows) THEN
  627. window := info.windows[index];
  628. rect := layout.GetPositionOf(x, y);
  629. END;
  630. lock.Release;
  631. IF (window # NIL) THEN
  632. same := lastWindow = window;
  633. IF 0 IN keys THEN lastWindow := window; ELSE lastWindow := NIL; END;
  634. IF keys * {0,1} # {} THEN
  635. IF same & window.isVisible THEN
  636. manager.SetIsVisible(window, FALSE);
  637. ELSE
  638. GoToWindow(window, 0 IN keys);
  639. END;
  640. ELSIF keys * {2} # {} THEN
  641. IF (menuLocation.Get() = Top) THEN
  642. ToWMCoordinates(rect.l, rect.t + ShadowWidth, gx, gy);
  643. ELSE
  644. ToWMCoordinates(rect.l, rect.b, gx, gy);
  645. END;
  646. IF window.GetInfo(info2) THEN
  647. NEW(menu, gx, gy, 200, menuLocation.Get(), showThumbnails.Get(), window, info2);
  648. ELSE
  649. NEW(menu, gx, gy, 200, menuLocation.Get(), showThumbnails.Get(), window, dummyInfo);
  650. END;
  651. menu.GetSelection(type, index2, infoKeys);
  652. IF ~(2 IN infoKeys) THEN
  653. IF (type = Document) THEN
  654. IF (info2.handleDocumentInfo # NIL) THEN
  655. info2.handleDocumentInfo(info2.openDocuments[index2], FALSE, res);
  656. END;
  657. GoToWindow(window, 0 IN infoKeys);
  658. ELSIF (type = SystemCommand) THEN
  659. IF (index2 = SystemCommand_Close) THEN
  660. NEW(closeWindow, window);
  661. ELSIF (index2 = SystemCommand_Hide) THEN
  662. manager.SetIsVisible(window, ~window.isVisible);
  663. ELSIF (index2 = SystemCommand_StayOnTop) THEN
  664. manager.SetWindowFlag(window, WMWindowManager.FlagStayOnTop, ~(WMWindowManager.FlagStayOnTop IN window.flags));
  665. ELSIF (index2 = SystemCommand_StayOnBottom) THEN
  666. manager.SetWindowFlag(window, WMWindowManager.FlagStayOnBottom, ~(WMWindowManager.FlagStayOnBottom IN window.flags));
  667. ELSIF (index2 = SystemCommand_WindowShot) THEN
  668. WindowShot(window, windowShotScale);
  669. ELSIF (index2 = SystemCommand_StoreWindow) THEN
  670. StoreWindow(window);
  671. ELSIF (index2 = SystemCommand_Frame) THEN
  672. manager.SetWindowFlag(window, WMWindowManager.FlagFrame, ~(WMWindowManager.FlagFrame IN window.flags));
  673. END;
  674. END;
  675. END;
  676. END;
  677. ELSE
  678. lastWindow := NIL;
  679. END;
  680. END;
  681. END PointerDown;
  682. PROCEDURE PointerUp(x, y : LONGINT; keys : SET);
  683. VAR window : WMWindowManager.Window; windowCloser : DoCloseWindow; index : LONGINT;
  684. BEGIN
  685. PointerUp^(x, y, keys);
  686. IF ~enabled.Get() THEN RETURN; END;
  687. IF (lastKeys * {0, 2} = {0, 2}) & ((keys = {0}) OR (keys = {2})) THEN
  688. window := NIL;
  689. lock.Acquire;
  690. index := layout.GetIndexOf(x, y);
  691. IF (index >= 0) & (index < info.nofWindows) THEN
  692. window := info.windows[index];
  693. END;
  694. lock.Release;
  695. IF (window # NIL) & (window = lastWindow) THEN
  696. NEW(windowCloser, window);
  697. END;
  698. END;
  699. lastKeys := keys;
  700. END PointerUp;
  701. PROCEDURE DrawInternalIcons(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN; VAR extImage : WMGraphics.Image);
  702. VAR
  703. image : WMGraphics.Image;
  704. imageRect, indicatorRect : WMRectangles.Rectangle;
  705. title : Strings.String;
  706. BEGIN
  707. CASE menuLocation.Get() OF
  708. |Top:
  709. imageRect := WMRectangles.MakeRect(x + Border, y + MenuSize, x + width - Border, y + height - Border);
  710. indicatorRect := WMRectangles.MakeRect(x + Border, y + Border, x + width - Border, y + MenuSize - Border);
  711. |Left:
  712. imageRect := WMRectangles.MakeRect(x + MenuSize, y + Border, x + width - Border, y + height - Border);
  713. indicatorRect := WMRectangles.MakeRect(x + Border, y + Border, x + MenuSize - Border, y + height - Border);
  714. |Right:
  715. imageRect := WMRectangles.MakeRect(x + Border, y + Border, x + width - MenuSize, y + height - Border);
  716. indicatorRect := WMRectangles.MakeRect(x + width - MenuSize + Border, y + Border, x + width - Border, y + height - Border);
  717. |Bottom:
  718. imageRect := WMRectangles.MakeRect(x + Border, y + Border, x + width - Border, y + height - MenuSize);
  719. indicatorRect := WMRectangles.MakeRect(x + Border, y + height - MenuSize + Border, x + width - Border, y + height - Border);
  720. END;
  721. IF (window.icon # NIL) THEN
  722. image := window.icon;
  723. ELSE
  724. IF (extImage = NIL) THEN extImage := GetWindowImage(window, 64, 64); END;
  725. image := extImage;
  726. END;
  727. IF (image # NIL) THEN
  728. canvas.ScaleImage(image,
  729. WMRectangles.MakeRect(0, 0, image.width, image.height),
  730. imageRect,
  731. WMGraphics.ModeSrcOverDst,
  732. WMGraphics.ScaleBilinear
  733. );
  734. IF ~window.isVisible THEN
  735. canvas.Fill(indicatorRect, clIndicateHidden.Get(), WMGraphics.ModeSrcOverDst);
  736. WMGraphicUtilities.ExtRectGlassShade(canvas, indicatorRect, {}, 1, FALSE);
  737. END;
  738. END;
  739. IF (window.icon = NIL) THEN
  740. title := window.GetTitle();
  741. IF (title = NIL) THEN title := StrNoName; END;
  742. IF ~window.isVisible THEN
  743. canvas.SetColor(WMGraphics.Yellow);
  744. ELSIF hasFocus & ~mouseOver THEN
  745. canvas.SetColor(WMGraphics.White);
  746. ELSE
  747. canvas.SetColor(WMGraphics.Black);
  748. END;
  749. canvas.DrawString(x + 4, y + height - 5, title^);
  750. ELSE
  751. IF showNames.Get() & window.isVisible & (window.info#NIL) THEN
  752. canvas.SetColor(WMGraphics.Black);
  753. canvas.DrawString(x+4, y + height-5, window.info.openDocuments[0].name); (* to do: show the ACTIVE window *)
  754. END;
  755. END;
  756. END DrawInternalIcons;
  757. PROCEDURE DrawInternalText(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN);
  758. VAR title : Strings.String;
  759. BEGIN
  760. title := window.GetTitle();
  761. IF (title = NIL) THEN title := StrNoName; END;
  762. IF ~window.isVisible THEN
  763. canvas.SetColor(clIndicateHidden.Get());
  764. ELSIF mouseOver & hasFocus THEN
  765. canvas.SetColor(clTextSelectedMouseOver.Get());
  766. ELSIF mouseOver THEN
  767. canvas.SetColor(clTextMouseOver.Get());
  768. ELSIF hasFocus THEN
  769. canvas.SetColor(clTextSelected.Get());
  770. ELSE
  771. canvas.SetColor(clTextDefault.Get());
  772. END;
  773. canvas.DrawString(x + 4, y + height - 5, title^);
  774. END DrawInternalText;
  775. PROCEDURE DrawInternal(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN; VAR extImage : WMGraphics.Image);
  776. BEGIN
  777. canvas.SetClipRect(WMRectangles.MakeRect(x, y, x + width, y + height));
  778. DrawInternal^(canvas, x, y, width, height, window, hasFocus, mouseOver, extImage);
  779. CASE style.Get() OF
  780. |Text: DrawInternalText(canvas, x, y, width, height, window, hasFocus, mouseOver);
  781. |Icons: DrawInternalIcons(canvas, x, y, width, height, window, hasFocus, mouseOver, extImage);
  782. ELSE
  783. END;
  784. END DrawInternal;
  785. PROCEDURE Finalize;
  786. BEGIN
  787. Finalize^;
  788. state := Terminating;
  789. WMWindowManager.IncOTimestamp; (* unblock active body WMWindowManager.AwaitChange *)
  790. BEGIN {EXCLUSIVE} AWAIT(state = Terminated); END;
  791. END Finalize;
  792. BEGIN {ACTIVE}
  793. LOOP
  794. IF (state # Running) THEN EXIT; END;
  795. WMWindowManager.AwaitChange(info.wTimestamp, info.oTimestamp);
  796. IF (state # Running) THEN EXIT; END;
  797. lock.Acquire;
  798. IF (info.wTimestamp # WMWindowManager.wTimestamp) THEN
  799. info.wTimestamp := WMWindowManager.wTimestamp;
  800. GetWindows(info.windows, info.nofWindows);
  801. IF (info.nofWindows > 0) THEN NEW(info.extImages, info.nofWindows); ELSE info.extImages := NIL; END;
  802. info.focusIdx := GetFocusOwnerIndex(info.windows, info.nofWindows);
  803. layout.Compute(info.nofWindows, bounds.GetWidth(), bounds.GetHeight(), itemWidth.Get(), itemHeight.Get(), layoutMode.Get());
  804. END;
  805. IF (info.oTimestamp # WMWindowManager.oTimestamp) THEN
  806. info.oTimestamp := WMWindowManager.oTimestamp;
  807. info.focusIdx := GetFocusOwnerIndex(info.windows, info.nofWindows);
  808. END;
  809. lock.Release;
  810. Invalidate;
  811. END;
  812. BEGIN {EXCLUSIVE} state := Terminated; END;
  813. END TaskList;
  814. CONST
  815. ShadowWidth = 5;
  816. LineHeight = 20;
  817. LeftBorder = 25;
  818. RightBorder = 5;
  819. NofSystemCommands = 7;
  820. SystemCommand = 99;
  821. SystemCommand_Close = 0;
  822. SystemCommand_Hide = 1;
  823. SystemCommand_StayOnTop = 2;
  824. SystemCommand_StayOnBottom = 3;
  825. SystemCommand_Frame = 4;
  826. SystemCommand_WindowShot = 5;
  827. SystemCommand_StoreWindow = 6;
  828. Document = 1;
  829. TYPE
  830. InfoView = OBJECT(WMComponents.VisualComponent)
  831. VAR
  832. window : WMWindowManager.Window;
  833. info : WMWindowManager.WindowInfo;
  834. nofDocuments: LONGINT;
  835. documentOffset, commandOffset, imageOffset : LONGINT;
  836. owner : MenuWindow;
  837. menuLocation : LONGINT;
  838. showThumbnails : BOOLEAN;
  839. type, index : LONGINT;
  840. keys : SET;
  841. xt, yt : LONGINT;
  842. image : WMGraphics.Image;
  843. imgX, imgY : LONGINT;
  844. imageYes, imageNo : WMGraphics.Image;
  845. PROCEDURE &New(owner : MenuWindow; menuLocation : LONGINT; showThumbnails : BOOLEAN);
  846. BEGIN
  847. ASSERT(owner # NIL);
  848. SELF.owner := owner;
  849. SELF.menuLocation := menuLocation;
  850. SELF.showThumbnails := showThumbnails;
  851. Init; (* no super call since Init does not exist in this scope *)
  852. SetNameAsString(Strings.NewString("InfoView"));
  853. nofDocuments := 0;
  854. keys := {};
  855. xt := -1; yt := -1;
  856. imageYes := WMGraphics.LoadImage("Navigation.rep://Yes.png", TRUE);
  857. imageNo := WMGraphics.LoadImage("Navigation.rep://No.png", TRUE);
  858. END New;
  859. PROCEDURE SetInfo(window : WMWindowManager.Window; CONST info : WMWindowManager.WindowInfo);
  860. VAR
  861. vc : WMComponents.VisualComponent; ptr : ANY; i : LONGINT; aux_canvas : WMGraphics.BufferCanvas;
  862. height, imageWidth, imageHeight : LONGINT;
  863. BEGIN
  864. SELF.window := window;
  865. Acquire;
  866. SELF.info := info;
  867. nofDocuments := 0;
  868. FOR i := 0 TO LEN(info.openDocuments)-1 DO
  869. IF (info.openDocuments[i].name # "") THEN INC(nofDocuments); END;
  870. END;
  871. vc := NIL;
  872. IF (info.vc.generator # NIL) THEN
  873. ptr := info.vc.generator();
  874. IF (ptr # NIL) & (ptr IS WMComponents.VisualComponent) THEN
  875. vc := ptr (WMComponents.VisualComponent);
  876. END;
  877. END;
  878. Release;
  879. height := NofSystemCommands * LineHeight + LineHeight; (* incl. 1 separator line *)
  880. IF (nofDocuments > 0) THEN
  881. height := height + nofDocuments * LineHeight + LineHeight; (* incl. 1 separator line *)
  882. END;
  883. IF (vc # NIL) THEN
  884. vc.alignment.Set(WMComponents.AlignNone);
  885. vc.bounds.SetTop(height);
  886. vc.bounds.SetHeight(info.vc.height);
  887. height := height + ((info.vc.height + LineHeight - 1) DIV LineHeight) * LineHeight + RightBorder;
  888. vc.bounds.SetLeft(LeftBorder);
  889. vc.bounds.SetRight(bounds.GetWidth() - RightBorder);
  890. END;
  891. IF showThumbnails THEN
  892. imageWidth := bounds.GetWidth() - LeftBorder - RightBorder;
  893. imageHeight := ENTIER(3 * imageWidth / 4);
  894. NEW(image);
  895. Raster.Create(image, imageWidth, imageHeight, Raster.BGRA8888);
  896. NEW(aux_canvas, image);
  897. aux_canvas.Fill(WMRectangles.MakeRect(0, 0, imageWidth, imageHeight), WMGraphics.White, WMGraphics.ModeCopy);
  898. DrawIntoCanvas(window, aux_canvas, imageWidth, imageHeight, imgX, imgY);
  899. IF (menuLocation = Top) THEN
  900. imageOffset := RightBorder;
  901. ELSE
  902. imageOffset := height;
  903. END;
  904. height := height + ((imageHeight + LineHeight - 1) DIV LineHeight) * LineHeight + RightBorder;
  905. ELSE
  906. imageWidth := 0; imageHeight := 0;
  907. END;
  908. IF (vc # NIL) THEN
  909. IF (menuLocation = Top) THEN
  910. vc.bounds.SetTop(2*RightBorder + ((imageHeight + LineHeight - 1) DIV LineHeight) * LineHeight);
  911. vc.bounds.SetHeight(info.vc.height);
  912. END;
  913. AddContent(vc);
  914. END;
  915. bounds.SetHeight(height);
  916. IF (menuLocation = Top) THEN
  917. documentOffset := height - (NofSystemCommands + nofDocuments + 1) * LineHeight;
  918. commandOffset := height - NofSystemCommands * LineHeight;
  919. ELSE
  920. commandOffset := 0;
  921. documentOffset := (NofSystemCommands + 1) * LineHeight;
  922. END;
  923. Invalidate;
  924. END SetInfo;
  925. PROCEDURE PointerMove(x, y : LONGINT; keys : SET); (** PROTECTED *)
  926. BEGIN
  927. IF enabled.Get() THEN
  928. xt := x; yt := y;
  929. Invalidate;
  930. ELSE
  931. xt := -1; yt := -1;
  932. END;
  933. PointerMove^(x, y, keys)
  934. END PointerMove;
  935. PROCEDURE PointerLeave;
  936. BEGIN
  937. PointerLeave^;
  938. xt := -1; yt := -1;
  939. Invalidate
  940. END PointerLeave;
  941. PROCEDURE PointerDown(x, y:LONGINT; keys:SET);
  942. BEGIN
  943. IF enabled.Get() THEN
  944. SELF.keys := keys;
  945. type := -1;
  946. index := -1;
  947. IF (commandOffset <= y) & (y < commandOffset + NofSystemCommands * LineHeight) THEN
  948. type := SystemCommand;
  949. IF (y < commandOffset + LineHeight) THEN
  950. index := SystemCommand_Close;
  951. ELSIF (y < commandOffset + 2 * LineHeight) THEN
  952. index := SystemCommand_Hide;
  953. ELSIF (y < commandOffset + 3 * LineHeight) THEN
  954. index := SystemCommand_StayOnTop;
  955. ELSIF (y < commandOffset + 4 * LineHeight) THEN
  956. index := SystemCommand_StayOnBottom;
  957. ELSIF (y < commandOffset + 5 * LineHeight) THEN
  958. index := SystemCommand_Frame;
  959. ELSIF (y < commandOffset + 6 * LineHeight) THEN
  960. index := SystemCommand_WindowShot;
  961. ELSIF (WMWindowManager.FlagStorable IN window.flags) & (y < commandOffset + 7 * LineHeight) THEN
  962. index := SystemCommand_StoreWindow;
  963. END;
  964. ELSIF (documentOffset <= y) & (y < documentOffset + nofDocuments * LineHeight) THEN
  965. type := Document;
  966. index := (y - documentOffset) DIV LineHeight;
  967. END;
  968. END;
  969. owner.Close;
  970. END PointerDown;
  971. PROCEDURE Draw(canvas : WMGraphics.Canvas);
  972. VAR y : LONGINT;
  973. PROCEDURE IsHighlighted(y : LONGINT) : BOOLEAN;
  974. BEGIN
  975. RETURN (y <= yt) & (yt < y + LineHeight);
  976. END IsHighlighted;
  977. PROCEDURE DrawBg(y : LONGINT);
  978. BEGIN
  979. IF IsHighlighted(y) THEN
  980. canvas.Fill(WMRectangles.MakeRect(0, y, bounds.GetWidth(), y + LineHeight), LONGINT(060606A0H), WMGraphics.ModeSrcOverDst);
  981. canvas.SetColor(WMGraphics.White);
  982. ELSE
  983. canvas.SetColor(WMGraphics.Black);
  984. END;
  985. END DrawBg;
  986. PROCEDURE DrawDocuments(VAR y : LONGINT);
  987. VAR row : LONGINT;
  988. BEGIN
  989. FOR row := 1 TO nofDocuments DO
  990. DrawBg(y);
  991. IF info.openDocuments[row - 1].modified THEN
  992. canvas.SetColor(WMGraphics.Red);
  993. ELSIF (info.openDocuments[row - 1].hasFocus) THEN
  994. canvas.SetColor(00DA00FFH);
  995. ELSIF IsHighlighted(y) THEN
  996. canvas.SetColor(WMGraphics.White);
  997. ELSE
  998. canvas.SetColor(WMGraphics.Black);
  999. END;
  1000. canvas.DrawString(LeftBorder, y + 16, info.openDocuments[row - 1].name);
  1001. INC(y, LineHeight);
  1002. END;
  1003. END DrawDocuments;
  1004. PROCEDURE DrawSystemCommands(VAR y : LONGINT);
  1005. BEGIN
  1006. canvas.SetColor(WMGraphics.Black);
  1007. DrawBg(y);
  1008. canvas.DrawString(LeftBorder, y + 16, "Close"); INC(y, LineHeight);
  1009. DrawBg(y);
  1010. DrawYesNo(y, window.isVisible);
  1011. canvas.DrawString(LeftBorder, y + 16, "Visible"); INC(y, LineHeight);
  1012. DrawBg(y);
  1013. DrawYesNo(y, WMWindowManager.FlagStayOnTop IN window.flags);
  1014. canvas.DrawString(LeftBorder, y + 16, "StayOnTop"); INC(y, LineHeight);
  1015. IF (NofSystemCommands > 3) THEN
  1016. DrawBg(y);
  1017. DrawYesNo(y, WMWindowManager.FlagStayOnBottom IN window.flags);
  1018. canvas.DrawString(LeftBorder, y + 16, "StayOnBottom"); INC(y, LineHeight);
  1019. END;
  1020. IF (NofSystemCommands > 4) THEN
  1021. DrawBg(y);
  1022. DrawYesNo(y, WMWindowManager.FlagFrame IN window.flags);
  1023. canvas.DrawString(LeftBorder, y + 16, "Frame"); INC(y, LineHeight);
  1024. END;
  1025. IF (NofSystemCommands > 5) THEN
  1026. DrawBg(y);
  1027. canvas.DrawString(LeftBorder, y + 16, "WindowShot"); INC(y, LineHeight);
  1028. END;
  1029. IF (*(window IS WMComponents.FormWindow) &*) (WMWindowManager.FlagStorable IN window.flags) & (NofSystemCommands > 6) THEN
  1030. DrawBg(y);
  1031. canvas.DrawString(LeftBorder, y + 16, "StoreWindowData"); INC(y, LineHeight);
  1032. END;
  1033. END DrawSystemCommands;
  1034. PROCEDURE DrawLine(VAR y : LONGINT);
  1035. BEGIN
  1036. canvas.Line(LeftBorder, y + (LineHeight DIV 2), bounds.GetWidth(), y + (LineHeight DIV 2), LONGINT(0C0C0C0FFH), WMGraphics.ModeCopy);
  1037. INC(y, LineHeight);
  1038. END DrawLine;
  1039. PROCEDURE DrawImage(y : LONGINT);
  1040. VAR canvasState : WMGraphics.CanvasState;
  1041. BEGIN
  1042. canvas.SaveState(canvasState);
  1043. canvas.SetClipRect(WMRectangles.MakeRect(LeftBorder, y, bounds.GetWidth() - RightBorder, y + image.height));
  1044. canvas.DrawImage(LeftBorder + imgX, y + imgY, image, WMGraphics.ModeCopy);
  1045. WMGraphicUtilities.DrawRect(canvas,
  1046. WMRectangles.MakeRect(LeftBorder, y, bounds.GetWidth() - RightBorder, y + image.height),
  1047. LONGINT(0C0C0C0C0H), WMGraphics.ModeSrcOverDst
  1048. );
  1049. canvas.RestoreState(canvasState);
  1050. END DrawImage;
  1051. PROCEDURE DrawYesNo(y : LONGINT; value : BOOLEAN);
  1052. BEGIN
  1053. IF value & (imageYes # NIL) THEN
  1054. canvas.DrawImage(5, y + 6, imageYes, WMGraphics.ModeSrcOverDst);
  1055. ELSIF ~value & (imageNo # NIL) THEN
  1056. canvas.DrawImage(5, y + 6, imageNo, WMGraphics.ModeSrcOverDst);
  1057. END;
  1058. END DrawYesNo;
  1059. BEGIN
  1060. Draw^(canvas);
  1061. canvas.Fill(WMRectangles.MakeRect(0, 0, LeftBorder - 5, bounds.GetHeight()), LONGINT(0C0C0C0C0H), WMGraphics.ModeSrcOverDst);
  1062. IF (menuLocation = Top) THEN
  1063. IF (nofDocuments > 0) THEN
  1064. y := documentOffset - LineHeight;
  1065. DrawLine(y);
  1066. DrawDocuments(y);
  1067. END;
  1068. y := commandOffset - LineHeight;
  1069. DrawLine(y);
  1070. DrawSystemCommands(y);
  1071. ELSE
  1072. y := commandOffset;
  1073. DrawSystemCommands(y);
  1074. DrawLine(y);
  1075. IF (nofDocuments > 0) THEN
  1076. DrawDocuments(y);
  1077. DrawLine(y);
  1078. END;
  1079. END;
  1080. IF showThumbnails & (image # NIL)THEN
  1081. DrawImage(imageOffset);
  1082. END;
  1083. END Draw;
  1084. END InfoView;
  1085. TYPE
  1086. MenuWindow = OBJECT (WMComponents.FormWindow)
  1087. VAR
  1088. isClosed : BOOLEAN;
  1089. shadowRectB, shadowRectR, borderRect : WMRectangles.Rectangle;
  1090. infoView : InfoView;
  1091. info : WMWindowManager.WindowInfo;
  1092. close : BOOLEAN;
  1093. PROCEDURE GetSelection(VAR type, index : LONGINT; VAR keys : SET);
  1094. BEGIN {EXCLUSIVE}
  1095. AWAIT(close);
  1096. type := infoView.type;
  1097. index := infoView.index;
  1098. keys := infoView.keys;
  1099. END GetSelection;
  1100. PROCEDURE&New(
  1101. x, y, width, menuLocation : LONGINT;
  1102. showThumbnails : BOOLEAN;
  1103. window : WMWindowManager.Window; CONST info : WMWindowManager.WindowInfo
  1104. );
  1105. VAR height : LONGINT;
  1106. BEGIN
  1107. ASSERT((width > 0));
  1108. isClosed := FALSE;
  1109. SELF.info := info;
  1110. NEW(infoView, SELF, menuLocation, showThumbnails);
  1111. infoView.fillColor.Set(WMGraphics.White);
  1112. infoView.bounds.SetWidth(width);
  1113. infoView.SetInfo(window, info);
  1114. height := infoView.bounds.GetHeight();
  1115. Init(width+ ShadowWidth, infoView.bounds.GetHeight() + ShadowWidth, TRUE);
  1116. SetContent(infoView);
  1117. SetTitle(Strings.NewString("WMNavigateMenu"));
  1118. infoView.alignment.Set(WMComponents.AlignNone);
  1119. infoView.bounds.SetExtents(width, height);
  1120. borderRect := WMRectangles.MakeRect(0, 0, width, height);
  1121. shadowRectB := WMRectangles.MakeRect(ShadowWidth, height, width+ShadowWidth, height+ShadowWidth);
  1122. shadowRectR := WMRectangles.MakeRect(width, ShadowWidth, width+ShadowWidth, height);
  1123. IF (menuLocation = Top) THEN
  1124. y := y - (infoView.bounds.GetHeight() + ShadowWidth);
  1125. END;
  1126. manager := WMWindowManager.GetDefaultManager();
  1127. manager.Add(x, y, SELF, {WMWindowManager.FlagStayOnTop, WMWindowManager.FlagNavigation, WMWindowManager.FlagHidden});
  1128. manager.SetFocus(SELF);
  1129. END New;
  1130. PROCEDURE Draw(canvas : WMGraphics.Canvas; w, h, q : LONGINT); (** override *)
  1131. BEGIN
  1132. Draw^(canvas, w, h, q);
  1133. canvas.Fill(shadowRectB, 04FH, WMGraphics.ModeSrcOverDst);
  1134. canvas.Fill(shadowRectR, 04FH, WMGraphics.ModeSrcOverDst);
  1135. WMGraphicUtilities.DrawRect(canvas, borderRect, WMGraphics.Black, WMGraphics.ModeCopy);
  1136. END Draw;
  1137. PROCEDURE SetClosed;
  1138. BEGIN
  1139. BEGIN {EXCLUSIVE} close := TRUE; END;
  1140. END SetClosed;
  1141. PROCEDURE Close;
  1142. BEGIN
  1143. SetClosed;
  1144. Close^;
  1145. END Close;
  1146. PROCEDURE KeyEvent(ucs : LONGINT; flags : SET; keysym : LONGINT); (* override *)
  1147. BEGIN
  1148. IF ~(Inputs.Release IN flags) THEN
  1149. IF keysym = 0FF54H THEN (* Cursor Down *)
  1150. ELSIF keysym = 0FF52H THEN (* Cursor Up *)
  1151. ELSIF (keysym = Inputs.KsTab) OR (keysym = Inputs.KsReturn) THEN
  1152. ELSIF (keysym = Inputs.KsEscape) THEN
  1153. Close;
  1154. ELSE
  1155. END;
  1156. ELSE
  1157. END;
  1158. END KeyEvent;
  1159. PROCEDURE FocusLost;
  1160. BEGIN
  1161. FocusLost^;
  1162. Close;
  1163. END FocusLost;
  1164. END MenuWindow;
  1165. CONST
  1166. MenuSize = 10;
  1167. TYPE
  1168. Window = OBJECT(WMComponents.FormWindow)
  1169. VAR
  1170. myId : LONGINT;
  1171. PROCEDURE &New*(id : LONGINT; component : WMComponents.VisualComponent; x, y, width, height : LONGINT; alpha : BOOLEAN; flags : SET);
  1172. VAR title, nbr : ARRAY 32 OF CHAR;
  1173. BEGIN
  1174. ASSERT((component # NIL) & (width > 0) & (height > 0));
  1175. Init(width, height, alpha);
  1176. SELF.myId := id;
  1177. SetContent(component);
  1178. COPY("WMNavigate", title); Strings.IntToStr(id, nbr); Strings.Append(title, nbr);
  1179. SetTitle(Strings.NewString(title));
  1180. IF (WMWindowManager.FlagNavigation IN flags) THEN
  1181. WMWindowManager.ExtAddViewBoundWindow(SELF, x, y, NIL, flags);
  1182. ELSE
  1183. WMWindowManager.ExtAddWindow(SELF, x, y, flags);
  1184. END;
  1185. component.bounds.SetExtents(width, height);
  1186. pointerThreshold := 1;
  1187. END New;
  1188. PROCEDURE Close;
  1189. BEGIN
  1190. Close^;
  1191. windows[myId] := NIL;
  1192. END Close;
  1193. END Window;
  1194. TYPE
  1195. Windows = ARRAY MaxNofWindows OF WMWindowManager.Window;
  1196. VAR
  1197. windows : ARRAY MaxNavigationWindows OF Window;
  1198. manager : WMWindowManager.WindowManager;
  1199. viewport : WMWindowManager.ViewPort;
  1200. StrWindowOverview : Strings.String;
  1201. StrNoName : Strings.String;
  1202. StrBase: Strings.String;
  1203. StrTaskList: Strings.String;
  1204. StrOverview: Strings.String;
  1205. width, height : LONGINT;
  1206. windowShotScale*:REAL;
  1207. windowsAreHidden : BOOLEAN;
  1208. navigationIsHidden : BOOLEAN;
  1209. showWindowNames: BOOLEAN;
  1210. ProtoClDefault, ProtoClSelected, ProtoClMouseOver, ProtoClSelectedMouseOver,
  1211. ProtoClTextDefault, ProtoClTextSelected, ProtoClTextMouseOver, ProtoClTextSelectedMouseOver,
  1212. ProtoClIndicateHidden : WMProperties.ColorProperty;
  1213. ProtoBorderWidth : WMProperties.Int32Property;
  1214. ProtoTaskListStyle, ProtoTaskListMenuLocation : WMProperties.Int32Property;
  1215. ProtoTaskListShowThumbnails, ProtoTaskListShowNames : WMProperties.BooleanProperty;
  1216. ProtoItemWidth, ProtoItemHeight : WMProperties.Int32Property;
  1217. ProtoLayoutMode : WMProperties.Int32Property;
  1218. PROCEDURE GetWindowImage(window : WMWindowManager.Window; width, height : LONGINT) : WMGraphics.Image;
  1219. VAR image : WMGraphics.Image; canvas : WMGraphics.BufferCanvas; ignore : LONGINT;
  1220. BEGIN (* must hold window manager lock *)
  1221. ASSERT((window # NIL));
  1222. NEW(image);
  1223. Raster.Create(image, width, height, Raster.BGRA8888);
  1224. NEW(canvas, image);
  1225. DrawIntoCanvas(window, canvas, width, height, ignore, ignore);
  1226. RETURN image;
  1227. END GetWindowImage;
  1228. PROCEDURE GenerateName(prefix: Strings.String; VAR str: ARRAY OF CHAR);
  1229. VAR i,j:LONGINT; num: ARRAY 32 OF CHAR; title: Files.FileName; c:CHAR;
  1230. BEGIN
  1231. i:=0; j:=0;
  1232. IF prefix#NIL THEN
  1233. WHILE (i<LEN(prefix)) & (j<LEN(title)-1) DO
  1234. c:=prefix[i];
  1235. IF (c>="A")&(c<="Z") OR (c>="a")&(c<="z") OR(c>="0")&(c<="9") OR (c="_") OR (c=" ")THEN
  1236. IF c=" " THEN c:="_" END;
  1237. title[j]:=c; INC(i); INC(j);
  1238. ELSE
  1239. INC(i);
  1240. END;
  1241. END;
  1242. title[j]:=0X;
  1243. IF title="" THEN title:="ScreenShot" END;
  1244. ELSE title:="ScreenShot"
  1245. END;
  1246. COPY(title, str);
  1247. END GenerateName;
  1248. PROCEDURE WindowShot(window: WMWindowManager.Window; scale:REAL);
  1249. VAR str,fn: Files.FileName; w,h, res: LONGINT; startTime: Dates.DateTime;
  1250. img:WMGraphics.Image;
  1251. BEGIN
  1252. GenerateName(window.GetTitle(),fn);
  1253. IF fn="" THEN COPY("WindowShot",fn) END;
  1254. Strings.FormatDateTime("_yyyymmdd__hhnnss",Dates.Now(),str);
  1255. Strings.Concat(fn,str,fn);
  1256. Strings.Append(fn,".bmp");
  1257. (* scaled storing not yet implemented *)
  1258. IF window IS WMWindowManager.DoubleBufferWindow THEN
  1259. WMGraphics.StoreImage(window(WMWindowManager.DoubleBufferWindow).backImg, fn, res);
  1260. ELSIF window IS WMWindowManager.BufferWindow THEN
  1261. WMGraphics.StoreImage(window(WMWindowManager.BufferWindow).img, fn, res);
  1262. ELSE
  1263. NEW(img); Raster.Create(img, window.GetWidth(), window.GetHeight(),Raster.BGRA8888);
  1264. window.Draw(WMGraphics.GenCanvas(img), window.GetWidth(), window.GetHeight(), 0);
  1265. WMGraphics.StoreImage(img, fn, res);
  1266. END;
  1267. IF res=0 THEN
  1268. KernelLog.String("stored window shot as "); KernelLog.String(fn); KernelLog.Ln;
  1269. END;
  1270. END WindowShot;
  1271. PROCEDURE StoreWindow(window: WMWindowManager.Window);
  1272. VAR fn0,fn: Files.FileName; s: ARRAY 6 OF CHAR; i, res: LONGINT; f:Files.File; w:Files.Writer;
  1273. xml:XML.Content; msg: WMMessages.Message;
  1274. BEGIN
  1275. IF (WMWindowManager.FlagStorable IN window.flags) THEN
  1276. GenerateName(window.GetTitle(),fn0);
  1277. IF window IS WMComponents.FormWindow THEN
  1278. Strings.Concat(fn0,".Cwd",fn); (* component window *)
  1279. f:=Files.Old(fn);
  1280. i:=0;
  1281. WHILE f#NIL DO
  1282. f:=NIL;
  1283. Strings.IntToStr(i,s);
  1284. COPY (fn0,fn);
  1285. Strings.Append(fn,"_");
  1286. Strings.Append(fn,s);
  1287. Strings.Append(fn,".Cwd");
  1288. f:=Files.Old(fn);
  1289. INC(i);
  1290. END;
  1291. (*? WMRestorable.StoreWindow*(window: WM.Window; CONST fileName: ARRAY OF CHAR);*)
  1292. f:=Files.New(fn);
  1293. IF f#NIL THEN
  1294. Files.OpenWriter(w,f,0);
  1295. w.String('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'); w.Ln;
  1296. window(WMComponents.FormWindow).ToXML().Write(w,NIL,0);
  1297. w.Update;
  1298. Files.Register(f);
  1299. KernelLog.String("WMNavigate.StoreWindow "); KernelLog.String(fn); KernelLog.Ln;
  1300. END;
  1301. ELSE (* try to serialize*)
  1302. msg.msgType := WMMessages.MsgSerialize;
  1303. window.Handle(msg);
  1304. (* IF (window.manager#NIL) & window.manager.SendMessage(window, msg) THEN END;*)
  1305. END;
  1306. END;
  1307. END StoreWindow;
  1308. PROCEDURE DrawIntoCanvas(window : WMWindowManager.Window; canvas : WMGraphics.BufferCanvas; width, height : LONGINT; VAR offsetX, offsetY : LONGINT);
  1309. VAR image : Raster.Image; winWidth, winHeight, imgWidth, imgHeight : LONGINT; scaleX, scaleY : REAL;
  1310. BEGIN (* must hold window manager lock *)
  1311. ASSERT((window # NIL) & (canvas # NIL));
  1312. image := canvas.GetImage();
  1313. canvas.Fill(WMRectangles.MakeRect(0, 0, image.width, image.height), 0, WMGraphics.ModeCopy);
  1314. winWidth := window.GetWidth(); (* TODO: Not threadsafe *)
  1315. winHeight := window.GetHeight();
  1316. scaleX := width / winWidth;
  1317. scaleY := height / winHeight;
  1318. IF (scaleX <= scaleY) THEN
  1319. imgWidth := width;
  1320. imgHeight := ENTIER(winHeight * scaleX);
  1321. offsetX := 0;
  1322. offsetY := height - imgHeight;
  1323. ELSE
  1324. imgWidth := ENTIER(winWidth * scaleY);
  1325. imgHeight := height;
  1326. offsetX := (width - imgWidth) DIV 2;
  1327. offsetY := 0;
  1328. END;
  1329. window.Draw(canvas, imgWidth, imgHeight, WMGraphics.ScaleBilinear);
  1330. END DrawIntoCanvas;
  1331. PROCEDURE Clear(VAR windows : Windows);
  1332. VAR i : LONGINT;
  1333. BEGIN
  1334. FOR i := 0 TO LEN(windows)-1 DO
  1335. windows[i] := NIL;
  1336. END;
  1337. END Clear;
  1338. PROCEDURE GetFocusOwnerIndex(CONST windows : Windows; nofWindows : LONGINT) : LONGINT; (* private *)
  1339. VAR index : LONGINT; focusOwner : WMWindowManager.Window;
  1340. BEGIN
  1341. focusOwner := manager.GetFocusOwner();
  1342. index := 0;
  1343. WHILE (index < nofWindows) & (windows[index] # focusOwner) DO INC(index); END;
  1344. IF (index >= LEN(windows)) THEN
  1345. index := -1;
  1346. END;
  1347. RETURN index;
  1348. END GetFocusOwnerIndex;
  1349. (** Postcondition: {(windows # NIL) & (0 <= nofWindows < MaxNofWindows) & (windows[i < nofWindows] # NIL)} *)
  1350. PROCEDURE GetWindows(VAR windows : Windows; VAR nofWindows : LONGINT);
  1351. VAR
  1352. window : WMWindowManager.Window;
  1353. PROCEDURE IsUserWindow(window : WMWindowManager.Window) : BOOLEAN;
  1354. BEGIN
  1355. ASSERT(window # NIL);
  1356. RETURN {WMWindowManager.FlagHidden, WMWindowManager.FlagDecorWindow} * window.flags = {};
  1357. END IsUserWindow;
  1358. PROCEDURE SortWindowsById(VAR windows : Windows);
  1359. VAR temp : WMWindowManager.Window; i, j : LONGINT;
  1360. BEGIN
  1361. (* for now bubble sort is sufficient *)
  1362. FOR i := 0 TO nofWindows-1 DO
  1363. FOR j := 0 TO nofWindows-2 DO
  1364. IF (windows[j].id > windows[j+1].id) THEN
  1365. temp := windows[j+1];
  1366. windows[j+1] := windows[j];
  1367. windows[j] := temp;
  1368. END;
  1369. END;
  1370. END;
  1371. END SortWindowsById;
  1372. BEGIN
  1373. ASSERT((manager # NIL));
  1374. (* clear all references *)
  1375. Clear(windows);
  1376. manager.lock.AcquireWrite;
  1377. nofWindows := 0;
  1378. window := manager.GetFirst();
  1379. WHILE (window # NIL) & (nofWindows < MaxNofWindows) DO
  1380. IF IsUserWindow(window) THEN
  1381. windows[nofWindows] := window;
  1382. INC(nofWindows);
  1383. END;
  1384. window := manager.GetNext(window);
  1385. END;
  1386. manager.lock.ReleaseWrite;
  1387. IF (nofWindows > 1) THEN SortWindowsById(windows); END;
  1388. END GetWindows;
  1389. PROCEDURE Open*(context : Commands.Context); (** [Options] id x y componentFile ~ *)
  1390. VAR
  1391. options : Options.Options;
  1392. id, x, y, w, h : LONGINT;
  1393. filename : ARRAY 256 OF CHAR;
  1394. content : XML.Content;
  1395. flags : SET;
  1396. BEGIN {EXCLUSIVE}
  1397. NEW(options);
  1398. options.Add("f", "frame", Options.Flag);
  1399. options.Add("s", "stayOnTop", Options.Flag);
  1400. options.Add("v", "viewport", Options.Flag);
  1401. options.Add("n", "names", Options.Flag);
  1402. IF options.Parse(context.arg, context.out) THEN
  1403. showWindowNames := options.GetFlag("names");
  1404. context.arg.SkipWhitespace; context.arg.Int(id, FALSE);
  1405. context.arg.SkipWhitespace; context.arg.Int(x, FALSE);
  1406. context.arg.SkipWhitespace; context.arg.Int(y, FALSE);
  1407. context.arg.SkipWhitespace; context.arg.String(filename);
  1408. IF (filename # "") THEN
  1409. IF (0 <= id) & (id < MaxNavigationWindows) THEN
  1410. IF (windows[id] = NIL) THEN
  1411. content := WMComponents.GetComponent(filename);
  1412. IF (content # NIL) THEN
  1413. IF (content IS WMComponents.VisualComponent) THEN
  1414. w := content(WMComponents.VisualComponent).bounds.GetWidth();
  1415. h := content(WMComponents.VisualComponent).bounds.GetHeight();
  1416. IF (w <= 0) THEN w := width; END;
  1417. IF (h <= 0) THEN h := height; END;
  1418. flags := {WMWindowManager.FlagHidden};
  1419. IF options.GetFlag("frame") THEN INCL(flags, WMWindowManager.FlagFrame); END;
  1420. IF options.GetFlag("stayOnTop") THEN INCL(flags, WMWindowManager.FlagStayOnTop); END;
  1421. IF options.GetFlag("viewport") THEN INCL(flags, WMWindowManager.FlagNavigation); END;
  1422. NEW(windows[id], id, content(WMComponents.VisualComponent), x, y, w, h, TRUE, flags);
  1423. WMWindowManager.IncWTimestamp;
  1424. windows[id].CSChanged;
  1425. ELSE
  1426. context.out.String("WMNavigate: Expected visual component"); context.out.Ln;
  1427. END;
  1428. ELSE
  1429. context.out.String("WMNavigate: Could not load component from file ");
  1430. context.out.String(filename); context.out.Ln;
  1431. END;
  1432. ELSE
  1433. context.out.String("WMNavigate: Window with id already open"); context.out.Ln;
  1434. END;
  1435. ELSE
  1436. context.out.String("WMNavigate: Invalid id parameter"); context.out.Ln;
  1437. END;
  1438. ELSE
  1439. context.out.String("WMNavigate.Open id x y width height componentFile ~"); context.out.Ln;
  1440. END;
  1441. END;
  1442. END Open;
  1443. PROCEDURE Close*(context : Commands.Context); (** id ~ *)
  1444. VAR id : LONGINT;
  1445. BEGIN {EXCLUSIVE}
  1446. IF context.arg.GetInteger(id, FALSE) & (0 <= id) & (id < MaxNavigationWindows) THEN
  1447. IF (windows[id] # NIL) THEN
  1448. windows[id].Close;
  1449. windows[id] := NIL;
  1450. ELSE
  1451. context.out.String("WMNavigate: Window with id is not open"); context.out.Ln;
  1452. END;
  1453. ELSE
  1454. context.out.String("WMNavigate: Invalid id parameter"); context.out.Ln;
  1455. END;
  1456. END Close;
  1457. PROCEDURE ToggleVisibility*(context : Commands.Context); (** id ~ *)
  1458. VAR id : LONGINT;
  1459. BEGIN {EXCLUSIVE}
  1460. IF context.arg.GetInteger(id, FALSE) & (0 <= id) & (id < MaxNavigationWindows) THEN
  1461. IF (windows[id] # NIL) THEN
  1462. manager.SetIsVisible(windows[id], ~windows[id].isVisible);
  1463. ELSE
  1464. context.out.String("WMNavigate: Window with id is not open"); context.out.Ln;
  1465. END;
  1466. ELSE
  1467. context.out.String("WMNavigate: Invalid id parameter"); context.out.Ln;
  1468. END;
  1469. END ToggleVisibility;
  1470. PROCEDURE HideNavigation*;
  1471. BEGIN {EXCLUSIVE}
  1472. SetIsVisibleNavigation(FALSE);
  1473. navigationIsHidden := TRUE;
  1474. END HideNavigation;
  1475. PROCEDURE RestoreNavigation*;
  1476. BEGIN {EXCLUSIVE}
  1477. SetIsVisibleNavigation(TRUE);
  1478. navigationIsHidden := FALSE;
  1479. END RestoreNavigation;
  1480. PROCEDURE ToggleNavigation*;
  1481. BEGIN {EXCLUSIVE}
  1482. navigationIsHidden := ~navigationIsHidden;
  1483. SetIsVisibleNavigation(~navigationIsHidden);
  1484. END ToggleNavigation;
  1485. PROCEDURE SetIsVisibleNavigation(isVisible : BOOLEAN);
  1486. VAR window : WMWindowManager.Window;
  1487. BEGIN
  1488. manager.lock.AcquireWrite;
  1489. window := manager.GetFirst();
  1490. WHILE (window # NIL) DO
  1491. IF (WMWindowManager.FlagNavigation IN window.flags) THEN
  1492. manager.SetIsVisible(window, isVisible);
  1493. END;
  1494. window := manager.GetNext(window);
  1495. END;
  1496. manager.lock.ReleaseWrite;
  1497. END SetIsVisibleNavigation;
  1498. PROCEDURE FocusToNext*;
  1499. BEGIN
  1500. SwitchFocus(FALSE);
  1501. END FocusToNext;
  1502. PROCEDURE FocusToPrevious*;
  1503. BEGIN
  1504. SwitchFocus(TRUE);
  1505. END FocusToPrevious;
  1506. PROCEDURE SwitchFocus(backwards : BOOLEAN);
  1507. VAR windows : Windows; nofWindows, focusIdx : LONGINT;
  1508. BEGIN {EXCLUSIVE}
  1509. GetWindows(windows, nofWindows);
  1510. IF (nofWindows >= 1) THEN
  1511. focusIdx := GetFocusOwnerIndex(windows, nofWindows);
  1512. IF (focusIdx >= 0) THEN
  1513. IF (nofWindows > 1) THEN
  1514. IF backwards THEN
  1515. IF focusIdx > 0 THEN
  1516. DEC(focusIdx);
  1517. ELSE
  1518. focusIdx := nofWindows - 1;
  1519. END;
  1520. ELSE
  1521. focusIdx := (focusIdx + 1) MOD nofWindows;
  1522. END;
  1523. END;
  1524. ELSE
  1525. focusIdx := 0; (* set focus to first user window *)
  1526. END;
  1527. IF (windows[focusIdx] = NIL) THEN RETURN (* can happen when no window has the focus initially *) END;
  1528. ASSERT((0 <= focusIdx) & (focusIdx < LEN(windows)));
  1529. manager.lock.AcquireWrite;
  1530. manager.ToFront(windows[focusIdx]);
  1531. manager.SetFocus(windows[focusIdx]);
  1532. manager.lock.ReleaseWrite;
  1533. END;
  1534. END SwitchFocus;
  1535. PROCEDURE HideAll*;
  1536. BEGIN {EXCLUSIVE}
  1537. SetIsVisible(FALSE);
  1538. windowsAreHidden := TRUE;
  1539. END HideAll;
  1540. PROCEDURE RestoreAll*;
  1541. BEGIN {EXCLUSIVE}
  1542. SetIsVisible(TRUE);
  1543. windowsAreHidden := FALSE;
  1544. END RestoreAll;
  1545. PROCEDURE ToggleAll*;
  1546. BEGIN {EXCLUSIVE}
  1547. windowsAreHidden := ~windowsAreHidden;
  1548. SetIsVisible(~windowsAreHidden);
  1549. END ToggleAll;
  1550. PROCEDURE SetIsVisible(isVisible : BOOLEAN);
  1551. VAR windows : Windows; nofWindows, i : LONGINT;
  1552. BEGIN
  1553. GetWindows(windows, nofWindows);
  1554. manager.lock.AcquireWrite;
  1555. FOR i := 0 TO nofWindows-1 DO
  1556. manager.SetIsVisible(windows[i], isVisible);
  1557. END;
  1558. manager.lock.ReleaseWrite;
  1559. END SetIsVisible;
  1560. (** Toggle minimized/fullscreen for the window that currently owns the focus *)
  1561. PROCEDURE ToggleFullscreen*;
  1562. VAR window : WMWindowManager.Window; newWidth, newHeight : LONGINT;
  1563. BEGIN {EXCLUSIVE}
  1564. manager.lock.AcquireWrite;
  1565. window := manager.GetFocusOwner();
  1566. IF (window # NIL) & (window.flags * {WMWindowManager.FlagNavigation, WMWindowManager.FlagHidden, WMWindowManager.FlagNoResizing} = {}) THEN
  1567. IF (window.GetWidth() = width) & (window.GetHeight() = height) THEN
  1568. manager.SetWindowPos(window, window.normalBounds.l, window.normalBounds.t);
  1569. newWidth := window.normalBounds.r - window.normalBounds.l;
  1570. newHeight := window.normalBounds.b - window.normalBounds.t;
  1571. SetIsVisibleNavigation(~navigationIsHidden);
  1572. ELSE
  1573. window.normalBounds := window.bounds;
  1574. manager.SetWindowPos(window, ENTIER(viewport.range.l), ENTIER(viewport.range.t));
  1575. newWidth := width;
  1576. newHeight := height;
  1577. SetIsVisibleNavigation(FALSE);
  1578. END;
  1579. manager.SetWindowSize(window, newWidth, newHeight);
  1580. (* 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 *)
  1581. manager.lock.ReleaseWrite;
  1582. window.Resized(newWidth, newHeight);
  1583. ELSE
  1584. manager.lock.ReleaseWrite;
  1585. END;
  1586. END ToggleFullscreen;
  1587. PROCEDURE MoveWindow*(context : Commands.Context);
  1588. VAR options : Options.Options; window : WMWindowManager.Window; x, y : LONGINT;
  1589. BEGIN {EXCLUSIVE}
  1590. NEW(options);
  1591. options.Add("d", "display", Options.Flag);
  1592. IF options.Parse(context.arg, context.out) THEN
  1593. IF context.arg.GetInteger(x, FALSE) & context.arg.GetInteger(y, FALSE) THEN
  1594. IF options.GetFlag("display") THEN
  1595. x := x * width;
  1596. y := y * height;
  1597. END;
  1598. window := manager.GetFocusOwner();
  1599. IF (window IS WMComponents.FormWindow) THEN
  1600. manager.SetWindowPos(window, window.bounds.l + x, window.bounds.t + y);
  1601. END;
  1602. END;
  1603. END;
  1604. END MoveWindow;
  1605. (** Close the window that currently owns the focus *)
  1606. PROCEDURE CloseWindow*;
  1607. VAR window : WMWindowManager.Window; formWindow : WMComponents.FormWindow;
  1608. BEGIN {EXCLUSIVE}
  1609. window := manager.GetFocusOwner();
  1610. IF window IS WMComponents.FormWindow THEN
  1611. formWindow := window (WMComponents.FormWindow);
  1612. formWindow.Close;
  1613. END;
  1614. END CloseWindow;
  1615. (**
  1616. * Set the range of the default view port. Can be used for virtual desktops.
  1617. * Parameters:
  1618. * x, y : Position of viewport ovservable range (pixel)
  1619. * w, h : width and height of viewport observable range (pixel, set to display width/height if omitted)
  1620. * "s" : show transition to new range
  1621. * "d": interpret x, y, w and h parameters as multiples of display width/height
  1622. *)
  1623. PROCEDURE SetViewportRange*(context : Commands.Context); (** [options] [x y [w h]] ~ *)
  1624. VAR options : Options.Options; x, y, w, h : LONGINT;
  1625. BEGIN
  1626. NEW(options);
  1627. options.Add("s", "showTransition", Options.Flag);
  1628. options.Add("d", "display", Options.Flag);
  1629. IF options.Parse(context.arg, context.out) THEN
  1630. x := 0; y := 0; w := 0; h := 0;
  1631. context.arg.SkipWhitespace; context.arg.Int(x, FALSE);
  1632. context.arg.SkipWhitespace; context.arg.Int(y, FALSE);
  1633. context.arg.SkipWhitespace; context.arg.Int(w, FALSE);
  1634. context.arg.SkipWhitespace; context.arg.Int(h, FALSE);
  1635. IF options.GetFlag("display") THEN
  1636. x := x * width; w := w * width;
  1637. y := y * height; h := h * height;
  1638. END;
  1639. IF w = 0 THEN w := width; END;
  1640. IF h = 0 THEN h := height; END;
  1641. viewport.SetRange(x, y, w, h, options.GetFlag("showTransition"));
  1642. END;
  1643. END SetViewportRange;
  1644. PROCEDURE GenTaskList*() : XML.Element;
  1645. VAR t : TaskList;
  1646. BEGIN
  1647. NEW(t); RETURN t;
  1648. END GenTaskList;
  1649. PROCEDURE GenOverview*() : XML.Element;
  1650. VAR o : WindowOverview;
  1651. BEGIN
  1652. NEW(o); RETURN o;
  1653. END GenOverview;
  1654. PROCEDURE InitStrings;
  1655. BEGIN
  1656. StrWindowOverview := Strings.NewString("WindowOverview");
  1657. StrTaskList := Strings.NewString("TaskList");
  1658. StrNoName := Strings.NewString("NoName");
  1659. StrBase := Strings.NewString("Base");
  1660. StrOverview:=Strings.NewString("Overview");
  1661. END InitStrings;
  1662. PROCEDURE InitProtos;
  1663. BEGIN
  1664. NEW(ProtoClDefault, NIL, Strings.NewString("ClDefault"), Strings.NewString("Default color of item"));
  1665. ProtoClDefault.Set(0A0A0A0A0H);
  1666. NEW(ProtoClSelected, NIL, Strings.NewString("ClSelected"), Strings.NewString("Color of selected item"));
  1667. ProtoClSelected.Set(060606A0H);
  1668. NEW(ProtoClMouseOver, NIL, Strings.NewString("ClMouseOver"), Strings.NewString("Mouse over color of item"));
  1669. ProtoClMouseOver.Set(0D0D0D0A0H);
  1670. NEW(ProtoClSelectedMouseOver, NIL, Strings.NewString("ClSelectedMouseOver"), Strings.NewString("Mouse over color of selected item"));
  1671. ProtoClSelectedMouseOver.Set(0F0F0F0A0H);
  1672. NEW(ProtoClTextDefault, NIL, Strings.NewString("ClTextDefault"), Strings.NewString("Default text color"));
  1673. ProtoClTextDefault.Set(WMGraphics.White);
  1674. NEW(ProtoClTextSelected, NIL, Strings.NewString("ClTextSelected"), Strings.NewString("Text color of selected item"));
  1675. ProtoClTextSelected.Set(WMGraphics.White);
  1676. NEW(ProtoClTextMouseOver, NIL, Strings.NewString("ClTextMouseOver"), Strings.NewString("Text color of mouse over item"));
  1677. ProtoClTextMouseOver.Set(WMGraphics.White);
  1678. NEW(ProtoClTextSelectedMouseOver, NIL, Strings.NewString("ClTextSelectedMouseOver"), Strings.NewString("Text color of selected mouse over item"));
  1679. ProtoClTextSelectedMouseOver.Set(WMGraphics.White);
  1680. NEW(ProtoClIndicateHidden, NIL, Strings.NewString("ClIndicateHidden"), Strings.NewString("Color used to indicate hidden windows"));
  1681. ProtoClIndicateHidden.Set(WMGraphics.Yellow);
  1682. NEW(ProtoBorderWidth, NIL, Strings.NewString("BorderWidth"), Strings.NewString("Width of border"));
  1683. ProtoBorderWidth.Set(2);
  1684. NEW(ProtoTaskListStyle, NIL, Strings.NewString("Style"), Strings.NewString("Style of task representation"));
  1685. ProtoTaskListStyle.Set(Icons);
  1686. NEW(ProtoTaskListMenuLocation, NIL, Strings.NewString("MenuLocation"), Strings.NewString("Location of submenu relative to task list"));
  1687. ProtoTaskListMenuLocation.Set(Bottom);
  1688. NEW(ProtoTaskListShowThumbnails, NIL, Strings.NewString("ShowThumbnails"), Strings.NewString("Show window thumbnails?"));
  1689. ProtoTaskListShowThumbnails.Set(TRUE);
  1690. NEW(ProtoTaskListShowNames, NIL, Strings.NewString("ShowNames"), Strings.NewString("Show window names?"));
  1691. ProtoTaskListShowNames.Set(TRUE);
  1692. NEW(ProtoItemWidth, NIL, Strings.NewString("ItemWidth"), Strings.NewString("Width of task list item"));
  1693. NEW(ProtoItemHeight, NIL, Strings.NewString("ItemHeight"), Strings.NewString("Height of task list item"));
  1694. NEW(ProtoLayoutMode, NIL, Strings.NewString("LayoutMode"), Strings.NewString("Item layouting mode"));
  1695. END InitProtos;
  1696. PROCEDURE Init;
  1697. VAR plugin : Plugins.Plugin;
  1698. BEGIN
  1699. manager := WMWindowManager.GetDefaultManager();
  1700. viewport := WMWindowManager.GetDefaultView();
  1701. plugin := Displays.registry.Get("");
  1702. IF plugin # NIL THEN
  1703. width := plugin(Displays.Display).width;
  1704. height := plugin(Displays.Display).height;
  1705. ELSE
  1706. width := 1024;
  1707. height := 768;
  1708. END;
  1709. END Init;
  1710. PROCEDURE Cleanup;
  1711. VAR i : LONGINT;
  1712. BEGIN {EXCLUSIVE}
  1713. FOR i := 0 TO LEN(windows)-1 DO
  1714. IF (windows[i] # NIL) THEN windows[i].Close; END;
  1715. END;
  1716. END Cleanup;
  1717. BEGIN
  1718. Modules.InstallTermHandler(Cleanup);
  1719. Init;
  1720. InitStrings;
  1721. InitProtos;
  1722. windowsAreHidden := FALSE;
  1723. navigationIsHidden := FALSE;
  1724. windowShotScale:=1.0;
  1725. ASSERT(manager # NIL);
  1726. END WMNavigate.
  1727. WMNavigate.SetViewportRange 0 0 ~
  1728. WMNavigate.SetViewportRange "-1" 0 1 1 sd ~
  1729. WMNavigate.MoveWindow -1280 ~
  1730. Example: Four virtual desktops with overview, depended on display resolution
  1731. WMNavigate.SetViewportRange -sd -1 0 1 1 ~ (* left desktop *)
  1732. WMNavigate.SetViewportRange -sd 0 0 1 1 ~ (* standard desktop *)
  1733. WMNavigate.SetViewportRange -sd -1 -1 1 1 ~ (* left/up desktop *)
  1734. WMNavigate.SetViewportRange -sd 0 -1 1 1 ~ (* up desktop *)
  1735. WMNavigate.SetViewportRange -sd -1 -1 2 2 ~ (* all four desktops *)
  1736. WMNavigate.Open -vs 1 0 0 Navigation:TaskList ~
  1737. WMNavigate.Open -vs 2 20 600 Navigation:TaskList ~
  1738. WMNavigate.Open -fs 6 20 20 Navigation:WindowList ~
  1739. WMNavigate.Close 1 ~
  1740. WMNavigate.ToggleVisibility 1 ~
  1741. WMNavigate.HideNavigation ~
  1742. WMNavigate.RestoreNavigation ~
  1743. WMNavigate.ToggleNavigation ~
  1744. SystemTools.Free WMNavigate ~