Bläddra i källkod

Gui: The beginning

Arthur Yefimov 3 år sedan
förälder
incheckning
72fe236057
3 ändrade filer med 190 tillägg och 471 borttagningar
  1. 44 0
      Programs/Buttons.Mod
  2. 122 471
      Programs/Gui.Mod
  3. 24 0
      Programs/TestGui.Mod

+ 44 - 0
Programs/Buttons.Mod

@@ -0,0 +1,44 @@
+MODULE Buttons;
+IMPORT Gui, G := Graph, Out;
+
+TYPE
+  Button* = POINTER TO ButtonDesc;
+  ButtonDesc* = RECORD(Gui.Widget)
+  END;
+
+PROCEDURE DrawButton*(W: Gui.Widget; x, y: INTEGER);
+VAR c: G.Color;
+  f: G.Font;
+  fw, fh: INTEGER;
+BEGIN
+  G.MakeCol(c, 210, 205, 200);
+  G.FillRect(x, y, x + W.w - 1, y + W.h - 1, c);
+  G.MakeCol(c, 255, 255, 255);
+  G.FillRect(x, y, x + W.w - 1, y + W.h - 1, c);
+  G.MakeCol(c, 0, 0, 0);
+  G.HLine(x, y + W.h - 1, x + W.w - 1, c);
+  G.VLine(x + W.w - 1, y, y + W.h - 1, c);
+  G.MakeCol(c, 80, 80, 80);
+  G.HLine(x + 1, y + W.h - 2, x + W.w - 2, c);
+  G.VLine(x + W.w - 2, y + 1, y + W.h - 2, c);
+  f := Gui.GetFont(W);
+  G.GetMonoFontSize(f, fw, fh);
+  G.MakeCol(c, 0, 0, 0);
+  G.DrawString(W.text.s(*!FIXME*), x + 4,
+    y + (W.h - fh) DIV 2, f, c)
+END DrawButton;
+
+PROCEDURE InitButton*(b: Button; w, h: INTEGER; text: ARRAY OF CHAR);
+BEGIN
+  Gui.InitWidget(b);
+  b.w := w; b.h := h;
+  Gui.SetText(b, text);
+  b.draw := DrawButton
+END InitButton;
+
+PROCEDURE NewButton*(w, h: INTEGER; text: ARRAY OF CHAR): Button;
+VAR b: Button;
+BEGIN NEW(b); InitButton(b, w, h, text)
+RETURN b END NewButton;
+
+END Buttons.

+ 122 - 471
Programs/Gui.Mod

@@ -1,526 +1,177 @@
-MODULE Gui; (* My GUI Module *)
-IMPORT Out, G := Graph;
-
-CONST
-  charW = 8; charH = 16;
-
-  (* redrawState *)
-  redrawNone* = 0;
-  redrawAll*  = 1;
-  redrawSome* = 2;
+MODULE Gui;
+IMPORT G := Graph, Strings, Out;
 
 TYPE
-  Method* = POINTER TO MethodDesc;
-  Component* = POINTER TO ComponentDesc;
-  Container* = POINTER TO ContainerDesc;
-  Form* = POINTER TO FormDesc;
-  Button* = POINTER TO ButtonDesc;
-  Edit* = POINTER TO EditDesc;
-  Circle* = POINTER TO CircleDesc;
+  Caption* = POINTER TO CaptionDesc;
+  CaptionDesc* = RECORD
+    s*: ARRAY 100 OF CHAR
+  END;
 
-  (* Handler Procedures *)  
-  OnDrawHandler = PROCEDURE (c: Component; bmp: G.Bitmap; x0, y0: INTEGER);
-  OnMouseDownHandler = PROCEDURE (c: Component; x, y, btn: INTEGER);
-  OnKeyDownHandler = PROCEDURE (c: Component; key: INTEGER);
+  DrawHandler* = PROCEDURE (W: Widget; x, y: INTEGER);
 
