Implements dbgrid.SelectedRows (issue #1849)

git-svn-id: trunk@9234 -
This commit is contained in:
jesus 2006-05-03 18:22:48 +00:00
parent 9662961394
commit 089474d7bb
2 changed files with 254 additions and 75 deletions

View File

@ -50,6 +50,8 @@ uses
type
TCustomDbGrid = class;
TColumn = class;
EInvalidGridOperation = class(Exception);
TDBGridOption = (
dgEditing, // Ya
@ -65,7 +67,7 @@ type
dgAlwaysShowSelection, // Ya
dgConfirmDelete,
dgCancelOnExit, // Ya
dgMultiselect
dgMultiselect // Ya
);
TDbGridOptions = set of TDbGridOption;
@ -93,6 +95,33 @@ type
type
{ TBookmarkList }
TBookmarkList=class
private
FList: TStringlist;
FGrid: TCustomDbGrid;
function GetCount: integer;
function GetCurrentRowSelected: boolean;
function GetItem(AIndex: Integer): TBookmarkStr;
procedure SetCurrentRowSelected(const AValue: boolean);
procedure CheckActive;
public
constructor Create(AGrid: TCustomDbGrid);
destructor Destroy; override;
procedure Clear;
procedure Delete;
function Find(const Item: TBookmarkStr; var AIndex: Integer): boolean;
function IndexOf(const Item: TBookmarkStr): Integer;
function Refresh: boolean;
property Count: integer read GetCount;
property CurrentRowSelected: boolean
read GetCurrentRowSelected write SetCurrentRowSelected;
property Items[AIndex: Integer]: TBookmarkStr read GetItem; default;
end;
{ TComponentDataLink }
TComponentDataLink=class(TDatalink)
@ -253,6 +282,7 @@ type
FSelectionLock: Boolean;
FTempText : string;
FDrawingActiveRecord: Boolean;
FDrawingMultiSelRecord: Boolean;
FEditingColumn: Integer;
FOldPosition: Integer;
FDefaultColWidths: boolean;
@ -261,6 +291,7 @@ type
FIsEditingCheckBox: Boolean; // For checkbox column editing emulation (by SSY)
FCheckedBitmap, FUnCheckedBitmap, FGrayedBitmap: TBitmap;
FNeedUpdateWidths: boolean;
FSelectedRows: TBookmarkList;
procedure EmptyGrid;
procedure CheckWidths;
function GetCurrentColumn: TColumn;
@ -312,6 +343,8 @@ type
function UpdatingData: boolean;
procedure SwapCheckBox;
function ValueMatch(const BaseValue, TestValue: string): Boolean;
procedure ToggleSelectedRow;
procedure SelectRecord(AValue: boolean);
protected
procedure AddAutomaticColumns;
procedure BeforeMoveSelection(const DCol,DRow: Integer); override;
@ -350,6 +383,7 @@ type
function GetFieldFromGridColumn(Column: Integer): TField;
function GetGridColumnFromField(F: TField): Integer;
function GetImageForCheckBox(CheckBoxView: TDBGridCheckBoxState): TBitmap;
function GetIsCellSelected(aCol, aRow: Integer): boolean; override;
function GridCanModify: boolean;
procedure HeaderClick(IsColumn: Boolean; index: Integer); override;
procedure HeaderSized(IsColumn: Boolean; Index: Integer); override;
@ -379,6 +413,7 @@ type
property Options: TDbGridOptions read FOptions write SetOptions;
property OptionsExtra: TDbgridExtraOptions read FExtraOptions write SetExtraOptions;
property ReadOnly: Boolean read FReadOnly write FReadOnly default false;
property SelectedRows: TBookmarkList read FSelectedRows;
property OnCellClick: TDBGridClickEvent read FOnCellClick write FOnCellClick;
property OnColEnter: TNotifyEvent read FOnColEnter write FOnColEnter;
@ -416,7 +451,7 @@ type
property GridLineColor;
property GridLineStyle;
property SelectedColor;
//property SelectedRows;
property SelectedRows;
published
property Align;
property AlternateColor;
@ -568,14 +603,23 @@ begin
RegisterComponents('Data Controls',[TDBGrid]);
end;
procedure DrawArrow(Canvas: TCanvas; R: TRect; Opt: TDataSetState);
procedure DrawIndicator(Canvas: TCanvas; R: TRect; Opt: TDataSetState;
MultiSel: boolean);
var
dx,dy, x, y: Integer;
procedure CenterY;
begin
y := R.Top + (R.Bottom-R.Top) div 2-1;
end;
procedure CenterX;
begin
X := R.Left + (R.Right-R.Left) div 2-1;
end;
procedure DrawEdit(clr: Tcolor);
begin
Canvas.Pen.Color := clr;
y := R.Top + (R.Bottom-R.Top) div 2 - 1;
X := R.Left + (R.Right-R.Left) div 2 - 1;
CenterY;
CenterX;
Canvas.MoveTo(X-2, Y-Dy-1);
Canvas.LineTo(X+3, Y-Dy-1);
Canvas.MoveTo(X, Y-Dy);
@ -591,14 +635,29 @@ begin
begin //
Canvas.Brush.Color:=clBlack;
Canvas.Pen.Color:=clBlack;
y:= R.top+ (R.Bottom-R.Top) div 2-1;
x:= R.Left+2;
CenterY;
x:= R.Left+3;
if MultiSel then begin
Canvas.Polyline([point(x,y-dy), point(x+dx,y),point(x,y+dy), point(x,y+dy-1)]);
Canvas.Polyline([point(x,y-dy+1),point(x+dx-1,y),point(x, y+dy-1), point(x,y+dy-2)]);
CenterX;
Dec(X,2);
Canvas.Ellipse(Rect(X-2,Y-2,X+2,Y+2));
end else
Canvas.Polygon([point(x,y-dy),point(x+dx,y),point(x, y+dy),point(x,y-dy)]);
end;
dsEdit:
DrawEdit(clBlack);
dsInsert:
DrawEdit(clGreen);
else
if MultiSel then begin
Canvas.Brush.Color:=clBlack;
Canvas.Pen.Color:=clBlack;
CenterX;
CenterY;
Canvas.Ellipse(Rect(X-3,Y-3,X+3,Y+3));
end;
end;
end;
@ -895,8 +954,10 @@ end;
procedure TCustomDbGrid.SetOptions(const AValue: TDbGridOptions);
var
OldOptions: TGridOptions;
MultiSel: boolean;
begin
if FOptions<>AValue then begin
MultiSel := dgMultiSelect in FOptions;
FOptions:=AValue;
OldOptions := inherited Options;
@ -947,6 +1008,9 @@ begin
inherited Options := OldOptions;
if MultiSel and not (dgMultiSelect in FOptions) then
FSelectedRows.Clear;
EndLayout;
end;
end;
@ -1463,6 +1527,11 @@ begin
Result := False;
end;
procedure TCustomDbGrid.ToggleSelectedRow;
begin
SelectRecord(not FSelectedRows.CurrentRowSelected);
end;
procedure TCustomDbGrid.LinkActive(Value: Boolean);
begin
if not Value then
@ -1580,6 +1649,7 @@ end;
procedure TCustomDbGrid.DefaultDrawCell(aCol, aRow: Integer; aRect: TRect;
aState: TGridDrawState);
function GetDatasetState: TDataSetState;
begin
if FDatalink.Active then
@ -1587,17 +1657,21 @@ procedure TCustomDbGrid.DefaultDrawCell(aCol, aRow: Integer; aRect: TRect;
else
result := dsInactive;
end;
var
S: string;
F: TField;
begin
if gdFixed in aState then begin
if (ACol=0) and FDrawingActiveRecord then begin
DrawArrow(Canvas, aRect, GetDataSetState);
DrawIndicator(Canvas, aRect, GetDataSetState, FDrawingMultiSelRecord);
{$ifdef dbgGridPaint}
dbgOut('>');
{$endif}
end else
if (ACol=0) and FDrawingMultiSelRecord then
DrawIndicator(Canvas, aRect, dsCurValue{dummy}, True)
else
if (aRow=0)and(ACol>=FixedCols) then
DrawCellText(aCol,aRow,aRect,aState,GetColumnTitle(aCol));
end else begin
@ -1864,6 +1938,12 @@ begin
end;
end;
VK_MULTIPLY:
begin
if ssCtrl in Shift then
ToggleSelectedRow;
end;
else
inherited KeyDown(Key, Shift);
end;
@ -1936,7 +2016,10 @@ begin
P:=MouseToCell(Point(X,Y));
if P.Y=Row then begin
//doAcceptValue;
doInherited
if ssCtrl in Shift then
ToggleSelectedRow
else
doInherited;
end else begin
doMouseDown;
if ValidDataSet then begin
@ -1944,6 +2027,9 @@ begin
doCancel;
doMoveBy;
end;
if ssCtrl in Shift then
ToggleSelectedRow
else
doMoveToColumn;
end;
end;
@ -2187,6 +2273,12 @@ begin
OnUserCheckboxBitmap(Self, CheckBoxView, Result);
end;
function TCustomDbGrid.GetIsCellSelected(aCol, aRow: Integer): boolean;
begin
Result:=inherited GetIsCellSelected(aCol, aRow) or
FDrawingMultiSelRecord;
end;
function TCustomDbGrid.GridCanModify: boolean;
begin
result := not ReadOnly and (dgEditing in Options) and not FDataLink.ReadOnly
@ -2241,8 +2333,12 @@ begin
//if (Arow>=FixedRows) and FCanBrowse then
FDataLink.ActiveRecord:=ARow-FixedRows;
FDrawingActiveRecord := ARow = Row;
end else
FDrawingMultiSelRecord := (dgMultiSelect in Options) and
SelectedRows.CurrentRowSelected
end else begin
FDrawingActiveRecord := False;
FDrawingMultiSelRecord := False;
end;
{$ifdef dbgGridPaint}
DbgOut('DrawRow Row=', IntToStr(ARow), ' Act=', Copy(BoolToStr(FDrawingActiveRecord),1,1));
{$endif}
@ -2441,6 +2537,8 @@ begin
FDataLink.OnUpdateData:=@OnUpdateData;
FDataLink.VisualControl:= True;
FSelectedRows := TBookmarkList.Create(Self);
FDefaultColWidths := True;
FOptions := [dgColumnResize, dgColumnMove, dgTitles, dgIndicator, dgRowLines,
@ -2491,6 +2589,7 @@ end;
procedure TCustomDbGrid.DefaultDrawColumnCell(const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
function GetDatasetState: TDataSetState;
begin
if FDatalink.Active then
@ -2498,13 +2597,17 @@ procedure TCustomDbGrid.DefaultDrawColumnCell(const Rect: TRect;
else
result := dsInactive;
end;
var
S: string;
F: TField;
begin
if gdFixed in State then begin
if (DataCol=0) and FDrawingActiveRecord then
DrawArrow(Canvas, Rect, GetDataSetState)
DrawIndicator(Canvas, Rect, GetDataSetState, FDrawingMultiSelRecord)
else
if (DataCol=0) and FDrawingMultiSelRecord then
DrawIndicator(Canvas, Rect, dsCurValue{dummy}, True)
else
if (DataCol>=FixedCols) then
DrawCellText(0{dummy}, DataCol{dummy}, Rect, State,GetColumnTitle(DataCol));
@ -2545,11 +2648,18 @@ begin
end;
end;
procedure TCustomDbGrid.SelectRecord(AValue: boolean);
begin
if dgMultiSelect in Options then
FSelectedRows.CurrentRowSelected := AValue;
end;
destructor TCustomDbGrid.Destroy;
begin
FUncheckedBitmap.Free;
FCheckedBitmap.Free;
FGrayedBitmap.Free;
FSelectedRows.Free;
FDataLink.OnDataSetChanged:=nil;
FDataLink.OnRecordChanged:=nil;
FDataLink.Free;
@ -3149,5 +3259,120 @@ begin
end;
end;
{ TBookmarkList }
function TBookmarkList.GetCount: integer;
begin
result := FList.Count;
end;
function TBookmarkList.GetCurrentRowSelected: boolean;
begin
CheckActive;
Result := IndexOf(FGrid.Datasource.Dataset.Bookmark)>=0;
end;
function TBookmarkList.GetItem(AIndex: Integer): TBookmarkStr;
begin
Result := FList[AIndex];
end;
procedure TBookmarkList.SetCurrentRowSelected(const AValue: boolean);
var
aBookStr: TBookmarkstr;
aIndex: Integer;
begin
CheckActive;
aBookStr := FGrid.Datasource.Dataset.Bookmark;
if ABookStr='' then
exit;
if Find(ABookStr, aIndex) then begin
if not AValue then begin
FList.Delete(aIndex);
FGrid.Invalidate;
end;
end else begin
if AValue then begin
FList.Add(ABookStr);
FGrid.Invalidate;
end;
end;
end;
procedure TBookmarkList.CheckActive;
begin
if not Fgrid.FDataLink.Active then
raise EInvalidGridOperation.Create('Dataset Inactive');
end;
constructor TBookmarkList.Create(AGrid: TCustomDbGrid);
begin
inherited Create;
FGrid := AGrid;
FList := TStringList.Create;
end;
destructor TBookmarkList.Destroy;
begin
Clear;
FList.Free;
inherited Destroy;
end;
procedure TBookmarkList.Clear;
begin
FList.Clear;
FGrid.Invalidate;
end;
procedure TBookmarkList.Delete;
var
i: Integer;
ds: TDataSet;
begin
ds := FGrid.Datasource.Dataset;
for i:=0 to FList.Count-1 do begin
ds.Bookmark := Items[i];
ds.Delete;
FList.delete(i);
end;
end;
function TBookmarkList.Find(const Item: TBookmarkStr; var AIndex: Integer): boolean;
var
Indx: integer;
begin
Indx := FList.IndexOf(Item);
if indx<0 then
Result := False
else begin
Result := True;
AIndex := indx;
end;
end;
function TBookmarkList.IndexOf(const Item: TBookmarkStr): Integer;
begin
result := FList.IndexOf(Item)
end;
function TBookmarkList.Refresh: boolean;
var
ds: TDataset;
i: LongInt;
begin
Result := False;
ds := FGrid.Datasource.Dataset;
for i:=FList.Count-1 downto 0 do
if not ds.BookmarkValid(TBookMark(Items[i])) then begin
Result := True;
Flist.Delete(i);
end;
if Result then
FGrid.Invalidate;
end;
end.

View File

@ -746,6 +746,7 @@ type
procedure InvalidateGrid;
procedure InvalidateRow(ARow: Integer);
procedure InvalidateFocused;
function GetIsCellSelected(aCol, aRow: Integer): boolean; virtual;
procedure KeyDown(var Key : Word; Shift : TShiftState); override;
procedure KeyUp(var Key : Word; Shift : TShiftState); override;
procedure LoadContent(cfg: TXMLConfig; Version: Integer); virtual;
@ -836,6 +837,7 @@ type
property GridLineWidth: Integer read FGridLineWidth write SetGridLineWidth default 1;
property GridWidth: Integer read FGCache.GridWidth;
property InplaceEditor: TWinControl read FEditor;
property IsCellSelected[aCol,aRow: Integer]: boolean read GetIsCellSelected;
property LeftCol:Integer read GetLeftCol write SetLeftCol;
property Options: TGridOptions read FOptions write SetOptions;
property Row: Integer read FRow write SetRow;
@ -887,7 +889,6 @@ type
procedure EndUpdate; overload;
procedure EraseBackground(DC: HDC); override;
function IscellSelected(aCol,aRow: Integer): Boolean;
function IscellVisible(aCol, aRow: Integer): Boolean;
procedure LoadFromFile(FileName: string);
function MouseCoord(X,Y: Integer): TGridCoord;
@ -966,6 +967,7 @@ type
property GridLineColor;
property GridLineStyle;
property GridWidth;
property IsCellSelected;
property LeftCol;
property Row;
property RowHeights;
@ -2686,7 +2688,7 @@ begin
(Rs and not(goRelaxedRowSelect in Options)) then
include(gds, gdSelected);
end else
if IsCellSelected(i, aRow) then
if IsCellSelected[i, aRow] then
include(gds, gdSelected);
end;
DrawCell(i, aRow, R, gds);
@ -3274,6 +3276,14 @@ begin
doTopleftChange(False)
end;
function TCustomGrid.GetIsCellSelected(aCol, aRow: Integer): boolean;
begin
Result:= (FRange.Left<=aCol) and
(aCol<=FRange.Right) and
(FRange.Top<=aRow) and
(aRow<=FRange.Bottom);
end;
function TCustomGrid.GetSelectedColumn: TGridColumn;
begin
Result := ColumnFromGridColumn(Col);
@ -4886,14 +4896,6 @@ begin
//
end;
function TCustomGrid.IsCellSelected(aCol, aRow: Integer): Boolean;
begin
Result:= (FRange.Left<=aCol) and
(aCol<=FRange.Right) and
(FRange.Top<=aRow) and
(aRow<=FRange.Bottom);
end;
procedure TCustomGrid.InvalidateCell(aCol, aRow: Integer);
begin
InvalidateCell(ACol,ARow, False);
@ -6928,54 +6930,6 @@ begin
end;
end;
(*
procedure TCustomStringGrid.DrawInteriorCells;
var
i,j: Integer;
gds: TGridDrawState;
c: PCellProps;
begin
with FGCache.VisibleGrid do
if goColSpanning in Options then begin
//
// Ordered draw should be done in order to this work
//
Gds:=[];
// Draw Empty (nil) cells First
For i:=Left to Right do
For j:=Top to Bottom do begin
if IsCellSelected(i,j) then Continue;
C:=Fgrid.Celda[i,j];
if (c=nil) then DrawCell(i,j, CellRect(i,j), gds);
end;
// Draw Cells Empty Cells (Text='') with Attribute
For i:=Left to Right do
For j:=Top to Bottom do begin
if IsCellSelected(i,j) then Continue;
if (i=FCol)or(j=FRow) then Continue;
C:=Fgrid.Celda[i,j];
if (c<>nil)and(C^.Text='') then
DrawCell(i,j, CellRect(i,j), gds);
end;
// Draw Cells not Empty (Text<>'')
For i:=Left to Right do
For j:=Top to Bottom do begin
if IsCellSelected(i,j) then Continue;
C:=Fgrid.Celda[i,j];
if (C<>nil)and(C^.Text<>'') then
DrawCell(i,j, CellRect(i,j), gds);
end;
gds:=[gdSelected];
For i:=Left To Right do
For j:=Top to Bottom do
if IsCellSelected(i,j) then begin
DrawCell(i,j, CellRect(i,j), gds);
end;
end else inherited DrawInteriorCells;
end;
*)
procedure TCustomStringGrid.SetEditText(aCol, aRow: Longint; const aValue: string);
begin
Include(GridFlags, gfEditorUpdateLock);