summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrewski207 <drewski207@ae50a9b5-8222-0410-bf8d-8a13f76226bf>2007-08-06 02:40:33 +0000
committerdrewski207 <drewski207@ae50a9b5-8222-0410-bf8d-8a13f76226bf>2007-08-06 02:40:33 +0000
commit4af59482534c3ab1ef83cd9fe379fcc0ddece98d (patch)
treecb5483cb46731886366b5d2d67b40b12a8d59285
parent4bd8d8738022685001d2b1d801ef00088e2a69bf (diff)
downloadfpGUI-4af59482534c3ab1ef83cd9fe379fcc0ddece98d.tar.xz
* Made the ScrollBars even more robust
* Fixed ListView Scrollbar slider sizes * Vastly improved the speed of adding many items at a time to a ListView
-rw-r--r--examples/gui/listviewtest/listviewtest.lpr38
-rw-r--r--src/gui/gui_listview.pas90
-rw-r--r--src/gui/gui_scrollbar.pas6
3 files changed, 105 insertions, 29 deletions
diff --git a/examples/gui/listviewtest/listviewtest.lpr b/examples/gui/listviewtest/listviewtest.lpr
index 9d503590..a8d64a31 100644
--- a/examples/gui/listviewtest/listviewtest.lpr
+++ b/examples/gui/listviewtest/listviewtest.lpr
@@ -15,6 +15,7 @@ type
FEdit: TfpgEdit;
FAddButton: TfpgButton;
FListView: TfpgListView;
+ FTmpListView: TfpgListView;
FQuitButton: TfpgButton;
FCheck: TfpgCheckBox;
@@ -22,7 +23,7 @@ type
procedure AddBttn(Sender: TObject);
procedure ShowHeadersChange(Sender: TObject);
procedure PaintItem(ListView: TfpgListView; ACanvas: TfpgCanvas; Item: TfpgLVItem;
- Area:TRect; var PaintPart: TfpgLVItemPaintPart);
+ ItemIndex: Integer; Area:TRect; var PaintPart: TfpgLVItemPaintPart);
public
constructor Create(AOwner: TComponent); override;
@@ -39,16 +40,22 @@ end;
procedure TMainForm.AddBttn(Sender: TObject);
var
Item: TfpgLVItem;
+ I: Integer;
begin
FListView.BeginUpdate;
- Item := FListView.ItemAdd;
- Item.Caption :=FEdit.Text+IntToStr(FListView.Items.Count);
- Item.SubItems.Add('0');
- Item.SubItems.Add('1');
- Item.SubItems.Add('2');
- Item.SubItems.Add('3');
- Item.SubItems.Add('4');
+ FTmpListView.BeginUpdate;
+ FListView.Items.Capacity := FListView.Items.Capacity +1000000;
+ for I := 0 to 999999 do begin
+ Item := FListView.ItemAdd;
+ Item.Caption :=FEdit.Text+IntToStr(FListView.Items.Count);
+ Item.SubItems.Add('0');
+ Item.SubItems.Add('1');
+ Item.SubItems.Add('2');
+ Item.SubItems.Add('3');
+ Item.SubItems.Add('4');
+ end;
FListView.EndUpdate;
+ FTmpListView.EndUpdate;
end;
@@ -58,15 +65,14 @@ begin
end;
procedure TMainForm.PaintItem(ListView: TfpgListView; ACanvas: TfpgCanvas;
- Item: TfpgLVItem; Area: TRect; var PaintPart: TfpgLVItemPaintPart);
+ Item: TfpgLVItem; ItemIndex: Integer; Area: TRect; var PaintPart: TfpgLVItemPaintPart);
begin
- if ListView.Items.IndexOf(Item) mod 2 = 0 then ACanvas.TextColor := clRed;;
+ if ItemIndex mod 2 = 0 then ACanvas.TextColor := clRed;
end;
constructor TMainForm.Create(AOwner: TComponent);
var
LVColumn: TfpgLVColumn;
- TmpListView : TfpgListView;
begin
inherited Create(AOwner);
@@ -84,8 +90,8 @@ begin
MultiSelect := True;
end;
- TmpListView := TfpgListView.Create(Self);
- with TmpListView do begin
+ FTmpListView := TfpgListView.Create(Self);
+ with FTmpListView do begin
Parent := Self;
Top := 10;
Left := 335;
@@ -101,7 +107,7 @@ begin
LVColumn.Width := 150;
LVColumn.Height := 50;
FListView.Columns.Add(LVColumn);
- TmpListView.Columns.Add(LVColumn);
+ FTmpListView.Columns.Add(LVColumn);
LVColumn := TfpgLVColumn.Create(FListView.Columns);
LVColumn.Caption := 'Column 2';
@@ -109,7 +115,7 @@ begin
LVColumn.Height := 50;
//LVColumn.Visible := False;
FListView.Columns.Add(LVColumn);
- //TmpListView.Columns.Add(LVColumn);
+ //FTmpListView.Columns.Add(LVColumn);
LVColumn := TfpgLVColumn.Create(FListView.Columns);
LVColumn.Caption := 'Column 3';
@@ -117,7 +123,7 @@ begin
LVColumn.Height := 50;
//LVColumn.Visible := False;
FListView.Columns.Add(LVColumn);
- TmpListView.Columns.Add(LVColumn);
+ FTmpListView.Columns.Add(LVColumn);
LVColumn.ColumnIndex := 2;
diff --git a/src/gui/gui_listview.pas b/src/gui/gui_listview.pas
index 926538e6..369ce03c 100644
--- a/src/gui/gui_listview.pas
+++ b/src/gui/gui_listview.pas
@@ -67,7 +67,7 @@ type
TfpgLVItemPaintPart = set of (lvppBackground, lvppIcon, lvppText, lvppFocused);
TfpgLVPaintItemEvent = procedure(ListView: TfpgListView; Canvas: TfpgCanvas; Item: TfpgLVItem;
- Area:TRect; var PaintPart: TfpgLVItemPaintPart) of object;
+ ItemIndex: Integer; Area:TRect; var PaintPart: TfpgLVItemPaintPart) of object;
IfpgLVItemViewer = interface
@@ -80,10 +80,13 @@ type
TfpgLVItems = class(TObject)
private
+ FUpdateCount: Integer;
FColumns: TfpgLVColumns;
FViewers: TList;
FItems: TList;
+ function GetCapacity: Integer;
function GetItem(AIndex: Integer): TfpgLVItem;
+ procedure SetCapacity(const AValue: Integer);
procedure SetItem(AIndex: Integer; const AValue: TfpgLVItem);
procedure AddViewer(AValue: IfpgLVItemViewer);
procedure DeleteViewer(AValue: IfpgLVItemViewer);
@@ -100,7 +103,10 @@ type
procedure Delete(AIndex: Integer);
function IndexOf(AItem: TfpgLVItem): Integer;
procedure InsertItem(AItem: TfpgLVItem; AIndex: Integer);
+ procedure BeginUpdate;
+ procedure EndUpdate;
+ property Capacity: Integer read GetCapacity write SetCapacity;
property Columns: TfpgLVColumns read FColumns;
property Item[AIndex: Integer]: TfpgLVItem read GetItem write SetItem;
end;
@@ -110,9 +116,9 @@ type
FCaption: String;
FItems: TfpgLVItems;
FSubItems: TStrings;
- function GetSelected(ListView: TfpgListView): Boolean;
+ function GetSelected(ListView: TfpgListView): Boolean;
procedure SetCaption(const AValue: String);
- procedure SetSelected(ListView: TfpgListView; const AValue: Boolean);
+ procedure SetSelected(ListView: TfpgListView; const AValue: Boolean);
procedure SubItemsChanged(Sender: TObject);
public
constructor Create(Items: TfpgLVItems); virtual;
@@ -154,6 +160,7 @@ type
procedure ItemSetSelected(const AItem: TfpgLVItem; const AValue: Boolean);
function ItemGetFromPoint(const X, Y: Integer): TfpgLVItem;
function ItemGetRect(AIndex: Integer): TRect;
+ function ItemIndexFromY(Y: Integer): Integer;
function HeaderHeight: Integer;
procedure DoRepaint;
protected
@@ -189,6 +196,16 @@ begin
Result := TfpgLVItem(FItems.Items[AIndex]);
end;
+function TfpgLVItems.GetCapacity: Integer;
+begin
+ Result := FItems.Capacity;
+end;
+
+procedure TfpgLVItems.SetCapacity(const AValue: Integer);
+begin
+ FItems.Capacity := AValue;
+end;
+
procedure TfpgLVItems.SetItem(AIndex: Integer; const AValue: TfpgLVItem);
begin
FItems.Items[AIndex] := AValue;
@@ -216,6 +233,7 @@ var
I: Integer;
AIndex: Integer;
begin
+ if FUpdateCount > 0 then Exit;
AIndex := IndexOf(AItem);
for I := 0 to FViewers.Count -1 do begin
IfpgLVItemViewer(FViewers.Items[I]).ItemChanged(AIndex);
@@ -227,6 +245,7 @@ var
I: Integer;
AIndex: Integer;
begin
+ if FUpdateCount > 0 then Exit;
AIndex := IndexOf(AItem);
for I := 0 to FViewers.Count -1 do begin
IfpgLVItemViewer(FViewers.Items[I]).ItemAdded(AIndex);
@@ -238,6 +257,7 @@ var
I: Integer;
AIndex: Integer;
begin
+ if FUpdateCount > 0 then Exit;
AIndex := IndexOf(AItem);
for I := 0 to FViewers.Count -1 do begin
IfpgLVItemViewer(FViewers.Items[I]).ItemDeleted(AIndex);
@@ -288,6 +308,18 @@ begin
else
raise Exception.Create('Item is not of TfpgLVItem type!');
end;
+
+procedure TfpgLVItems.BeginUpdate;
+begin
+ Inc(FUpdateCount);
+end;
+
+procedure TfpgLVItems.EndUpdate;
+begin
+ Dec(FUpdateCount);
+ if FUpdateCount < 0 then FUpdateCount := 0;
+end;
+
{ TfpgLVItem }
procedure TfpgLVItem.SetCaption(const AValue: String);
@@ -430,6 +462,18 @@ begin
if FVScrollBar.Visible then Dec(Result.Right, FVScrollBar.Width);
end;
+function TfpgListView.ItemIndexFromY(Y: Integer): Integer;
+var
+ TopPos: Integer;
+begin
+ if ShowHeaders and (Y < HeaderHeight) then Exit(-1);
+
+ TopPos := (FVScrollBar.Position + Y) - 2;
+ if ShowHeaders then Dec(TopPos, HeaderHeight);
+ Result := TopPos div ItemHeight;
+ if Result > Fitems.Count-1 then Result := -1;
+end;
+
function TfpgListView.HeaderHeight: Integer;
begin
Result := Canvas.Font.Height + 10;
@@ -451,13 +495,25 @@ procedure TfpgListView.HandleLMouseDown(x, y: integer; shiftstate: TShiftState
);
var
Item: TfpgLVItem;
+ MinY, MinX, MaxY, MaxX: Integer;
begin
inherited HandleLMouseDown(x, y, shiftstate);
+
+ MinY := 2; MinX := 2; MaxY := Height -2; MaxX := Width -2;
+
+ if FVScrollBar.Visible then Dec(MaxX, FVScrollBar.Width);
+ if FHScrollBar.Visible then Dec(MaxY, FHScrollBar.Height);
+ if FShowHeaders then begin
+ // TODO HeaderClick
+ Inc(MinY, HeaderHeight);
+ end;
+
+ if (X > MaxX) or (X < MinX) or (Y > MaxY) or (Y < MinY) then Exit;
+
Item := ItemGetFromPoint(X, Y);
if not FMultiSelect then FSelected.Clear;
if Item <> nil then begin
- //WriteLn('Got ITem: ', Item.Caption);
- FItemIndex := FItems.IndexOf(Item);
+ FItemIndex := ItemIndexFromY(Y);
if FMultiSelect then begin
if not ((ssCtrl in shiftstate) or (ssShift in shiftstate)) then begin
FSelected.Clear;
@@ -527,7 +583,6 @@ end;
procedure TfpgListView.PaintItems;
var
- //ItemRect: TfpgRect;
VisibleItem: TfpgLVItem;
FirstIndex,
LastIndex: Integer;
@@ -568,7 +623,7 @@ begin
Canvas.FillRectangle(ItemRect);
Exclude(PaintPart, lvppBackground);
TextColor := Canvas.TextColor;
- if Assigned(FOnPaintItem) then FOnPaintItem(Self, Canvas, Item, ItemRect, PaintPart);
+ if Assigned(FOnPaintItem) then FOnPaintItem(Self, Canvas, Item, I, ItemRect, PaintPart);
if lvppIcon in PaintPart then begin
// TODO paint icon
@@ -621,16 +676,13 @@ begin
Inc(MaxH, Columns.Column[I].Width);
end;
- MaxV := (FItems.Count+1) * ItemHeight - (Height);
+ MaxV := (FItems.Count+2) * ItemHeight - (Height);
if ShowHeaders then Inc(MaxV, HeaderHeight);
-
-
if FHScrollBar.Visible then begin
FHScrollBar.Top := Height - FHScrollBar.Height - (BevelSize );
FHScrollBar.Left := BevelSize;
FHScrollBar.Width := Width - (BevelSize * 2);
- Inc(MaxV, FHScrollBar.Height);
end;
if FVScrollBar.Visible then begin
@@ -649,6 +701,20 @@ begin
FHScrollBar.Max := MaxH-(Width-(BevelSize * 2));
FVScrollBar.Max := MaxV;
+ if FVScrollBar.Max = 0 then
+ FVScrollBar.SliderSize := 1
+ else
+ FVScrollBar.SliderSize := FVScrollBar.Height / (FVScrollBar.Max + FVScrollBar.Height);
+ FVScrollBar.RepaintSlider;
+
+ if FHScrollBar.Max = 0 then
+ FHScrollBar.SliderSize := 1
+ else
+ FHScrollBar.SliderSize := FHScrollBar.Width / (FHScrollBar.Max + FHScrollBar.Width);
+ FHScrollBar.RepaintSlider;
+
+
+
FHScrollBar.UpdateWindowPosition;
FVScrollBar.UpdateWindowPosition;
end;
@@ -687,10 +753,12 @@ end;
procedure TfpgListView.BeginUpdate;
begin
Inc(FUpdateCount);
+ FItems.BeginUpdate;
end;
procedure TfpgListView.EndUpdate;
begin
+ FItems.EndUpdate;
Dec(FUpdateCount);
if FUpdateCount < 0 then FUpdateCount := 0;
if FUpdateCount = 0 then DoRePaint;
diff --git a/src/gui/gui_scrollbar.pas b/src/gui/gui_scrollbar.pas
index 56baa257..e95d3a2f 100644
--- a/src/gui/gui_scrollbar.pas
+++ b/src/gui/gui_scrollbar.pas
@@ -125,14 +125,16 @@ end;
procedure TfpgScrollBar.SetMax(const AValue: integer);
begin
if AValue = FMax then Exit;
- FMax := AValue;
+ if AValue < FMin then FMax := FMin
+ else FMax := AValue;
if FPosition > FMax then SetPosition(FMax);
end;
procedure TfpgScrollBar.SetMin(const AValue: integer);
begin
if AValue = FMin then Exit;
- FMin := AValue;
+ if AValue > FMax then FMin := FMax
+ else FMin := AValue;
if FPosition < FMin then SetPosition(FMin);
end;