123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- MODULE MainMenu; (** AUTHOR "TF"; PURPOSE "Menu for Bluebottle"; *)
- IMPORT
- KernelLog, XML, Modules, Files, Inputs,
- WMMessages, WMStandardComponents, WMComponents, WMTabComponents,
- Strings, WM := WMWindowManager;
- CONST
- MenuFilePrefix = "MenuPage";
- TYPE
- Window* = OBJECT (WMComponents.FormWindow)
- VAR
- tabs : WMTabComponents.Tabs;
- pages : ARRAY 100 OF WMComponents.VisualComponent;
- tabList : ARRAY 100 OF WMTabComponents.Tab;
- currentPage : WMComponents.VisualComponent;
- currentPageNr : LONGINT;
- page : WMStandardComponents.Panel;
- moveToFront : BOOLEAN;
- PROCEDURE CreateForm(): WMComponents.VisualComponent;
- VAR
- panel : WMStandardComponents.Panel;
- pagePanel : WMStandardComponents.Panel;
- tabs : WMTabComponents.Tabs;
- BEGIN
- NEW(panel); panel.bounds.SetExtents(1024, 60); panel.fillColor.Set(0); panel.takesFocus.Set(TRUE);
- NEW(tabs); tabs.fillColor.Set(000600080H); tabs.bounds.SetHeight(20); tabs.alignment.Set(WMComponents.AlignTop);
- panel.AddContent(tabs);
- SELF.tabs := tabs;
- NEW(pagePanel); pagePanel.fillColor.Set(0H); pagePanel.alignment.Set(WMComponents.AlignClient);
- panel.AddContent(pagePanel);
- page := pagePanel;
- RETURN panel
- END CreateForm;
- PROCEDURE &New*;
- VAR vc : WMComponents.VisualComponent;
- view : WM.ViewPort;
- BEGIN
- vc := CreateForm();
- moveToFront := TRUE;
- currentPageNr := -1;
- tabs.onSelectTab.Add(TabSelected);
- Init(vc.bounds.GetWidth(), vc.bounds.GetHeight(), TRUE);
- SetContent(vc);
- SetTitle(Strings.NewString("MainMenu"));
- pointerThreshold := 10;
- manager := WM.GetDefaultManager();
- view := WM.GetDefaultView();
- manager.Add(0, view.height0 - GetHeight(), SELF, {WM.FlagNavigation, WM.FlagHidden});
- END New;
- PROCEDURE PointerMove*(x, y : LONGINT; keys : SET);
- BEGIN
- PointerMove^(x, y, keys);
- moveToFront := FALSE;
- manager.ToFront(SELF);
- END PointerMove;
- PROCEDURE PointerLeave*;
- BEGIN
- PointerLeave^;
- moveToFront := TRUE;
- END PointerLeave;
- PROCEDURE SetOriginator*(extView : ANY);
- VAR view : WM.ViewPort;
- BEGIN
- IF (extView # NIL) & (extView IS WM.ViewPort) THEN
- view := extView(WM.ViewPort)
- ELSE view := WM.GetDefaultView()
- END;
- Refresh(NIL, NIL);
- IF ~(WM.FlagNavigation IN SELF.flags) THEN
- manager.SetWindowPos(SELF, ENTIER(view.range.l), ENTIER(view.range.b) - GetHeight());
- END;
- manager.ToFront(SELF)
- END SetOriginator;
- PROCEDURE UpdatePages;
- VAR i : LONGINT;
- tab : WMTabComponents.Tab;
- s : Strings.String;
- BEGIN
- DisableUpdate;
- tabs.RemoveAllTabs;
- IF currentPage # NIL THEN page.RemoveContent(currentPage);
- currentPage := NIL
- END;
- IF currentPageNr >= 0 THEN currentPage := pages[currentPageNr] END;
- FOR i := 0 TO 99 DO
- tabList[i] := NIL;
- IF pages[i] # NIL THEN
- pages[i].alignment.Set(WMComponents.AlignClient);
- tab := tabs.NewTab();
- tabs.AddTab(tab);
- tabList[i] := tab;
- s := pages[i].GetAttributeValue("caption");
- IF s = NIL THEN s := Strings.NewString("Untitled") END;
- tabs.SetTabCaption(tab, s);
- tabs.SetTabData(tab, pages[i])
- END
- END;
- IF currentPage = NIL THEN
- i := 0;
- WHILE (i < 100) & (currentPage = NIL) DO
- IF pages[i] # NIL THEN currentPage := pages[i]; currentPageNr := i END;
- INC(i);
- END
- END;
- EnableUpdate;
- IF currentPage # NIL THEN
- page.AddContent(currentPage);
- currentPage.Reset(SELF, NIL);
- page.AlignSubComponents;
- page.Invalidate;
- IF tabList[currentPageNr] # NIL THEN tabs.Select(tabList[currentPageNr]) END
- END;
- tabs.Invalidate
- END UpdatePages;
- PROCEDURE TryLoad(CONST name : ARRAY OF CHAR; pos : LONGINT);
- VAR x : XML.Content;
- BEGIN
- IF (pos >= 0) & (pos <= 99) THEN
- x := WMComponents.Load(name);
- IF x # NIL THEN
- IF x IS WMComponents.VisualComponent THEN
- pages[pos] := x(WMComponents.VisualComponent);
- END
- END
- END
- END TryLoad;
- PROCEDURE LoadPages*;
- VAR mask : ARRAY 64 OF CHAR;
- name : ARRAY 256 OF CHAR; flags : SET;
- time, date, size : LONGINT;
- i: LONGINT;
- enumerator : Files.Enumerator;
- number: LONGINT;
- PROCEDURE IsNum(ch : CHAR) : BOOLEAN;
- BEGIN
- RETURN (ch >= '0') & (ch <= '9')
- END IsNum;
- BEGIN
- DisableUpdate;
- NEW(enumerator);
- FOR i := 0 TO 99 DO
- IF pages[i] = currentPage THEN currentPageNr := i END;
- pages[i] := NIL
- END;
- mask := MenuFilePrefix;
- i := Strings.Length(mask);
- Strings.Append(mask, "*.XML");
- enumerator.Open(mask, {});
- WHILE enumerator.HasMoreEntries() DO
- IF enumerator.GetEntry(name, flags, time, date, size) THEN
- i := Strings.Length(name);
- IF IsNum(name[i - 6]) & IsNum(name[i - 5]) THEN
- number := (ORD(name[i - 6]) - ORD('0')) * 10 + (ORD(name[i - 5]) - ORD('0'));
- IF pages[number] = NIL THEN (* use first incident for respecting the search path order *)
- TryLoad(name, number);
- END;
- END
- END
- END;
- enumerator.Close;
- EnableUpdate;
- UpdatePages
- END LoadPages;
- PROCEDURE Refresh(sender, data : ANY);
- BEGIN
- LoadPages
- END Refresh;
- PROCEDURE TabSelected(sender, data : ANY);
- VAR tab : WMTabComponents.Tab;
- BEGIN
- IF (data # NIL) & (data IS WMTabComponents.Tab) THEN
- DisableUpdate;
- page.RemoveContent(currentPage);
- tab := data(WMTabComponents.Tab);
- IF (tab.data # NIL) & (tab.data IS WMComponents.VisualComponent) THEN
- currentPage := tab.data(WMComponents.VisualComponent);
- page.AddContent(currentPage);
- IF ~currentPage.initialized THEN currentPage.Initialize END;
- currentPage.Reset(SELF, NIL);
- page.AlignSubComponents;
- END;
- EnableUpdate;
- page.Invalidate
- END
- END TabSelected;
- PROCEDURE Close*;
- BEGIN
- Close^;
- window := NIL
- END Close;
- END Window;
- (* the starter decouples the sensitive callback from the WindowManager. *)
- TYPE
- Starter = OBJECT
- VAR
- originator : ANY;
- w : Window;
- PROCEDURE &Init*(o : ANY);
- BEGIN
- originator := o;
- w := NIL;
- END Init;
- BEGIN {ACTIVE}
- BEGIN {EXCLUSIVE}
- IF (window = NIL) THEN NEW(window); w := window;
- ELSE window.SetOriginator(originator);
- END;
- END;
- IF (w # NIL) THEN w.LoadPages; END;
- END Starter;
- VAR
- window : Window;
- manager : WM.WindowManager;
- (* This procedure is directly called by the window manager. It must be safe. *)
- PROCEDURE MessagePreview(VAR m : WMMessages.Message; VAR discard : BOOLEAN);
- VAR starter : Starter;
- BEGIN
- IF m.msgType = WMMessages.MsgKey THEN
- IF (m.y = 0FF1BH) & ((m.flags * Inputs.Ctrl # {}) OR (m.flags * Inputs.Meta # {})) THEN
- NEW(starter, m.originator); discard := TRUE
- END
- END
- END MessagePreview;
- PROCEDURE Open*;
- VAR w : Window;
- BEGIN
- BEGIN {EXCLUSIVE}
- IF window = NIL THEN NEW(window); w := window;
- ELSE window.SetOriginator(NIL)
- END;
- END;
- IF w # NIL THEN w.LoadPages END;
- END Open;
- PROCEDURE Cleanup;
- BEGIN {EXCLUSIVE}
- KernelLog.String("Cleanup"); KernelLog.Ln;
- (* removal must be done in all cases to avoid system freeze *)
- manager.RemoveMessagePreview(MessagePreview);
- IF window # NIL THEN window.Close END;
- END Cleanup;
- BEGIN
- manager := WM.GetDefaultManager();
- Modules.InstallTermHandler(Cleanup)
- END MainMenu.
- SystemTools.Free MainMenu WMTabComponents ~
- MainMenu.Open ~
|