Subversion Repositories Kolibri OS

Rev

Rev 9648 | 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, maxVal, n, m: INTEGER;
  189. BEGIN
  190.         maxVal := scroll.maxVal;
  191.         IF scroll.vertical THEN
  192.                 maxPos := scroll.height
  193.         ELSE
  194.                 maxPos := scroll.width
  195.         END;
  196.         maxPos := maxPos - scroll.btnSize*2 - scroll.sliderSize + 1;
  197.         IF (value < 0) OR (maxVal <= 0) THEN
  198.                 value := 0;
  199.                 pos := 0
  200.         ELSIF value > maxVal THEN
  201.                 value := maxVal;
  202.                 pos := maxPos
  203.         ELSE
  204.                 IF (maxPos + 1) >= maxVal THEN
  205.                         n := (maxPos + 1) DIV maxVal;
  206.                         m := (maxPos + 1) MOD maxVal;
  207.                         pos := value*n + MIN(value, m)
  208.                 ELSE
  209.                         pos := FLOOR(FLT(value)*FLT(maxPos + 1)/FLT(maxVal))
  210.                 END;
  211.                 IF pos > maxPos THEN
  212.                         pos := maxPos;
  213.                         value := maxVal
  214.                 END
  215.         END;
  216.         scroll.pos := pos;
  217.         scroll.value := value
  218. END setValue;
  219.  
  220.  
  221. PROCEDURE ceil (p, q: INTEGER): INTEGER;
  222.         RETURN p DIV q + ORD(p MOD q # 0)
  223. END ceil;
  224.  
  225.  
  226. PROCEDURE setPos (VAR scroll: tScroll; pos: INTEGER);
  227. VAR
  228.         maxPos, value, maxVal, n, m, x, x0, q: INTEGER;
  229. BEGIN
  230.         maxVal := scroll.maxVal;
  231.         IF maxVal > 0 THEN
  232.                 IF scroll.vertical THEN
  233.                         maxPos := scroll.height
  234.                 ELSE
  235.                         maxPos := scroll.width
  236.                 END;
  237.                 maxPos := maxPos - scroll.btnSize*2 - scroll.sliderSize + 1;
  238.                 IF pos <= 0 THEN
  239.                         pos := 0;
  240.                         value := 0
  241.                 ELSIF pos >= maxPos THEN
  242.                         pos := maxPos;
  243.                         value := maxVal
  244.                 ELSE
  245.                         IF maxVal <= maxPos + 1 THEN
  246.                                 n := (maxPos + 1) DIV maxVal;
  247.                                 m := (maxPos + 1) MOD maxVal;
  248.  
  249.                                 q := m*(n + 1);
  250.                                 IF q < pos THEN
  251.                                         value := ceil(pos - m, n)
  252.                                 ELSIF q > pos THEN
  253.                                         value := ceil(pos, n + 1)
  254.                                 ELSE
  255.                                         value := m
  256.                                 END;
  257.  
  258.                                 x := value*n + MIN(value, m);
  259.                                 x0 := (value - 1)*n + MIN(value - 1, m);
  260.  
  261.                                 IF x - pos > pos - x0 THEN
  262.                                         pos := x0;
  263.                                         DEC(value)
  264.                                 ELSE
  265.                                         pos := x;
  266.                                         IF pos > maxPos THEN
  267.                                                 pos := maxPos;
  268.                                                 value := maxVal
  269.                                         END
  270.                                 END
  271.                         ELSE
  272.                                 value := FLOOR(FLT(maxVal)*FLT(pos)/FLT(maxPos + 1))
  273.                         END
  274.                 END
  275.         ELSE
  276.                 pos := 0;
  277.                 value := 0
  278.         END;
  279.         scroll.pos := pos;
  280.         scroll.value := value
  281. END setPos;
  282.  
  283.  
  284. PROCEDURE MouseMove (VAR scroll: tScroll; x, y: INTEGER);
  285. VAR
  286.         c: INTEGER;
  287. BEGIN
  288.         IF scroll.vertical THEN
  289.                 c := y - scroll.top
  290.         ELSE
  291.                 c := x - scroll.left
  292.         END;
  293.         setPos(scroll, scroll.pos0 + c - scroll.Slider);
  294.         draw(scroll)
  295. END MouseMove;
  296.  
  297.  
  298. PROCEDURE button (VAR scroll: tScroll);
  299. VAR
  300.         btn: INTEGER;
  301. BEGIN
  302.         WHILE scroll.btn # 0 DO
  303.                 btn := scroll.btn;
  304.                 setValue(scroll, scroll.value + btn);
  305.                 draw(scroll);
  306.                 IF scroll.change # NIL THEN
  307.                         scroll.change
  308.                 END;
  309.                 scroll.btn := 0;
  310.                 IF 0 IN K.MouseState() THEN
  311.                         WHILE (0 IN K.MouseState()) & (scroll.delay > 0) DO
  312.                                 K.Pause(1);
  313.                                 DEC(scroll.delay)
  314.                         END;
  315.                         IF scroll.delay = 0 THEN
  316.                                 scroll.btn := btn;
  317.                                 scroll.delay := 3
  318.                         ELSE
  319.                                 scroll.delay := DELAY
  320.                         END
  321.                 ELSE
  322.                         scroll.delay := DELAY
  323.                 END
  324.         END
  325. END button;
  326.  
  327.  
  328. PROCEDURE MouseDown (VAR scroll: tScroll; x, y: INTEGER);
  329. VAR
  330.         c, size: INTEGER;
  331. BEGIN
  332.         DEC(x, scroll.left);
  333.         DEC(y, scroll.top);
  334.         scroll.mouse := TRUE;
  335.         IF U.between(1, x, scroll.width - 2) & U.between(1, y, scroll.height - 2) THEN
  336.                 IF scroll.vertical THEN
  337.                         c := y;
  338.                         size := scroll.height
  339.                 ELSE
  340.                         c := x;
  341.                         size := scroll.width
  342.                 END;
  343.                 IF U.between(scroll.btnSize + scroll.pos - 1, c, scroll.btnSize + scroll.pos + scroll.sliderSize - 1) THEN
  344.                         scroll.pos0 := scroll.pos;
  345.                         scroll.Slider := c
  346.                 ELSIF U.between(0, c, scroll.btnSize - 1) THEN
  347.                         scroll.btn := -1
  348.                 ELSIF U.between(size - scroll.btnSize, c, size - 1) THEN
  349.                         scroll.btn := 1
  350.                 ELSE
  351.                         setPos(scroll, c - scroll.btnSize - scroll.sliderSize DIV 2);
  352.                         scroll.pos0 := scroll.pos;
  353.                         scroll.Slider := c;
  354.                         draw(scroll)
  355.                 END
  356.         END
  357. END MouseDown;
  358.  
  359.  
  360. PROCEDURE mouse* (VAR scroll: tScroll);
  361. VAR
  362.         msState: SET;
  363.         x, y: INTEGER;
  364. BEGIN
  365.         K.mouse(msState, x, y);
  366.         IF 0 IN msState THEN
  367.                 IF ~scroll.mouse THEN
  368.                         MouseDown(scroll, x, y)
  369.                 ELSIF scroll.Slider # -1 THEN
  370.                         MouseMove(scroll, x, y)
  371.                 END
  372.         ELSIF scroll.mouse THEN
  373.                 MouseUp(scroll);
  374.                 draw(scroll)
  375.         END;
  376.         button(scroll)
  377. END mouse;
  378.  
  379.  
  380. END Scroll.