MODULE DevCmds; 
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- 20161216, center #144, inconsistent docu and usage of Files.Locator error codes
	"
	issues	= "
	- ...
	"

**)

	IMPORT
		Services, Files, Fonts, Ports, Stores, Models, Views, Controllers, Dialog,
		Containers, Controls, Properties, Documents,
		TextModels, TextMappers, TextRulers, TextViews, TextControllers,
		StdDialog, StdCmds, StdMenuTool;


	PROCEDURE OpenModuleList*;
		VAR v: Views.View;
			c: TextControllers.Controller; s: TextMappers.Scanner;
			loc: Files.Locator; name: Files.Name;
			beg, end: INTEGER; error, one: BOOLEAN;
	BEGIN
		c := TextControllers.Focus();
		IF c # NIL THEN
			s.ConnectTo(c.text);
			IF c.HasSelection() THEN c.GetSelection(beg, end)
			ELSE beg := 0; end := c.text.Length()
			END;
			s.SetPos(beg); s.Scan; one := FALSE;
			WHILE (s.start < end) & (s.type = TextMappers.string) & (s.len < LEN(name)) DO
				s.Scan; one := TRUE
			END;
			IF one & ((s.start >= end) OR (s.type = TextMappers.eot)) THEN
				s.SetPos(beg); s.Scan; error := FALSE;
				WHILE (s.start < end) & (s.type = TextMappers.string) & ~error DO
					StdDialog.GetSubLoc(s.string, "Mod", loc, name);
					IF loc.res = 0 THEN
						v := Views.OldView(loc, name);
						IF v # NIL THEN
							Views.Open(v, loc, name, NIL)
						ELSE
							Dialog.ShowParamMsg("#System:CannotOpenFile", name, "", "");
							error := TRUE
						END
					ELSE
						Dialog.ShowParamMsg("#Dev:ModuleNotFound", s.string, "", "");
						error := TRUE
					END;
					s.Scan
				END
			ELSE Dialog.ShowMsg("#Dev:NotOnlyModNames")
			END;
			s.ConnectTo(NIL)
		ELSE Dialog.ShowMsg("#Text:FocusShouldBeText")
		END
	END OpenModuleList;
	
	PROCEDURE Scan (VAR s: TextMappers.Scanner);
		VAR ch: CHAR; i, max: INTEGER;
	BEGIN
		s.Skip(ch);
		IF s.type # TextMappers.eot THEN
			IF ch = '"' THEN s.Scan;
			ELSE i := 0; max := LEN(s.string)-1;
				WHILE (i < max) & ~s.rider.eot & (ch > " ") DO
					s.string[i] := ch; s.rider.ReadChar(ch); INC(i);
				END;
				s.string[i] := 0X; s.len := SHORT(i);
				IF s.len > 0 THEN s.type := TextMappers.string
				ELSE s.type := TextMappers.invalid
				END
			END
		END
	END Scan;
	
	PROCEDURE OpenFileList*;	(* Pre: focus is text and has a selection *)
		VAR c: TextControllers.Controller; s: TextMappers.Scanner; beg, end: INTEGER;
	BEGIN
		c := TextControllers.Focus();
		IF (c # NIL) & c.HasSelection() THEN 
			c.GetSelection(beg, end);
			s.ConnectTo(c.text);
			s.SetPos(beg); Scan(s);
			WHILE (s.type # TextMappers.eot) & (s.start < end) DO
				IF s.type = TextMappers.string THEN StdCmds.OpenDoc(s.string) END;
				Scan(s);
			END
		ELSE Dialog.ShowMsg("#Text:FocusShouldBeText")
		END
	END OpenFileList;

	PROCEDURE FlushResources*;
	BEGIN
		(* flush menu guards *)
		StdMenuTool.dir.RevalidateGuards;
		(* flush string cache *)
		Dialog.FlushMappings
	END FlushResources;

	PROCEDURE RevalidateView*;
		VAR ops: Controllers.PollOpsMsg; v: Views.View;
	BEGIN
		Controllers.PollOps(ops);
		IF ops.singleton # NIL THEN v := ops.singleton
		ELSE v := Controllers.FocusView();
		END;
		IF v # NIL THEN Views.RevalidateView(v) END
	END RevalidateView;
	
	PROCEDURE RevalidateViewGuard* (VAR par: Dialog.Par);
		VAR ops: Controllers.PollOpsMsg; v: Views.View;
	BEGIN
		Controllers.PollOps(ops);
		IF ops.singleton # NIL THEN v := ops.singleton
		ELSE v := Controllers.FocusView();
		END;
		IF (v = NIL) OR ~Views.IsInvalid(v) THEN par.disabled := TRUE END
	END RevalidateViewGuard;

	PROCEDURE SetDefault (c: Views.View; default: BOOLEAN);
		VAR p: Controls.Prop; msg: Properties.SetMsg;
	BEGIN
		NEW(p); p.valid := {Controls.opt0}; p.opt[Controls.default] := default;
		msg.prop := p; Views.HandlePropMsg(c, msg)
	END SetDefault;

	PROCEDURE SetDefaultButton*;
		VAR s, v: Views.View; c: Containers.Controller; script: Stores.Operation;
	BEGIN
		c := Containers.Focus();
		IF c # NIL THEN
			s := c.Singleton();
			c.SelectAll(FALSE);
			Views.BeginScript(c.ThisView(), "#Dev:SetDefault", script);
			c.GetFirstView(Containers.any, v);
			WHILE v # NIL DO SetDefault(v, FALSE); c.GetNextView(Containers.any, v) END;
			IF s # NIL THEN SetDefault(s, TRUE); c.SetSingleton(s) END;
			Views.EndScript(c.ThisView(), script)
		ELSE Dialog.Beep
		END
	END SetDefaultButton;

	PROCEDURE SetCancel (c: Views.View; cancel: BOOLEAN);
		VAR p: Controls.Prop; msg: Properties.SetMsg;
	BEGIN
		NEW(p); p.valid := {Controls.opt1}; p.opt[Controls.cancel] := cancel;
		msg.prop := p; Views.HandlePropMsg(c, msg)
	END SetCancel;

	PROCEDURE SetCancelButton*;
		VAR s, v: Views.View; c: Containers.Controller; script: Stores.Operation;
	BEGIN
		c := Containers.Focus();
		IF c # NIL THEN
			s := c.Singleton();
			c.SelectAll(FALSE);
			Views.BeginScript(c.ThisView(), "#Dev:SetCancel", script);
			c.GetFirstView(Containers.any, v);
			WHILE v # NIL DO SetCancel(v, FALSE); c.GetNextView(Containers.any, v) END;
			IF s # NIL THEN SetCancel(s, TRUE); c.SetSingleton(s) END;
			Views.EndScript(c.ThisView(), script)
		ELSE Dialog.Beep
		END
	END SetCancelButton;

	PROCEDURE NewRuler (): TextRulers.Ruler;
		CONST mm = Ports.mm; pt = Ports.point;
		VAR p: TextRulers.Prop;
	BEGIN
		NEW(p);
		p.valid := {TextRulers.right, TextRulers.tabs, TextRulers.opts};
		p.opts.val := {TextRulers.rightFixed}; p.opts.mask := p.opts.val;
		p.tabs.len := 7;
		p.right := 200 * mm;
		p.tabs.tab[0].stop := 40 * mm; p.tabs.tab[0].type := {TextRulers.rightTab};
		p.tabs.tab[1].stop := 50 * mm; p.tabs.tab[1].type := {TextRulers.rightTab};
		p.tabs.tab[2].stop := 55 * mm;
		p.tabs.tab[3].stop := 90 * mm;
		p.tabs.tab[4].stop := 100 * mm;
		p.tabs.tab[5].stop := 140 * mm;
		p.tabs.tab[6].stop := 180 * mm; p.tabs.tab[6].type := {TextRulers.rightTab};
		RETURN TextRulers.dir.NewFromProp(p)
	END NewRuler;

	PROCEDURE ShowControlList*;
	(** Guard: StdCmds.ContainerGuard **)
		VAR c: Containers.Controller; v: Views.View; s, t: Stores.TypeName;
			msg: Properties.PollMsg; p: Properties.Property;
			out: TextMappers.Formatter; str: Dialog.String; w, h: INTEGER;

		PROCEDURE WriteEntry(name, value: Dialog.String);
		BEGIN
			out.WriteTab; out.WriteString(name); out.WriteTab; out.WriteString(value); out.WriteLn
		END WriteEntry;

	BEGIN
		c := Containers.Focus();
		IF c # NIL THEN
			out.ConnectTo(TextModels.dir.New());out.WriteView(NewRuler());
			out.rider.SetAttr(TextModels.NewStyle(out.rider.attr, {Fonts.italic}));
			out.WriteString("type"); out.WriteTab;
			out.WriteString("width"); out.WriteTab;
			out.WriteString("height"); out.WriteTab;
			out.WriteString("label"); out.WriteTab;
			out.WriteString("link"); out.WriteTab;
			out.WriteString("guard"); out.WriteTab;
			out.WriteString("notifier"); out.WriteTab;
			out.WriteString("level"); out.WriteTab;
			out.WriteLn; out.WriteLn;
			out.rider.SetAttr(TextModels.NewStyle(out.rider.attr, {}));
			c.GetFirstView(Containers.any, v);
			WHILE v # NIL DO
				Services.GetTypeName(v, t);
				s := "#Dev:"; s := s + t;
				Dialog.MapString(s, s);
				out.WriteString(s); out.WriteTab;
				v.context.GetSize(w, h);
				out.WriteInt(w DIV Ports.point); out.WriteTab;
				out.WriteInt(h DIV Ports.point); out.WriteTab;
				msg.prop := NIL; Views.HandlePropMsg(v, msg);
				p := msg.prop; WHILE (p # NIL) & ~(p IS Controls.Prop) DO p := p.next END;
				IF p # NIL THEN
					WITH p: Controls.Prop DO
						IF Controls.label IN p.valid THEN out.WriteString(p.label) END; out.WriteTab;
						IF Controls.link IN p.valid THEN out.WriteString(p.link) END; out.WriteTab;
						IF Controls.level IN p.valid THEN out.WriteTab; out.WriteTab; out.WriteInt(p.level) END;
						IF (Controls.guard IN p.valid) & (p.guard # "") OR
							(Controls.notifier IN p.valid) & (p.notifier # "") THEN
							out.WriteLn; out.WriteTab; out.WriteTab; out.WriteTab; out.WriteTab; out.WriteTab;
							IF Controls.guard IN p.valid THEN out.WriteString(p.guard) END; out.WriteTab;
							IF Controls.notifier IN p.valid THEN out.WriteString(p.notifier) END
						END
					END
				END;
				out.WriteLn;
				c.GetNextView(Containers.any, v)
			END;
			Views.OpenAux(Documents.dir.New(TextViews.dir.New(out.rider.Base()), 200*Ports.mm, -1), "Controls");
		END
	END ShowControlList;

END DevCmds.
