123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- (* ETH Oberon, Copyright 2001 ETH Zuerich Institut fuer Computersysteme, ETH Zentrum, CH-8092 Zuerich.
- Refer to the "General ETH Oberon System Source License" contract available at: http://www.oberon.ethz.ch/ *)
- MODULE ColorTools IN Oberon; (** portable *) (** jm 19.1.95 *)
- (** ColorPicker implementation *)
- (*
- jm 1.3.93 - fixed selection
- - increased size of command string
- 25.7.94 - added ChangeColor command
- *)
- IMPORT
- Objects, Gadgets, Effects, Display, Display3, Oberon, Files, Input, Texts, Views, Printer, Printer3;
- CONST
- VersionNo = 2; ModName = "ColorTools";
- TYPE
- ColorPicker* = POINTER TO ColorPickerDesc;
- ColorPickerDesc* = RECORD (Gadgets.FrameDesc)
- cmd*: ARRAY 64 OF CHAR; (** Cmd attribute *)
- colors*: ARRAY 256 OF INTEGER; (** colors to be displayed *)
- col*: INTEGER; (** last color to be picked *)
- END;
- VAR
- W: Texts.Writer;
- (* --- Version check --- *)
- PROCEDURE WriteVersion(VAR R: Files.Rider);
- BEGIN
- Files.WriteNum(R, VersionNo);
- END WriteVersion;
- (* ----------- Color Picker ---------- *)
- PROCEDURE Parse(VAR s: ARRAY OF CHAR; VAR n: INTEGER; VAR values: ARRAY OF INTEGER);
- VAR i: INTEGER; val: LONGINT; neg: BOOLEAN;
- BEGIN
- n := 0;
- i := 0;
- LOOP
- WHILE (s[i] # 0X) & (s[i] <= " ") DO INC(i) END;
- IF s[i] = 0X THEN EXIT END;
- IF s[i] = "-" THEN INC(i); neg := TRUE ELSE neg := FALSE END;
- IF (s[i] >= "0") & (s[i] <= "9") THEN
- val := 0;
- WHILE (s[i] >= "0") & (s[i] <= "9") DO val := val * 10 + ORD(s[i]) - ORD("0"); INC(i) END;
- IF neg THEN val := -val END;
- IF val < -127 THEN val := -127
- ELSIF val > 255 THEN val := 255
- END;
- values[n] := ABS(SHORT(val)); INC(n);
- ELSE EXIT
- END
- END
- END Parse;
- PROCEDURE Unparse(n: INTEGER; VAR values: ARRAY OF INTEGER; VAR s: ARRAY OF CHAR);
- VAR i, j: INTEGER;
- PROCEDURE Out(i: LONGINT);
- VAR k: INTEGER; x0: LONGINT; a: ARRAY 10 OF CHAR;
- BEGIN k := 0;
- IF i < 0 THEN x0 := -i
- ELSE x0 := i
- END;
- REPEAT
- a[k] := CHR(x0 MOD 10 + 30H); x0 := x0 DIV 10; INC(k)
- UNTIL x0 = 0;
- IF i < 0 THEN s[j] := "-"; INC(j); END;
- REPEAT DEC(k); s[j] := a[k]; INC(j); UNTIL k = 0;
- s[j] := " "; INC(j);
- END Out;
- BEGIN
- j := 0;
- i := 0;
- WHILE i < n DO Out(values[i]); INC(i) END; s[j] := 0X;
- END Unparse;
- PROCEDURE ColorPickerAttr(F: ColorPicker; VAR M: Objects.AttrMsg);
- VAR n: INTEGER;
- BEGIN
- IF M.id = Objects.get THEN
- IF M.name = "Gen" THEN M.class := Objects.String; COPY("ColorTools.NewColorPicker", M.s); M.res := 0
- ELSIF M.name = "Cmd" THEN M.class := Objects.String; COPY(F.cmd, M.s); M.res := 0
- ELSIF M.name = "Col" THEN M.class := Objects.Int; M.i := F.col; M.res := 0
- ELSIF M.name = "Colors" THEN M.class := Objects.String; Unparse(16, F.colors, M.s); M.res := 0
- ELSE Gadgets.framehandle(F, M);
- END;
- ELSIF M.id = Objects.set THEN
- IF M.name = "Cmd" THEN
- IF (M.class = Objects.String) THEN COPY(M.s, F.cmd); M.res := 0 END;
- ELSIF M.name = "Col" THEN
- IF (M.class = Objects.Int) THEN F.col := SHORT(M.i); M.res := 0; END
- ELSIF M.name = "Colors" THEN
- IF (M.class = Objects.String) THEN
- Parse(M.s, n, F.colors);
- WHILE n < 256 DO F.colors[n] := n; INC(n) END;
- M.res := 0
- END
- ELSE Gadgets.framehandle(F, M);
- END;
- ELSIF M.id = Objects.enum THEN
- M.Enum("Colors"); M.Enum("Col"); M.Enum("Cmd");
- Gadgets.framehandle(F, M);
- END;
- END ColorPickerAttr;
- PROCEDURE Grid(F: ColorPicker; R: Display3.Mask; b, x, y: INTEGER);
- VAR i, j, c, max: INTEGER;
- BEGIN
- IF Display.Depth(0) >= 8 THEN max := 16 ELSE max := 4 END;
- c := 0; j := max - 1;
- WHILE j >= 0 DO
- i := 0;
- WHILE i < max DO Display3.ReplConst(R, F.colors[c] , x + i * b, y + j * b, b, b, Display.replace); INC(i); INC(c) END;
- DEC(j);
- END;
- END Grid;
- PROCEDURE ClipAgainst(VAR x, y, w, h: INTEGER; x1, y1, w1, h1: INTEGER);
- VAR r, t, r1, t1: INTEGER;
- BEGIN
- r := x + w - 1; r1 := x1 + w1 - 1; t := y + h - 1; t1 := y1 + h1 - 1;
- IF x < x1 THEN x := x1 END;
- IF y < y1 THEN y := y1 END;
- IF r > r1 THEN r := r1 END;
- IF t > t1 THEN t := t1 END;
- w := r - x + 1; h := t - y + 1;
- END ClipAgainst;
- PROCEDURE PickColor(F: ColorPicker; x, y, w, h: INTEGER; VAR M: Oberon.InputMsg);
- VAR bw, bw4: INTEGER;
- VAR keys, keysum: SET; X, Y, i, j, li, lj, ofs, px, py, b, max: INTEGER; block: Views.Block;
- PROCEDURE Cell(X, Y: INTEGER; VAR i, j: INTEGER);
- BEGIN
- IF Effects.Inside(X, Y, x+2, y + 2 + ofs, bw, bw) THEN
- i := (X - x - 2) DIV b; j := (Y - (y + 2 + ofs)) DIV b;
- ELSE
- i := -1; j := -1;
- END;
- END Cell;
- PROCEDURE Highlight(colno, i, j: INTEGER);
- BEGIN
- IF i >= 0 THEN
- Oberon.FadeCursor(Oberon.Mouse);
- Display3.Rect(block.mask, F.colors[colno], Display.solid, x + 2 + i * b, y + 2 + ofs + j * b, b, b, 1, Display.replace);
- END;
- END Highlight;
- PROCEDURE CalcPlace(VAR px, py: INTEGER);
- VAR cx, cy, cw, ch: INTEGER; (* clipping area *) f: Objects.Object;
- BEGIN
- cx := 0; cy := 0; cw := Display.Width; ch := Display.Height;
- f := Gadgets.context;
- WHILE f # NIL DO
- IF f IS Gadgets.View THEN
- WITH f: Gadgets.View DO
- ClipAgainst(cx, cy, cw, ch, f.absX, f.absY, f.W, f.H);
- END
- END;
- f := f.dlink
- END;
- px := x; py := y + h - (bw4-1);
- IF px < cx THEN px := cx; END;
- IF px + bw4 >= cx + cw THEN px := cx + cw - 1 - bw4; END;
- IF py < cy THEN py := cy; END;
- IF py + bw4 >= cy + ch THEN py := cy + ch - 1 - bw4 END;
- END CalcPlace;
- BEGIN
- IF Display.Depth(0) >= 8 THEN bw := 112; max := 16 ELSE bw := 80; max := 4 END;
- bw4 := bw + 4; b := bw DIV max;
- CalcPlace(px, py);
- ofs := 0;
- x := px; y := py;
- Oberon.RemoveMarks(x, y+ofs, bw4, bw4);
- Views.GetBlock(x, y+ofs, bw4, bw4, M.dlink, block);
- Display3.ReplConst(block.mask, Display3.black, x, y+ofs, bw4, bw4, Display.replace);
- Grid(F, block.mask, b, x+2, y+2+ofs);
- Input.Mouse(keys, X, Y); keysum := keys;
- Cell(X, Y, li, lj); Highlight(15, li, lj);
- WHILE keys # {} DO
- Input.Mouse(keys, X, Y);
- Cell(X, Y, i, j);
- IF (i # li) OR (j # lj) THEN
- Highlight(li + (max - 1 - lj) * max, li, lj); li := i; lj := j; Highlight(15, li, lj);
- END;
- keysum := keysum + keys;
- Oberon.DrawCursor(Oberon.Mouse, Effects.Arrow, X, Y);
- END;
- Highlight(li + (max - 1 - lj) * max, li, lj);
- Oberon.RemoveMarks(x, y+ofs, bw4, bw4);
- Views.RestoreBlock(block);
- IF ((keysum = {1}) OR (Oberon.New & (M.keys = {2}))) & (i >= 0) THEN
- F.col := F.colors[li + (max - 1 - lj) * max];
- IF F.cmd[0] # 0X THEN
- Gadgets.Execute(F.cmd, F, M.dlink, NIL, NIL);
- END;
- END;
- END PickColor;
- PROCEDURE RestoreColorPicker(R: Display3.Mask; F: ColorPicker; x, y, w, h: INTEGER);
- VAR b, max: INTEGER;
- BEGIN
- IF Display.Depth(0) >= 8 THEN max := 16 ELSE max := 4 END;
- b := (w - 4) DIV max;
- Display3.ReplConst(R, Display3.black, x, y, w, h, Display.replace);
- Grid(F, R, b, x+2, y+2);
- IF Gadgets.selected IN F.state THEN Display3.FillPattern(R, Display3.white, Display3.selectpat, 0, 0, x, y, w, h, Display.paint); END;
- END RestoreColorPicker;
- PROCEDURE PrintColorPicker(F: ColorPicker; VAR M: Display.DisplayMsg);
- VAR R: Display3.Mask; x, y, w, h, b, i, j, c, max: INTEGER;
- PROCEDURE P(x: INTEGER): INTEGER;
- BEGIN RETURN SHORT(x * Display.Unit DIV Printer.Unit)
- END P;
- BEGIN
- Gadgets.MakePrinterMask(F, M.x, M.y, M.dlink, R);
- x := M.x; y := M.y; w := P(F.W); h := P(F.H);
- Printer3.ReplConst(R, Display3.black, x, y, w, h, Display.replace);
- IF Display.Depth(0) >= 8 THEN max := 16 ELSE max := 4 END;
- b := (F.W - 4) DIV max;
- x := M.x + P(2); y := M.y + P(2);
- c := 0; j := max - 1;
- WHILE j >= 0 DO
- i := 0;
- WHILE i < max DO
- Printer3.ReplConst(R, F.colors[c] , x + P(i * b), y + P(j * b), P(b), P(b), Display.replace);
- INC(i); INC(c)
- END;
- DEC(j);
- END;
- END PrintColorPicker;
- PROCEDURE CopyColorPicker*(VAR M: Objects.CopyMsg; from, to: ColorPicker);
- BEGIN
- Gadgets.CopyFrame(M, from, to); to.col := from.col; COPY(from.cmd, to.cmd); to.colors := from.colors;
- END CopyColorPicker;
- PROCEDURE ColorPickerHandler*(F: Objects.Object; VAR M: Objects.ObjMsg);
- VAR x, y, w, h, u, v: INTEGER; F0: ColorPicker; R: Display3.Mask; ver: LONGINT;
- BEGIN
- WITH F: ColorPicker DO
- IF M IS Objects.AttrMsg THEN
- WITH M: Objects.AttrMsg DO ColorPickerAttr(F, M) END;
- ELSIF M IS Objects.FileMsg THEN
- WITH M: Objects.FileMsg DO
- IF M.id = Objects.store THEN
- WriteVersion(M.R);
- Files.WriteString(M.R, F.cmd);
- x := 0; WHILE x < 256 DO Files.WriteInt(M.R, F.colors[x]); INC(x) END;
- Gadgets.framehandle(F, M)
- ELSIF M.id = Objects.load THEN
- Files.ReadNum(M.R, ver);
- IF ver = 1 THEN
- Files.ReadString(M.R, F.cmd);
- Gadgets.framehandle(F, M)
- ELSIF ver = VersionNo THEN
- Files.ReadString(M.R, F.cmd);
- x := 0; WHILE x < 256 DO
- Files.ReadInt(M.R, F.colors[x]);
- IF F.colors[x] < 0 THEN F.colors[x] := x END;
- INC(x)
- END;
- Gadgets.framehandle(F, M)
- ELSE
- Texts.WriteString(W, "Version "); Texts.WriteInt(W, VersionNo, 3); Texts.WriteString(W, " of ");
- Texts.WriteString(W, ModName);
- Texts.WriteString(W, " cannot read version "); Texts.WriteInt(W, ver, 3); Texts.WriteLn(W);
- Texts.Append(Oberon.Log, W.buf);
- HALT(99);
- END
- END
- END
- ELSIF M IS Objects.CopyMsg THEN
- WITH M: Objects.CopyMsg DO
- IF M.stamp = F.stamp THEN M.obj := F.dlink
- ELSE NEW(F0); F.stamp := M.stamp; F.dlink := F0; CopyColorPicker(M, F, F0); M.obj := F0
- END
- END
- ELSIF M IS Display.FrameMsg THEN
- WITH M: Display.FrameMsg DO
- x := M.x + F.X; y := M.y + F.Y; w := F.W; h := F.H; (* calculate actual coordinates *)
- u := M.x; v := M.y; (* store volatile info *)
- IF M IS Display.DisplayMsg THEN
- WITH M: Display.DisplayMsg DO
- IF M.device = Display.screen THEN
- IF (M.F = NIL) OR ((M.id = Display.full) & (M.F = F)) THEN
- Gadgets.MakeMask(F, x, y, M.dlink, R);
- RestoreColorPicker(R, F, x, y, w, h);
- ELSIF (M.id = Display.area) & (M.F = F) THEN
- Gadgets.MakeMask(F, x, y, M.dlink, R);
- Display3.AdjustMask(R, x + M.u, y + h - 1 + M.v, M.w, M.h);
- RestoreColorPicker(R, F, x, y, w, h);
- END
- ELSIF M.device = Display.printer THEN PrintColorPicker(F, M)
- END
- END
- ELSIF M IS Oberon.InputMsg THEN
- WITH M: Oberon.InputMsg DO
- IF ~(Gadgets.selected IN F.state) THEN
- IF (M.id = Oberon.track) & ((M.keys = {1}) OR (Oberon.New & (M.keys = {2}))) & Gadgets.InActiveArea(F, M) THEN
- PickColor(F, x, y, w, h, M); M.res := 0;
- ELSE
- Gadgets.framehandle(F, M);
- END;
- END;
- END;
- ELSE
- Gadgets.framehandle(F, M);
- END;
- M.x := u; M.y := v; (* restore volatile info *)
- END;
- ELSE
- Gadgets.framehandle(F, M);
- END;
- END;
- END ColorPickerHandler;
- PROCEDURE InitColorPicker*(F: ColorPicker);
- VAR i: INTEGER;
- BEGIN F.W := 32+4; F.H := 32+4; F.col := 15; F.state := {Gadgets.lockedsize};
- F.handle := ColorPickerHandler;
- F.cmd := "ColorTools.ChangeColor #Col ~";
- i := 0; WHILE i < 256 DO F.colors[i] := i; INC(i) END;
- END InitColorPicker;
- PROCEDURE NewColorPicker*;
- VAR F: ColorPicker;
- BEGIN
- NEW(F); InitColorPicker(F); Objects.NewObj := F;
- END NewColorPicker;
- (** Used in the form:
- ColorTools.ChangeColor <colno>
- Change the color of the selected text or the selected gadgets.
- *)
- PROCEDURE ChangeColor*;
- VAR col: INTEGER; S: Texts.Scanner;
- MOS: Display.SelectMsg; MTS: Oberon.SelectMsg; MA: Objects.AttrMsg; MU: Gadgets.UpdateMsg;
- obj: Objects.Object;
- BEGIN
- Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
- Texts.Scan(S); col := SHORT(S.i);
- MOS.id := Display.get; MOS.time := -1; MOS.F := NIL; MOS.obj := NIL;
- MTS.id := Oberon.get; MTS.time := -1; MTS.F := NIL; MTS.sel := NIL; MTS.text := NIL;
- Display.Broadcast(MOS); Display.Broadcast(MTS);
- IF (MTS.time # -1) & (((MOS.time-MTS.time) < 0) OR (MOS.time = -1)) THEN
- Texts.ChangeLooks(MTS.text, MTS.beg, MTS.end, {1}, NIL, SHORT(col), 0)
- ELSIF (MOS.time # -1) & (((MTS.time-MOS.time) < 0) OR (MTS.time = -1)) & (MOS.obj # NIL) THEN
- obj := MOS.obj;
- WHILE obj # NIL DO
- MA.id := Objects.set; MA.name := "Color"; MA.class := Objects.Int; MA.i := col; MA.res := -1;
- obj.handle(obj, MA);
- obj := obj.slink
- END;
- MU.obj := MOS.obj; MU.F := NIL; Display.Broadcast(MU);
- END
- END ChangeColor;
- BEGIN
- Texts.OpenWriter(W);
- END ColorTools.
|