Bladeren bron

SimpleGui: scroll box with invisible scroll bars

Arthur Yefimov 1 jaar geleden
bovenliggende
commit
96c727d5b0
3 gewijzigde bestanden met toevoegingen van 145 en 37 verwijderingen
  1. BIN
      Programs/Examples/Game/Data/Graph/tiles.png
  2. 92 17
      Programs/Examples/Game/MapEditor.Mod
  3. 53 20
      Programs/Examples/Game/SimpleGui.Mod

BIN
Programs/Examples/Game/Data/Graph/tiles.png


+ 92 - 17
Programs/Examples/Game/MapEditor.Mod

@@ -8,6 +8,11 @@ TYPE
     curX, curY: INTEGER
   END;
 
+  TilesetWidget = POINTER TO TilesetWidgetDesc;
+  TilesetWidgetDesc = RECORD(S.ScrollBox)
+    curTile: INTEGER
+  END;
+
 VAR
   frmMain: S.Form;
 
@@ -19,10 +24,10 @@ VAR
   btnExit: S.Button;
 
   pnlSide: S.Panel;
-  scbVert: S.ScrollBar;
 
   sbxMap: S.ScrollBox;
   wgtMap: MapWidget;
+  wgtTileset: TilesetWidget;
 
   game: E.Game;
 
@@ -55,10 +60,6 @@ BEGIN
   INC(cy, E.cellW * 2);
   DEC(cw, E.cellW * 4);
   DEC(ch, E.cellW * 4); *)
-(*  INC(cx, 1);
-  INC(cy, 1);
-  DEC(cw, 2);
-  DEC(ch, 2);*)
 
   x0 := (cx - msg.x) DIV E.cellW;
   IF x0 < 0 THEN x0 := 0 END;
@@ -91,11 +92,33 @@ BEGIN
     X := msg.x + m.curX * E.cellW;
     Y := msg.y + m.curY * E.cellH;
     G.Rect(X - 1, Y - 1, X + E.cellW, Y + E.cellH, col);
-  END;
-  ;G.MakeCol(col, 0, 0, 0);
-  G.Rect(cx - 2, cy - 2, cx + cw + 1, cy + ch + 1, col);
+  END
 END MapWidgetHandleDraw;
 
+(** (x; y) in cells *)
+PROCEDURE OnMapMouseDown(x, y: INTEGER);
+  PROCEDURE P(VAR cell: E.Cell);
+  BEGIN
+    IF cell.kind # wgtTileset.curTile THEN
+      cell.kind := wgtTileset.curTile;
+      S.Redraw(wgtMap)
+    END
+  END P;
+BEGIN P(game.map.cells[y, x])
+END OnMapMouseDown;
+
+PROCEDURE MapWidgetHandleMouseDown(c: S.Widget; VAR msg: S.MouseDownMsg);
+VAR m: MapWidget;
+  x, y: INTEGER;
+BEGIN
+  m := c(MapWidget);
+  x := Limit(msg.x DIV E.cellW, 0, game.map.w - 1);
+  y := Limit(msg.y DIV E.cellH, 0, game.map.h - 1);
+  IF msg.btn = 1 THEN
+    OnMapMouseDown(x, y)
+  END
+END MapWidgetHandleMouseDown;
+
 PROCEDURE MapWidgetHandleMouseMove(c: S.Widget; VAR msg: S.MouseMoveMsg);
 VAR m: MapWidget;
   x, y: INTEGER;
