MODULE StdViewSizer;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- 20160321, center #110, use mapped strings for labels in all forms
	"
	issues	= "
	- ...
	"

**)

	IMPORT Services, Ports, Dialog, Views, Containers, Properties;

	CONST width = 1; height = 2;

	VAR
		size*: RECORD
			typeName-: Dialog.String;
			w*, h*: REAL;
			proportional*, fixedW, fixedH: BOOLEAN;
			unit, scaleW, scaleH, lastChanged: INTEGER;
			unitText: ARRAY 12 OF CHAR;
			view: Views.View;
			container: Containers.Controller
		END;

	PROCEDURE ConnectDialog (v: Views.View; c: Containers.Controller);
		VAR pref: Properties.ResizePref;
	BEGIN
		IF (v # NIL) & (v.context # NIL) THEN
			IF Dialog.metricSystem THEN size.unit := Ports.mm * 10; size.unitText := "#Std:cm"
			ELSE size.unit := Ports.inch; size.unitText := "#Std:inch"
			END;
			size.view := v; size.container := c;
			Services.GetTypeName(v, size.typeName);
			v.context.GetSize(size.scaleW, size.scaleH);
			size.w := size.scaleW / size.unit; size.h := size.scaleH / size.unit;
			pref.fixed := FALSE;
			pref.horFitToPage := FALSE; pref.verFitToPage := FALSE;
			pref.horFitToWin := FALSE; pref.verFitToWin := FALSE;
			Views.HandlePropMsg(v, pref);
			size.fixedW := pref.fixed;
			size.fixedH := pref.fixed;
			size.proportional := FALSE
		ELSE
			size.view := NIL; size.container := c; size.typeName := ""
		END;
		Dialog.Update(size)
	END ConnectDialog;

	PROCEDURE SetViewSize*;
	BEGIN
		IF size.view # NIL THEN
			size.view.context.SetSize(SHORT(ENTIER(size.w * size.unit + 0.5)),
												SHORT(ENTIER(size.h * size.unit + 0.5)));
			IF size.container # NIL THEN size.container.SetSingleton(size.view) END;
			ConnectDialog(size.view, size.container)
		ELSE Dialog.Beep
		END
	END SetViewSize;

	PROCEDURE InitDialog*;
		VAR v: Views.View; c: Containers.Controller;
	BEGIN
		c := Containers.Focus();
		IF c # NIL THEN v := c.Singleton() ELSE v := NIL END;
		IF (v # size.view) OR (c # size.container) THEN ConnectDialog(v, c) END
	END InitDialog;

	PROCEDURE ResetDialog*;
		VAR proportional: BOOLEAN; v: Views.View;
	BEGIN
		proportional := size.proportional; v := size.view;
		size.view := NIL; InitDialog;
		IF proportional & (v = size.view) THEN size.proportional := TRUE; Dialog.Update(size) END
	END ResetDialog;

	PROCEDURE WidthGuard* (VAR par: Dialog.Par);
	BEGIN
		InitDialog;
		par.disabled := size.view = NIL;
		par.readOnly := size.fixedW
	END WidthGuard;

	PROCEDURE HeightGuard* (VAR par: Dialog.Par);
	BEGIN
		InitDialog;
		par.disabled := size.view = NIL;
		par.readOnly := size.fixedH
	END HeightGuard;

	PROCEDURE ProportionGuard* (VAR par: Dialog.Par);
	BEGIN
		par.disabled := (size.view = NIL) OR size.fixedW OR size.fixedH OR (size.scaleW = 0) OR (size.scaleH = 0)
	END ProportionGuard;

	PROCEDURE UnitGuard* (VAR par: Dialog.Par);
	BEGIN
		IF size.view # NIL THEN par.label := size.unitText$ ELSE par.label := "" END
	END UnitGuard;

	PROCEDURE AdjustDialogToPref (fixedW, fixedH: BOOLEAN);
		VAR w, h: INTEGER; w0, h0: REAL; pref: Properties.SizePref;
	BEGIN
		w := SHORT(ENTIER(size.w * size.unit + 0.5)); h := SHORT(ENTIER(size.h * size.unit + 0.5));
		IF size.proportional & (w > 0) & (h > 0) & (size.scaleW > 0) & (size.scaleH > 0) THEN
			Properties.ProportionalConstraint(size.scaleW, size.scaleH, fixedW, fixedH, w, h)
		END;
		pref.w := w; pref.h := h; pref.fixedW := fixedW; pref.fixedH := fixedH;
		Views.HandlePropMsg(size.view, pref);
		IF ~fixedW THEN w0 := pref.w / size.unit ELSE w0 := size.w END;
		IF ~fixedH THEN h0 := pref.h / size.unit ELSE h0 := size.h END;
		IF (w0 # size.w) OR (h0 # size.h) THEN size.w := w0; size.h := h0; Dialog.Update(size) END
	END AdjustDialogToPref;

	PROCEDURE WNotifier* (op, from, to: INTEGER);
	BEGIN
		IF size.w > 0 THEN AdjustDialogToPref(TRUE, FALSE); size.lastChanged := width
		ELSIF size.w # 0 THEN Dialog.Beep
		END
	END WNotifier;

	PROCEDURE HNotifier* (op, from, to: INTEGER);
	BEGIN
		IF size.h > 0 THEN AdjustDialogToPref(FALSE, TRUE); size.lastChanged := height
		ELSIF size.h # 0 THEN Dialog.Beep
		END
	END HNotifier;

	PROCEDURE ProportionNotifier* (op, from, to: INTEGER);
	BEGIN
		IF (op = Dialog.changed) & size.proportional THEN
			IF size.lastChanged = width THEN AdjustDialogToPref(TRUE, FALSE)
			ELSIF size.lastChanged = height THEN AdjustDialogToPref(FALSE, TRUE)
			END
		END
	END ProportionNotifier;

END StdViewSizer.
