123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 |
- MODULE WMStringGrids; (** AUTHOR "TF"; PURPOSE "String grid component"; *)
- IMPORT
- Objects, Strings, XML, WMComponents, WMGraphics, WMGraphicUtilities,
- WMProperties, WMEvents, WMRectangles, WMGrids;
- CONST
- (* Cell.flags *)
- UsePerCellColors = 0;
- UseInternalBuffer = 1;
- TYPE
- String = Strings.String;
- Cell* = OBJECT
- VAR
- caption : String;
- color, textColor : WMGraphics.Color;
- align: LONGINT;
- img : WMGraphics.Image;
- data : ANY;
- flags : SET;
- PROCEDURE &Init;
- BEGIN
- caption := NIL;
- color := 0; textColor := 0; align := 0;
- img := NIL;
- data := NIL;
- flags := {};
- END Init;
- END Cell;
- CellArray = POINTER TO ARRAY OF Cell;
- Row = POINTER TO RECORD
- cells : CellArray;
- END;
- RowArray = POINTER TO ARRAY OF Row;
- TYPE
- StringGridModel* = OBJECT
- VAR
- lockedBy : ANY;
- lockLevel : LONGINT;
- viewChanged : BOOLEAN;
- onChanged* : WMEvents.EventSource; (** does not hold the lock, if called *)
- rows : RowArray;
- nofRows, nofCols : LONGINT;
- PROCEDURE &Init*;
- BEGIN
- NEW(onChanged, SELF, WMComponents.NewString("TreeModelChanged"), NIL, NIL);
- NEW(rows, 4);
- lockLevel :=0;
- END Init;
- (** acquire a read/write lock on the object *)
- PROCEDURE Acquire*;
- VAR me : ANY;
- BEGIN {EXCLUSIVE}
- me := Objects.ActiveObject();
- IF lockedBy = me THEN
- ASSERT(lockLevel # -1); (* overflow *)
- INC(lockLevel)
- ELSE
- AWAIT(lockedBy = NIL); viewChanged := FALSE;
- lockedBy := me; lockLevel := 1
- END
- END Acquire;
- (** release the read/write lock on the object *)
- PROCEDURE Release*;
- VAR hasChanged : BOOLEAN;
- BEGIN
- BEGIN {EXCLUSIVE}
- ASSERT(lockedBy = Objects.ActiveObject(), 3000);
- hasChanged := FALSE;
- DEC(lockLevel);
- IF lockLevel = 0 THEN lockedBy := NIL; hasChanged := viewChanged END
- END;
- IF hasChanged THEN onChanged.Call(NIL) END
- END Release;
- PROCEDURE AdjustRows(newSize : LONGINT);
- VAR i : LONGINT; newRows : RowArray;
- BEGIN
- NEW(newRows, newSize);
- FOR i := 0 TO MIN(nofRows, newSize) - 1 DO
- newRows[i] := rows[i]
- END;
- FOR i := MIN(nofRows, newSize) TO newSize - 1 DO
- NEW(newRows[i]);
- AdjustRow(newRows[i])
- END;
- rows := newRows
- END AdjustRows;
- PROCEDURE AdjustRow(row : Row);
- VAR i : LONGINT; newCells : CellArray;
- BEGIN
- IF row.cells = NIL THEN NEW(row.cells, nofCols) END;
- IF LEN(row.cells) # nofCols THEN
- NEW(newCells, nofCols);
- FOR i := 0 TO MIN(nofCols, LEN(row.cells)) - 1 DO
- newCells[i] := row.cells[i]
- END;
- row.cells := newCells
- END
- END AdjustRow;
- PROCEDURE SetNofRows*(newNofRows : LONGINT);
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (newNofRows > nofRows) OR (newNofRows < nofRows DIV 2) THEN AdjustRows(newNofRows) END;
- nofRows := newNofRows;
- viewChanged := TRUE
- END SetNofRows;
- PROCEDURE SetNofCols*(newNofCols : LONGINT);
- VAR i : LONGINT;
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- nofCols := newNofCols;
- FOR i := 0 TO nofRows - 1 DO AdjustRow(rows[i]) END;
- viewChanged := TRUE
- END SetNofCols;
- PROCEDURE GetNofRows*() : LONGINT;
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- RETURN nofRows
- END GetNofRows;
- PROCEDURE GetNofCols*() : LONGINT;
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- RETURN nofCols
- END GetNofCols;
- PROCEDURE SetCellText*(col, row : LONGINT; caption : String);
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF rows[row].cells[col] = NIL THEN NEW(rows[row].cells[col]) END;
- EXCL(rows[row].cells[col].flags, UseInternalBuffer);
- IF rows[row].cells[col].caption # caption THEN
- rows[row].cells[col].caption := caption;
- viewChanged := TRUE
- END
- END
- END SetCellText;
- PROCEDURE GetCellText*(col, row : LONGINT ) : String;
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF rows[row].cells[col] = NIL THEN RETURN NIL END;
- RETURN rows[row].cells[col].caption
- ELSE RETURN NIL
- END
- END GetCellText;
- PROCEDURE SetCellTextAOC*(col, row, minBufferSize : LONGINT; CONST caption : ARRAY OF CHAR);
- VAR cell : Cell; length : LONGINT;
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF rows[row].cells[col] = NIL THEN NEW(rows[row].cells[col]) END;
- length := MAX(minBufferSize, Strings.Length(caption) + 1); (* 0X *)
- cell := rows[row].cells[col];
- IF (cell.caption = NIL) OR ~(UseInternalBuffer IN cell.flags) OR (LEN(cell.caption) < length) THEN
- NEW(cell.caption, length);
- INCL(cell.flags, UseInternalBuffer);
- END;
- IF (cell.caption^ # caption) THEN
- COPY(caption, rows[row].cells[col].caption^);
- viewChanged := TRUE
- END
- END
- END SetCellTextAOC;
- PROCEDURE GetCellTextAOC*(col, row : LONGINT; VAR caption : ARRAY OF CHAR);
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF rows[row].cells[col] # NIL THEN
- COPY(rows[row].cells[col].caption^, caption);
- ELSE
- caption := "";
- END;
- ELSE
- caption := "";
- END
- END GetCellTextAOC;
- PROCEDURE SetCellColors*(col, row : LONGINT; color, textColor : WMGraphics.Color);
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF rows[row].cells[col] = NIL THEN NEW(rows[row].cells[col]) END;
- INCL(rows[row].cells[col].flags, UsePerCellColors);
- IF rows[row].cells[col].color # color THEN
- rows[row].cells[col].color := color;
- viewChanged := TRUE;
- END;
- IF rows[row].cells[col].textColor # textColor THEN
- rows[row].cells[col].textColor := textColor;
- viewChanged := TRUE;
- END;
- END;
- END SetCellColors;
- PROCEDURE GetCellColors*(col, row : LONGINT; VAR color, textColor : WMGraphics.Color; VAR valid : BOOLEAN);
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- valid := FALSE;
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF (rows[row].cells[col] # NIL) & (UsePerCellColors IN rows[row].cells[col].flags) THEN
- valid := TRUE;
- color := rows[row].cells[col].color;
- textColor := rows[row].cells[col].textColor;
- END;
- END;
- END GetCellColors;
- PROCEDURE SetCellData*(col, row : LONGINT; data : ANY);
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF rows[row].cells[col] = NIL THEN NEW(rows[row].cells[col]) END;
- IF rows[row].cells[col].data # data THEN
- rows[row].cells[col].data:= data;
- viewChanged := TRUE
- END
- END
- END SetCellData;
- PROCEDURE GetCellData*(col, row : LONGINT) : ANY;
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF rows[row].cells[col] = NIL THEN RETURN NIL END;
- RETURN rows[row].cells[col].data
- ELSE RETURN NIL
- END
- END GetCellData;
- PROCEDURE SetCellImage*(col, row : LONGINT; img : WMGraphics.Image);
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF rows[row].cells[col] = NIL THEN NEW(rows[row].cells[col]) END;
- IF rows[row].cells[col].img # img THEN
- rows[row].cells[col].img := img;
- viewChanged := TRUE
- END
- END
- END SetCellImage;
- PROCEDURE GetCellImage*(col, row : LONGINT) : WMGraphics.Image;
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF rows[row].cells[col] = NIL THEN RETURN NIL END;
- RETURN rows[row].cells[col].img
- ELSE RETURN NIL
- END
- END GetCellImage;
- PROCEDURE SetTextAlign*(col, row, align : LONGINT);
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF rows[row].cells[col] = NIL THEN NEW(rows[row].cells[col]) END;
- IF rows[row].cells[col].align # align THEN
- rows[row].cells[col].align:= align;
- viewChanged := TRUE
- END
- END
- END SetTextAlign;
- PROCEDURE GetTextAlign*(col, row : LONGINT) : LONGINT;
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (col >= 0) & (row >= 0) & (col < nofCols) & (row < nofRows) THEN
- IF rows[row].cells[col] = NIL THEN RETURN 0 END;
- RETURN rows[row].cells[col].align
- ELSE RETURN 0
- END
- END GetTextAlign;
- PROCEDURE DeleteRow*(rowNo : LONGINT; viewChanged : BOOLEAN);
- VAR i : LONGINT;
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (rowNo >= 0) & (rowNo < nofRows) THEN
- FOR i := rowNo TO nofRows - 2 DO
- rows[i] := rows[i + 1]
- END;
- DEC(nofRows);
- SELF.viewChanged := viewChanged
- END
- END DeleteRow;
- PROCEDURE InsertEmptyRow*(atRowNo : LONGINT);
- VAR i : LONGINT;
- newRows : RowArray;
- BEGIN
- ASSERT(Objects.ActiveObject() = lockedBy, 3000);
- IF (atRowNo >= 0) & (atRowNo <= nofRows) THEN
- NEW(newRows, nofRows + 1);
- FOR i := 0 TO atRowNo - 1 DO
- newRows[i] := rows[i]
- END;
- NEW(newRows[atRowNo]);
- AdjustRow(newRows[atRowNo]);
- FOR i := atRowNo + 1 TO nofRows DO
- newRows[i] := rows[i - 1]
- END
- END;
- INC(nofRows);
- rows := newRows;
- viewChanged := TRUE
- END InsertEmptyRow;
- END StringGridModel;
- TYPE
- StringGrid* = OBJECT(WMGrids.GenericGrid)
- VAR
- model- : StringGridModel;
- cellColor, hoverColor, selectedColor, fixedColor, textHoverColor, textColor, textSelectedColor : WMGraphics.Color;
- clCell-, clFixed-, clHover-, clSelected-, clTextDefault-, clTextHover-, clTextSelected- : WMProperties.ColorProperty;
- PROCEDURE &Init*;
- BEGIN
- Init^;
- SetNameAsString(StrStringGrid);
- SetGenerator("WMStringGrids.GenStringGrid");
- NEW(clCell, PrototypeTclCell, NIL, NIL); properties.Add(clCell);
- NEW(clHover, PrototypeTclHover, NIL, NIL); properties.Add(clHover);
- NEW(clSelected, PrototypeTclSelected, NIL, NIL); properties.Add(clSelected);
- NEW(clFixed, PrototypeTclFixed, NIL, NIL); properties.Add(clFixed);
- NEW(clTextDefault, PrototypeTclTextDefault, NIL, NIL); properties.Add(clTextDefault);
- NEW(clTextHover, PrototypeTclTextHover, NIL, NIL); properties.Add(clTextHover);
- NEW(clTextSelected, PrototypeTclTextSelected, NIL, NIL); properties.Add(clTextSelected);
- (* NEW(fontHeight, PrototypeTfontHeight, NIL, NIL); properties.Add(fontHeight); *)
- takesFocus.Set(TRUE);
- NEW(model);
- model.onChanged.Add(ModelChanged);
- ModelChanged(NIL,NIL);
- END Init;
- PROCEDURE ModelChanged(sender, data : ANY);
- BEGIN
- Acquire;
- nofCols.Set(model.nofCols);
- nofRows.Set(model.nofRows);
- Invalidate;
- SetDrawCellProc(DrawCell);
- Release
- END ModelChanged;
- PROCEDURE DrawBackground*(canvas : WMGraphics.Canvas);
- BEGIN
- cellColor := clCell.Get();
- hoverColor := clHover.Get();
- selectedColor := clSelected.Get();
- fixedColor := clFixed.Get();
- textColor := clTextDefault.Get();
- textHoverColor := clTextHover.Get();
- textSelectedColor := clTextSelected.Get();
- model.Acquire;
- DrawBackground^(canvas);
- model.Release
- END DrawBackground;
- PROCEDURE GetCellData*(col, row : LONGINT) : ANY;
- VAR data : ANY;
- BEGIN
- model.Acquire;
- data := model.GetCellData(col, row);
- model.Release;
- RETURN data
- END GetCellData;
- (* PROCEDURE CellClicked*(col, row : LONGINT); (** PROTECTED *)
- BEGIN
- model.Acquire;
- data := model.GetCellData(col, row);
- model.Release;
- CellClicked^(col, row);
- (* onClick.Call(data);
- IF wasSelected & onClickSelected.HasListeners() THEN
- onClickSelected.Call(data)
- END; *)
- END CellClicked; *)
- PROCEDURE DrawCell(canvas : WMGraphics.Canvas; w, h : LONGINT; state : SET; x, y : LONGINT);
- VAR
- s : String; font : WMGraphics.Font; left: LONGINT; c, tc: WMGraphics.Color; img : WMGraphics.Image; dispW, dispH: LONGINT;
- valid : BOOLEAN;
- BEGIN
- s := model.GetCellText(x, y);
- model.GetCellColors(x, y, c, tc, valid);
- IF ~valid THEN
- c := cellColor;
- tc := textColor;
- END;
- IF WMGrids.CellFixed IN state THEN
- c := fixedColor;
- IF WMGrids.CellSelected IN state THEN
- c := WMGraphicUtilities.InterpolateColorLinear(c, selectedColor, 128)
- ELSIF WMGrids.CellHighlighted IN state THEN
- c := WMGraphicUtilities.InterpolateColorLinear(c, hoverColor, 128)
- END;
- canvas.Fill(WMRectangles.MakeRect(0, 0, w, h), c, WMGraphics.ModeCopy)
- ELSIF WMGrids.CellSelected IN state THEN
- canvas.Fill(WMRectangles.MakeRect(0, 0, w, h), selectedColor, WMGraphics.ModeSrcOverDst);
- tc := textSelectedColor
- ELSIF WMGrids.CellHighlighted IN state THEN
- canvas.Fill(WMRectangles.MakeRect(0, 0, w, h), hoverColor, WMGraphics.ModeSrcOverDst);
- tc := textHoverColor
- ELSE
- canvas.Fill(WMRectangles.MakeRect(0, 0, w, h), c, WMGraphics.ModeSrcOverDst)
- END;
- font := GetFont();
- canvas.SetColor(tc);
- left := 1; img := model.GetCellImage(x, y);
- IF img # NIL THEN INC(left, img.width + 1) END;
- IF s # NIL THEN
- IF img # NIL THEN
- dispW := img.width;
- dispH := img.height;
- IF dispW > w-2 THEN dispW := w-2 END;
- IF dispH > h-2 THEN dispH := h-2 END;
- IF (dispW # img.width) OR (dispH # img.height) THEN
- canvas.ScaleImage(img, WMRectangles.MakeRect(0, 0, img.width, img.height), WMRectangles.MakeRect(1, 1, dispW, dispH), WMGraphics.ModeSrcOverDst, 10);
- ELSE
- canvas.DrawImage(1, 1, img, WMGraphics.ModeSrcOverDst);
- END
- END;
- WMGraphics.DrawStringInRect(canvas, WMRectangles.MakeRect(left, 1, w - 2, h - 2), FALSE,
- model.GetTextAlign(x, y), WMGraphics.AlignCenter, s^)
- END;
- IF WMGrids.CellSelected IN state THEN
- WMGraphicUtilities.ExtRectGlassShade(canvas, WMRectangles.MakeRect(0, 0, w, h), {1, 3}, 5, FALSE);
- END
- (* IF s # NIL THEN canvas.DrawString(0, h - font.descent, s^) END *)
- END DrawCell;
- END StringGrid;
- VAR
- PrototypeTclCell*, PrototypeTclHover*, PrototypeTclSelected*, PrototypeTclTextDefault*,
- PrototypeTclTextHover*, PrototypeTclTextSelected*, PrototypeTclFixed* : WMProperties.ColorProperty;
- PrototypeTfontHeight* : WMProperties.Int32Property;
- StrStringGrid : Strings.String;
- PROCEDURE GenStringGrid*() : XML.Element;
- VAR stringGrid : StringGrid;
- BEGIN
- NEW(stringGrid); RETURN stringGrid;
- END GenStringGrid;
- PROCEDURE InitStrings;
- BEGIN
- StrStringGrid := Strings.NewString("StringGrid");
- END InitStrings;
- PROCEDURE InitPrototypes;
- VAR plStringGrid : WMProperties.PropertyList;
- BEGIN
- NEW(plStringGrid);
- NEW(PrototypeTclCell, NIL, Strings.NewString("ClCell"), Strings.NewString("color of the cell"));
- plStringGrid.Add(PrototypeTclCell);
- NEW(PrototypeTclFixed, NIL, Strings.NewString("ClFixed"), Strings.NewString("color of a fixed cell"));
- plStringGrid.Add(PrototypeTclFixed);
- NEW(PrototypeTclHover, NIL, Strings.NewString("ClHover"), Strings.NewString("color of the tree item, if the mouse is over it"));
- plStringGrid.Add(PrototypeTclHover);
- NEW(PrototypeTclSelected, NIL, Strings.NewString("ClSelected"), Strings.NewString("color of the the tree item, if it is selected"));
- plStringGrid.Add(PrototypeTclSelected);
- NEW(PrototypeTclTextDefault, NIL, Strings.NewString("ClTextDefault"), Strings.NewString("default text color of the tree item"));
- plStringGrid.Add(PrototypeTclTextDefault);
- NEW(PrototypeTclTextHover, NIL, Strings.NewString("ClTextHover"), Strings.NewString("text color of the tree item, if the mouse is over it"));
- plStringGrid.Add(PrototypeTclTextHover);
- NEW(PrototypeTclTextSelected, NIL, Strings.NewString("ClTextSelected"), Strings.NewString("text color of the tree item, when selected"));
- plStringGrid.Add(PrototypeTclTextSelected);
- NEW(PrototypeTfontHeight, NIL, Strings.NewString("FontHeight"), Strings.NewString("height of the tree item text"));
- plStringGrid.Add(PrototypeTfontHeight);
- PrototypeTclCell.Set(LONGINT(0FFFFFFFFH));
- PrototypeTclFixed.Set(LONGINT(0CCCCCCFFH));
- PrototypeTclHover.Set(LONGINT(0FFFF00FFH));
- PrototypeTclSelected.Set(00000FFFFH);
- PrototypeTclTextDefault.Set(0000000FFH);
- PrototypeTclTextHover.Set(00000FFFFH);
- PrototypeTclTextSelected.Set(LONGINT(0FFFFFFFFH));
- PrototypeTfontHeight.Set(12);
- WMComponents.propertyListList.Add("StringGrid", plStringGrid);
- WMComponents.propertyListList.UpdateStyle;
- END InitPrototypes;
- BEGIN
- InitStrings;
- InitPrototypes;
- END WMStringGrids.
- System.Free WMStringGrids ~
|