@@ -105,6 +128,9 @@ BEGIN
   y := Limit(msg.y DIV E.cellH, 0, game.map.h - 1);
   IF (x # m.curX) OR (y # m.curY) THEN
     m.curX := x; m.curY := y;
+    IF 1 IN msg.btns THEN
+      OnMapMouseDown(x, y)
+    END;
     S.Redraw(c)
   END
 END MapWidgetHandleMouseMove;
@@ -115,6 +141,8 @@ BEGIN
     MapWidgetHandleMouseMove(c, msg(S.MouseMoveMsg))
   ELSIF msg IS S.MouseLeaveMsg THEN
     c(MapWidget).curX := -1; S.Redraw(c)
+  ELSIF msg IS S.MouseDownMsg THEN
+    MapWidgetHandleMouseDown(c, msg(S.MouseDownMsg))
   ELSIF msg IS S.DrawMsg THEN
     MapWidgetHandleDraw(c, msg(S.DrawMsg))
   ELSE
@@ -130,6 +158,54 @@ BEGIN
   c.handle := MapWidgetHandler;
   S.Put(c, where, x, y)
 RETURN c END NewMapWidget;
+
+(** Tileset Widget **)
+
+PROCEDURE TilesetWidgetOnInnerPaint(c: S.Widget; x, y, w, h: INTEGER);
+VAR col: G.Color;
+  n, X, Y: INTEGER;
+  t: TilesetWidget;
+BEGIN
+  t := c.parent.parent(TilesetWidget);
+  G.Draw(E.tiles, x, y);
+
+  G.MakeCol(col, 0, 110, 240);
+  X := x + t.curTile MOD E.tilesInRow * E.cellW;
+  Y := y + t.curTile DIV E.tilesInRow * E.cellH;
+  G.Rect(X, Y, X + E.cellW - 1, Y + E.cellH - 1, col)
+END TilesetWidgetOnInnerPaint;
+
+PROCEDURE TilesetWidgetOnMouseDown(c: S.Widget; x, y, btn: INTEGER);
+VAR t: TilesetWidget;
+  n: INTEGER;
+BEGIN t := c.parent.parent(TilesetWidget);
+  IF btn = 1 THEN
+    IF x < 0 THEN x := 0 ELSIF x >= c.w THEN x := c.w - 1 END;
+    IF y < 0 THEN y := 0 ELSIF y >= c.h THEN y := c.h - 1 END;
+
+    n := y DIV E.cellH * E.tilesInRow + x DIV E.cellW;
+    IF t.curTile # n THEN
+      t.curTile := n;
+      S.Redraw(c)
+    END
+  END
+END TilesetWidgetOnMouseDown;
+
+PROCEDURE TilesetWidgetOnMouseMove(c: S.Widget; x, y: INTEGER; btns: SET);
+BEGIN IF 1 IN btns THEN TilesetWidgetOnMouseDown(c, x, y, 1) END
+END TilesetWidgetOnMouseMove;
+
+PROCEDURE NewTilesetWidget(where: S.Widget; x, y, w, h: INTEGER): TilesetWidget;
+VAR c: TilesetWidget;
+BEGIN
+  NEW(c); S.InitScrollBox(c, where, x, y, w, h);
+  S.ScrollBoxSetInnerSize(c, E.tiles.w, E.tiles.h);
+  S.SetOnPaint(c.inner, TilesetWidgetOnInnerPaint);
+  S.SetOnMouseMove(c.inner, TilesetWidgetOnMouseMove);
+  S.SetOnMouseDown(c.inner, TilesetWidgetOnMouseDown);
+  c.curTile := 0
+RETURN c END NewTilesetWidget;
+
 (** - **)
 
 PROCEDURE BtnExitOnClick(c: S.Widget);
@@ -138,7 +214,7 @@ BEGIN
 END BtnExitOnClick;
 
 PROCEDURE InitInterface(): BOOLEAN;
-VAR W, H: INTEGER;
+VAR W, H, w, h: INTEGER;
   color: G.Color;
 BEGIN
   G.GetScreenSize(W, H);
@@ -161,21 +237,20 @@ BEGIN
   btnExit := S.NewButton(pnlTop, W - 68, 8, 60, 24, 'Выход');
   S.SetOnClick(btnExit, BtnExitOnClick);
 
-  pnlSide := S.NewPanel(frmMain, 0, pnlTop.h, 180, H - pnlTop.h);
+  pnlSide := S.NewPanel(frmMain, 0, pnlTop.h, 144, H - pnlTop.h);
   G.MakeCol(color, 40, 150, 40);
   S.SetBgColor(pnlSide, color);
 
-  scbVert := S.NewScrollBar(pnlSide, 20, 20, 16, 150);
-  S.ScrollBarSetVertical(scbVert, TRUE);
-  scbVert.max := 8;
+  wgtTileset := NewTilesetWidget(pnlSide, 0, 0, pnlSide.w, 200);
 
   sbxMap := S.NewScrollBox(frmMain, pnlSide.w, pnlTop.h,
       W - pnlSide.w, H - pnlTop.h);
-  S.ScrollBoxSetInnerSize(sbxMap, 1024, 1024);
-  G.MakeCol(color, 0, 0, 0);
-  S.ScrollBoxSetNoBg(sbxMap, TRUE);
+  w := game.map.w * E.cellW;
+  h := game.map.h * E.cellH;
+  S.ScrollBoxSetInnerSize(sbxMap, w, h);
+  (*S.ScrollBoxSetNoBg(sbxMap, TRUE);*)
 
-  wgtMap := NewMapWidget(sbxMap, 0, 0, 1024, 1024)
+  wgtMap := NewMapWidget(sbxMap, 0, 0, w, h)
 RETURN TRUE END InitInterface;
 
 PROCEDURE Init(): BOOLEAN;

+ 53 - 20
Programs/Examples/Game/SimpleGui.Mod

@@ -331,9 +331,7 @@ BEGIN
     IF c.redraw THEN
       IF c.redrawSelf THEN
         x := msg(DrawMsg).x; y := msg(DrawMsg).y;
-        IF c.onPaint # NIL THEN
-          c.onPaint(c, x, y, msg(DrawMsg).w, msg(DrawMsg).h)
-        ELSE
+        IF c.onPaint = NIL THEN
           G.FillRect(x, y, x + c.w - 1, y + c.h - 1, c.bgColor);
           G.Rect(x, y, x + c.w - 1, y + c.h - 1, c.fgColor);
           G.Rect(x + 2, y + 2, x + c.w - 3, y + c.h - 3, c.fgColor)
@@ -355,7 +353,10 @@ PROCEDURE DrawWidget*(c: Widget; x, y, w, h: INTEGER);
 VAR M: DrawMsg;
 BEGIN
   M.x := x; M.y := y; M.w := w; M.h := h;
-  c.handle(c, M)
+  c.handle(c, M);
+  IF c.onPaint # NIL THEN
+    c.onPaint(c, x, y, w, h);
+  END
 END DrawWidget;
 
 PROCEDURE DrawBody*(c: Widget; x, y, w, h: INTEGER; forced: BOOLEAN);
@@ -373,7 +374,7 @@ BEGIN
     IF CY < y THEN DEC(CH, y - CY); CY := y END;
     REPEAT
       IF forced THEN p.redraw := TRUE; p.redrawSelf := TRUE END;
-      IF p.redraw THEN
+      IF p.redraw & p.visible THEN
         x2 := x + p.x; y2 := y + p.y;
         w2 := w - p.x; h2 := h - p.y;
 
@@ -400,6 +401,14 @@ PROCEDURE SetFgColor*(c: Widget; color: G.Color);
 BEGIN c.fgColor := color
 END SetFgColor;
 
+PROCEDURE SetVisible*(c: Widget; visible: BOOLEAN);
+BEGIN c.visible := visible
+END SetVisible;
+
+PROCEDURE SetEnabled*(c: Widget; enabled: BOOLEAN);
+BEGIN c.enabled := enabled
+END SetEnabled;
+
 PROCEDURE SetOnPaint*(c: Widget; proc: PROCEDURE (c: Widget; x, y, w, h: INTEGER));
 BEGIN c.onPaint := proc
 END SetOnPaint;
@@ -554,13 +563,13 @@ BEGIN
   G.HLine(x + 2, y, X - 1, bl);
   G.HLine(x, Y - 1, X - 4, bl);
   G.VLine(x, y + 2, Y - 1, bl);
-  G.VLine(X - 1, y + 1, Y - 4, bl);
+  G.VLine(X - 1, y + 1, Y - 3, bl);
 
   IF ~down THEN
     G.HLine(x + 3, y + 1, X - 2, wh);
     G.HLine(x + 2, Y - 2, X - 4, g1);
     G.VLine(x + 1, y + 3, Y - 2, wh);
-    G.VLine(X - 2, y + 2, Y - 4, g1);
+    G.VLine(X - 2, y + 2, Y - 3, g1);
     G.PutPixel(X - 3, Y - 3, g1);
     G.Line(X - 4, Y - 3, X - 3, Y - 4, g1);
     G.PutPixel(x + 2, y + 2, wh)
@@ -829,7 +838,10 @@ BEGIN
   IF pos < c.min THEN pos := c.min ELSIF pos > c.max THEN pos := c.max END;
 
   range := c.max - c.min;
-  c.handlePos := bs - 2 + (pos * (maxHs - hs) + range DIV 2) DIV range
+  c.handlePos := bs - 2;
+  IF range # 0 THEN
+    INC(c.handlePos, (pos * (maxHs - hs) + range DIV 2) DIV range)
+  END
 END ScrollBarCalcMetrics;
 
 PROCEDURE DrawHorzScrollBar(c: ScrollBar; x, y, w, h: INTEGER);
@@ -910,7 +922,7 @@ END ScrollBarSetHandleSize;
 
 PROCEDURE ScrollBarSetValue*(c: ScrollBar; value: INTEGER);
 BEGIN
-  IF value < c.min THEN value := c.min
+  IF (value < c.min) OR (c.min >= c.max) THEN value := c.min
   ELSIF value > c.max THEN value := c.max
   END;
   IF c.value # value THEN
@@ -928,10 +940,11 @@ BEGIN
     ELSE x := msg.x; size := c.w
     END;
 
-    w := size - c.btnSize * 2 - c.handleSize;
-    n := x - c.handlePressPos - c.btnSize;
-    n := (n * (c.max - c.min) + w DIV 2) DIV w + c.min;
-
+    w := size - c.btnSize * 2 - c.handleSize + 4;
+    IF w = 0 THEN n := c.min
+    ELSE n := x - c.handlePressPos - c.btnSize + 2;
+      n := (n * (c.max - c.min) + w DIV 2) DIV w + c.min;
+    END;
     ScrollBarSetValue(c, n)
   END
 END HandleScrollBarMouseMove;
@@ -1029,14 +1042,34 @@ END ScrollBoxHandler;
 PROCEDURE ScrollBoxSetInnerSize*(c: ScrollBox; w, h: INTEGER);
 BEGIN
   Resize(c.inner, w, h);
-  c.scbHorz.max := w - c.outer.w;
-  c.scbVert.max := h - c.outer.h;
-  IF w # 0 THEN
-    ScrollBarSetHandleSize(c.scbHorz, c.outer.w * (c.outer.w - 32) DIV w)
+  c.scbHorz.max := w - c.w - 16;
+  c.scbVert.max := h - c.h - 16;
+
+  IF (c.scbHorz.max > 0) & (w > 0) THEN
+    SetVisible(c.scbHorz, TRUE);
+    c.outer.h := c.h - c.scbHorz.h
+  ELSE
+    SetVisible(c.scbHorz, FALSE);
+    c.outer.h := c.h
   END;
-  IF h # 0 THEN
-    ScrollBarSetHandleSize(c.scbVert, c.outer.h * (c.outer.h - 32) DIV h)
+  c.scbVert.h := c.outer.h;
+
+  IF (c.scbVert.max > 0) & (h > 0) THEN
+    SetVisible(c.scbVert, TRUE);
+    c.outer.w := c.w - c.scbVert.w
+  ELSE
+    SetVisible(c.scbVert, FALSE);
+    c.outer.w := c.w
   END;
+  c.scbHorz.w := c.outer.w;
+
+  IF w > 0 THEN
+    ScrollBarSetHandleSize(c.scbHorz, c.outer.w * (c.outer.w - 28) DIV w)
+  END;
+  IF h > 0 THEN
+    ScrollBarSetHandleSize(c.scbVert, c.outer.h * (c.outer.h - 28) DIV h)
+  END;
+
   Redraw(c)
 END ScrollBoxSetInnerSize;
 
@@ -1074,7 +1107,7 @@ BEGIN InitWidget(c, w, h);
   PanelSetNoBg(c.outer, TRUE);
 
   c.inner := NewPanel(c.outer, 0, 0, 1, 1);
-  ScrollBoxSetInnerSize(c, w * 2, h * 3);
+  ScrollBoxSetInnerSize(c, c.outer.w, c.outer.h);
 
   Put(c, where, x, y)
 END InitScrollBox;