kolibrios/programs/develop/cedit/SRC/Tabs.ob07
Anton Krotov 759e2688de CEdit: reduced memory usage, small improvements
git-svn-id: svn://kolibrios.org@9903 a494cfbc-eb01-0410-851d-a64ba20cac60
2023-02-24 15:02:24 +00:00

296 lines
7.7 KiB
Plaintext

(*
Copyright 2021-2023 Anton Krotov
This file is part of CEdit.
CEdit is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CEdit is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CEdit. If not, see <http://www.gnu.org/licenses/>.
*)
MODULE Tabs;
IMPORT List, K := KolibriOS, RW, U := Utils;
CONST
btnID* = 100;
btnClose* = btnID + 100;
btnLeft* = btnID - 1;
btnRight* = btnID - 2;
tabHeight* = 22;
curTabHeight = 26;
scrWidth = 15;
btnCloseColor* = 0EF999FH;
modifColor = 0FF0000H;
strLen = 30;
TYPE
tItem = POINTER TO RECORD (List.tItem)
val: ARRAY strLen + 1 OF CHAR;
modified: BOOLEAN
END;
tTabs* = POINTER TO RECORD
strings: List.tList;
first, current: INTEGER;
width, height: INTEGER;
x, y, freeX: INTEGER
END;
PROCEDURE DblClicked* (t: tTabs; x, y: INTEGER): BOOLEAN;
RETURN (x > t.freeX) & U.between(t.y, y, t.y + t.height - 1)
END DblClicked;
PROCEDURE drawTab (t: tTabs; id, x, y, width, height: INTEGER; s: ARRAY OF CHAR; modified: BOOLEAN);
CONST
btnCloseSize = 14;
VAR
x2, y2, color, closeColor, closeForeColor, textColor: INTEGER;
left, top: INTEGER;
BEGIN
IF id = t.current THEN
INC(height, curTabHeight - tabHeight);
DEC(y, curTabHeight - tabHeight)
END;
color := K.colors.work;
textColor := K.colors.work_text;
DEC(x); INC(width);
x2 := x + width - 1;
y2 := y + height - 1;
K.DrawRect(x, y, width, height, color);
K.DrawLine(x, y, x2, y, K.colors.line);
K.DrawLine(x2, y, x2, y2, K.colors.line);
top := y + 3;
IF id # t.current THEN
K.DrawLine(x2 - 1, y2, x, y2, K.colors.line);
closeColor := K.colors.button;
closeForeColor := K.colors.button_text
ELSE
INC(top, (curTabHeight - tabHeight) DIV 2);
closeColor := btnCloseColor;
closeForeColor := 0FFFFFFH
END;
K.DrawLine(x, y2, x, y, K.colors.line);
K.DrawText866bk(x + K.fontWidth + K.fontWidth DIV 2, y + (height - K.fontHeight) DIV 2, textColor, color, s);
IF modified THEN
K.DrawText866bk(x + K.fontWidth DIV 2, y + (height - K.fontHeight) DIV 2, modifColor, color, "*")
END;
K.CreateButton(id + ORD({30}) + btnID, x + 1, y - 1, width - 1, height - 1, 0, "");
left := x + width - btnCloseSize - 5;
K.CreateButton(id + btnClose, left, top, btnCloseSize, btnCloseSize, closeColor, "");
K.DrawLine(left + 5, top + 4, left + btnCloseSize - 4, top + btnCloseSize - 5, closeForeColor);
K.DrawLine(left + 4, top + 4, left + btnCloseSize - 4, top + btnCloseSize - 4, closeForeColor);
K.DrawLine(left + 4, top + 5, left + btnCloseSize - 5, top + btnCloseSize - 4, closeForeColor);
K.DrawLine(left + 4, top + btnCloseSize - 4, left + btnCloseSize - 4, top + 4, closeForeColor);
K.DrawLine(left + 4, top + btnCloseSize - 5, left + btnCloseSize - 5, top + 4, closeForeColor);
K.DrawLine(left + 5, top + btnCloseSize - 4, left + btnCloseSize - 4, top + 5, closeForeColor);
END drawTab;
PROCEDURE tabWidth (tab: tItem): INTEGER;
RETURN (LENGTH(tab.val) + 5)*K.fontWidth
END tabWidth;
PROCEDURE Width (t: tTabs; pos, n: INTEGER): INTEGER;
VAR
res, i: INTEGER;
item: List.tItem;
BEGIN
res := 0;
i := pos;
item := List.getItem(t.strings, i);
WHILE (item # NIL) & (i <= n) DO
INC(res, tabWidth(item(tItem)));
item := item.next;
INC(i)
END
RETURN res
END Width;
PROCEDURE draw* (t: tTabs);
VAR
x, y, xmax, n, width, i: INTEGER;
item: List.tItem;
scroll: BOOLEAN;
BEGIN
y := t.y;
x := t.x;
K.DrawRect(x, y - (curTabHeight - tabHeight), t.width + (2*scrWidth + 2), t.height + (curTabHeight - tabHeight) - 1, K.colors.work);
IF Width(t, 0, t.strings.count - 1) > t.width THEN
INC(x, 2*scrWidth);
K.DeleteButton(btnLeft);
K.DeleteButton(btnRight);
K.CreateButton(btnLeft, t.x, y, scrWidth, t.height - 1, K.colors.button, "<");
K.CreateButton(btnRight, t.x + scrWidth, y, scrWidth, t.height - 1, K.colors.button, ">");
scroll := TRUE
ELSE
t.first := 0;
scroll := FALSE
END;
xmax := x + t.width - 1;
n := t.strings.count - 1;
FOR i := 0 TO n DO
K.DeleteButton(i + btnID)
END;
WHILE (n >= 0) & (Width(t, n, t.strings.count - 1) <= t.width) DO
DEC(n)
END;
IF n < 0 THEN
n := 0
ELSE
INC(n)
END;
IF n < t.first THEN
t.first := n
END;
K.DrawRect(x, y, t.width, t.height - 1, K.colors.work);
K.DrawLine(x, y + tabHeight - 1, x + t.width - 1 + 2*scrWidth*(1 - ORD(scroll)), y + tabHeight - 1, K.colors.line);
item := List.getItem(t.strings, t.first);
n := t.first;
WHILE (item # NIL) & (x <= xmax) DO
width := tabWidth(item(tItem));
IF x + width - 1 <= xmax THEN
drawTab(t, n, x + 1, y, width, t.height, item(tItem).val, item(tItem).modified);
INC(n);
INC(x, width);
item := item.next
ELSE
item := NIL
END
END;
t.freeX := x
END draw;
PROCEDURE setText (item: tItem; s: ARRAY OF CHAR);
VAR
i: INTEGER;
BEGIN
IF LENGTH(s) > strLen THEN
FOR i := 0 TO strLen - 4 DO
item.val[i] := s[i]
END;
item.val[strLen - 3] := 0X;
U.append8(item.val, "...")
ELSE
COPY(s, item.val)
END
END setText;
PROCEDURE add* (t: tTabs; s: ARRAY OF CHAR);
VAR
item: tItem;
BEGIN
NEW(item);
setText(item, s);
item.modified := FALSE;
List.append(t.strings, item)
END add;
PROCEDURE modify* (t: tTabs; n: INTEGER; val: BOOLEAN);
VAR
item: List.tItem;
BEGIN
item := List.getItem(t.strings, n);
IF item(tItem).modified # val THEN
item(tItem).modified := val;
draw(t)
END
END modify;
PROCEDURE rename* (t: tTabs; n: INTEGER; s: ARRAY OF CHAR);
VAR
item: List.tItem;
BEGIN
item := List.getItem(t.strings, n);
setText(item(tItem), s)
END rename;
PROCEDURE delete* (t: tTabs; n: INTEGER);
VAR
item: List.tItem;
BEGIN
item := List.getItem(t.strings, n);
List.delete(t.strings, item);
DISPOSE(item)
END delete;
PROCEDURE scroll* (t: tTabs; btn: INTEGER);
VAR
pos: INTEGER;
BEGIN
pos := t.first + ORD(btn = btnRight) - ORD(btn = btnLeft);
IF pos < 0 THEN
pos := 0
ELSIF pos >= t.strings.count THEN
pos := t.strings.count - 1
END;
t.first := pos
END scroll;
PROCEDURE switch* (t: tTabs; n: INTEGER);
BEGIN
IF (0 <= n) & (n < t.strings.count) THEN
t.current := n;
IF n < t.first THEN
t.first := 0
END;
WHILE Width(t, t.first, n) > t.width DO
INC(t.first)
END
END
END switch;
PROCEDURE setArea* (t: tTabs; x, y, width, height: INTEGER);
BEGIN
t.x := x;
t.y := y;
t.width := width - 2*scrWidth;
t.height := height
END setArea;
PROCEDURE create* (): tTabs;
VAR
res: tTabs;
BEGIN
NEW(res);
res.strings := List.create(NIL);
res.current := 0;
res.first := 0
RETURN res
END create;
END Tabs.