MODULE WMNavigate;
IMPORT
Modules, Kernel, Commands, Options, Locks, Strings, Raster, Plugins, Displays, KernelLog, Inputs, XML,
WMRectangles, WMGraphics, WMGraphicUtilities, WMWindowManager, WMComponents, WMProperties;
CONST
Text* = 0;
Icons* = 1;
Left* = 0;
Top* = 1;
Right* = 2;
Bottom* = 3;
Fixed* = 0;
Default* =1;
ScaleUp*= 2;
ScaleUpWidthOnly* = 3;
ScaleUpHeightOnly* = 4;
Aspect* = 5;
ThumbnailWidth = 128;
ThumbnailHeight = 92;
UpdateInterval = 100;
MaxNofWindows = 100;
MaxNavigationWindows = 10;
Running = 0;
Terminating = 1;
Terminated = 2;
TYPE
Layout = OBJECT
VAR
width, height : LONGINT;
entryWidth, entryHeight : LONGINT;
fixX, fixY : LONGINT;
nofRows, nofColumns : LONGINT;
nofEntries : LONGINT;
PROCEDURE GetIndexOf(x, y : LONGINT) : LONGINT;
VAR result, row, column : LONGINT;
BEGIN
result := -1;
IF (nofEntries > 0) & (nofRows > 0) & (nofColumns > 0) THEN
column := x DIV entryWidth;
row := y DIV entryHeight;
IF (column < nofColumns) & (row < nofRows) THEN
result := row * nofColumns + column;
IF (result >= nofEntries) THEN result := -1; END;
END;
END;
RETURN result;
END GetIndexOf;
PROCEDURE GetPositionOf(x, y : LONGINT) : WMRectangles.Rectangle;
VAR rect : WMRectangles.Rectangle; row, column : LONGINT;
BEGIN
rect := WMRectangles.MakeRect(0, 0, 0, 0);
IF (nofEntries > 0) & (nofRows > 0) & (nofColumns > 0) THEN
column := x DIV entryWidth;
row := y DIV entryHeight;
IF (column < nofColumns) & (row < nofRows) THEN
rect.l := column * entryWidth;
rect.r := rect.l + entryWidth;
rect.t := row * entryHeight;
rect.b := rect.t + entryHeight;
END;
END;
RETURN rect;
END GetPositionOf;
PROCEDURE Compute(nofEntries, width, height, desiredEntryWidth, desiredEntryHeight, mode : LONGINT);
BEGIN
ASSERT(nofEntries >= 0);
ASSERT((width >= 0) & (height >= 0));
ASSERT((desiredEntryWidth > 0) & (desiredEntryHeight > 0));
ASSERT((mode = Fixed) OR (mode = Default) OR (mode = ScaleUp) OR (mode = ScaleUpWidthOnly) OR (mode = ScaleUpHeightOnly) OR (mode = Aspect));
SELF.nofEntries := nofEntries;
SELF.width := width; SELF.height := height;
SELF.entryWidth := desiredEntryWidth; SELF.entryHeight := desiredEntryHeight;
fixX := 0; fixY := 0;
IF (mode # Aspect) THEN
ComputeDefault;
IF (mode = Fixed) THEN
entryWidth := desiredEntryWidth;
END;
IF (mode = ScaleUp) OR (mode = ScaleUpWidthOnly) THEN
IF (nofEntries < nofColumns) THEN
nofColumns := nofEntries;
IF (nofColumns = 0) THEN nofColumns := 1; END;
END;
entryWidth := width DIV nofColumns;
fixX := width MOD nofColumns;
END;
IF (mode = ScaleUp) OR (mode = ScaleUpHeightOnly) THEN
entryHeight := height DIV nofRows;
fixY := height MOD nofRows;
END;
ELSE
ComputeAspect;
END;
END Compute;
PROCEDURE ComputeDefault;
VAR nofEntriesPerRow, nofAvailableRows, nofRequiredRows : LONGINT;
BEGIN
nofEntriesPerRow := width DIV entryWidth;
IF (nofEntriesPerRow = 0) THEN nofEntriesPerRow := 1; END;
IF (nofEntries > 0) & (width > 0) & (height > 0) THEN
IF (nofEntries * entryWidth > width) THEN
nofAvailableRows := height DIV entryHeight;
IF (nofAvailableRows = 0) THEN nofAvailableRows := 1; END;
nofRequiredRows := (nofEntries + nofEntriesPerRow - 1) DIV nofEntriesPerRow;
IF (nofAvailableRows > 1) THEN
IF (nofRequiredRows <= nofAvailableRows) THEN
nofRows := nofRequiredRows;
nofColumns := nofEntriesPerRow;
ELSE
nofRows := nofAvailableRows;
nofColumns := (nofEntries + nofRows - 1) DIV nofRows;
entryWidth := width DIV nofColumns;
END;
ELSE
nofRows := 1;
nofColumns := nofEntries;
entryWidth := width DIV nofEntries;
IF (entryWidth = 0) THEN entryWidth := 1; END;
END;
ELSE
nofRows := 1;
nofColumns := nofEntriesPerRow;
END;
ELSE
nofRows := 1;
nofColumns := nofEntriesPerRow;
END;
ASSERT((nofRows >= 1) & (nofColumns >= 0));
ASSERT(entryWidth > 0); ASSERT(entryHeight > 0);
END ComputeDefault;
PROCEDURE ComputeAspect;
VAR entryRatio, areaRatio : REAL; eWidth, eHeight : LONGINT; doesFit : BOOLEAN;
BEGIN
entryRatio := entryWidth / entryHeight;
areaRatio := width / height;
doesFit := FALSE;
IF (entryRatio >= areaRatio) THEN
nofRows := 0;
WHILE ~doesFit DO
INC(nofRows);
eHeight := height DIV nofRows;
eWidth := ENTIER(eHeight / entryHeight * entryWidth);
IF (eWidth = 0) THEN eWidth := 1; END;
nofColumns := width DIV eWidth;
IF (nofColumns = 0) THEN INC(nofColumns); END;
doesFit := nofEntries <= nofRows * nofColumns;
END;
ELSE
nofColumns := 0;
WHILE ~doesFit DO
INC(nofColumns);
eWidth := width DIV nofColumns;
eHeight := ENTIER(eWidth / entryWidth * entryHeight);
IF (eHeight = 0) THEN eHeight := 1; END;
nofRows := height DIV eHeight;
IF (nofRows = 0) THEN INC(nofRows); END;
doesFit := nofEntries <= nofRows * nofColumns;
END;
END;
entryWidth := width DIV nofColumns;
fixX := width MOD nofColumns;
IF (entryWidth = 0) THEN entryWidth := 1; END;
entryHeight := height DIV nofRows;
fixY := height MOD nofRows;
IF (entryHeight = 0) THEN entryHeight := 1; END;
ASSERT((nofRows >= 1) & (nofColumns >= 0));
ASSERT(entryWidth > 0); ASSERT(entryHeight > 0);
END ComputeAspect;
PROCEDURE Show;
BEGIN
KernelLog.String("--- Layout ---"); KernelLog.Ln;
KernelLog.String("width: "); KernelLog.Int(width, 0);
KernelLog.String(", height: "); KernelLog.Int(height, 0);
KernelLog.Ln;
KernelLog.String("nofEntries: "); KernelLog.Int(nofEntries, 0);
KernelLog.Ln;
KernelLog.String("nofRows: "); KernelLog.Int(nofRows, 0);
KernelLog.String(", nofColumns: "); KernelLog.Int(nofColumns, 0);
KernelLog.Ln;
KernelLog.String("entryWidth: "); KernelLog.Int(entryWidth, 0);
KernelLog.String(", entryHeight: "); KernelLog.Int(entryHeight, 0);
KernelLog.Ln;
KernelLog.String("fixX: "); KernelLog.Int(fixX, 0);
KernelLog.String(", fixY: "); KernelLog.Int(fixY, 0);
KernelLog.Ln;
END Show;
END Layout;
TYPE
DoCloseWindow = OBJECT
VAR
window : WMWindowManager.Window;
PROCEDURE &Init(window : WMWindowManager.Window);
BEGIN
ASSERT(window # NIL);
SELF.window := window;
END Init;
BEGIN {ACTIVE}
window.Close;
END DoCloseWindow;
TYPE
Info = RECORD
nofWindows : LONGINT;
windows : Windows;
extImages : POINTER TO ARRAY OF WMGraphics.Image;
focusIdx : LONGINT;
wTimestamp : LONGINT;
oTimestamp : LONGINT;
END;
TYPE
Base* = OBJECT(WMComponents.VisualComponent)
VAR
clDefault-, clSelected-, clMouseOver-, clSelectedMouseOver-,
clTextDefault-, clTextSelected-, clTextMouseOver-, clTextSelectedMouseOver-,
clIndicateHidden- : WMProperties.ColorProperty;
borderWidth- : WMProperties.Int32Property;
layoutMode- : WMProperties.Int32Property;
itemWidth-, itemHeight- : WMProperties.Int32Property;
info : Info;
layout : Layout;
lock : Locks.Lock;
state : LONGINT;
mouseOverIdx, lastMouseOverIdx : LONGINT;
PROCEDURE &Init;
BEGIN
Init^;
NEW(clDefault, ProtoClDefault, NIL, NIL); properties.Add(clDefault);
NEW(clSelected, ProtoClSelected, NIL, NIL); properties.Add(clSelected);
NEW(clMouseOver, ProtoClMouseOver, NIL, NIL); properties.Add(clMouseOver);
NEW(clSelectedMouseOver, ProtoClSelectedMouseOver, NIL, NIL); properties.Add(clSelectedMouseOver);
NEW(clTextDefault, ProtoClTextDefault, NIL, NIL); properties.Add(clTextDefault);
NEW(clTextSelected, ProtoClTextSelected, NIL, NIL); properties.Add(clTextSelected);
NEW(clTextMouseOver, ProtoClTextMouseOver, NIL, NIL); properties.Add(clTextMouseOver);
NEW(clTextSelectedMouseOver, ProtoClTextSelectedMouseOver, NIL, NIL); properties.Add(clTextSelectedMouseOver);
NEW(clIndicateHidden, ProtoClIndicateHidden, NIL, NIL); properties.Add(clIndicateHidden);
NEW(borderWidth, ProtoBorderWidth, NIL, NIL); properties.Add(borderWidth);
NEW(layoutMode, ProtoLayoutMode, NIL, NIL); properties.Add(layoutMode);
NEW(itemWidth, ProtoItemWidth, NIL, NIL); properties.Add(itemWidth);
NEW(itemHeight, ProtoItemHeight, NIL, NIL); properties.Add(itemHeight);
info.nofWindows := 0;
Clear(info.windows);
info.focusIdx := -1;
info.wTimestamp := WMWindowManager.wTimestamp - 1;
info.oTimestamp := WMWindowManager.oTimestamp - 1;
NEW(layout);
NEW(lock);
state := Running;
mouseOverIdx := -1; lastMouseOverIdx := -1;
END Init;
PROCEDURE PropertyChanged(sender, data : ANY);
BEGIN
IF (data = clDefault) OR (data = clSelected) OR (data = clMouseOver) OR (data = clSelectedMouseOver) OR
(data = clTextDefault) OR (data = clTextSelected) OR (data = clTextMouseOver) OR (data = clTextSelectedMouseOver) OR
(data = clIndicateHidden)
THEN
Invalidate;
ELSIF (data = layoutMode) OR (data = itemWidth) OR (data = itemHeight) OR (data = borderWidth) THEN
Invalidate;
WMWindowManager.IncWTimestamp;
ELSE
PropertyChanged^(sender, data);
END;
END PropertyChanged;
PROCEDURE PointerMove(x, y : LONGINT; keys : SET);
BEGIN
IF enabled.Get() THEN
lock.Acquire;
mouseOverIdx := layout.GetIndexOf(x, y);
lock.Release;
IF (mouseOverIdx # lastMouseOverIdx) THEN
lastMouseOverIdx := mouseOverIdx;
IF (mouseOverIdx >= 0) THEN
Invalidate;
END;
END
ELSE
mouseOverIdx := -1; lastMouseOverIdx := -1;
END;
PointerMove^(x, y, keys)
END PointerMove;
PROCEDURE PointerLeave;
BEGIN
PointerLeave^;
mouseOverIdx := -1; lastMouseOverIdx := -1;
Invalidate
END PointerLeave;
PROCEDURE PointerDown(x, y:LONGINT; keys:SET);
VAR index : LONGINT; window : WMWindowManager.Window;
BEGIN
IF (keys = {}) OR ~enabled.Get() THEN RETURN; END;
IF (keys * {0, 2} # {}) THEN
window := NIL;
lock.Acquire;
index := layout.GetIndexOf(x, y);
IF (index >= 0) & (index < info.nofWindows) THEN
window := info.windows[index];
END;
lock.Release;
IF (window # NIL) THEN
IF keys * {0} # {} THEN
manager.SetIsVisible(window, TRUE);
manager.SetFocus(window);
manager.ToFront(window);
ELSIF keys * {2} # {} THEN
manager.SetIsVisible(window, ~window.isVisible);
END;
END;
END;
END PointerDown;
PROCEDURE DrawInternal(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN; VAR extImage : WMGraphics.Image);
VAR rect : WMRectangles.Rectangle;
BEGIN
ASSERT(lock.HasLock());
ASSERT(window # NIL);
rect := WMRectangles.MakeRect(x, y, x + width, y + height);
IF mouseOver & hasFocus THEN
canvas.Fill(rect, clSelectedMouseOver.Get(), WMGraphics.ModeSrcOverDst);
ELSIF mouseOver THEN
canvas.Fill(rect, clMouseOver.Get(), WMGraphics.ModeSrcOverDst);
ELSIF hasFocus THEN
canvas.Fill(rect, clSelected.Get(), WMGraphics.ModeSrcOverDst);
ELSE
canvas.Fill(rect, clDefault.Get(), WMGraphics.ModeSrcOverDst);
END;
WMGraphicUtilities.RectGlassShade(canvas, rect, borderWidth.Get(), hasFocus);
END DrawInternal;
PROCEDURE DrawBackground(canvas : WMGraphics.Canvas);
VAR
row, column, x, y : LONGINT;
width, height : LONGINT;
i : LONGINT;
BEGIN
DrawBackground^(canvas);
lock.Acquire;
IF (layout.nofEntries > 0) & (layout.width > 0) & (layout.height > 0) THEN
row := 0; column := 0;
FOR i := 0 TO info.nofWindows-1 DO
x := column * layout.entryWidth;
y := row * layout.entryHeight;
width := layout.entryWidth;
IF (column = layout.nofColumns - 1) THEN width := width + layout.fixX; END;
height := layout.entryHeight;
IF (row = layout.nofRows - 1) THEN height := height + layout.fixY; END;
DrawInternal(canvas, x, y, width, height, info.windows[i], i = info.focusIdx, i = mouseOverIdx, info.extImages[i]);
INC(column);
IF (column >= layout.nofColumns) THEN
column := 0;
INC(row);
END;
END;
END;
lock.Release;
END DrawBackground;
END Base;
CONST
Border = 2;
TitleHeight = 20;
TYPE
WindowOverview* = OBJECT(Base)
VAR
aux_canvas : WMGraphics.BufferCanvas;
rect : WMRectangles.Rectangle;
font : WMGraphics.Font;
timer : Kernel.Timer;
PROCEDURE CreateAuxCanvas(width, height : LONGINT; alpha : BOOLEAN) : WMGraphics.BufferCanvas;
VAR canvas : WMGraphics.BufferCanvas; img : WMGraphics.Image;
BEGIN
rect := WMRectangles.MakeRect(0, 0, width, height);
NEW(img);
IF alpha THEN
Raster.Create(img, width, height, Raster.BGRA8888);
ELSE
Raster.Create(img, width, height, WMWindowManager.format);
END;
NEW(canvas, img);
RETURN canvas;
END CreateAuxCanvas;
PROCEDURE PropertyChanged(sender, data : ANY);
BEGIN
PropertyChanged^(sender, data);
IF (data = bounds) THEN
lock.Acquire;
UpdateLayout;
lock.Release;
Invalidate;
END;
END PropertyChanged;
PROCEDURE UpdateLayout;
VAR border : LONGINT;
BEGIN
ASSERT(lock.HasLock());
border := borderWidth.Get();
layout.Compute(info.nofWindows, bounds.GetWidth(), bounds.GetHeight(), itemWidth.Get() , itemHeight.Get(), layoutMode.Get());
IF (layout.entryWidth - 2*border > 0) & (layout.entryHeight - TitleHeight - border > 0) THEN
aux_canvas := CreateAuxCanvas(layout.entryWidth - 2*border, layout.entryHeight - TitleHeight - border, FALSE);
ELSE
aux_canvas := NIL;
END;
END UpdateLayout;
PROCEDURE &Init;
BEGIN
Init^;
layoutMode.Set(Aspect);
borderWidth.Set(Border);
itemWidth.Set(ThumbnailWidth + 2*Border);
itemHeight.Set(ThumbnailHeight + TitleHeight + Border);
takesFocus.Set(TRUE);
font := WMGraphics.GetFont("Oberon", 8, {});
aux_canvas := CreateAuxCanvas(ThumbnailWidth, ThumbnailHeight, FALSE);
NEW(timer);
END Init;
PROCEDURE DrawInternal(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN; VAR extImage : WMGraphics.Image);
VAR
image : Raster.Image;
title : Strings.String;
sizeX, sizeY : LONGINT;
imgX, imgY, imgWidth, imgHeight, winWidth, winHeight : LONGINT;
t_width, t_height : LONGINT;
scaleX, scaleY : REAL;
canvasState : WMGraphics.CanvasState;
BEGIN
DrawInternal^(canvas, x, y, width, height, window, hasFocus, mouseOver, extImage);
canvas.SetFont(font);
t_width := width - 2*Border;
t_height := height - 2*Border - TitleHeight;
IF (aux_canvas # NIL) THEN
aux_canvas.Fill(rect, fillColor.Get(), WMGraphics.ModeSrcOverDst);
winWidth := window.GetWidth();
winHeight := window.GetHeight();
scaleX := t_width / winWidth;
scaleY := t_height / winHeight;
IF (scaleX <= scaleY) THEN
imgWidth := t_width;
imgHeight := ENTIER(winHeight * scaleX);
imgX := 0;
imgY := t_height - imgHeight;
ELSE
imgWidth := ENTIER(winWidth * scaleY);
imgHeight := t_height;
imgX := (t_width - imgWidth) DIV 2;
imgY := 0;
END;
window.Draw(aux_canvas, imgWidth, imgHeight, WMGraphics.ScaleBilinear);
image := aux_canvas.GetImage();
canvas.SaveState(canvasState);
canvas.SetClipRect(WMRectangles.MakeRect(x + Border + imgX, y + TitleHeight + imgY, x + Border + imgX + imgWidth, y + imgY + TitleHeight + imgHeight));
canvas.DrawImage(x + Border + imgX, y + TitleHeight + imgY, image, WMGraphics.ModeSrcOverDst);
canvas.RestoreState(canvasState);
END;
title := window.GetTitle();
IF (title = NIL) THEN title := StrNoName; END;
font.GetStringSize(title^, sizeX, sizeY);
IF ~window.isVisible THEN
canvas.SetColor(clIndicateHidden.Get());
ELSIF (hasFocus OR mouseOver) THEN
canvas.SetColor(WMGraphics.White);
ELSE
canvas.SetColor(WMGraphics.Black);
END;
canvas.DrawString(x + (width - sizeX) DIV 2, y + 15, title^);
END DrawInternal;
PROCEDURE Finalize;
BEGIN
Finalize^;
state := Terminating; timer.Wakeup;
BEGIN {EXCLUSIVE} AWAIT(state = Terminated); END;
END Finalize;
PROCEDURE Update;
BEGIN
IF (info.wTimestamp # WMWindowManager.wTimestamp) OR (info.oTimestamp # WMWindowManager.oTimestamp) THEN
lock.Acquire;
IF (info.wTimestamp # WMWindowManager.wTimestamp) THEN
info.wTimestamp := WMWindowManager.wTimestamp;
GetWindows(info.windows, info.nofWindows);
IF (info.nofWindows > 0) THEN NEW(info.extImages, info.nofWindows); ELSE info.extImages := NIL; END;
info.focusIdx := GetFocusOwnerIndex(info.windows, info.nofWindows);
UpdateLayout;
END;
IF (info.oTimestamp # WMWindowManager.oTimestamp) THEN
info.oTimestamp := WMWindowManager.oTimestamp;
info.focusIdx := GetFocusOwnerIndex(info.windows, info.nofWindows);
END;
lock.Release;
END;
Invalidate;
END Update;
BEGIN {ACTIVE}
LOOP
IF (state # Running) THEN EXIT; END;
Update;
timer.Sleep(UpdateInterval);
END;
BEGIN {EXCLUSIVE} state := Terminated; END;
END WindowOverview;
TYPE
TaskList* = OBJECT(Base)
VAR
style- : WMProperties.Int32Property;
menuLocation- : WMProperties.Int32Property;
showThumbnails- : WMProperties.BooleanProperty;
viewport : WMWindowManager.ViewPort;
dummyInfo : WMWindowManager.WindowInfo;
lastKeys : SET;
lastWindow : WMWindowManager.Window;
PROCEDURE &Init;
BEGIN
Init^;
NEW(style, ProtoTaskListStyle, NIL, NIL); properties.Add(style);
NEW(menuLocation, ProtoTaskListMenuLocation, NIL, NIL); properties.Add(menuLocation);
NEW(showThumbnails, ProtoTaskListShowThumbnails, NIL, NIL); properties.Add(showThumbnails);
CASE style.Get() OF
| Text:
itemWidth.Set(150); itemHeight.Set(20);
layoutMode.Set(ScaleUp);
| Icons:
itemWidth.Set(40); itemHeight.Set(50);
layoutMode.Set(Fixed);
ELSE
itemWidth.Set(100); itemHeight.Set(50);
END;
viewport := WMWindowManager.GetDefaultView();
WMWindowManager.ClearInfo(dummyInfo);
lastKeys := {};
lastWindow := NIL;
END Init;
PROCEDURE PropertyChanged(sender, data : ANY);
BEGIN
PropertyChanged^(sender, data);
IF (data = menuLocation) THEN
Invalidate;
ELSIF (data = bounds) OR (data = style) THEN
lock.Acquire;
layout.Compute(info.nofWindows, bounds.GetWidth(), bounds.GetHeight(), itemWidth.Get(), itemHeight.Get(), layoutMode.Get());
lock.Release;
Invalidate;
END;
END PropertyChanged;
PROCEDURE GoToWindow(window : WMWindowManager.Window; moveViewport : BOOLEAN);
VAR rect : WMRectangles.Rectangle; px, py : LONGINT;
BEGIN
ASSERT(window # NIL);
manager.lock.AcquireWrite;
manager.SetIsVisible(window, TRUE);
manager.SetFocus(window);
manager.ToFront(window);
IF (viewport # NIL) THEN
rect := WMRectangles.MakeRect(ENTIER(viewport.range.l), ENTIER(viewport.range.t), ENTIER(viewport.range.r), ENTIER(viewport.range.b));
IF ~WMRectangles.IsContained(rect, window.bounds) THEN
IF (window.bounds.l < viewport.range.l) OR (window.bounds.t < viewport.range.t) OR
~WMRectangles.Intersect(rect, window.bounds)
THEN
IF (moveViewport) THEN
IF window.GetWidth() < (viewport.range.r - viewport.range.l) THEN
px := window.bounds.l - ENTIER((viewport.range.r - viewport.range.l - window.GetWidth()) / 2);
ELSE
px := window.bounds.l - 20;
END;
IF window.GetHeight() < (viewport.range.b - viewport.range.t) THEN
py := window.bounds.t - ENTIER((viewport.range.b - viewport.range.t - window.GetHeight()) / 2);
ELSE
py := window.bounds.t - 20;
END;
viewport.SetRange(px, py, viewport.range.r - viewport.range.l, viewport.range.b - viewport.range.t, TRUE);
ELSE
IF window.GetWidth() < (viewport.range.r - viewport.range.l) THEN
px := ENTIER(viewport.range.l + (viewport.range.r - viewport.range.l - window.GetWidth()) / 2);
ELSE
px := ENTIER(viewport.range.l) + 20;
END;
IF window.GetHeight() < (viewport.range.b - viewport.range.t) THEN
py := ENTIER(viewport.range.t + (viewport.range.b - viewport.range.t - window.GetHeight()) / 2);
ELSE
py := ENTIER(viewport.range.t) + 20;
END;
manager.SetWindowPos(window, px, py);
END;
END;
END;
END;
manager.lock.ReleaseWrite;
END GoToWindow;
PROCEDURE FocusLost;
BEGIN
FocusLost^;
lastKeys := {};
END FocusLost;
PROCEDURE PointerDown(x, y:LONGINT; keys:SET);
VAR
index : LONGINT; window : WMWindowManager.Window; info2 : WMWindowManager.WindowInfo;
gx, gy: LONGINT;
menu : MenuWindow;
type, index2 : LONGINT;
infoKeys : SET;
res : LONGINT;
rect : WMRectangles.Rectangle;
closeWindow : DoCloseWindow;
same: BOOLEAN;
BEGIN
IF ~enabled.Get() THEN RETURN; END;
lastKeys := keys;
IF (keys * {0, 1, 2} # {}) THEN
window := NIL;
lock.Acquire;
index := layout.GetIndexOf(x, y);
IF (index >= 0) & (index < info.nofWindows) THEN
window := info.windows[index];
rect := layout.GetPositionOf(x, y);
END;
lock.Release;
IF (window # NIL) THEN
same := lastWindow = window;
IF 0 IN keys THEN lastWindow := window; ELSE lastWindow := NIL; END;
IF keys * {0,1} # {} THEN
IF same & window.isVisible THEN
manager.SetIsVisible(window, FALSE);
ELSE
GoToWindow(window, 0 IN keys);
END;
ELSIF keys * {2} # {} THEN
IF (menuLocation.Get() = Top) THEN
ToWMCoordinates(rect.l, rect.t + ShadowWidth, gx, gy);
ELSE
ToWMCoordinates(rect.l, rect.b, gx, gy);
END;
IF window.GetInfo(info2) THEN
NEW(menu, gx, gy, 200, menuLocation.Get(), showThumbnails.Get(), window, info2);
ELSE
NEW(menu, gx, gy, 200, menuLocation.Get(), showThumbnails.Get(), window, dummyInfo);
END;
menu.GetSelection(type, index2, infoKeys);
IF ~(2 IN infoKeys) THEN
IF (type = Document) THEN
IF (info2.handleDocumentInfo # NIL) THEN
info2.handleDocumentInfo(info2.openDocuments[index2], FALSE, res);
END;
GoToWindow(window, 0 IN infoKeys);
ELSIF (type = SystemCommand) THEN
IF (index2 = SystemCommand_Close) THEN
NEW(closeWindow, window);
ELSIF (index2 = SystemCommand_Hide) THEN
manager.SetIsVisible(window, ~window.isVisible);
ELSIF (index2 = SystemCommand_StayOnTop) THEN
manager.SetWindowFlag(window, WMWindowManager.FlagStayOnTop, ~(WMWindowManager.FlagStayOnTop IN window.flags));
ELSIF (index2 = SystemCommand_StayOnBottom) THEN
manager.SetWindowFlag(window, WMWindowManager.FlagStayOnBottom, ~(WMWindowManager.FlagStayOnBottom IN window.flags));
ELSIF (index2 = SystemCommand_Frame) THEN
manager.SetWindowFlag(window, WMWindowManager.FlagFrame, ~(WMWindowManager.FlagFrame IN window.flags));
END;
END;
END;
END;
ELSE
lastWindow := NIL;
END;
END;
END PointerDown;
PROCEDURE PointerUp(x, y : LONGINT; keys : SET);
VAR window : WMWindowManager.Window; windowCloser : DoCloseWindow; index : LONGINT;
BEGIN
PointerUp^(x, y, keys);
IF ~enabled.Get() THEN RETURN; END;
IF (lastKeys * {0, 2} = {0, 2}) & ((keys = {0}) OR (keys = {2})) THEN
window := NIL;
lock.Acquire;
index := layout.GetIndexOf(x, y);
IF (index >= 0) & (index < info.nofWindows) THEN
window := info.windows[index];
END;
lock.Release;
IF (window # NIL) & (window = lastWindow) THEN
NEW(windowCloser, window);
END;
END;
lastKeys := keys;
END PointerUp;
PROCEDURE DrawInternalIcons(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN; VAR extImage : WMGraphics.Image);
VAR
image : WMGraphics.Image;
imageRect, indicatorRect : WMRectangles.Rectangle;
title : Strings.String;
BEGIN
CASE menuLocation.Get() OF
|Top:
imageRect := WMRectangles.MakeRect(x + Border, y + MenuSize, x + width - Border, y + height - Border);
indicatorRect := WMRectangles.MakeRect(x + Border, y + Border, x + width - Border, y + MenuSize - Border);
|Left:
imageRect := WMRectangles.MakeRect(x + MenuSize, y + Border, x + width - Border, y + height - Border);
indicatorRect := WMRectangles.MakeRect(x + Border, y + Border, x + MenuSize - Border, y + height - Border);
|Right:
imageRect := WMRectangles.MakeRect(x + Border, y + Border, x + width - MenuSize, y + height - Border);
indicatorRect := WMRectangles.MakeRect(x + width - MenuSize + Border, y + Border, x + width - Border, y + height - Border);
|Bottom:
imageRect := WMRectangles.MakeRect(x + Border, y + Border, x + width - Border, y + height - MenuSize);
indicatorRect := WMRectangles.MakeRect(x + Border, y + height - MenuSize + Border, x + width - Border, y + height - Border);
END;
IF (window.icon # NIL) THEN
image := window.icon;
ELSE
IF (extImage = NIL) THEN extImage := GetWindowImage(window, 64, 64); END;
image := extImage;
END;
IF (image # NIL) THEN
canvas.ScaleImage(image,
WMRectangles.MakeRect(0, 0, image.width, image.height),
imageRect,
WMGraphics.ModeSrcOverDst,
WMGraphics.ScaleBilinear
);
IF ~window.isVisible THEN
canvas.Fill(indicatorRect, clIndicateHidden.Get(), WMGraphics.ModeSrcOverDst);
WMGraphicUtilities.ExtRectGlassShade(canvas, indicatorRect, {}, 1, FALSE);
END;
END;
IF (window.icon = NIL) THEN
title := window.GetTitle();
IF (title = NIL) THEN title := StrNoName; END;
IF ~window.isVisible THEN
canvas.SetColor(WMGraphics.Yellow);
ELSIF hasFocus & ~mouseOver THEN
canvas.SetColor(WMGraphics.White);
ELSE
canvas.SetColor(WMGraphics.Black);
END;
canvas.DrawString(x + 4, y + height - 5, title^);
END;
END DrawInternalIcons;
PROCEDURE DrawInternalText(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN);
VAR title : Strings.String;
BEGIN
title := window.GetTitle();
IF (title = NIL) THEN title := StrNoName; END;
IF ~window.isVisible THEN
canvas.SetColor(clIndicateHidden.Get());
ELSIF mouseOver & hasFocus THEN
canvas.SetColor(clTextSelectedMouseOver.Get());
ELSIF mouseOver THEN
canvas.SetColor(clTextMouseOver.Get());
ELSIF hasFocus THEN
canvas.SetColor(clTextSelected.Get());
ELSE
canvas.SetColor(clTextDefault.Get());
END;
canvas.DrawString(x + 4, y + height - 5, title^);
END DrawInternalText;
PROCEDURE DrawInternal(canvas : WMGraphics.Canvas; x, y, width, height : LONGINT; window : WMWindowManager.Window; hasFocus, mouseOver : BOOLEAN; VAR extImage : WMGraphics.Image);
BEGIN
canvas.SetClipRect(WMRectangles.MakeRect(x, y, x + width, y + height));
DrawInternal^(canvas, x, y, width, height, window, hasFocus, mouseOver, extImage);
CASE style.Get() OF
|Text: DrawInternalText(canvas, x, y, width, height, window, hasFocus, mouseOver);
|Icons: DrawInternalIcons(canvas, x, y, width, height, window, hasFocus, mouseOver, extImage);
ELSE
END;
END DrawInternal;
PROCEDURE Finalize;
BEGIN
Finalize^;
state := Terminating;
WMWindowManager.IncOTimestamp;
BEGIN {EXCLUSIVE} AWAIT(state = Terminated); END;
END Finalize;
BEGIN {ACTIVE}
LOOP
IF (state # Running) THEN EXIT; END;
WMWindowManager.AwaitChange(info.wTimestamp, info.oTimestamp);
IF (state # Running) THEN EXIT; END;
lock.Acquire;
IF (info.wTimestamp # WMWindowManager.wTimestamp) THEN
info.wTimestamp := WMWindowManager.wTimestamp;
GetWindows(info.windows, info.nofWindows);
IF (info.nofWindows > 0) THEN NEW(info.extImages, info.nofWindows); ELSE info.extImages := NIL; END;
info.focusIdx := GetFocusOwnerIndex(info.windows, info.nofWindows);
layout.Compute(info.nofWindows, bounds.GetWidth(), bounds.GetHeight(), itemWidth.Get(), itemHeight.Get(), layoutMode.Get());
END;
IF (info.oTimestamp # WMWindowManager.oTimestamp) THEN
info.oTimestamp := WMWindowManager.oTimestamp;
info.focusIdx := GetFocusOwnerIndex(info.windows, info.nofWindows);
END;
lock.Release;
Invalidate;
END;
BEGIN {EXCLUSIVE} state := Terminated; END;
END TaskList;
CONST
ShadowWidth = 5;
LineHeight = 20;
LeftBorder = 25;
RightBorder = 5;
NofSystemCommands = 3;
SystemCommand = 99;
SystemCommand_Close = 0;
SystemCommand_Hide = 1;
SystemCommand_StayOnTop = 2;
SystemCommand_StayOnBottom = 3;
SystemCommand_Frame = 4;
Document = 1;
TYPE
InfoView = OBJECT(WMComponents.VisualComponent)
VAR
window : WMWindowManager.Window;
info : WMWindowManager.WindowInfo;
nofDocuments: LONGINT;
documentOffset, commandOffset, imageOffset : LONGINT;
owner : MenuWindow;
menuLocation : LONGINT;
showThumbnails : BOOLEAN;
type, index : LONGINT;
keys : SET;
xt, yt : LONGINT;
image : WMGraphics.Image;
imgX, imgY : LONGINT;
imageYes, imageNo : WMGraphics.Image;
PROCEDURE &New(owner : MenuWindow; menuLocation : LONGINT; showThumbnails : BOOLEAN);
BEGIN
ASSERT(owner # NIL);
SELF.owner := owner;
SELF.menuLocation := menuLocation;
SELF.showThumbnails := showThumbnails;
Init;
nofDocuments := 0;
keys := {};
xt := -1; yt := -1;
imageYes := WMGraphics.LoadImage("Navigation.rep://Yes.png", TRUE);
imageNo := WMGraphics.LoadImage("Navigation.rep://No.png", TRUE);
END New;
PROCEDURE SetInfo(window : WMWindowManager.Window; CONST info : WMWindowManager.WindowInfo);
VAR
vc : WMComponents.VisualComponent; ptr : ANY; i : LONGINT; aux_canvas : WMGraphics.BufferCanvas;
height, imageWidth, imageHeight : LONGINT;
BEGIN
SELF.window := window;
Acquire;
SELF.info := info;
nofDocuments := 0;
FOR i := 0 TO LEN(info.openDocuments)-1 DO
IF (info.openDocuments[i].name # "") THEN INC(nofDocuments); END;
END;
vc := NIL;
IF (info.vc.generator # NIL) THEN
ptr := info.vc.generator();
IF (ptr # NIL) & (ptr IS WMComponents.VisualComponent) THEN
vc := ptr (WMComponents.VisualComponent);
END;
END;
Release;
height := NofSystemCommands * LineHeight + LineHeight;
IF (nofDocuments > 0) THEN
height := height + nofDocuments * LineHeight + LineHeight;
END;
IF (vc # NIL) THEN
vc.alignment.Set(WMComponents.AlignNone);
vc.bounds.SetTop(height);
vc.bounds.SetHeight(info.vc.height);
height := height + ((info.vc.height + LineHeight - 1) DIV LineHeight) * LineHeight + RightBorder;
vc.bounds.SetLeft(LeftBorder);
vc.bounds.SetRight(bounds.GetWidth() - RightBorder);
END;
IF showThumbnails THEN
imageWidth := bounds.GetWidth() - LeftBorder - RightBorder;
imageHeight := ENTIER(3 * imageWidth / 4);
NEW(image);
Raster.Create(image, imageWidth, imageHeight, Raster.BGRA8888);
NEW(aux_canvas, image);
aux_canvas.Fill(WMRectangles.MakeRect(0, 0, imageWidth, imageHeight), WMGraphics.White, WMGraphics.ModeCopy);
DrawIntoCanvas(window, aux_canvas, imageWidth, imageHeight, imgX, imgY);
IF (menuLocation = Top) THEN
imageOffset := RightBorder;
ELSE
imageOffset := height;
END;
height := height + ((imageHeight + LineHeight - 1) DIV LineHeight) * LineHeight + RightBorder;
ELSE
imageWidth := 0; imageHeight := 0;
END;
IF (vc # NIL) THEN
IF (menuLocation = Top) THEN
vc.bounds.SetTop(2*RightBorder + ((imageHeight + LineHeight - 1) DIV LineHeight) * LineHeight);
vc.bounds.SetHeight(info.vc.height);
END;
AddContent(vc);
END;
bounds.SetHeight(height);
IF (menuLocation = Top) THEN
documentOffset := height - (NofSystemCommands + nofDocuments + 1) * LineHeight;
commandOffset := height - NofSystemCommands * LineHeight;
ELSE
commandOffset := 0;
documentOffset := (NofSystemCommands + 1) * LineHeight;
END;
Invalidate;
END SetInfo;
PROCEDURE PointerMove(x, y : LONGINT; keys : SET);
BEGIN
IF enabled.Get() THEN
xt := x; yt := y;
Invalidate;
ELSE
xt := -1; yt := -1;
END;
PointerMove^(x, y, keys)
END PointerMove;
PROCEDURE PointerLeave;
BEGIN
PointerLeave^;
xt := -1; yt := -1;
Invalidate
END PointerLeave;
PROCEDURE PointerDown(x, y:LONGINT; keys:SET);
BEGIN
IF enabled.Get() THEN
SELF.keys := keys;
type := -1;
index := -1;
IF (commandOffset <= y) & (y < commandOffset + NofSystemCommands * LineHeight) THEN
type := SystemCommand;
IF (y < commandOffset + LineHeight) THEN
index := SystemCommand_Close;
ELSIF (y < commandOffset + 2 * LineHeight) THEN
index := SystemCommand_Hide;
ELSIF (y < commandOffset + 3 * LineHeight) THEN
index := SystemCommand_StayOnTop;
ELSIF (y < commandOffset + 4 * LineHeight) THEN
index := SystemCommand_StayOnBottom;
ELSIF (y < commandOffset + 5 * LineHeight) THEN
index := SystemCommand_Frame;
END;
ELSIF (documentOffset <= y) & (y < documentOffset + nofDocuments * LineHeight) THEN
type := Document;
index := (y - documentOffset) DIV LineHeight;
END;
END;
owner.Close;
END PointerDown;
PROCEDURE Draw(canvas : WMGraphics.Canvas);
VAR y : LONGINT;
PROCEDURE IsHighlighted(y : LONGINT) : BOOLEAN;
BEGIN
RETURN (y <= yt) & (yt < y + LineHeight);
END IsHighlighted;
PROCEDURE DrawBg(y : LONGINT);
BEGIN
IF IsHighlighted(y) THEN
canvas.Fill(WMRectangles.MakeRect(0, y, bounds.GetWidth(), y + LineHeight), LONGINT(060606A0H), WMGraphics.ModeSrcOverDst);
canvas.SetColor(WMGraphics.White);
ELSE
canvas.SetColor(WMGraphics.Black);
END;
END DrawBg;
PROCEDURE DrawDocuments(VAR y : LONGINT);
VAR row : LONGINT;
BEGIN
FOR row := 1 TO nofDocuments DO
DrawBg(y);
IF info.openDocuments[row - 1].modified THEN
canvas.SetColor(WMGraphics.Red);
ELSIF (info.openDocuments[row - 1].hasFocus) THEN
canvas.SetColor(00DA00FFH);
ELSIF IsHighlighted(y) THEN
canvas.SetColor(WMGraphics.White);
ELSE
canvas.SetColor(WMGraphics.Black);
END;
canvas.DrawString(LeftBorder, y + 16, info.openDocuments[row - 1].name);
INC(y, LineHeight);
END;
END DrawDocuments;
PROCEDURE DrawSystemCommands(VAR y : LONGINT);
BEGIN
canvas.SetColor(WMGraphics.Black);
DrawBg(y);
canvas.DrawString(LeftBorder, y + 16, "Close"); INC(y, LineHeight);
DrawBg(y);
DrawYesNo(y, window.isVisible);
canvas.DrawString(LeftBorder, y + 16, "Visible"); INC(y, LineHeight);
DrawBg(y);
DrawYesNo(y, WMWindowManager.FlagStayOnTop IN window.flags);
canvas.DrawString(LeftBorder, y + 16, "StayOnTop"); INC(y, LineHeight);
IF (NofSystemCommands > 3) THEN
DrawBg(y);
DrawYesNo(y, WMWindowManager.FlagStayOnBottom IN window.flags);
canvas.DrawString(LeftBorder, y + 16, "StayOnBottom"); INC(y, LineHeight);
END;
IF (NofSystemCommands > 4) THEN
DrawBg(y);
DrawYesNo(y, WMWindowManager.FlagFrame IN window.flags);
canvas.DrawString(LeftBorder, y + 16, "Frame"); INC(y, LineHeight);
END;
END DrawSystemCommands;
PROCEDURE DrawLine(VAR y : LONGINT);
BEGIN
canvas.Line(LeftBorder, y + (LineHeight DIV 2), bounds.GetWidth(), y + (LineHeight DIV 2), LONGINT(0C0C0C0FFH), WMGraphics.ModeCopy);
INC(y, LineHeight);
END DrawLine;
PROCEDURE DrawImage(y : LONGINT);
VAR canvasState : WMGraphics.CanvasState;
BEGIN
canvas.SaveState(canvasState);
canvas.SetClipRect(WMRectangles.MakeRect(LeftBorder, y, bounds.GetWidth() - RightBorder, y + image.height));
canvas.DrawImage(LeftBorder + imgX, y + imgY, image, WMGraphics.ModeCopy);
WMGraphicUtilities.DrawRect(canvas,
WMRectangles.MakeRect(LeftBorder, y, bounds.GetWidth() - RightBorder, y + image.height),
LONGINT(0C0C0C0C0H), WMGraphics.ModeSrcOverDst
);
canvas.RestoreState(canvasState);
END DrawImage;
PROCEDURE DrawYesNo(y : LONGINT; value : BOOLEAN);
BEGIN
IF value & (imageYes # NIL) THEN
canvas.DrawImage(5, y + 6, imageYes, WMGraphics.ModeSrcOverDst);
ELSIF ~value & (imageNo # NIL) THEN
canvas.DrawImage(5, y + 6, imageNo, WMGraphics.ModeSrcOverDst);
END;
END DrawYesNo;
BEGIN
Draw^(canvas);
canvas.Fill(WMRectangles.MakeRect(0, 0, LeftBorder - 5, bounds.GetHeight()), LONGINT(0C0C0C0C0H), WMGraphics.ModeSrcOverDst);
IF (menuLocation = Top) THEN
IF (nofDocuments > 0) THEN
y := documentOffset - LineHeight;
DrawLine(y);
DrawDocuments(y);
END;
y := commandOffset - LineHeight;
DrawLine(y);
DrawSystemCommands(y);
ELSE
y := commandOffset;
DrawSystemCommands(y);
DrawLine(y);
IF (nofDocuments > 0) THEN
DrawDocuments(y);
DrawLine(y);
END;
END;
IF showThumbnails & (image # NIL)THEN
DrawImage(imageOffset);
END;
END Draw;
END InfoView;
TYPE
MenuWindow = OBJECT (WMComponents.FormWindow)
VAR
isClosed : BOOLEAN;
shadowRectB, shadowRectR, borderRect : WMRectangles.Rectangle;
infoView : InfoView;
info : WMWindowManager.WindowInfo;
close : BOOLEAN;
PROCEDURE GetSelection(VAR type, index : LONGINT; VAR keys : SET);
BEGIN {EXCLUSIVE}
AWAIT(close);
type := infoView.type;
index := infoView.index;
keys := infoView.keys;
END GetSelection;
PROCEDURE&New(
x, y, width, menuLocation : LONGINT;
showThumbnails : BOOLEAN;
window : WMWindowManager.Window; CONST info : WMWindowManager.WindowInfo
);
VAR height : LONGINT;
BEGIN
ASSERT((width > 0));
isClosed := FALSE;
SELF.info := info;
NEW(infoView, SELF, menuLocation, showThumbnails);
infoView.fillColor.Set(WMGraphics.White);
infoView.bounds.SetWidth(width);
infoView.SetInfo(window, info);
height := infoView.bounds.GetHeight();
Init(width+ ShadowWidth, infoView.bounds.GetHeight() + ShadowWidth, TRUE);
SetContent(infoView);
SetTitle(Strings.NewString("WMNavigateMenu"));
infoView.alignment.Set(WMComponents.AlignNone);
infoView.bounds.SetExtents(width, height);
borderRect := WMRectangles.MakeRect(0, 0, width, height);
shadowRectB := WMRectangles.MakeRect(ShadowWidth, height, width+ShadowWidth, height+ShadowWidth);
shadowRectR := WMRectangles.MakeRect(width, ShadowWidth, width+ShadowWidth, height);
IF (menuLocation = Top) THEN
y := y - (infoView.bounds.GetHeight() + ShadowWidth);
END;
manager := WMWindowManager.GetDefaultManager();
manager.Add(x, y, SELF, {WMWindowManager.FlagStayOnTop, WMWindowManager.FlagNavigation, WMWindowManager.FlagHidden});
manager.SetFocus(SELF);
END New;
PROCEDURE Draw(canvas : WMGraphics.Canvas; w, h, q : LONGINT);
BEGIN
Draw^(canvas, w, h, q);
canvas.Fill(shadowRectB, 04FH, WMGraphics.ModeSrcOverDst);
canvas.Fill(shadowRectR, 04FH, WMGraphics.ModeSrcOverDst);
WMGraphicUtilities.DrawRect(canvas, borderRect, WMGraphics.Black, WMGraphics.ModeCopy);
END Draw;
PROCEDURE SetClosed;
BEGIN
BEGIN {EXCLUSIVE} close := TRUE; END;
END SetClosed;
PROCEDURE Close;
BEGIN
SetClosed;
Close^;
END Close;
PROCEDURE KeyEvent(ucs : LONGINT; flags : SET; keysym : LONGINT);
BEGIN
IF ~(Inputs.Release IN flags) THEN
IF keysym = 0FF54H THEN
ELSIF keysym = 0FF52H THEN
ELSIF (keysym = Inputs.KsTab) OR (keysym = Inputs.KsReturn) THEN
ELSIF (keysym = Inputs.KsEscape) THEN
Close;
ELSE
END;
ELSE
END;
END KeyEvent;
PROCEDURE FocusLost;
BEGIN
FocusLost^;
Close;
END FocusLost;
END MenuWindow;
CONST
MenuSize = 10;
TYPE
Window = OBJECT(WMComponents.FormWindow)
VAR
myId : LONGINT;
PROCEDURE &New*(id : LONGINT; component : WMComponents.VisualComponent; x, y, width, height : LONGINT; alpha : BOOLEAN; flags : SET);
VAR title, nbr : ARRAY 32 OF CHAR;
BEGIN
ASSERT((component # NIL) & (width > 0) & (height > 0));
Init(width, height, alpha);
SELF.myId := id;
SetContent(component);
COPY("WMNavigate", title); Strings.IntToStr(id, nbr); Strings.Append(title, nbr);
SetTitle(Strings.NewString(title));
IF (WMWindowManager.FlagNavigation IN flags) THEN
WMWindowManager.ExtAddViewBoundWindow(SELF, x, y, NIL, flags);
ELSE
WMWindowManager.ExtAddWindow(SELF, x, y, flags);
END;
component.bounds.SetExtents(width, height);
pointerThreshold := 1;
END New;
PROCEDURE Close;
BEGIN
Close^;
windows[myId] := NIL;
END Close;
END Window;
TYPE
Windows = ARRAY MaxNofWindows OF WMWindowManager.Window;
VAR
windows : ARRAY MaxNavigationWindows OF Window;
manager : WMWindowManager.WindowManager;
viewport : WMWindowManager.ViewPort;
StrWindowOverview : Strings.String;
StrNoName : Strings.String;
width, height : LONGINT;
windowsAreHidden : BOOLEAN;
navigationIsHidden : BOOLEAN;
ProtoClDefault, ProtoClSelected, ProtoClMouseOver, ProtoClSelectedMouseOver,
ProtoClTextDefault, ProtoClTextSelected, ProtoClTextMouseOver, ProtoClTextSelectedMouseOver,
ProtoClIndicateHidden : WMProperties.ColorProperty;
ProtoBorderWidth : WMProperties.Int32Property;
ProtoTaskListStyle, ProtoTaskListMenuLocation : WMProperties.Int32Property;
ProtoTaskListShowThumbnails : WMProperties.BooleanProperty;
ProtoItemWidth, ProtoItemHeight : WMProperties.Int32Property;
ProtoLayoutMode : WMProperties.Int32Property;
PROCEDURE GetWindowImage(window : WMWindowManager.Window; width, height : LONGINT) : WMGraphics.Image;
VAR image : WMGraphics.Image; canvas : WMGraphics.BufferCanvas; ignore : LONGINT;
BEGIN
ASSERT((window # NIL));
NEW(image);
Raster.Create(image, width, height, Raster.BGRA8888);
NEW(canvas, image);
DrawIntoCanvas(window, canvas, width, height, ignore, ignore);
RETURN image;
END GetWindowImage;
PROCEDURE DrawIntoCanvas(window : WMWindowManager.Window; canvas : WMGraphics.BufferCanvas; width, height : LONGINT; VAR offsetX, offsetY : LONGINT);
VAR image : Raster.Image; winWidth, winHeight, imgWidth, imgHeight : LONGINT; scaleX, scaleY : REAL;
BEGIN
ASSERT((window # NIL) & (canvas # NIL));
image := canvas.GetImage();
canvas.Fill(WMRectangles.MakeRect(0, 0, image.width, image.height), 0, WMGraphics.ModeCopy);
winWidth := window.GetWidth();
winHeight := window.GetHeight();
scaleX := width / winWidth;
scaleY := height / winHeight;
IF (scaleX <= scaleY) THEN
imgWidth := width;
imgHeight := ENTIER(winHeight * scaleX);
offsetX := 0;
offsetY := height - imgHeight;
ELSE
imgWidth := ENTIER(winWidth * scaleY);
imgHeight := height;
offsetX := (width - imgWidth) DIV 2;
offsetY := 0;
END;
window.Draw(canvas, imgWidth, imgHeight, WMGraphics.ScaleBilinear);
END DrawIntoCanvas;
PROCEDURE Clear(VAR windows : Windows);
VAR i : LONGINT;
BEGIN
FOR i := 0 TO LEN(windows)-1 DO
windows[i] := NIL;
END;
END Clear;
PROCEDURE GetFocusOwnerIndex(CONST windows : Windows; nofWindows : LONGINT) : LONGINT;
VAR index : LONGINT; focusOwner : WMWindowManager.Window;
BEGIN
focusOwner := manager.GetFocusOwner();
index := 0;
WHILE (index < nofWindows) & (windows[index] # focusOwner) DO INC(index); END;
IF (index >= LEN(windows)) THEN
index := -1;
END;
RETURN index;
END GetFocusOwnerIndex;
PROCEDURE GetWindows(VAR windows : Windows; VAR nofWindows : LONGINT);
VAR
window : WMWindowManager.Window;
PROCEDURE IsUserWindow(window : WMWindowManager.Window) : BOOLEAN;
BEGIN
ASSERT(window # NIL);
RETURN {WMWindowManager.FlagHidden, WMWindowManager.FlagDecorWindow} * window.flags = {};
END IsUserWindow;
PROCEDURE SortWindowsById(VAR windows : Windows);
VAR temp : WMWindowManager.Window; i, j : LONGINT;
BEGIN
FOR i := 0 TO nofWindows-1 DO
FOR j := 0 TO nofWindows-2 DO
IF (windows[j].id > windows[j+1].id) THEN
temp := windows[j+1];
windows[j+1] := windows[j];
windows[j] := temp;
END;
END;
END;
END SortWindowsById;
BEGIN
ASSERT((manager # NIL));
Clear(windows);
manager.lock.AcquireWrite;
nofWindows := 0;
window := manager.GetFirst();
WHILE (window # NIL) & (nofWindows < MaxNofWindows) DO
IF IsUserWindow(window) THEN
windows[nofWindows] := window;
INC(nofWindows);
END;
window := manager.GetNext(window);
END;
manager.lock.ReleaseWrite;
IF (nofWindows > 1) THEN SortWindowsById(windows); END;
END GetWindows;
PROCEDURE Open*(context : Commands.Context);
VAR
options : Options.Options;
id, x, y, w, h : LONGINT;
filename : ARRAY 256 OF CHAR;
content : XML.Content;
flags : SET;
BEGIN {EXCLUSIVE}
NEW(options);
options.Add("f", "frame", Options.Flag);
options.Add("s", "stayOnTop", Options.Flag);
options.Add("v", "viewport", Options.Flag);
IF options.Parse(context.arg, context.out) THEN
context.arg.SkipWhitespace; context.arg.Int(id, FALSE);
context.arg.SkipWhitespace; context.arg.Int(x, FALSE);
context.arg.SkipWhitespace; context.arg.Int(y, FALSE);
context.arg.SkipWhitespace; context.arg.String(filename);
IF (filename # "") THEN
IF (0 <= id) & (id < MaxNavigationWindows) THEN
IF (windows[id] = NIL) THEN
content := WMComponents.GetComponent(filename);
IF (content # NIL) THEN
IF (content IS WMComponents.VisualComponent) THEN
w := content(WMComponents.VisualComponent).bounds.GetWidth();
h := content(WMComponents.VisualComponent).bounds.GetHeight();
IF (w <= 0) THEN w := width; END;
IF (h <= 0) THEN h := height; END;
flags := {WMWindowManager.FlagHidden};
IF options.GetFlag("frame") THEN INCL(flags, WMWindowManager.FlagFrame); END;
IF options.GetFlag("stayOnTop") THEN INCL(flags, WMWindowManager.FlagStayOnTop); END;
IF options.GetFlag("viewport") THEN INCL(flags, WMWindowManager.FlagNavigation); END;
NEW(windows[id], id, content(WMComponents.VisualComponent), x, y, w, h, TRUE, flags);
WMWindowManager.IncWTimestamp;
windows[id].CSChanged;
ELSE
context.out.String("WMNavigate: Expected visual component"); context.out.Ln;
END;
ELSE
context.out.String("WMNavigate: Could not load component from file ");
context.out.String(filename); context.out.Ln;
END;
ELSE
context.out.String("WMNavigate: Window with id already open"); context.out.Ln;
END;
ELSE
context.out.String("WMNavigate: Invalid id parameter"); context.out.Ln;
END;
ELSE
context.out.String("WMNavigate.Open id x y width height componentFile ~"); context.out.Ln;
END;
END;
END Open;
PROCEDURE Close*(context : Commands.Context);
VAR id : LONGINT;
BEGIN {EXCLUSIVE}
IF context.arg.GetInteger(id, FALSE) & (0 <= id) & (id < MaxNavigationWindows) THEN
IF (windows[id] # NIL) THEN
windows[id].Close;
windows[id] := NIL;
ELSE
context.out.String("WMNavigate: Window with id is not open"); context.out.Ln;
END;
ELSE
context.out.String("WMNavigate: Invalid id parameter"); context.out.Ln;
END;
END Close;
PROCEDURE ToggleVisibility*(context : Commands.Context);
VAR id : LONGINT;
BEGIN {EXCLUSIVE}
IF context.arg.GetInteger(id, FALSE) & (0 <= id) & (id < MaxNavigationWindows) THEN
IF (windows[id] # NIL) THEN
manager.SetIsVisible(windows[id], ~windows[id].isVisible);
ELSE
context.out.String("WMNavigate: Window with id is not open"); context.out.Ln;
END;
ELSE
context.out.String("WMNavigate: Invalid id parameter"); context.out.Ln;
END;
END ToggleVisibility;
PROCEDURE HideNavigation*;
BEGIN {EXCLUSIVE}
SetIsVisibleNavigation(FALSE);
navigationIsHidden := TRUE;
END HideNavigation;
PROCEDURE RestoreNavigation*;
BEGIN {EXCLUSIVE}
SetIsVisibleNavigation(TRUE);
navigationIsHidden := FALSE;
END RestoreNavigation;
PROCEDURE ToggleNavigation*;
BEGIN {EXCLUSIVE}
navigationIsHidden := ~navigationIsHidden;
SetIsVisibleNavigation(~navigationIsHidden);
END ToggleNavigation;
PROCEDURE SetIsVisibleNavigation(isVisible : BOOLEAN);
VAR window : WMWindowManager.Window;
BEGIN
manager.lock.AcquireWrite;
window := manager.GetFirst();
WHILE (window # NIL) DO
IF (WMWindowManager.FlagNavigation IN window.flags) THEN
manager.SetIsVisible(window, isVisible);
END;
window := manager.GetNext(window);
END;
manager.lock.ReleaseWrite;
END SetIsVisibleNavigation;
PROCEDURE FocusToNext*;
BEGIN
SwitchFocus(FALSE);
END FocusToNext;
PROCEDURE FocusToPrevious*;
BEGIN
SwitchFocus(TRUE);
END FocusToPrevious;
PROCEDURE SwitchFocus(backwards : BOOLEAN);
VAR windows : Windows; nofWindows, focusIdx : LONGINT;
BEGIN {EXCLUSIVE}
GetWindows(windows, nofWindows);
IF (nofWindows >= 1) THEN
focusIdx := GetFocusOwnerIndex(windows, nofWindows);
IF (focusIdx >= 0) THEN
IF (nofWindows > 1) THEN
IF backwards THEN
IF focusIdx > 0 THEN
DEC(focusIdx);
ELSE
focusIdx := nofWindows - 1;
END;
ELSE
focusIdx := (focusIdx + 1) MOD nofWindows;
END;
END;
ELSE
focusIdx := 0;
END;
ASSERT((0 <= focusIdx) & (focusIdx < LEN(windows)) & (windows[focusIdx] # NIL));
manager.lock.AcquireWrite;
manager.ToFront(windows[focusIdx]);
manager.SetFocus(windows[focusIdx]);
manager.lock.ReleaseWrite;
END;
END SwitchFocus;
PROCEDURE HideAll*;
BEGIN {EXCLUSIVE}
SetIsVisible(FALSE);
windowsAreHidden := TRUE;
END HideAll;
PROCEDURE RestoreAll*;
BEGIN {EXCLUSIVE}
SetIsVisible(TRUE);
windowsAreHidden := FALSE;
END RestoreAll;
PROCEDURE ToggleAll*;
BEGIN {EXCLUSIVE}
windowsAreHidden := ~windowsAreHidden;
SetIsVisible(~windowsAreHidden);
END ToggleAll;
PROCEDURE SetIsVisible(isVisible : BOOLEAN);
VAR windows : Windows; nofWindows, i : LONGINT;
BEGIN
GetWindows(windows, nofWindows);
manager.lock.AcquireWrite;
FOR i := 0 TO nofWindows-1 DO
manager.SetIsVisible(windows[i], isVisible);
END;
manager.lock.ReleaseWrite;
END SetIsVisible;
PROCEDURE ToggleFullscreen*;
VAR window : WMWindowManager.Window; newWidth, newHeight : LONGINT;
BEGIN {EXCLUSIVE}
manager.lock.AcquireWrite;
window := manager.GetFocusOwner();
IF (window.flags * {WMWindowManager.FlagNavigation, WMWindowManager.FlagHidden, WMWindowManager.FlagNoResizing} = {}) THEN
IF (window.GetWidth() = width) & (window.GetHeight() = height) THEN
manager.SetWindowPos(window, window.normalBounds.l, window.normalBounds.t);
newWidth := window.normalBounds.r - window.normalBounds.l;
newHeight := window.normalBounds.b - window.normalBounds.t;
ELSE
window.normalBounds := window.bounds;
manager.SetWindowPos(window, ENTIER(viewport.range.l), ENTIER(viewport.range.t));
newWidth := width;
newHeight := height;
END;
manager.SetWindowSize(window, newWidth, newHeight);
window.Resized(newWidth, newHeight);
END;
manager.lock.ReleaseWrite;
END ToggleFullscreen;
PROCEDURE MoveWindow*(context : Commands.Context);
VAR options : Options.Options; window : WMWindowManager.Window; x, y : LONGINT;
BEGIN {EXCLUSIVE}
NEW(options);
options.Add("d", "display", Options.Flag);
IF options.Parse(context.arg, context.out) THEN
IF context.arg.GetInteger(x, FALSE) & context.arg.GetInteger(y, FALSE) THEN
IF options.GetFlag("display") THEN
x := x * width;
y := y * height;
END;
window := manager.GetFocusOwner();
IF (window IS WMComponents.FormWindow) THEN
manager.SetWindowPos(window, window.bounds.l + x, window.bounds.t + y);
END;
END;
END;
END MoveWindow;
PROCEDURE CloseWindow*;
VAR window : WMWindowManager.Window; formWindow : WMComponents.FormWindow;
BEGIN {EXCLUSIVE}
window := manager.GetFocusOwner();
IF window IS WMComponents.FormWindow THEN
formWindow := window (WMComponents.FormWindow);
formWindow.Close;
END;
END CloseWindow;
PROCEDURE SetViewportRange*(context : Commands.Context);
VAR options : Options.Options; x, y, w, h : LONGINT;
BEGIN
NEW(options);
options.Add("s", "showTransition", Options.Flag);
options.Add("d", "display", Options.Flag);
IF options.Parse(context.arg, context.out) THEN
x := 0; y := 0; w := 0; h := 0;
context.arg.SkipWhitespace; context.arg.Int(x, FALSE);
context.arg.SkipWhitespace; context.arg.Int(y, FALSE);
context.arg.SkipWhitespace; context.arg.Int(w, FALSE);
context.arg.SkipWhitespace; context.arg.Int(h, FALSE);
IF options.GetFlag("display") THEN
x := x * width; w := w * width;
y := y * height; h := h * height;
END;
IF w = 0 THEN w := width; END;
IF h = 0 THEN h := height; END;
viewport.SetRange(x, y, w, h, options.GetFlag("showTransition"));
END;
END SetViewportRange;
PROCEDURE GenTaskList*() : XML.Element;
VAR t : TaskList;
BEGIN
NEW(t); RETURN t;
END GenTaskList;
PROCEDURE GenOverview*() : XML.Element;
VAR o : WindowOverview;
BEGIN
NEW(o); RETURN o;
END GenOverview;
PROCEDURE InitStrings;
BEGIN
StrWindowOverview := Strings.NewString("WindowOverview");
StrNoName := Strings.NewString("NoName");
END InitStrings;
PROCEDURE InitProtos;
BEGIN
NEW(ProtoClDefault, NIL, Strings.NewString("ClDefault"), Strings.NewString("Default color of item"));
ProtoClDefault.Set(0A0A0A0A0H);
NEW(ProtoClSelected, NIL, Strings.NewString("ClSelected"), Strings.NewString("Color of selected item"));
ProtoClSelected.Set(060606A0H);
NEW(ProtoClMouseOver, NIL, Strings.NewString("ClMouseOver"), Strings.NewString("Mouse over color of item"));
ProtoClMouseOver.Set(0D0D0D0A0H);
NEW(ProtoClSelectedMouseOver, NIL, Strings.NewString("ClSelectedMouseOver"), Strings.NewString("Mouse over color of selected item"));
ProtoClSelectedMouseOver.Set(0F0F0F0A0H);
NEW(ProtoClTextDefault, NIL, Strings.NewString("ClTextDefault"), Strings.NewString("Default text color"));
ProtoClTextDefault.Set(WMGraphics.White);
NEW(ProtoClTextSelected, NIL, Strings.NewString("ClTextSelected"), Strings.NewString("Text color of selected item"));
ProtoClTextSelected.Set(WMGraphics.White);
NEW(ProtoClTextMouseOver, NIL, Strings.NewString("ClTextMouseOver"), Strings.NewString("Text color of mouse over item"));
ProtoClTextMouseOver.Set(WMGraphics.White);
NEW(ProtoClTextSelectedMouseOver, NIL, Strings.NewString("ClTextSelectedMouseOver"), Strings.NewString("Text color of selected mouse over item"));
ProtoClTextSelectedMouseOver.Set(WMGraphics.White);
NEW(ProtoClIndicateHidden, NIL, Strings.NewString("ClIndicateHidden"), Strings.NewString("Color used to indicate hidden windows"));
ProtoClIndicateHidden.Set(WMGraphics.Yellow);
NEW(ProtoBorderWidth, NIL, Strings.NewString("BorderWidth"), Strings.NewString("Width of border"));
ProtoBorderWidth.Set(2);
NEW(ProtoTaskListStyle, NIL, Strings.NewString("Style"), Strings.NewString("Style of task representation"));
ProtoTaskListStyle.Set(Icons);
NEW(ProtoTaskListMenuLocation, NIL, Strings.NewString("MenuLocation"), Strings.NewString("Location of submenu relative to task list"));
ProtoTaskListMenuLocation.Set(Bottom);
NEW(ProtoTaskListShowThumbnails, NIL, Strings.NewString("ShowThumbnails"), Strings.NewString("Show window thumbnails?"));
ProtoTaskListShowThumbnails.Set(TRUE);
NEW(ProtoItemWidth, NIL, Strings.NewString("ItemWidth"), Strings.NewString("Width of task list item"));
NEW(ProtoItemHeight, NIL, Strings.NewString("ItemHeight"), Strings.NewString("Height of task list item"));
NEW(ProtoLayoutMode, NIL, Strings.NewString("LayoutMode"), Strings.NewString("Item layouting mode"));
END InitProtos;
PROCEDURE Init;
VAR plugin : Plugins.Plugin;
BEGIN
manager := WMWindowManager.GetDefaultManager();
viewport := WMWindowManager.GetDefaultView();
plugin := Displays.registry.Get("");
IF plugin # NIL THEN
width := plugin(Displays.Display).width;
height := plugin(Displays.Display).height;
ELSE
width := 1024;
height := 768;
END;
END Init;
PROCEDURE Cleanup;
VAR i : LONGINT;
BEGIN {EXCLUSIVE}
FOR i := 0 TO LEN(windows)-1 DO
IF (windows[i] # NIL) THEN windows[i].Close; END;
END;
END Cleanup;
BEGIN
Modules.InstallTermHandler(Cleanup);
Init;
InitStrings;
InitProtos;
windowsAreHidden := FALSE;
navigationIsHidden := FALSE;
ASSERT(manager # NIL);
END WMNavigate.
WMNavigate.SetViewportRange 0 0 ~
WMNavigate.SetViewportRange "-1" 0 1 1 sd ~
WMNavigate.MoveWindow -1280 ~
Example: Four virtual desktops with overview, depended on display resolution
WMNavigate.SetViewportRange -sd -1 0 1 1 ~ (* left desktop *)
WMNavigate.SetViewportRange -sd 0 0 1 1 ~ (* standard desktop *)
WMNavigate.SetViewportRange -sd -1 -1 1 1 ~ (* left/up desktop *)
WMNavigate.SetViewportRange -sd 0 -1 1 1 ~ (* up desktop *)
WMNavigate.SetViewportRange -sd -1 -1 2 2 ~ (* all four desktops *)
WMNavigate.Open -vs 1 0 0 Navigation:TaskList ~
WMNavigate.Open -vs 2 20 600 Navigation:TaskList ~
WMNavigate.Open -fs 6 20 20 Navigation:WindowList ~
WMNavigate.Close 1 ~
WMNavigate.ToggleVisibility 1 ~
WMNavigate.HideNavigation ~
WMNavigate.RestoreNavigation ~
WMNavigate.ToggleNavigation ~
SystemTools.Free WMNavigate ~