Subversion Repositories Kolibri OS

Rev

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

  1. (*
  2.     Copyright 2021 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;
  23.  
  24. CONST
  25.  
  26.         ScrollIPC* = 0;
  27.  
  28. TYPE
  29.  
  30.         tScroll* = RECORD
  31.                 vertical, Inc*, Dec*, mouse*: BOOLEAN;
  32.                 top*, left*,
  33.                 width*, height*: INTEGER; (* read only *)
  34.                 btnSize, sliderSize: INTEGER;
  35.                 pos, Slider, pos0, maxVal*, value*: INTEGER;
  36.                 canvas*: G.tCanvas
  37.         END;
  38.  
  39.  
  40. PROCEDURE create* (vertical: BOOLEAN; width, height: INTEGER; btnSize, sliderSize: INTEGER; VAR scroll: tScroll);
  41. BEGIN
  42.         scroll.vertical := vertical;
  43.         scroll.Inc := FALSE;
  44.         scroll.Dec := FALSE;
  45.         scroll.Slider := -1;
  46.         scroll.mouse := FALSE;
  47.         scroll.left := 0;
  48.         scroll.top := 0;
  49.         scroll.width := width;
  50.         scroll.height := height;
  51.         scroll.btnSize := btnSize;
  52.         scroll.sliderSize := sliderSize;
  53.         scroll.pos := 0;
  54.         scroll.maxVal := 0;
  55.         scroll.canvas := G.CreateCanvas(width, height)
  56. END create;
  57.  
  58.  
  59. PROCEDURE Rect (canvas: G.tCanvas; left, top, right, bottom: INTEGER);
  60. BEGIN
  61.         G.FillRect(canvas, left, top, right, bottom);
  62.         G.SetColor(canvas, K.borderColor);
  63.         G.Rect(canvas, left, top, right, bottom);
  64. END Rect;
  65.  
  66.  
  67. PROCEDURE _paint (scroll: tScroll);
  68. VAR
  69.         canvas: G.tCanvas;
  70.         x, y, d, x1, x2, y1, y2,
  71.         width, height, btn: INTEGER;
  72.  
  73.  
  74.         PROCEDURE SetColor (canvas: G.tCanvas; c: BOOLEAN);
  75.         VAR
  76.                 color: INTEGER;
  77.         BEGIN
  78.                 IF c THEN
  79.                         color := K.btnColor
  80.                 ELSE
  81.                         color := K.btnTextColor
  82.                 END;
  83.                 G.SetColor(canvas, color)
  84.         END SetColor;
  85.  
  86.  
  87. BEGIN
  88.         btn := scroll.btnSize;
  89.         width := scroll.width;
  90.         height := scroll.height;
  91.         canvas := scroll.canvas;
  92.         G.SetColor(canvas, K.winColor);
  93.         G.clear(canvas);
  94.         G.SetColor(canvas, K.borderColor);
  95.         G.Rect(canvas, 0, 0, width - 1, height - 1);
  96.         IF scroll.vertical THEN
  97.                 SetColor(canvas, ~scroll.Dec);
  98.                 Rect(canvas, 0, 0, width - 1, btn - 1);
  99.                 SetColor(canvas, ~scroll.Inc);
  100.                 Rect(canvas, 0, height - btn, width - 1, height - 1);
  101.                 G.SetColor(canvas, K.btnColor);
  102.                 Rect(canvas, 0, btn + scroll.pos - 1, width - 1, btn + scroll.pos + scroll.sliderSize - 1);
  103.  
  104.                 G.SetColor(canvas, K.btnTextColor);
  105.  
  106.                 y := btn + scroll.pos + scroll.sliderSize DIV 2 - 1;
  107.                 G.HLine(canvas, y, width DIV 4, 3*width DIV 4);
  108.                 G.HLine(canvas, y - 3, width DIV 3, 2*width DIV 3);
  109.                 G.HLine(canvas, y + 3, width DIV 3, 2*width DIV 3);
  110.  
  111.                 d := 4*width DIV 10;
  112.                 x1 := (width - d) DIV 2;
  113.                 x2 := x1 + d;
  114.  
  115.                 SetColor(canvas, scroll.Dec);
  116.                 y := (btn - d DIV 2) DIV 2 + d DIV 2 - 1;
  117.                 G.Triangle(canvas, x1 - 1, y, x2, y, G.triUp);
  118.  
  119.                 SetColor(canvas, scroll.Inc);
  120.                 y := y + height - btn - d DIV 2 + 1;
  121.                 G.Triangle(canvas, x1 - 1, y, x2, y, G.triDown);
  122.         ELSE
  123.                 SetColor(canvas, ~scroll.Dec);
  124.                 Rect(canvas, 0, 0, btn - 1, height - 1);
  125.                 SetColor(canvas, ~scroll.Inc);
  126.                 Rect(canvas, width - btn, 0, width - 1, height - 1);
  127.                 G.SetColor(canvas, K.btnColor);
  128.                 Rect(canvas, btn + scroll.pos - 1, 0, btn + scroll.pos + scroll.sliderSize - 1, height - 1);
  129.  
  130.                 G.SetColor(canvas, K.btnTextColor);
  131.  
  132.                 x := btn + scroll.pos + scroll.sliderSize DIV 2 - 1;
  133.                 G.VLine(canvas, x, height DIV 4, 3*height DIV 4);
  134.                 G.VLine(canvas, x - 3, height DIV 3, 2*height DIV 3);
  135.                 G.VLine(canvas, x + 3, height DIV 3, 2*height DIV 3);
  136.  
  137.                 d := 4*height DIV 10;
  138.                 y1 := (height - d) DIV 2;
  139.                 y2 := y1 + d;
  140.  
  141.                 SetColor(canvas, scroll.Dec);
  142.                 x := (btn - d DIV 2) DIV 2 + d DIV 2 - 1;
  143.                 G.Triangle(canvas, x, y1 - 1, x, y2, G.triLeft);
  144.  
  145.                 SetColor(canvas, scroll.Inc);
  146.                 x := x + width - btn - d DIV 2 + 1;
  147.                 G.Triangle(canvas, x, y1 - 1, x, y2, G.triRight);
  148.         END;
  149.         G.DrawCanvas(scroll.canvas, scroll.left, scroll.top)
  150. END _paint;
  151.  
  152.  
  153. PROCEDURE paint* (scroll: tScroll);
  154. BEGIN
  155.         IF scroll.canvas # NIL THEN
  156.                 _paint(scroll)
  157.         END
  158. END paint;
  159.  
  160.  
  161. PROCEDURE resize* (VAR scroll: tScroll; width, height: INTEGER);
  162. BEGIN
  163.         G.destroy(scroll.canvas);
  164.         scroll.canvas := G.CreateCanvas(width, height);
  165.         scroll.width := width;
  166.         scroll.height := height;
  167.         paint(scroll)
  168. END resize;
  169.  
  170.  
  171. PROCEDURE setValue* (VAR scroll: tScroll; value: INTEGER);
  172. VAR
  173.         pos, maxPos, n, m: INTEGER;
  174. BEGIN
  175.         IF scroll.vertical THEN
  176.                 maxPos := scroll.height
  177.         ELSE
  178.                 maxPos := scroll.width
  179.         END;
  180.         maxPos := maxPos - scroll.btnSize*2 - scroll.sliderSize + 1;
  181.         IF (value < 0) OR (scroll.maxVal <= 0) THEN
  182.                 value := 0;
  183.                 pos := 0
  184.         ELSIF value > scroll.maxVal THEN
  185.                 value := scroll.maxVal;
  186.                 pos := maxPos
  187.         ELSE
  188.                 IF (maxPos + 1) >= scroll.maxVal THEN
  189.                         n := (maxPos + 1) DIV scroll.maxVal;
  190.                         m := (maxPos + 1) MOD scroll.maxVal;
  191.                         pos := value*n + MIN(value, m)
  192.                 ELSE
  193.                         pos := value*(maxPos + 1) DIV scroll.maxVal
  194.                 END;
  195.                 IF pos > maxPos THEN
  196.                         pos := maxPos;
  197.                         value := scroll.maxVal
  198.                 END
  199.         END;
  200.         scroll.pos := pos;
  201.         scroll.value := value
  202. END setValue;
  203.  
  204.  
  205. PROCEDURE change* (VAR scroll: tScroll);
  206. BEGIN
  207.         IF scroll.Inc THEN
  208.                 setValue(scroll, scroll.value + 1)
  209.         ELSIF scroll.Dec THEN
  210.                 setValue(scroll, scroll.value - 1)
  211.         END;
  212.         paint(scroll)
  213. END change;
  214.  
  215.  
  216. PROCEDURE ceil (p, q: INTEGER): INTEGER;
  217.         RETURN p DIV q + ORD(p MOD q # 0)
  218. END ceil;
  219.  
  220.  
  221. PROCEDURE setPos (VAR scroll: tScroll; pos: INTEGER);
  222. VAR
  223.         maxPos, value, n, m, x, x0, q: INTEGER;
  224. BEGIN
  225.         IF scroll.maxVal > 0 THEN
  226.                 IF scroll.vertical THEN
  227.                         maxPos := scroll.height
  228.                 ELSE
  229.                         maxPos := scroll.width
  230.                 END;
  231.                 maxPos := maxPos - scroll.btnSize*2 - scroll.sliderSize + 1;
  232.                 IF pos <= 0 THEN
  233.                         pos := 0;
  234.                         value := 0
  235.                 ELSIF pos >= maxPos THEN
  236.                         pos := maxPos;
  237.                         value := scroll.maxVal
  238.                 ELSE
  239.                         IF scroll.maxVal <= maxPos + 1 THEN
  240.                                 n := (maxPos + 1) DIV scroll.maxVal;
  241.                                 m := (maxPos + 1) MOD scroll.maxVal;
  242.  
  243.                                 q := m*(n + 1);
  244.                                 IF q < pos THEN
  245.                                         value := ceil(pos - m, n)
  246.                                 ELSIF q > pos THEN
  247.                                         value := ceil(pos, n + 1)
  248.                                 ELSE
  249.                                         value := m
  250.                                 END;
  251.  
  252.                                 x := value*n + MIN(value, m);
  253.                                 x0 := (value - 1)*n + MIN(value - 1, m);
  254.  
  255.                                 IF x - pos > pos - x0 THEN
  256.                                         pos := x0;
  257.                                         DEC(value)
  258.                                 ELSE
  259.                                         pos := x;
  260.                                         IF pos > maxPos THEN
  261.                                                 pos := maxPos;
  262.                                                 value := scroll.maxVal
  263.                                         END
  264.                                 END
  265.                         ELSE
  266.                                 value := scroll.maxVal*pos DIV (maxPos + 1)
  267.                         END
  268.                 END
  269.         ELSE
  270.                 pos := 0;
  271.                 scroll.value := 0
  272.         END;
  273.         scroll.pos := pos;
  274.         scroll.value := value
  275. END setPos;
  276.  
  277.  
  278. PROCEDURE isActive* (scroll: tScroll): BOOLEAN;
  279.         RETURN scroll.Inc OR scroll.Dec OR (scroll.Slider # -1)
  280. END isActive;
  281.  
  282.  
  283. PROCEDURE MouseMove* (VAR scroll: tScroll; x, y: INTEGER);
  284. VAR
  285.         c: INTEGER;
  286. BEGIN
  287.         IF scroll.Slider # -1 THEN
  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.                 paint(scroll)
  295.         END
  296. END MouseMove;
  297.  
  298.  
  299. PROCEDURE between (a, b, c: INTEGER): BOOLEAN;
  300.         RETURN (a <= b) & (b <= c)
  301. END between;
  302.  
  303.  
  304. PROCEDURE SendIPC*;
  305. BEGIN
  306.         K.SendIPC(K.ThreadID(), ScrollIPC)
  307. END SendIPC;
  308.  
  309.  
  310. PROCEDURE MouseDown* (VAR scroll: tScroll; x, y: INTEGER);
  311. VAR
  312.         c, size: INTEGER;
  313. BEGIN
  314.         x := x - scroll.left;
  315.         y := y - scroll.top;
  316.         scroll.mouse := TRUE;
  317.         IF between(0, x, scroll.width - 1) & between(0, y, scroll.height - 1) THEN
  318.                 IF scroll.vertical THEN
  319.                         c := y;
  320.                         size := scroll.height
  321.                 ELSE
  322.                         c := x;
  323.                         size := scroll.width
  324.                 END;
  325.                 IF between(scroll.btnSize + scroll.pos - 1, c, scroll.btnSize + scroll.pos + scroll.sliderSize - 1) THEN
  326.                         scroll.pos0 := scroll.pos;
  327.                         scroll.Slider := c
  328.                 ELSE
  329.                         IF between(0, c, scroll.btnSize - 1) THEN
  330.                                 scroll.Dec := TRUE;
  331.                                 SendIPC
  332.                         ELSE
  333.                                 IF between(size - scroll.btnSize, c, size - 1) THEN
  334.                                         scroll.Inc := TRUE;
  335.                                         SendIPC
  336.                                 ELSE
  337.                                         setPos(scroll, c - scroll.btnSize - scroll.sliderSize DIV 2);
  338.                                         scroll.pos0 := scroll.pos;
  339.                                         scroll.Slider := c;
  340.                                         paint(scroll)
  341.                                 END
  342.                         END
  343.                 END
  344.         END
  345. END MouseDown;
  346.  
  347.  
  348. PROCEDURE MouseUp* (VAR scroll: tScroll);
  349. BEGIN
  350.         IF scroll.mouse THEN
  351.                 scroll.Slider := -1;
  352.                 scroll.Inc := FALSE;
  353.                 scroll.Dec := FALSE;
  354.                 scroll.mouse := FALSE;
  355.                 paint(scroll)
  356.         END
  357. END MouseUp;
  358.  
  359.  
  360. END Scroll.