{*********************************************************} {* OVCTBRWS.PAS 4.06 *} {*********************************************************} {* ***** BEGIN LICENSE BLOCK ***** *} {* Version: MPL 1.1 *} {* *} {* The contents of this file are subject to the Mozilla Public License *} {* Version 1.1 (the "License"); you may not use this file except in *} {* compliance with the License. You may obtain a copy of the License at *} {* http://www.mozilla.org/MPL/ *} {* *} {* Software distributed under the License is distributed on an "AS IS" basis, *} {* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License *} {* for the specific language governing rights and limitations under the *} {* License. *} {* *} {* The Original Code is TurboPower Orpheus *} {* *} {* The Initial Developer of the Original Code is TurboPower Software *} {* *} {* Portions created by TurboPower Software Inc. are Copyright (C)1995-2002 *} {* TurboPower Software Inc. All Rights Reserved. *} {* *} {* Contributor(s): *} {* *} {* ***** END LICENSE BLOCK ***** *} {$I OVC.INC} {$B-} {Complete Boolean Evaluation} {$I+} {Input/Output-Checking} {$P+} {Open Parameters} {$T-} {Typed @ Operator} {.W-} {Windows Stack Frame} {$X+} {Extended Syntax} unit ovctbrws; {-Orpheus Table Rows array} interface uses {$IFNDEF LCL} Windows, {$ELSE} LclIntf, LclType, {$ENDIF} SysUtils, Classes, OvcConst, OvcTCmmn, OvcSpAry; type TOvcTableRows = class(TPersistent) {-Sparse array for rows} protected {private} {property fields} FActiveCount : TRowNum; FList : TOvcSparseArray; FDefHeight : integer; FLimit : TRowNum; {property event fields} FOnCfgChanged : TRowChangeNotifyEvent; protected {property read access} function GetRow(RowNum : TRowNum) : TRowStyle; function GetRowHeight(RowNum : TRowNum) : integer; function GetRowHidden(RowNum : TRowNum) : boolean; function GetRowIsSpecial(RowNum : TRowNum) : boolean; {property write access} procedure SetDefHeight(H : integer); procedure SetRow(RowNum : TRowNum; const RS : TRowStyle); procedure SetRowHeight(RowNum : TRowNum; H : integer); procedure SetRowHidden(RowNum : TRowNum; H : boolean); procedure SetLimit(RowNum : TRowNum); {general} procedure trDoCfgChanged(RowNum1, RowNum2 : TRowNum; Action : TOvcTblActions); public {protected} procedure rwScaleHeights(M, D : integer); property OnCfgChanged : TRowChangeNotifyEvent write FOnCfgChanged; public constructor Create; {-Create an array of row styles} destructor Destroy; override; {-Destroy an array of row styles} procedure Append(const RS : TRowStyle); {-Add row to end of current list, increment Limit} procedure Clear; {-Delete all row styles (reset all rows to the defaults)} procedure Delete(RowNum : TRowNum); {-Delete a row, move rows below it up one, decrement Limit} procedure Exchange(const RowNum1, RowNum2 : TRowNum); {-Exchange two rows} procedure Insert(const RowNum : TRowNum; const RS : TRowStyle); {-Insert a row, move rows below it down one, increment Limit} procedure Reset(const RowNum : TRowNum); {-Reset a row to the defaults} property List [RowNum : TRowNum] : TRowStyle {-Array of row styles} read GetRow write SetRow; default; {properties} property Count : TRowNum {-The current number of rows with explicit attributes} read FActiveCount; property DefaultHeight : integer {-The default row height} read FDefHeight write SetDefHeight; property Height [RowNum : TRowNum] : integer {-Array of row heights} read GetRowHeight write SetRowHeight; property Hidden [RowNum : TRowNum] : boolean {-Array of row hidden flags} read GetRowHidden write SetRowHidden; property RowIsSpecial [RowNum : TRowNum] : boolean read GetRowIsSpecial; property Limit : TRowNum {-Maximum number of rows} read FLimit write SetLimit; end; implementation {===Extra RowStyle routines==========================================} function NewRowStyle(AHeight : integer; AHidden : boolean) : PRowStyle; {-Allocate a row style on the heap} begin Result := New(PRowStyle); with Result^ do begin Height := AHeight; Hidden := AHidden; end; end; {--------} function DelRow(Index : longint; Item : pointer; ExtraData : pointer) : boolean; far; {-Iterator to delete a row style from the sparse list} var R : PRowStyle absolute Item; begin Dispose(R); Result := true; end; {--------------------------------------------------------------------} {Note: the row numbers passed to this class have a minimum limit of zero, and an upper limit that consists of two parts. Firstly the real upper limit is the value of Limit: if a row number is greater than this an out-of-bounds exception is generated. Secondly the upper limit for rows with explicit styles is MaxSparseArrayItems, since that is the limit for the under- lying sparse array. Generally exceeding this limit causes the action to be ignored, no exception is generated.} {===TOvcTableRows==========================================================} constructor TOvcTableRows.Create; begin FList := TOvcSparseArray.Create; FDefHeight := tbDefRowHeight; FLimit := tbDefRowCount; end; {--------} destructor TOvcTableRows.Destroy; begin if Assigned(FList) then begin Clear; FList.Free; end; end; {--------} procedure TOvcTableRows.Append(const RS : TRowStyle); begin Insert(Limit, RS); end; {--------} procedure TOvcTableRows.Clear; var DummyPtr : pointer; begin DummyPtr := nil; FList.ForAll(DelRow, false, DummyPtr); FList.Clear; FActiveCount := 0; trDoCfgChanged(0, 0, taAll); end; {--------} procedure TOvcTableRows.Delete(RowNum : TRowNum); var RS : PRowStyle; begin if (RowNum < 0) or (RowNum >= Limit) then TableErrorRes(SCTableRowOutOfBounds); if (RowNum < OvcSpAry.MaxSparseArrayItems) then begin RS := PRowStyle(FList[RowNum]); if Assigned(RS) then begin Dispose(RS); dec(FActiveCount); end; FList.Delete(RowNum); Limit := Limit - 1; trDoCfgChanged(RowNum, 0, taDelete); end; end; {--------} procedure TOvcTableRows.trDoCfgChanged(RowNum1, RowNum2 : TRowNum; Action : TOvcTblActions); {-On a change, call the notify event handler} begin if Assigned(FOnCfgChanged) then FOnCfgChanged(Self, RowNum1, RowNum2, Action); end; {--------} procedure TOvcTableRows.Exchange(const RowNum1, RowNum2 : TRowNum); begin if (RowNum1 < 0) or (RowNum1 >= Limit) then TableErrorRes(SCTableRowOutOfBounds); if (RowNum2 < 0) or (RowNum2 >= Limit) then TableErrorRes(SCTableRowOutOfBounds); if (RowNum1 <> RowNum2) and (RowNum1 < OvcSpAry.MaxSparseArrayItems) and (RowNum2 < OvcSpAry.MaxSparseArrayItems) then begin FList.Exchange(RowNum1, RowNum2); trDoCfgChanged(RowNum1, RowNum2, taExchange); end; end; {--------} function TOvcTableRows.GetRow(RowNum : TRowNum) : TRowStyle; var PRS : PRowStyle; begin if (RowNum < 0) or (RowNum >= Limit) then TableErrorRes(SCTableRowOutOfBounds); if (FActiveCount > 0) and (RowNum < OvcSpAry.MaxSparseArrayItems) then PRS := PRowStyle(FList[RowNum]) else PRS := nil; if Assigned(PRS) then begin Result := PRS^; if (Result.Height = UseDefHt) then Result.Height := DefaultHeight; end else with Result do begin Height := DefaultHeight; Hidden := false; end; end; {--------} function TOvcTableRows.GetRowHeight(RowNum : TRowNum) : integer; var PRS : PRowStyle; begin if (RowNum < 0) or (RowNum >= Limit) then TableErrorRes(SCTableRowOutOfBounds); Result := DefaultHeight; if (FActiveCount > 0) and (RowNum < OvcSpAry.MaxSparseArrayItems) then begin PRS := PRowStyle(FList[RowNum]); if Assigned(PRS) then begin Result := PRS^.Height; if (Result = UseDefHt) then Result := DefaultHeight; end; end; end; {--------} function TOvcTableRows.GetRowHidden(RowNum : TRowNum) : boolean; var PRS : PRowStyle; begin if (RowNum < 0) or (RowNum >= Limit) then TableErrorRes(SCTableRowOutOfBounds); Result := false; if (FActiveCount > 0) and (RowNum < OvcSpAry.MaxSparseArrayItems) then begin PRS := PRowStyle(FList[RowNum]); if Assigned(PRS) then Result := PRS^.Hidden; end; end; {--------} function TOvcTableRows.GetRowIsSpecial(RowNum : TRowNum) : boolean; var PRS : PRowStyle; begin if (RowNum < 0) or (RowNum >= Limit) then TableErrorRes(SCTableRowOutOfBounds); if (FActiveCount > 0) and (RowNum < OvcSpAry.MaxSparseArrayItems) then begin PRS := PRowStyle(FList[RowNum]); Result := Assigned(PRS); end else Result := false; end; {--------} procedure TOvcTableRows.Insert(const RowNum : TRowNum; const RS : TRowStyle); var Height : integer; begin {note: you can insert a style at row number Limit} if (RowNum < 0) or (RowNum > Limit) then TableErrorRes(SCTableRowOutOfBounds); if (RowNum >= OvcSpAry.MaxSparseArrayItems) then TableErrorRes(SCTableMaxRows); Height := RS.Height; if (Height < 1) or (Height = DefaultHeight) then Height := UseDefHt; if (RS.Hidden = false) and (Height = UseDefHt) then FList.Insert(RowNum, nil) else begin FList.Insert(RowNum, NewRowStyle(Height, RS.Hidden)); inc(FActiveCount); end; Limit := Limit + 1; trDoCfgChanged(RowNum, 0, taInsert); end; {--------} procedure TOvcTableRows.Reset(const RowNum : TRowNum); var PRS : PRowStyle; begin if (RowNum < 0) or (RowNum >= Limit) then TableErrorRes(SCTableRowOutOfBounds); if (FActiveCount > 0) and (RowNum < OvcSpAry.MaxSparseArrayItems) then begin PRS := PRowStyle(FList[RowNum]); if Assigned(PRS) then begin Dispose(PRS); FList[RowNum] := nil; dec(FActiveCount); trDoCfgChanged(RowNum, 0, taSingle); end; end; end; {--------} type PScaleExtraData = ^TScaleExtraData; TScaleExtraData = packed record M, D : integer; end; {------} function ScaleHeight(Index : longint; Item : pointer; ExtraData : pointer) : boolean; far; var RS : PRowStyle absolute Item; ED : PScaleExtraData absolute ExtraData; begin Result := true; with RS^ do if (Height <> UseDefHt) then Height := MulDiv(Height, ED^.M, ED^.D); end; {------} procedure TOvcTableRows.rwScaleHeights(M, D : integer); var ExtraData : TScaleExtraData; begin FDefHeight := MulDiv(FDefHeight, M, D); if (FActiveCount > 0) then begin ExtraData.M := M; ExtraData.D := D; FList.ForAll(ScaleHeight, false, @ExtraData); end; end; {--------} procedure TOvcTableRows.SetDefHeight(H : integer); begin if (H <> FDefHeight) and (H >= 1) then begin FDefHeight := H; trDoCfgChanged(0, 0, taAll); end; end; {--------} procedure TOvcTableRows.SetLimit(RowNum : TRowNum); begin if RowNum < 1 then RowNum := 1; if (RowNum <> FLimit) then begin FLimit := RowNum; trDoCfgChanged(RowLimitChanged, 0, taGeneral); end; end; {--------} procedure TOvcTableRows.SetRow(RowNum : TRowNum; const RS : TRowStyle); var PRS : PRowStyle; Height : integer; begin if (RowNum < 0) or (RowNum >= Limit) then TableErrorRes(SCTableRowOutOfBounds); if (RowNum < OvcSpAry.MaxSparseArrayItems) then begin Height := RS.Height; if (Height < 1) or (Height = DefaultHeight) then Height := UseDefHt; if (RS.Hidden = false) and (Height = UseDefHt) then Reset(RowNum) else begin PRS := PRowStyle(FList[RowNum]); if Assigned(PRS) then PRS^ := RS else begin FList[RowNum] := NewRowStyle(Height, RS.Hidden); inc(FActiveCount); end; trDoCfgChanged(RowNum, 0, taSingle); end; end; end; {--------} procedure TOvcTableRows.SetRowHeight(RowNum : TRowNum; H : integer); var PRS : PRowStyle; begin if (RowNum < 0) or (RowNum >= Limit) then TableErrorRes(SCTableRowOutOfBounds); if (RowNum < OvcSpAry.MaxSparseArrayItems) then begin if (H < 1) or (H = DefaultHeight) then H := UseDefHt; PRS := PRowStyle(FList[RowNum]); if Assigned(PRS) then begin if (H <> PRS^.Height) then begin if (H = UseDefHt) then if not PRS^.Hidden then begin Dispose(PRS); FList[RowNum] := nil; dec(FActiveCount); end else PRS^.Height := UseDefHt else PRS^.Height := H; trDoCfgChanged(RowNum, 0, taSingle); end; end else if (H <> UseDefHt) then {only create new style if not default} begin FList[RowNum] := NewRowStyle(H, false); inc(FActiveCount); trDoCfgChanged(RowNum, 0, taSingle); end; end; end; {--------} procedure TOvcTableRows.SetRowHidden(RowNum : TRowNum; H : boolean); var PRS : PRowStyle; begin if (RowNum < 0) or (RowNum >= Limit) then TableErrorRes(SCTableRowOutOfBounds); if (RowNum < OvcSpAry.MaxSparseArrayItems) then begin PRS := PRowStyle(FList[RowNum]); if Assigned(PRS) then begin if (H <> PRS^.Hidden) then begin if (not H) and (PRS^.Height = UseDefHt) then begin Dispose(PRS); FList[RowNum] := nil; dec(FActiveCount); end else PRS^.Hidden := H; trDoCfgChanged(RowNum, 0, taSingle); end; end else if H then {only create new style if hidden} begin FList[RowNum] := NewRowStyle(UseDefHt, H); inc(FActiveCount); trDoCfgChanged(RowNum, 0, taSingle); end; end; end; {====================================================================} end.