-  MethodDesc* = RECORD
-    draw*: OnDrawHandler;
-    mouseDown*: OnMouseDownHandler;
-    keyDown*: OnKeyDownHandler;
-    add*: PROCEDURE (c, toAdd: Component);
-    updated*: PROCEDURE (c: Component; moved: BOOLEAN);
-    redraw*: PROCEDURE (c: Component; bmp: G.Bitmap; x0, y0: INTEGER);
-    (* Setters *)
-    setX*: PROCEDURE (c: Component; x: INTEGER);
-    setY*: PROCEDURE (c: Component; y: INTEGER);
-    setW*: PROCEDURE (c: Component; w: INTEGER);
-    setH*: PROCEDURE (c: Component; h: INTEGER);
-    setBounds*: PROCEDURE (c: Component; x, y, w, h: INTEGER);
-    setVisible*: PROCEDURE (c: Component; visible: BOOLEAN);
-    (* Event Handler Setters *)
-    setOnDraw*: PROCEDURE (c: Component; hn: OnDrawHandler);
-    setOnMouseDown*: PROCEDURE (c: Component; hn: OnMouseDownHandler);
-    setOnKeyDown*: PROCEDURE (c: Component; hn: OnKeyDownHandler);
-  END;
-  ComponentDesc* = RECORD
+  Widget* = POINTER TO WidgetDesc;
+  WidgetDesc* = RECORD
     x*, y*, w*, h*: INTEGER;
-    visible*: BOOLEAN;
-    redrawState*: INTEGER; (* see constants with prefix 'redraw' *)
-    do*: Method;
-    onDraw*: OnDrawHandler;
-    onMouseDown*: OnMouseDownHandler;
-    onKeyDown*: OnKeyDownHandler;
-    parent*: Component;
-    next*: Component
-  END;
-  ContainerDesc* = RECORD(ComponentDesc)
-    first*: Component
+    body*: Widget;
+    text*: Caption;
+    bmp*: G.Bitmap;
+    parent*: Widget;
+    prev*, next*: Widget;
+    draw*: DrawHandler
   END;
-  FormDesc* = RECORD(ContainerDesc)
-    bgColor*: INTEGER
-  END;
-  ButtonDesc* = RECORD(ComponentDesc)
-    caption*: ARRAY 100 OF CHAR
-  END;
-  EditDesc* = RECORD(ComponentDesc)
-    text*: ARRAY 4096 OF CHAR;
-    selStart*: INTEGER;
-    selLen*: INTEGER
-  END;
-  CircleDesc* = RECORD(ComponentDesc)
-    color*: INTEGER
+
+  Window* = POINTER TO WindowDesc;
+  WindowDesc* = RECORD(WidgetDesc)
+    win*: G.Window
   END;
 
 VAR
-  screen: G.Bitmap;
+  Done*: BOOLEAN;
+  exitRunLoop: BOOLEAN; (* See procedure Run *)
   font: G.Font;
