trestle_by_example/src/source/Source.m3


MODULE Source EXPORTS Main;
IMPORT Trestle, VBT, TextVBT, ShadowedFeedbackVBT, RigidVBT, SourceVBT;
IMPORT HVSplit, Shadow, FeedbackVBT, Axis, Random, Fmt;
FROM Colors IMPORT lblue, dblue, lred, dred;
TYPE
  Source = SourceVBT.T OBJECT
           METHODS
             init (f: FeedbackVBT.T; t1, t2: VBT.T): Source := Init
           OVERRIDES
             hit      := SourceVBT.AlwaysHit;
             callback := Callback;
           END;
PROCEDURE Init (v: Source; f: FeedBackVBT.T; t1, t2: VBT.T): Source =
  BEGIN
    SourceVBT.BeTarget(t1, SourceVBT.NewTarget());
    SourceVBT.BeTarget(t2, SourceVBT.NewTarget());
    EVAL SourceVBT.T.init(v, f);
    RETURN v;
  END Init;
PROCEDURE Callback (v: Source; READONLY cd: VBT.MouseRec) =
  VAR t := SourceVBT.GetTarget(v);
  BEGIN
    IF (t # NIL) THEN
      IF t = target1 THEN
        TextVBT.Put(slot1, TextVBT.Get(number));
      ELSE                       (* t = target2 *)
        TextVBT.Put(slot2, TextVBT.Get(number));
      END;
      TextVBT.Put(number, Fmt.Int(Random.Subrange(seed, 0, 100)));
    END;
  END Callback;
PROCEDURE New (t: TextVBT.T; s: Shadow.T): ShadowedFeedbackVBT.T =
  VAR r := RigidVBT.FromHV(t, hMin := 15.0, vMin := 10.0);
  BEGIN
    RETURN (NEW(ShadowedFeedbackVBT.T).init(r, s));
  END New;
VAR
  seed    := Random.New(-1);
  number  := TextVBT.New(Fmt.Int(Random.Subrange(seed, 0, 100)));
  slot1   := TextVBT.New("");
  slot2   := TextVBT.New("");
  red_sh  := Shadow.New(5.0, light := lred, dark := dred);
  blue_sh := Shadow.New(5.0, light := lblue, dark := dblue);
  target1 := New(slot1, blue_sh);
  target2 := New(slot2, blue_sh);
  source  := NEW(Source).init(New(number, red_sh), target1, target2);
  vbt     := RigidVBT.FromHV(TextVBT.New("Drag and Drop"), 25.0, 15.0);
  hsplit  := HVSplit.Cons(Axis.T.Hor, target1, target2);
  main    := HVSplit.Cons(Axis.T.Ver, source, vbt, hsplit);
BEGIN
  Trestle.Install(main);
  Trestle.AwaitDelete(main);
END Source.