По просьбам трудящихся (
viewtopic.php?p=16854#p16854).
Принцип использования тот же, что у Tools->Add Scroller.
Выделяем монолитно (singleton) вьюшку, для которой нужна поддержка невидимости. Даём команду AbfTools.AddInvisibiler.
Включение невидимости ведётся через обычный контроловский Guard, свойством disabled.
Выбираем Properties - открывается стандартное окно настройки контрола.
Далее два случая:
1) если обёрнутая вьюшка - не контрол: имеет значение только поле Guard.
2) если обёрнутая вьюшка - контрол: настраиваем все свойства сразу для неё (получается полный синхрон с обёрткой). Т.е. disabled для контрола начинает работать как invisible.
Код:
MODULE AbfTools;
IMPORT Views, Controls, Stores, Meta, Controllers, Properties, Dialog, Models, Services;
CONST
invVersion = 0;
TYPE
Invisibiler = POINTER TO RECORD (Controls.Control)
inner: Views.View
END;
PROCEDURE Init (v: Invisibiler);
VAR prop: Controls.Prop;
BEGIN
Stores.Join(v, v.inner);
IF v.inner IS Controls.Control THEN
Controls.OpenLink(v, v.inner(Controls.Control).prop)
ELSE
NEW(prop);
Controls.OpenLink(v, prop)
END
END Init;
PROCEDURE (v: Invisibiler) Externalize2 (VAR wr: Stores.Writer);
BEGIN
wr.WriteVersion(invVersion);
Views.WriteView(wr, v.inner)
END Externalize2;
PROCEDURE (v: Invisibiler) Internalize2 (VAR rd: Stores.Reader);
VAR ver: INTEGER;
BEGIN
rd.ReadVersion(invVersion, invVersion, ver);
IF ~rd.cancelled THEN
ASSERT(ver = invVersion, 100);
Views.ReadView(rd, v.inner);
END
END Internalize2;
PROCEDURE (v: Invisibiler) CopyFromSimpleView2 (source: Controls.Control);
BEGIN
WITH source: Invisibiler DO
v.inner := Views.CopyOf(source.inner, Views.deep);
Init(v)
END
END CopyFromSimpleView2;
PROCEDURE GetVis (v: Invisibiler; OUT x: BOOLEAN);
BEGIN
x := ~v.disabled
END GetVis;
PROCEDURE (v: Invisibiler) Restore (f: Views.Frame; l, t, r, b: INTEGER);
VAR vis: BOOLEAN;
w, h: INTEGER;
BEGIN
GetVis(v, vis);
IF vis THEN
Views.InstallFrame(f, v.inner, 0, 0, 0, TRUE)
ELSE
v.context.GetSize(w, h);
Views.RemoveFrames(f, 0, 0, w, h)
END
END Restore;
PROCEDURE (v: Invisibiler) HandleCtrlMsg2 (f: Views.Frame; VAR msg: Controllers.Message; VAR focus: Views.View);
VAR vis: BOOLEAN;
BEGIN
GetVis(v, vis);
IF vis THEN focus := v.inner END
END HandleCtrlMsg2;
PROCEDURE (v: Invisibiler) HandlePropMsg2 (VAR msg: Properties.Message);
VAR prop: Properties.Property;
BEGIN
WITH msg: Controls.DefaultsPref DO
msg.disabled := FALSE
ELSE
Views.HandlePropMsg(v.inner, msg)
END
END HandlePropMsg2;
PROCEDURE (v: Invisibiler) Neutralize;
BEGIN
v.inner.Neutralize
END Neutralize;
PROCEDURE (v: Invisibiler) InitContext (context: Models.Context);
BEGIN
v.InitContext^(context);
v.inner.InitContext(context)
END InitContext;
PROCEDURE AddInvisibiler*;
VAR poll: Controllers.PollOpsMsg; v: Invisibiler; replace: Controllers.ReplaceViewMsg;
BEGIN
Controllers.PollOps(poll);
IF (poll.singleton # NIL) & ~(poll.singleton IS Invisibiler) THEN
NEW(v); v.inner := poll.singleton; Init(v);
replace.old := poll.singleton; replace.new := v;
Controllers.Forward(replace)
ELSE Dialog.Beep
END
END AddInvisibiler;
PROCEDURE RemoveInvisibiler*;
VAR poll: Controllers.PollOpsMsg; replace: Controllers.ReplaceViewMsg;
BEGIN
Controllers.PollOps(poll);
IF (poll.singleton # NIL) & (poll.singleton IS Invisibiler) THEN
replace.old := poll.singleton;
replace.new := Views.CopyOf(poll.singleton(Invisibiler).inner, Views.shallow);
Controllers.Forward(replace)
ELSE Dialog.Beep
END
END RemoveInvisibiler;
PROCEDURE IsInvisibiler* (v: Views.View): BOOLEAN;
BEGIN
RETURN v IS Invisibiler
END IsInvisibiler;
PROCEDURE InnerView* (v: Views.View): Views.View;
BEGIN
ASSERT(v IS Invisibiler, 20);
RETURN v(Invisibiler).inner
END InnerView;
END AbfTools.