Subversion Repositories Kolibri OS

Rev

Rev 9659 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. (*
  2.     Copyright 2021-2023 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.         SetColor(canvas, scroll.btn # -1);
  112.         IF scroll.vertical THEN
  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.                 Rect(canvas, 0, 0, btn - 1, height - 1);
  139.                 SetColor(canvas, scroll.btn # 1);
  140.                 Rect(canvas, width - btn, 0, width - 1, height - 1);
  141.                 G.SetColor(canvas, K.colors.button);
  142.                 Rect(canvas, btn + scroll.pos - 1, 0, btn + scroll.pos + scroll.sliderSize - 1, height - 1);
  143.  
  144.                 G.SetColor(canvas, K.colors.button_text);
  145.  
  146.                 x := btn + scroll.pos + scroll.sliderSize DIV 2 - 1;
  147.                 G.VLine(canvas, x, height DIV 4, 3*height DIV 4);
  148.                 G.VLine(canvas, x - 3, height DIV 3, 2*height DIV 3);
  149.                 G.VLine(canvas, x + 3, height DIV 3, 2*height DIV 3);
  150.  
  151.                 d := 4*height DIV 10;
  152.                 y1 := (height - d) DIV 2;
  153.                 y2 := y1 + d;
  154.  
  155.                 SetColor(canvas, scroll.btn = -1);
  156.                 x := (btn - d DIV 2) DIV 2 + d DIV 2 - 1;
  157.                 G.Triangle(canvas, x, y1 - 1, x, y2, G.triLeft);
  158.  
  159.                 SetColor(canvas, scroll.btn = 1);
  160.                 x := x + width - btn - d DIV 2 + 1;
  161.                 G.Triangle(canvas, x, y1 - 1, x, y2, G.triRight);
  162.         END;
  163.         G.DrawCanvas(scroll.canvas, scroll.left, scroll.top)
  164. END _draw;
  165.  
  166.  
  167. PROCEDURE draw* (scroll: tScroll);
  168. BEGIN
  169.         IF scroll.canvas # NIL THEN
  170.                 _draw(scroll)
  171.         END
  172. END draw;
  173.  
  174.  
  175. PROCEDURE resize* (VAR scroll: tScroll; width, height: INTEGER);
  176. BEGIN
  177.         G.destroy(scroll.canvas);
  178.         scroll.canvas := G.CreateCanvas(width, height);
  179.         scroll.width := width;
  180.         scroll.height := height;
  181.         draw(scroll)
  182. END resize;
  183.  
  184.  
  185. PROCEDURE setValue* (VAR scroll: tScroll; value: INTEGER);
  186. VAR
  187.         pos, maxPos, maxVal, n, m: INTEGER;
  188. BEGIN
  189.         maxVal := scroll.maxVal;
  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 (maxVal <= 0) THEN
  197.                 value := 0;
  198.                 pos := 0
  199.         ELSIF value > maxVal THEN
  200.                 value := maxVal;
  201.                 pos := maxPos
  202.         ELSE
  203.                 IF (maxPos + 1) >= maxVal THEN
  204.                         n := (maxPos + 1) DIV maxVal;
  205.                         m := (maxPos + 1) MOD maxVal;
  206.                         pos := value*n + MIN(value, m)
  207.                 ELSE
  208.                         pos := FLOOR(FLT(value)*FLT(maxPos + 1)/FLT(maxVal))
  209.                 END;
  210.                 IF pos > maxPos THEN
  211.                         pos := maxPos;
  212.                         value := 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, maxVal, n, m, x, x0, q: INTEGER;
  228. BEGIN
  229.         maxVal := scroll.maxVal;
  230.         IF maxVal > 0 THEN
  231.                 IF scroll.vertical THEN
  232.                         maxPos := scroll.height
  233.                 ELSE
  234.                         maxPos := scroll.width
  235.                 END;
  236.                 maxPos := maxPos - scroll.btnSize*2 - scroll.sliderSize + 1;
  237.                 IF pos <= 0 THEN
  238.                         pos := 0;
  239.                         value := 0
  240.                 ELSIF pos >= maxPos THEN
  241.                         pos := maxPos;
  242.                         value := maxVal
  243.                 ELSE
  244.                         IF maxVal <= maxPos + 1 THEN
  245.                                 n := (maxPos + 1) DIV maxVal;
  246.                                 m := (maxPos + 1) MOD maxVal;
  247.  
  248.                                 q := m*(n + 1);
  249.                                 IF q < pos THEN
  250.                                         value := ceil(pos - m, n)
  251.                                 ELSIF q > pos THEN
  252.                                         value := ceil(pos, n + 1)
  253.                                 ELSE
  254.                                         value := m
  255.                                 END;
  256.  
  257.                                 x := value*n + MIN(value, m);
  258.                                 x0 := (value - 1)*n + MIN(value - 1, m);
  259.  
  260.                                 IF x - pos > pos - x0 THEN
  261.                                         pos := x0;
  262.                                         DEC(value)
  263.                                 ELSE
  264.                                         pos := x;
  265.                                         IF pos > maxPos THEN
  266.                                                 pos := maxPos;
  267.                                                 value := maxVal
  268.                                         END
  269.                                 END
  270.                         ELSE
  271.                                 value := FLOOR(FLT(maxVal)*FLT(pos)/FLT(maxPos + 1))
  272.                         END
  273.                 END
  274.         ELSE
  275.                 pos := 0;
  276.                 value := 0
  277.         END;
  278.         scroll.pos := pos;
  279.         scroll.value := value
  280. END setPos;
  281.  
  282.  
  283. PROCEDURE MouseMove (VAR scroll: tScroll; x, y: INTEGER);
  284. VAR
  285.         c: INTEGER;
  286. BEGIN
  287.         IF scroll.vertical THEN
  288.                 c := y - scroll.top
  289.         ELSE
  290.                 c := x - scroll.left
  291.         END;
  292.         setPos(scroll, scroll.pos0 + c - scroll.Slider);
  293.         draw(scroll)
  294. END MouseMove;
  295.  
  296.  
  297. PROCEDURE button (VAR scroll: tScroll);
  298. VAR
  299.         btn: INTEGER;
  300. BEGIN
  301.         WHILE scroll.btn # 0 DO
  302.                 btn := scroll.btn;
  303.                 setValue(scroll, scroll.value + btn);
  304.                 draw(scroll);
  305.                 IF scroll.change # NIL THEN
  306.                         scroll.change
  307.                 END;
  308.                 scroll.btn := 0;
  309.                 IF 0 IN K.MouseState() THEN
  310.                         WHILE (0 IN K.MouseState()) & (scroll.delay > 0) DO
  311.                                 K.Pause(1);
  312.                                 DEC(scroll.delay)
  313.                         END;
  314.                         IF scroll.delay = 0 THEN
  315.                                 scroll.btn := btn;
  316.                                 scroll.delay := 3
  317.                         ELSE
  318.                                 scroll.delay := DELAY
  319.                         END
  320.                 ELSE
  321.                         scroll.delay := DELAY
  322.                 END
  323.         END
  324. END button;
  325.  
  326.  
  327. PROCEDURE MouseDown (VAR scroll: tScroll; x, y: INTEGER);
  328. VAR
  329.         c, size: INTEGER;
  330. BEGIN
  331.         DEC(x, scroll.left);
  332.         DEC(y, scroll.top);
  333.         scroll.mouse := TRUE;
  334.         IF U.between(1, x, scroll.width - 2) & U.between(1, y, scroll.height - 2) THEN
  335.                 IF scroll.vertical THEN
  336.                         c := y;
  337.                         size := scroll.height
  338.                 ELSE
  339.                         c := x;
  340.                         size := scroll.width
  341.                 END;
  342.                 IF U.between(scroll.btnSize + scroll.pos - 1, c, scroll.btnSize + scroll.pos + scroll.sliderSize - 1) THEN
  343.                         scroll.pos0 := scroll.pos;
  344.                         scroll.Slider := c
  345.                 ELSIF U.between(0, c, scroll.btnSize - 1) THEN
  346.                         scroll.btn := -1
  347.                 ELSIF U.between(size - scroll.btnSize, c, size - 1) THEN
  348.                         scroll.btn := 1
  349.                 ELSE
  350.                         setPos(scroll, c - scroll.btnSize - scroll.sliderSize DIV 2);
  351.                         scroll.pos0 := scroll.pos;
  352.                         scroll.Slider := c;
  353.                         draw(scroll)
  354.                 END
  355.         END
  356. END MouseDown;
  357.  
  358.  
  359. PROCEDURE mouse* (VAR scroll: tScroll);
  360. VAR
  361.         msState: SET;
  362.         x, y: INTEGER;
  363. BEGIN
  364.         K.mouse(msState, x, y);
  365.         IF 0 IN msState THEN
  366.                 IF ~scroll.mouse THEN
  367.                         MouseDown(scroll, x, y)
  368.                 ELSIF scroll.Slider # -1 THEN
  369.                         MouseMove(scroll, x, y)
  370.                 END
  371.         ELSIF scroll.mouse THEN
  372.                 MouseUp(scroll);
  373.                 draw(scroll)
  374.         END;
  375.         button(scroll)
  376. END mouse;
  377.  
  378.  
  379. END Scroll.