Subversion Repositories Kolibri OS

Rev

Rev 9187 | Rev 9208 | 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, U := Utils;
  23.  
  24. CONST
  25.  
  26.         ScrollIPC* = 0;
  27.         Delay* = 40;
  28.  
  29. TYPE
  30.  
  31.         tScroll* = RECORD
  32.                 vertical, Inc*, Dec*, mouse: BOOLEAN;
  33.                 top*, left*,
  34.                 width*, height*: INTEGER; (* read only *)
  35.                 btnSize, sliderSize: INTEGER;
  36.                 pos, Slider, pos0, maxVal*, value*: INTEGER;
  37.                 canvas*: G.tCanvas
  38.         END;
  39.  
  40.  
  41. PROCEDURE create* (vertical: BOOLEAN; width, height: INTEGER; btnSize, sliderSize: INTEGER; VAR scroll: tScroll);
  42. VAR
  43.         res: tScroll;
  44. BEGIN
  45.         res.vertical := vertical;
  46.         res.Inc := FALSE;
  47.         res.Dec := FALSE;
  48.         res.Slider := -1;
  49.         res.mouse := FALSE;
  50.         res.left := 0;
  51.         res.top := 0;
  52.         res.width := width;
  53.         res.height := height;
  54.         res.btnSize := btnSize;
  55.         res.sliderSize := sliderSize;
  56.         res.pos := 0;
  57.         res.maxVal := 0;
  58.         res.canvas := G.CreateCanvas(width, height);
  59.         scroll := res
  60. END create;
  61.  
  62.  
  63. PROCEDURE Rect (canvas: G.tCanvas; left, top, right, bottom: INTEGER);
  64. BEGIN
  65.         G.FillRect(canvas, left, top, right, bottom);
  66.         G.SetColor(canvas, K.borderColor);
  67.         G.Rect(canvas, left, top, right, bottom);
  68. END Rect;
  69.  
  70.  
  71. PROCEDURE _paint (scroll: tScroll);
  72. VAR
  73.         canvas: G.tCanvas;
  74.         x, y, d, x1, x2, y1, y2,
  75.         width, height, btn: INTEGER;
  76.  
  77.  
  78.         PROCEDURE SetColor (canvas: G.tCanvas; c: BOOLEAN);
  79.         VAR
  80.                 color: INTEGER;
  81.         BEGIN
  82.                 IF c THEN
  83.                         color := K.btnColor
  84.                 ELSE
  85.                         color := K.btnTextColor
  86.                 END;
  87.                 G.SetColor(canvas, color)
  88.         END SetColor;
  89.  
  90.  
  91. BEGIN
  92.         btn := scroll.btnSize;
  93.         width := scroll.width;
  94.         height := scroll.height;
  95.         canvas := scroll.canvas;
  96.         G.SetColor(canvas, K.winColor);
  97.         G.clear(canvas);
  98.         G.SetColor(canvas, K.borderColor);
  99.         G.Rect(canvas, 0, 0, width - 1, height - 1);
  100.         IF scroll.vertical THEN
  101.                 SetColor(canvas, ~scroll.Dec);
  102.                 Rect(canvas, 0, 0, width - 1, btn - 1);
  103.                 SetColor(canvas, ~scroll.Inc);
  104.                 Rect(canvas, 0, height - btn, width - 1, height - 1);
  105.                 G.SetColor(canvas, K.btnColor);
  106.                 Rect(canvas, 0, btn + scroll.pos - 1, width - 1, btn + scroll.pos + scroll.sliderSize - 1);
  107.  
  108.                 G.SetColor(canvas, K.btnTextColor);
  109.  
  110.                 y := btn + scroll.pos + scroll.sliderSize DIV 2 - 1;
  111.                 G.HLine(canvas, y, width DIV 4, 3*width DIV 4);
  112.                 G.HLine(canvas, y - 3, width DIV 3, 2*width DIV 3);
  113.                 G.HLine(canvas, y + 3, width DIV 3, 2*width DIV 3);
  114.  
  115.                 d := 4*width DIV 10;
  116.                 x1 := (width - d) DIV 2;
  117.                 x2 := x1 + d;
  118.  
  119.                 SetColor(canvas, scroll.Dec);
  120.                 y := (btn - d DIV 2) DIV 2 + d DIV 2 - 1;
  121.                 G.Triangle(canvas, x1 - 1, y, x2, y, G.triUp);
  122.  
  123.                 SetColor(canvas, scroll.Inc);
  124.                 y := y + height - btn - d DIV 2 + 1;
  125.                 G.Triangle(canvas, x1 - 1, y, x2, y, G.triDown);
  126.         ELSE
  127.                 SetColor(canvas, ~scroll.Dec);
  128.                 Rect(canvas, 0, 0, btn - 1, height - 1);
  129.                 SetColor(canvas, ~scroll.Inc);
  130.                 Rect(canvas, width - btn, 0, width - 1, height - 1);
  131.                 G.SetColor(canvas, K.btnColor);
  132.                 Rect(canvas, btn + scroll.pos - 1, 0, btn + scroll.pos + scroll.sliderSize - 1, height - 1);
  133.  
  134.                 G.SetColor(canvas, K.btnTextColor);
  135.  
  136.                 x := btn + scroll.pos + scroll.sliderSize DIV 2 - 1;
  137.                 G.VLine(canvas, x, height DIV 4, 3*height DIV 4);
  138.                 G.VLine(canvas, x - 3, height DIV 3, 2*height DIV 3);
  139.                 G.VLine(canvas, x + 3, height DIV 3, 2*height DIV 3);
  140.  
  141.                 d := 4*height DIV 10;
  142.                 y1 := (height - d) DIV 2;
  143.                 y2 := y1 + d;
  144.  
  145.                 SetColor(canvas, scroll.Dec);
  146.                 x := (btn - d DIV 2) DIV 2 + d DIV 2 - 1;
  147.                 G.Triangle(canvas, x, y1 - 1, x, y2, G.triLeft);
  148.  
  149.                 SetColor(canvas, scroll.Inc);
  150.                 x := x + width - btn - d DIV 2 + 1;
  151.                 G.Triangle(canvas, x, y1 - 1, x, y2, G.triRight);
  152.         END;
  153.         G.DrawCanvas(scroll.canvas, scroll.left, scroll.top)
  154. END _paint;
  155.  
  156.  
  157. PROCEDURE paint* (scroll: tScroll);
  158. BEGIN
  159.         IF scroll.canvas # NIL THEN
  160.                 _paint(scroll)
  161.         END
  162. END paint;
  163.  
  164.  
  165. PROCEDURE resize* (VAR scroll: tScroll; width, height: INTEGER);
  166. BEGIN
  167.         G.destroy(scroll.canvas);
  168.         scroll.canvas := G.CreateCanvas(width, height);
  169.         scroll.width := width;
  170.         scroll.height := height;
  171.         paint(scroll)
  172. END resize;
  173.  
  174.  
  175. PROCEDURE setValue* (VAR scroll: tScroll; value: INTEGER);
  176. VAR
  177.         pos, maxPos, n, m: INTEGER;
  178. BEGIN
  179.         IF scroll.vertical THEN
  180.                 maxPos := scroll.height
  181.         ELSE
  182.                 maxPos := scroll.width
  183.         END;
  184.         maxPos := maxPos - scroll.btnSize*2 - scroll.sliderSize + 1;
  185.         IF (value < 0) OR (scroll.maxVal <= 0) THEN
  186.                 value := 0;
  187.                 pos := 0
  188.         ELSIF value > scroll.maxVal THEN
  189.                 value := scroll.maxVal;
  190.                 pos := maxPos
  191.         ELSE
  192.                 IF (maxPos + 1) >= scroll.maxVal THEN
  193.                         n := (maxPos + 1) DIV scroll.maxVal;
  194.                         m := (maxPos + 1) MOD scroll.maxVal;
  195.                         pos := value*n + MIN(value, m)
  196.                 ELSE
  197.                         pos := FLOOR(FLT(value)*FLT(maxPos + 1)/FLT(scroll.maxVal))
  198.                 END;
  199.                 IF pos > maxPos THEN
  200.                         pos := maxPos;
  201.                         value := scroll.maxVal
  202.                 END
  203.         END;
  204.         scroll.pos := pos;
  205.         scroll.value := value
  206. END setValue;
  207.  
  208.  
  209. PROCEDURE change* (VAR scroll: tScroll);
  210. BEGIN
  211.         IF scroll.Inc THEN
  212.                 setValue(scroll, scroll.value + 1)
  213.         ELSIF scroll.Dec THEN
  214.                 setValue(scroll, scroll.value - 1)
  215.         END;
  216.         paint(scroll)
  217. END change;
  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 isActive* (scroll: tScroll): BOOLEAN;
  283.         RETURN scroll.Inc OR scroll.Dec OR (scroll.Slider # -1)
  284. END isActive;
  285.  
  286.  
  287. PROCEDURE MouseMove* (VAR scroll: tScroll; x, y: INTEGER);
  288. VAR
  289.         c: INTEGER;
  290. BEGIN
  291.         IF scroll.Slider # -1 THEN
  292.                 IF scroll.vertical THEN
  293.                         c := y - scroll.top
  294.                 ELSE
  295.                         c := x - scroll.left
  296.                 END;
  297.                 setPos(scroll, scroll.pos0 + c - scroll.Slider);
  298.                 paint(scroll)
  299.         END
  300. END MouseMove;
  301.  
  302.  
  303. PROCEDURE SendIPC*;
  304. BEGIN
  305.         K.SendIPC(K.ThreadID(), ScrollIPC)
  306. END SendIPC;
  307.  
  308.  
  309. PROCEDURE MouseDown* (VAR scroll: tScroll; x, y: INTEGER);
  310. VAR
  311.         c, size: INTEGER;
  312. BEGIN
  313.         IF ~scroll.mouse THEN
  314.                 DEC(x, scroll.left);
  315.                 DEC(y, scroll.top);
  316.                 scroll.mouse := TRUE;
  317.                 IF U.between(1, x, scroll.width - 2) & U.between(1, y, scroll.height - 2) 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 U.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.                         ELSIF U.between(0, c, scroll.btnSize - 1) THEN
  329.                                 scroll.Dec := TRUE;
  330.                                 SendIPC
  331.                         ELSIF U.between(size - scroll.btnSize, c, size - 1) THEN
  332.                                 scroll.Inc := TRUE;
  333.                                 SendIPC
  334.                         ELSE
  335.                                 setPos(scroll, c - scroll.btnSize - scroll.sliderSize DIV 2);
  336.                                 scroll.pos0 := scroll.pos;
  337.                                 scroll.Slider := c;
  338.                                 paint(scroll)
  339.                         END
  340.                 END
  341.         END
  342. END MouseDown;
  343.  
  344.  
  345. PROCEDURE MouseUp* (VAR scroll: tScroll);
  346. BEGIN
  347.         IF scroll.mouse THEN
  348.                 scroll.Slider := -1;
  349.                 scroll.Inc := FALSE;
  350.                 scroll.Dec := FALSE;
  351.                 scroll.mouse := FALSE;
  352.                 paint(scroll)
  353.         END
  354. END MouseUp;
  355.  
  356.  
  357. END Scroll.