-  needFlip: BOOLEAN;
-
-  (* Methods *)
-  method, formMethod, buttonMethod, circleMethod, editMethod: Method;
-
-  form: Form;
-  btnHello: Button;
-  circle: Circle;
-  edit: Edit;
-
-(* Component *)
-
-PROCEDURE InitComponent*(c: Component);
-BEGIN
-  c.x := 0; c.y := 0; c.w := 0; c.h := 0;
-  c.visible := TRUE;
-  c.redrawState := redrawNone;
-  c.do := method; c.next := NIL; c.parent := NIL;
-  c.onDraw := NIL; c.onMouseDown := NIL
-END InitComponent;
-
-PROCEDURE UpdatedComponent*(c: Component; moved: BOOLEAN);
-BEGIN
-  IF c.redrawState # redrawAll THEN
-    c.redrawState := redrawAll;
-    c := c.parent;
-    IF moved & (c # NIL) & (c.redrawState # redrawAll)  THEN
-      c.redrawState := redrawAll;
-      c := c.parent
-    END;
-    WHILE (c # NIL) & (c.redrawState = redrawNone) DO
-      c.redrawState := redrawSome;
-      c := c.parent
-    END
-  END
-END UpdatedComponent;
 
-PROCEDURE RedrawComponent*(c: Component; bmp: G.Bitmap; x0, y0: INTEGER);
-BEGIN
-  IF (c.redrawState = redrawAll) & c.visible THEN
-    c.do.draw(c, bmp, x0, y0);
-    needFlip := TRUE
-  END;
-  c.redrawState := redrawNone
-END RedrawComponent;
-
-PROCEDURE ComponentSetX(c: Component; x: INTEGER);
-BEGIN c.x := x; c.do.updated(c, TRUE)
-END ComponentSetX;
-
-PROCEDURE ComponentSetY(c: Component; y: INTEGER);
-BEGIN c.y := y; c.do.updated(c, TRUE)
-END ComponentSetY;
-
-PROCEDURE ComponentSetW(c: Component; w: INTEGER);
-BEGIN c.w := w; c.do.updated(c, TRUE)
-END ComponentSetW;
-
-PROCEDURE ComponentSetH(c: Component; h: INTEGER);
-BEGIN c.h := h; c.do.updated(c, TRUE)
-END ComponentSetH;
-
-PROCEDURE ComponentSetBounds(c: Component; x, y, w, h: INTEGER);
-BEGIN c.x := x; c.y := y; c.w := w; c.h := h; c.do.updated(c, TRUE)
-END ComponentSetBounds;
-
-PROCEDURE ComponentSetVisible(c: Component; visible: BOOLEAN);
-BEGIN
-  IF c.visible # visible THEN
-    c.visible := visible;
-    c.do.updated(c, ~visible)
-  END
-END ComponentSetVisible;
-
-PROCEDURE ComponentSetOnDraw(c: Component; hn: OnDrawHandler);
-BEGIN c.onDraw := hn
-END ComponentSetOnDraw;
-
-PROCEDURE ComponentSetOnMouseDown(c: Component; hn: OnMouseDownHandler);
-BEGIN c.onMouseDown := hn
-END ComponentSetOnMouseDown;
-
-PROCEDURE ComponentSetOnKeyDown(c: Component; hn: OnKeyDownHandler);
-BEGIN c.onKeyDown := hn
-END ComponentSetOnKeyDown;
-
-(* Container *)
-
-PROCEDURE InitContainer*(c: Container);
-BEGIN
-  InitComponent(c);
-  c.first := NIL
-END InitContainer;
-
-PROCEDURE RedrawContainer*(c: Component; bmp: G.Bitmap; x0, y0: INTEGER);
-VAR x: Component;
-BEGIN
-  IF c.visible THEN
-    IF c.redrawState = redrawAll THEN
-      c.do.draw(c, bmp, x0, y0);
-      needFlip := TRUE
-    ELSIF c.redrawState = redrawSome THEN
-      INC(x0, c.x); INC(y0, c.y);
-      x := c(Container).first;
-      WHILE x # NIL DO
-        IF x.redrawState # redrawNone THEN
-          x.do.redraw(x, bmp, x0, y0)
-        END;
-        x := x.next
-      END;
-      needFlip := TRUE
-    END
-  END;
-  c.redrawState := redrawNone
-END RedrawContainer;
+  newWindowW, newWindowH: INTEGER;
+  newWindowSettings: SET;
+  ZZZ: INTEGER;
 
-PROCEDURE DrawContainerChildren(c: Component; bmp: G.Bitmap; x0, y0: INTEGER);
-VAR d: Component;
-BEGIN
-  INC(x0, c.x); INC(y0, c.y);
-  d := c(Container).first;
-  WHILE d # NIL DO
-    IF d.visible THEN d.do.draw(d, bmp, x0, y0) END;
-    d.redrawState := redrawNone;
-    d := d.next
-  END
-END DrawContainerChildren;
+  globalWin: Window; (* !FIXME *)
 
-PROCEDURE MouseDownContainer(c: Component; x, y, btn: INTEGER);
-VAR d: Component;
-BEGIN
-  d := c(Container).first;
-  WHILE (d # NIL) &
-       ~(d.visible &
-         (x >= d.x) & (x < d.x + d.w) &
-         (y >= d.y) & (y < d.y + d.h))
-  DO d := d.next
-  END;
-  IF d # NIL THEN d.do.mouseDown(d, x - d.x, y - d.y, btn) END
-END MouseDownContainer;
+(* Widget *)
 
-PROCEDURE AddToContainer(c, toAdd: Component);
+PROCEDURE InitWidget*(w: Widget);
 BEGIN
-  toAdd.next := c(Container).first;
-  c(Container).first := toAdd;
-  toAdd.parent := c;
-  toAdd.do.updated(c, TRUE)
-END AddToContainer;
+  w.x := 0; w.y := 0; w.w := 24; w.h := 24;
+  w.draw := NIL;
 
-(* Form *)
+  (* Замок *)
+  NEW(w.body); w.body.prev := w.body; w.body.next := w.body
+END InitWidget;
 
-PROCEDURE InitForm*(f: Form);
+PROCEDURE SetText*(w: Widget; s: ARRAY OF CHAR);
 BEGIN
-  InitContainer(f);
-  f.do := formMethod;
-  f.bgColor := G.MakeCol(180, 180, 180)
-END InitForm;
+  IF w.text = NIL THEN NEW(w.text) END;
+  Strings.Copy(s, w.text.s)
+END SetText;
 
-PROCEDURE NewForm*(): Form;
-VAR f: Form;
+PROCEDURE Place*(where, what: Widget; x, y: INTEGER);
 BEGIN
-  NEW(f); InitForm(f); RETURN f
-END NewForm;
+  what.x := x; what.y := y;
 
-PROCEDURE DrawForm(c: Component; bmp: G.Bitmap; x0, y0: INTEGER);
-VAR x, y: INTEGER;
-BEGIN
-  x := x0 + c.x; y := y0 + c.y;
-  G.RectFill(bmp, x, y, x + c.w - 1, y + c.h - 1, c(Form).bgColor);
-  DrawContainerChildren(c, bmp, x0, y0)
-END DrawForm;
-
-(* Button *)
+  (* Добавление в кольцо с замком *)
+  what.prev := where.body.prev;
+  what.next := where.body;
+  where.body.prev.next := what;
+  where.body.prev := what
+END Place;
 
-PROCEDURE InitButton*(b: Button; caption: ARRAY OF CHAR);
-BEGIN
-  InitComponent(b);
-  b.do := buttonMethod;
-  b.caption := caption
-END InitButton;
+(* Window *)
 
-PROCEDURE NewButton*(caption: ARRAY OF CHAR): Button;
-VAR b: Button;
+PROCEDURE NewWindowSettings*(w, h: INTEGER; settings: SET);
 BEGIN
-  NEW(b); InitButton(b, caption); RETURN b
-END NewButton;
+  newWindowW := w;
+  newWindowH := h;
+  newWindowSettings := settings
+END NewWindowSettings;
 
-PROCEDURE DrawButton(c: Component; bmp: G.Bitmap; x0, y0: INTEGER);
-VAR i, len, c1, c2, c3: INTEGER;
+PROCEDURE DrawBody*(W: Widget; x, y: INTEGER);
+VAR p: Widget;
 BEGIN
-  INC(x0, c.x); INC(y0, c.y);
-  c1 := G.MakeCol(255, 255, 255);
-  c2 := G.MakeCol(160, 160, 160);
-  c3 := G.MakeCol(100, 100, 100);
-  len := 0; WHILE c(Button).caption[len] # 0X DO INC(len) END;
-  G.RectFill(bmp, x0 + 1, y0 + 1, x0 + c.w - 3, y0 + c.h - 3,
-             G.MakeCol(200, 200, 200));
-  G.HLine(bmp, x0, y0, x0 + c.w - 2, c1);
-  G.VLine(bmp, x0, y0, y0 + c.h - 2, c1);
-  G.HLine(bmp, x0 + 1, y0 + c.h - 2, x0 + c.w - 3, c2);
-  G.VLine(bmp, x0 + c.w - 2, y0 + 1, y0 + c.h - 2, c2);
-  G.HLine(bmp, x0, y0 + c.h - 1, x0 + c.w - 1, c3);
-  G.VLine(bmp, x0 + c.w - 1, y0, y0 + c.h - 2, c3);
-  FOR i := 0 TO len - 1 DO
-    G.DrawCharacter(screen, font, x0 + (c.w - charW * len) DIV 2,
-                    y0 + (c.h - charH) DIV 2, c(Button).caption[i],
-                    G.MakeCol(0, 0, 0));
-    INC(x0, charW)
+  p := W.body.next;
+  WHILE p # W.body DO
+    p.draw(p, x + p.x, y + p.y);
+    p := p.next
   END
-END DrawButton;
+END DrawBody;
 
-PROCEDURE MouseDownButton(c: Component; x, y, btn: INTEGER);
+PROCEDURE DrawWindow*(W: Widget; x, y: INTEGER);
+VAR c: G.Color;
+  w, h: INTEGER;
 BEGIN
-  IF c.onMouseDown # NIL THEN c.onMouseDown(c, x, y, btn) END
-END MouseDownButton;
+  G.MakeCol(c, ZZZ * 40 MOD 256, 0, 0);
+  G.ClearToColor(c);
+  G.MakeCol(c, 0, 0, ZZZ * 20 MOD 256);
+  G.GetScreenSize(w, h);
+  G.Rect(5, 5, w - 6, h - 6, c);
 
-(* Edit *)
+  DrawBody(W, x, y)
+END DrawWindow;
 
-PROCEDURE InitEdit*(e: Edit);
+PROCEDURE InitWindow*(win: Window);
 BEGIN
-  InitComponent(e);
-  e.do := editMethod;
-  e.text[0] := 0X;
-  e.selStart := 0;
-  e.selLen := 0
-END InitEdit;
+  InitWidget(win);
+  win.win := G.NewWindow(-1, -1, newWindowW, newWindowH,
+    'Window', newWindowSettings);
+  win.x := 0; win.y := 0;
+  win.w := win.win.w; win.h := win.win.h;
+  win.draw := DrawWindow
+END InitWindow;
 
-PROCEDURE NewEdit*(): Edit;
-VAR e: Edit;
+PROCEDURE NewWindow*(): Window;
+VAR win: Window;
 BEGIN
-  NEW(e); InitEdit(e); RETURN e
-END NewEdit;
+  NEW(win);
+  InitWindow(win);
+  globalWin := win
+RETURN win END NewWindow;
 
-PROCEDURE DrawEdit(c: Component; bmp: G.Bitmap; x0, y0: INTEGER);
-VAR i, len, c1, c2, c3: INTEGER;
-BEGIN
-  INC(x0, c.x); INC(y0, c.y);
-  c1 := G.MakeCol(255, 255, 255);
-  c2 := G.MakeCol(160, 160, 160);
-  c3 := G.MakeCol(100, 100, 100);
-  len := 0; WHILE c(Edit).text[len] # 0X DO INC(len) END;
-  G.RectFill(bmp, x0 + 1, y0 + 1, x0 + c.w - 3, y0 + c.h - 3,
-             G.MakeCol(200, 200, 200));
-  G.HLine(bmp, x0, y0, x0 + c.w - 2, c1);
-  G.VLine(bmp, x0, y0, y0 + c.h - 2, c1);
-  G.HLine(bmp, x0 + 1, y0 + c.h - 2, x0 + c.w - 3, c2);
-  G.VLine(bmp, x0 + c.w - 2, y0 + 1, y0 + c.h - 2, c2);
-  G.HLine(bmp, x0, y0 + c.h - 1, x0 + c.w - 1, c3);
-  G.VLine(bmp, x0 + c.w - 1, y0, y0 + c.h - 2, c3);
-  FOR i := 0 TO len - 1 DO
-    G.DrawCharacter(screen, font, x0 + (c.w - charW * len) DIV 2,
-                    y0 + (c.h - charH) DIV 2, c(Edit).text[i],
-                    G.MakeCol(0, 0, 0));
-    INC(x0, charW)
-  END
-END DrawEdit;
+(* Draw *)
 
-PROCEDURE MouseDownEdit(c: Component; x, y, btn: INTEGER);
+PROCEDURE DrawAll;
 BEGIN
-  IF c.onMouseDown # NIL THEN c.onMouseDown(c, x, y, btn) END
-END MouseDownEdit;
+  globalWin.draw(globalWin, 0, 0);
+  G.Flip
+END DrawAll;
 
-PROCEDURE KeyDownEdit(c: Component; key: INTEGER);
-BEGIN
-  IF c.onKeyDown # NIL THEN c.onKeyDown(c, key) END
-END KeyDownEdit;
+(* Fonts *)
 
-(* Circle *)
+PROCEDURE GetFont*(W: Widget): G.Font;
+RETURN font END GetFont;
 
-PROCEDURE InitCircle*(c: Circle);
-BEGIN
-  InitComponent(c);
-  c.do := circleMethod;
-  c.color := G.MakeCol(0, 0, 0)
-END InitCircle;
+(* General *)
 
-PROCEDURE NewCircle*(): Circle;
-VAR c: Circle;
+PROCEDURE HandleEvent(e: G.Event);
 BEGIN
-  NEW(c); InitCircle(c); RETURN c
-END NewCircle;
-
-PROCEDURE DrawCircle(c: Component; bmp: G.Bitmap; x0, y0: INTEGER);
-VAR r, x, y, err, color: INTEGER;
-BEGIN
-  INC(x0, c.x); INC(y0, c.y);
-  IF c.w <= c.h THEN r := (c.w - 1) DIV 2 ELSE r := (c.h - 1) DIV 2 END;
-  IF r > 0 THEN
-    INC(x0, c.w DIV 2); INC(y0, c.h DIV 2);
-    x := 0; y := r; err := 3 - 2 * r; color := c(Circle).color;
-    WHILE y >= x DO
-      G.PutPixel(screen, x0 + x, y0 + y, color);
-      G.PutPixel(screen, x0 + y, y0 + x, color);
-      G.PutPixel(screen, x0 - y, y0 + x, color);
-      G.PutPixel(screen, x0 - x, y0 + y, color);
-      G.PutPixel(screen, x0 - x, y0 - y, color);
-      G.PutPixel(screen, x0 - y, y0 - x, color);
-      G.PutPixel(screen, x0 + y, y0 - x, color);
-      G.PutPixel(screen, x0 + x, y0 - y, color);
-      IF err < 0 THEN INC(err, 4 * x + 6); INC(x, 1)
-      ELSE INC(err, 4 * (x - y)); INC(x); DEC(y)
-      END
-    END
+  IF e.type = G.keyDown THEN
+    IF e.key = G.kEsc THEN exitRunLoop := TRUE END;
+    INC(ZZZ)
+  ELSIF e.type = G.quit THEN
+    exitRunLoop := TRUE
   END
-END DrawCircle;
-
-PROCEDURE MouseDownCircle(c: Component; x, y, btn: INTEGER);
-BEGIN
-  c(Circle).color := G.MakeCol(G.Random(256), G.Random(256), G.Random(256));
-  DEC(c.x); DEC(c.w);
-  c.do.updated(c, TRUE)
-END MouseDownCircle;
-
-(* Other *)
-
-PROCEDURE btnHelloMouseDown(c: Component; x, y, btn: INTEGER);
-VAR i: INTEGER;
-BEGIN
-  c(Button).caption[1] := CHR(33 + (ORD(c(Button).caption[1]) + y * c.w + x) MOD 64);
-  i := 0; WHILE c(Button).caption[i] # 0X DO INC(i) END;
-  IF i < LEN(c(Button).caption) - 1 THEN
-    c(Button).caption[i] := CHR(i+ORD('0')); c(Button).caption[i+1] := 0X
-  END;
-  IF c.next # NIL THEN c.next.do.setVisible(c.next, ~c.next.visible) END;
-  c.do.setX(c, c.x + 1)
-END btnHelloMouseDown;
+END HandleEvent;
 
-PROCEDURE Act;
-BEGIN
-  form.do.redraw(form, screen, 0, 0);
-  IF needFlip THEN G.Flip; needFlip := FALSE ELSE G.RepeatFlip END
-END Act;
-
-PROCEDURE Run;
+PROCEDURE Run*;
 VAR e: G.Event;
-    quit: BOOLEAN;
 BEGIN
-  quit := FALSE;
+  exitRunLoop := FALSE;
   REPEAT
-    G.WaitEvents(50);
-    WHILE G.PollEvent(e) DO
-      IF e.type = G.quit THEN
-        quit := TRUE
-      ELSIF e.type = G.keyDown THEN
-        IF e.key.code = G.kEsc THEN quit := TRUE END
-      ELSIF e.type = G.mouseDown THEN
-        form.do.mouseDown(form, e.x, e.y, e.button)
-      ELSIF e.type = G.mouseMove THEN
-        needFlip := TRUE
-      END
+    WHILE G.HasEvents() DO
+      G.WaitEvent(e);
+      HandleEvent(e)
     END;
-    Act
-  UNTIL quit
+    DrawAll
+  UNTIL exitRunLoop
 END Run;
 
-PROCEDURE Init;
-VAR i: INTEGER;
+PROCEDURE Init*;
 BEGIN
-  form := NewForm();
-  form.w := screen.w;
-  form.h := screen.h;
-
-  FOR i := 0 TO 4 DO
-    btnHello := NewButton('Hello');
-    btnHello.x := 10;
-    btnHello.y := 1 + i * 21;
-    btnHello.w := 70;
-    btnHello.h := 20;
-    btnHello.onMouseDown := btnHelloMouseDown;
-    btnHello.visible := i MOD 2 = 0;
-    form.do.add(form, btnHello)
-  END;
-
-  FOR i := 1 TO G.Random(10) + 10 DO 
-    circle := NewCircle();
-    circle.w := 10 + G.Random(100);
-    circle.h := circle.w;
-    circle.x := 100 + G.Random(screen.w - circle.w - 101);
-    circle.y := G.Random(screen.h - 1 - circle.h);
-    form.do.add(form, circle)
-  END;
-
-  edit := NewEdit();
-  edit.do.setBounds(edit, 10, screen.h - 30, 80, 20);
-  edit.text := 'World';
-  form.do.add(form, edit);
-
-  G.ClearScreen;
-  needFlip := TRUE
+  G.Settings(0, 0, {G.manual});
+  G.Init;
+  IF G.Done THEN
+    font := G.LoadFont('../Data/Fonts/Main');
+    IF font = NIL THEN
+      Out.String('Gui: Could not load font.'); Out.Ln;
+      Done := FALSE
+    END
+  ELSE Done := FALSE
+  END
 END Init;
 
+PROCEDURE Close*;
 BEGIN
-  NEW(method);
-  method.draw := NIL;
-  method.mouseDown := NIL;
-  method.keyDown := NIL;
-  method.add := NIL;
-  method.updated := UpdatedComponent;
-  method.redraw := RedrawComponent;
-  method.setX := ComponentSetX;
-  method.setY := ComponentSetY;
-  method.setW := ComponentSetW;
-  method.setH := ComponentSetH;
-  method.setBounds := ComponentSetBounds;
-  method.setVisible := ComponentSetVisible;
-  method.setOnDraw := ComponentSetOnDraw;
-  method.setOnMouseDown := ComponentSetOnMouseDown;
-  method.setOnKeyDown := ComponentSetOnKeyDown;
-
-  NEW(formMethod);
-  formMethod^ := method^;
-  formMethod.draw := DrawForm;
-  formMethod.mouseDown := MouseDownContainer;
-  formMethod.add := AddToContainer;
-  formMethod.redraw := RedrawContainer;
-
-  NEW(buttonMethod);
-  buttonMethod^ := method^;
-  buttonMethod.draw := DrawButton;
-  buttonMethod.mouseDown := MouseDownButton;
-
-  NEW (editMethod);
-  editMethod^ := method^;
-  editMethod.draw := DrawEdit;
-  editMethod.mouseDown := MouseDownEdit;
-  editMethod.keyDown := KeyDownEdit;
+  G.Close
+END Close;
 
-  NEW(circleMethod);
-  circleMethod^ := method^;
-  circleMethod.draw := DrawCircle;
-  circleMethod.mouseDown := MouseDownCircle;
-  circleMethod.add := NIL;
-  circleMethod.updated := UpdatedComponent;
-  circleMethod.redraw := RedrawComponent;
-
-  G.Settings(320, 200, {G.fullscreen, G.spread, G.sharpPixels, G.initMouse});
-  (*G.Settings(640, 480, {G.fullscreen, G.spread, G.sharpPixels, G.initMouse});*)
-  screen := G.Init();
-  IF screen # NIL THEN
-    font := G.LoadFont('../Data/Fonts/Main', charW, charH);
-    IF font # NIL THEN
-      Init;
-      Run
-    ELSE
-      Out.String('Could not load font.'); Out.Ln
-    END
-  ELSE Out.String('Graphics init failed.'); Out.Ln
-  END;
-  G.Close()
-END Gui.
+BEGIN
+  Done := TRUE;
+  ZZZ := 0
+END Gui.

+ 24 - 0
Programs/TestGui.Mod

@@ -0,0 +1,24 @@
+MODULE TestGui;
+IMPORT Gui, B := Buttons, G := Graph, Out;
+
+VAR
+  win: Gui.Window;
+  btn: B.Button;
+
+PROCEDURE InitInterface;
+BEGIN
+  Gui.NewWindowSettings(320, 200, {G.fullscreen});
+  win := Gui.NewWindow();
+  btn := B.NewButton(110, 24, 'Нажми меня');
+  Gui.Place(win, btn, (win.w - btn.w) DIV 2, (win.h - btn.h) DIV 3)
+END InitInterface;
+
+BEGIN
+  Gui.Init;
+  IF Gui.Done THEN
+    InitInterface;
+    Gui.Run;
+    Gui.Close
+  ELSE Out.String('Could not init GUI.'); Out.Ln
+  END
+END TestGui.