Subversion Repositories Kolibri OS

Rev

Rev 9630 | Rev 9659 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. (*
  2.     Copyright 2021, 2022 Anton Krotov
  3.  
  4.     This file is part of CEdit.
  5.  
  6.     CEdit is free software: you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation, either version 3 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     CEdit is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with CEdit. If not, see <http://www.gnu.org/licenses/>.
  18. *)
  19.  
  20. MODULE Scroll;
  21.  
  22. IMPORT G := Graph, K := KolibriOS, U := Utils;
  23.  
  24. CONST
  25.  
  26.         DELAY = 40;
  27.  
  28. TYPE
  29.  
  30.         tProcedure = PROCEDURE;
  31.  
  32.         tScroll* = RECORD
  33.                 vertical, mouse: BOOLEAN;
  34.                 top*, left*,
  35.                 width*, height*: INTEGER; (* read only *)
  36.                 btnSize, sliderSize: INTEGER;
  37.                 pos, Slider, pos0, maxVal*, value*: INTEGER;
  38.                 canvas: G.tCanvas;
  39.                 change: tProcedure;
  40.                 delay: INTEGER;
  41.                 btn*: INTEGER
  42.         END;
  43.  
  44.  
  45. PROCEDURE MouseUp (VAR scroll: tScroll);
  46. BEGIN
  47.         scroll.Slider := -1;
  48.         scroll.btn := 0;
  49.         scroll.mouse := FALSE;
  50.         scroll.delay := DELAY
  51. END MouseUp;
  52.  
  53.  
  54. PROCEDURE create* (vertical: BOOLEAN; width, height: INTEGER; btnSize, sliderSize: INTEGER; change: tProcedure; VAR scroll: tScroll);
  55. VAR
  56.         res: tScroll;
  57. BEGIN
  58.         MouseUp(res);
  59.         res.vertical := vertical;
  60.         res.left := 0;
  61.         res.top := 0;
  62.         res.width := width;
  63.         res.height := height;
  64.         res.btnSize := btnSize;
  65.         res.sliderSize := sliderSize;
  66.         res.pos := 0;
  67.         res.maxVal := 0;
  68.         res.canvas := G.CreateCanvas(width, height);
  69.         res.change := change;
  70.         scroll := res
  71. END create;
  72.  
  73.  
  74. PROCEDURE Rect (canvas: G.tCanvas; left, top, right, bottom: INTEGER);
  75. BEGIN
  76.         G.FillRect(canvas, left, top, right, bottom);
  77.         G.SetColor(canvas, K.colors.line);
  78.         G.Rect(canvas, left, top, right, bottom);
  79. END Rect;
  80.  
  81.  
  82. PROCEDURE _draw (scroll: tScroll);
  83. VAR
  84.         canvas: G.tCanvas;
  85.         x, y, d, x1, x2, y1, y2,
  86.         width, height, btn: INTEGER;
  87.  
  88.  
  89.         PROCEDURE SetColor (canvas: G.tCanvas; c: BOOLEAN);
  90.         VAR
  91.                 color: INTEGER;
  92.         BEGIN
  93.                 IF c THEN
  94.                         color := K.colors.button
  95.                 ELSE
  96.                         color := K.colors.button_text
  97.                 END;
  98.                 G.SetColor(canvas, color)
  99.         END SetColor;
  100.  
  101.  
  102. BEGIN
  103.         btn := scroll.btnSize;
  104.         width := scroll.width;
  105.         height := scroll.height;
  106.         canvas := scroll.canvas;
  107.         G.SetColor(canvas, K.colors.light);
  108.         G.clear(canvas);
  109.         G.SetColor(canvas, K.colors.line);
  110.         G.Rect(canvas, 0, 0, width - 1, height - 1);
  111.         IF scroll.vertical THEN
  112.                 SetColor(canvas, scroll.btn # -1);
  113.                 Rect(canvas, 0, 0, width - 1, btn - 1);
  114.                 SetColor(canvas, scroll.btn # 1);
  115.                 Rect(canvas, 0, height - btn, width - 1, height - 1);
  116.                 G.SetColor(canvas, K.colors.button);
  117.                 Rect(canvas, 0, btn + scroll.pos - 1, width - 1, btn + scroll.pos + scroll.sliderSize - 1);
  118.  
  119.                 G.SetColor(canvas, K.colors.button_text);
  120.  
  121.                 y := btn + scroll.pos + scroll.sliderSize DIV 2 - 1;
  122.                 G.HLine(canvas, y, width DIV 4, 3*width DIV 4);
  123.                 G.HLine(canvas, y - 3, width DIV 3, 2*width DIV 3);
  124.                 G.HLine(canvas, y + 3, width DIV 3, 2*width DIV 3);
  125.  
  126.                 d := 4*width DIV 10;
  127.                 x1 := (width - d) DIV 2;
  128.                 x2 := x1 + d;
  129.  
  130.                 SetColor(canvas, scroll.btn = -1);
  131.                 y := (btn - d DIV 2) DIV 2 + d DIV 2 - 1;
  132.                 G.Triangle(canvas, x1 - 1, y, x2, y, G.triUp);
  133.  
  134.                 SetColor(canvas, scroll.btn = 1);
  135.                 y := y + height - btn - d DIV 2 + 1;
  136.                 G.Triangle(canvas, x1 - 1, y, x2, y, G.triDown);
  137.         ELSE
  138.                 SetColor(canvas, scroll.btn # -1);
  139.                 Rect(canvas, 0, 0, btn - 1, height - 1);
  140.                 SetColor(canvas, scroll.btn # 1);
  141.                 Rect(canvas, width - btn, 0, width - 1, height - 1);
  142.                 G.SetColor(canvas, K.colors.button);
  143.                 Rect(canvas, btn + scroll.pos - 1, 0, btn + scroll.pos + scroll.sliderSize - 1, height - 1);
  144.  
  145.                 G.SetColor(canvas, K.colors.button_text);
  146.  
  147.                 x := btn + scroll.pos + scroll.sliderSize DIV 2 - 1;
  148.                 G.VLine(canvas, x, height DIV 4, 3*height DIV 4);
  149.                 G.VLine(canvas, x - 3, height DIV 3, 2*height DIV 3);
  150.                 G.VLine(canvas, x + 3, height DIV 3, 2*height DIV 3);
  151.  
  152.                 d := 4*height DIV 10;
  153.                 y1 := (height - d) DIV 2;
  154.                 y2 := y1 + d;
  155.  
  156.                 SetColor(canvas, scroll.btn = -1);
  157.                 x := (btn - d DIV 2) DIV 2 + d DIV 2 - 1;
  158.                 G.Triangle(canvas, x, y1 - 1, x, y2, G.triLeft);
  159.  
  160.                 SetColor(canvas, scroll.btn = 1);
  161.                 x := x + width - btn - d DIV 2 + 1;
  162.                 G.Triangle(canvas, x, y1 - 1, x, y2, G.triRight);
  163.         END;
  164.         G.DrawCanvas(scroll.canvas, scroll.left, scroll.top)
  165. END _draw;
  166.  
  167.  
  168. PROCEDURE draw* (scroll: tScroll);
  169. BEGIN
  170.         IF scroll.canvas # NIL THEN
  171.                 _draw(scroll)
  172.         END
  173. END draw;
  174.  
  175.  
  176. PROCEDURE resize* (VAR scroll: tScroll; width, height: INTEGER);
  177. BEGIN
  178.         G.destroy(scroll.canvas);
  179.         scroll.canvas := G.CreateCanvas(width, height);
  180.         scroll.width := width;
  181.         scroll.height := height;
  182.         draw(scroll)
  183. END resize;
  184.  
  185.  
  186. PROCEDURE setValue* (VAR scroll: tScroll; value: INTEGER);
  187. VAR
  188.         pos, maxPos, n, m: INTEGER;
  189. BEGIN
  190.         IF scroll.vertical THEN
  191.                 maxPos := scroll.height
  192.         ELSE
  193.                 maxPos := scroll.width
  194.         END;
  195.         maxPos := maxPos - scroll.btnSize*2 - scroll.sliderSize + 1;
  196.         IF (value < 0) OR (scroll.maxVal <= 0) THEN
  197.                 value := 0;
  198.                 pos := 0
  199.         ELSIF value > scroll.maxVal THEN
  200.                 value := scroll.maxVal;
  201.                 pos := maxPos
  202.         ELSE
  203.                 IF (maxPos + 1) >= scroll.maxVal THEN
  204.                         n := (maxPos + 1) DIV scroll.maxVal;
  205.                         m := (maxPos + 1) MOD scroll.maxVal;
  206.                         pos := value*n + MIN(value, m)
  207.                 ELSE
  208.                         pos := FLOOR(FLT(value)*FLT(maxPos + 1)/FLT(scroll.maxVal))
  209.                 END;
  210.                 IF pos > maxPos THEN
  211.                         pos := maxPos;
  212.                         value := scroll.maxVal
  213.                 END
  214.         END;
  215.         scroll.pos := pos;
  216.         scroll.value := value
  217. END setValue;
  218.  
  219.  
  220. PROCEDURE ceil (p, q: INTEGER): INTEGER;
  221.         RETURN p DIV q + ORD(p MOD q # 0)
  222. END ceil;
  223.  
  224.  
  225. PROCEDURE setPos (VAR scroll: tScroll; pos: INTEGER);
  226. VAR
  227.         maxPos, value, n, m, x, x0, q: INTEGER;
  228. BEGIN
  229.         IF scroll.maxVal > 0 THEN
  230.                 IF scroll.vertical THEN
  231.                         maxPos := scroll.height
  232.                 ELSE
  233.                         maxPos := scroll.width
  234.                 END;
  235.                 maxPos := maxPos - scroll.btnSize*2 - scroll.sliderSize + 1;
  236.                 IF pos <= 0 THEN
  237.                         pos := 0;
  238.                         value := 0
  239.                 ELSIF pos >= maxPos THEN
  240.                         pos := maxPos;
  241.                         value := scroll.maxVal
  242.                 ELSE
  243.                         IF scroll.maxVal <= maxPos + 1 THEN
  244.                                 n := (maxPos + 1) DIV scroll.maxVal;
  245.                                 m := (maxPos + 1) MOD scroll.maxVal;
  246.  
  247.                                 q := m*(n + 1);
  248.                                 IF q < pos THEN
  249.                                         value := ceil(pos - m, n)
  250.                                 ELSIF q > pos THEN
  251.                                         value := ceil(pos, n + 1)
  252.                                 ELSE
  253.                                         value := m
  254.                                 END;
  255.  
  256.                                 x := value*n + MIN(value, m);
  257.                                 x0 := (value - 1)*n + MIN(value - 1, m);
  258.  
  259.                                 IF x - pos > pos - x0 THEN
  260.                                         pos := x0;
  261.                                         DEC(value)
  262.                                 ELSE
  263.                                         pos := x;
  264.                                         IF pos > maxPos THEN
  265.                                                 pos := maxPos;
  266.                                                 value := scroll.maxVal
  267.                                         END
  268.                                 END
  269.                         ELSE
  270.                                 value := FLOOR(FLT(scroll.maxVal)*FLT(pos)/FLT(maxPos + 1))
  271.                         END
  272.                 END
  273.         ELSE
  274.                 pos := 0;
  275.                 scroll.value := 0
  276.         END;
  277.         scroll.pos := pos;
  278.         scroll.value := value
  279. END setPos;
  280.  
  281.  
  282. PROCEDURE MouseMove (VAR scroll: tScroll; x, y: INTEGER);
  283. VAR
  284.         c: INTEGER;
  285. BEGIN
  286.         IF scroll.vertical THEN
  287.                 c := y - scroll.top
  288.         ELSE
  289.                 c := x - scroll.left
  290.         END;
  291.         setPos(scroll, scroll.pos0 + c - scroll.Slider);
  292.         draw(scroll)
  293. END MouseMove;
  294.  
  295.  
  296. PROCEDURE button (VAR scroll: tScroll);
  297. VAR
  298.         btn: INTEGER;
  299. BEGIN
  300.         WHILE scroll.btn # 0 DO
  301.                 btn := scroll.btn;
  302.                 setValue(scroll, scroll.value + btn);
  303.                 draw(scroll);
  304.                 IF scroll.change # NIL THEN
  305.                         scroll.change
  306.                 END;
  307.                 scroll.btn := 0;
  308.                 IF 0 IN K.MouseState() THEN
  309.                         WHILE (0 IN K.MouseState()) & (scroll.delay > 0) DO
  310.                                 K.Pause(1);
  311.                                 DEC(scroll.delay)
  312.                         END;
  313.                         IF scroll.delay = 0 THEN
  314.                                 scroll.btn := btn;
  315.                                 scroll.delay := 3
  316.                         ELSE
  317.                                 scroll.delay := DELAY
  318.                         END
  319.                 ELSE
  320.                         scroll.delay := DELAY
  321.                 END
  322.         END
  323. END button;
  324.  
  325.  
  326. PROCEDURE MouseDown (VAR scroll: tScroll; x, y: INTEGER);
  327. VAR
  328.         c, size: INTEGER;
  329. BEGIN
  330.         DEC(x, scroll.left);
  331.         DEC(y, scroll.top);
  332.         scroll.mouse := TRUE;
  333.         IF U.between(1, x, scroll.width - 2) & U.between(1, y, scroll.height - 2) THEN
  334.                 IF scroll.vertical THEN
  335.                         c := y;
  336.                         size := scroll.height
  337.                 ELSE
  338.                         c := x;
  339.                         size := scroll.width
  340.                 END;
  341.                 IF U.between(scroll.btnSize + scroll.pos - 1, c, scroll.btnSize + scroll.pos + scroll.sliderSize - 1) THEN
  342.                         scroll.pos0 := scroll.pos;
  343.                         scroll.Slider := c
  344.                 ELSIF U.between(0, c, scroll.btnSize - 1) THEN
  345.                         scroll.btn := -1
  346.                 ELSIF U.between(size - scroll.btnSize, c, size - 1) THEN
  347.                         scroll.btn := 1
  348.                 ELSE
  349.                         setPos(scroll, c - scroll.btnSize - scroll.sliderSize DIV 2);
  350.                         scroll.pos0 := scroll.pos;
  351.                         scroll.Slider := c;
  352.                         draw(scroll)
  353.                 END
  354.         END
  355. END MouseDown;
  356.  
  357.  
  358. PROCEDURE mouse* (VAR scroll: tScroll);
  359. VAR
  360.         msState: SET;
  361.         x, y: INTEGER;
  362. BEGIN
  363.         K.mouse(msState, x, y);
  364.         IF 0 IN msState THEN
  365.                 IF ~scroll.mouse THEN
  366.                         MouseDown(scroll, x, y)
  367.                 ELSIF scroll.Slider # -1 THEN
  368.                         MouseMove(scroll, x, y)
  369.                 END
  370.         ELSIF scroll.mouse THEN
  371.                 MouseUp(scroll);
  372.                 draw(scroll)
  373.         END;
  374.         button(scroll)
  375. END mouse;
  376.  
  377.  
  378. END Scroll.