summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrewski207 <drewski207@ae50a9b5-8222-0410-bf8d-8a13f76226bf>2007-08-06 00:05:07 +0000
committerdrewski207 <drewski207@ae50a9b5-8222-0410-bf8d-8a13f76226bf>2007-08-06 00:05:07 +0000
commit4bd8d8738022685001d2b1d801ef00088e2a69bf (patch)
tree4fa9300a539400802ea1c52fe8f5936fce832651
parent842be2507dbf85dd5d91b464f19d6945772a753f (diff)
downloadfpGUI-4bd8d8738022685001d2b1d801ef00088e2a69bf.tar.xz
* Added basic listview
* Added a test project for the listview widget * made the Scrollbar more robust * changed canvas.color and canvas.textcolor to be read/write A cool feature of a listview is to be able to share it's .Items property with other listviews so the list doesn't have to exits in memory. The test project uses that feature.
-rw-r--r--examples/gui/listviewtest/listviewtest.lpi51
-rw-r--r--examples/gui/listviewtest/listviewtest.lpr178
-rw-r--r--src/corelib/gfxbase.pas4
-rw-r--r--src/gui/fpgui_package.lpk5
-rw-r--r--src/gui/fpgui_package.pas3
-rw-r--r--src/gui/gui_listview.pas799
-rw-r--r--src/gui/gui_scrollbar.pas35
7 files changed, 1067 insertions, 8 deletions
diff --git a/examples/gui/listviewtest/listviewtest.lpi b/examples/gui/listviewtest/listviewtest.lpi
new file mode 100644
index 00000000..8e8f6e62
--- /dev/null
+++ b/examples/gui/listviewtest/listviewtest.lpi
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <ProjectOptions>
+ <PathDelim Value="/"/>
+ <Version Value="5"/>
+ <General>
+ <SessionStorage Value="InProjectDir"/>
+ <MainUnit Value="0"/>
+ <IconPath Value="./"/>
+ <TargetFileExt Value=""/>
+ </General>
+ <VersionInfo>
+ <ProjectVersion Value=""/>
+ </VersionInfo>
+ <PublishOptions>
+ <Version Value="2"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ <RequiredPackages Count="2">
+ <Item1>
+ <PackageName Value="fpgui_package"/>
+ </Item1>
+ <Item2>
+ <PackageName Value="fpgfx_package"/>
+ </Item2>
+ </RequiredPackages>
+ <Units Count="1">
+ <Unit0>
+ <Filename Value="listviewtest.lpr"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="listviewtest"/>
+ </Unit0>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="5"/>
+ <CodeGeneration>
+ <Generate Value="Faster"/>
+ </CodeGeneration>
+ <Other>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+</CONFIG>
diff --git a/examples/gui/listviewtest/listviewtest.lpr b/examples/gui/listviewtest/listviewtest.lpr
new file mode 100644
index 00000000..9d503590
--- /dev/null
+++ b/examples/gui/listviewtest/listviewtest.lpr
@@ -0,0 +1,178 @@
+program listviewtest;
+
+{$mode objfpc}{$H+}
+
+uses
+ Classes, fpgui_package, fpgfx_package, fpgfx, sysutils ,
+ gui_listview, gui_form, gui_button, gui_edit, gfxbase, gui_checkbox;
+
+type
+
+ { TMainForm }
+
+ TMainForm = class(TfpgForm)
+ private
+ FEdit: TfpgEdit;
+ FAddButton: TfpgButton;
+ FListView: TfpgListView;
+ FQuitButton: TfpgButton;
+ FCheck: TfpgCheckBox;
+
+ procedure CloseBttn(Sender: TObject);
+ procedure AddBttn(Sender: TObject);
+ procedure ShowHeadersChange(Sender: TObject);
+ procedure PaintItem(ListView: TfpgListView; ACanvas: TfpgCanvas; Item: TfpgLVItem;
+ Area:TRect; var PaintPart: TfpgLVItemPaintPart);
+
+ public
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+ end;
+
+{ TMainForm }
+
+procedure TMainForm.CloseBttn(Sender: TObject);
+begin
+ Close;
+end;
+
+procedure TMainForm.AddBttn(Sender: TObject);
+var
+ Item: TfpgLVItem;
+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');
+ FListView.EndUpdate;
+
+end;
+
+procedure TMainForm.ShowHeadersChange(Sender: TObject);
+begin
+ FListView.ShowHeaders := TfpgCheckBox(Sender).Checked;
+end;
+
+procedure TMainForm.PaintItem(ListView: TfpgListView; ACanvas: TfpgCanvas;
+ Item: TfpgLVItem; Area: TRect; var PaintPart: TfpgLVItemPaintPart);
+begin
+ if ListView.Items.IndexOf(Item) mod 2 = 0 then ACanvas.TextColor := clRed;;
+end;
+
+constructor TMainForm.Create(AOwner: TComponent);
+var
+ LVColumn: TfpgLVColumn;
+ TmpListView : TfpgListView;
+begin
+ inherited Create(AOwner);
+
+ WindowTitle := 'ListView Test';
+ SetPosition(200, 200, 610, 455);
+
+ FListView := TfpgListView.Create(Self);
+ with FListView do begin
+ Parent := Self;
+ Top := 10;
+ Left := 10;
+ Width := 320;
+ Height := 400;
+ OnPaintItem := @PaintItem;
+ MultiSelect := True;
+ end;
+
+ TmpListView := TfpgListView.Create(Self);
+ with TmpListView do begin
+ Parent := Self;
+ Top := 10;
+ Left := 335;
+ Width := 270;
+ Height := 400;
+ //OnPaintItem := @PaintItem;
+ Items := FListView.Items;
+ end;
+
+
+ LVColumn := TfpgLVColumn.Create(FListView.Columns);
+ LVColumn.Caption := 'Column 1';
+ LVColumn.Width := 150;
+ LVColumn.Height := 50;
+ FListView.Columns.Add(LVColumn);
+ TmpListView.Columns.Add(LVColumn);
+
+ LVColumn := TfpgLVColumn.Create(FListView.Columns);
+ LVColumn.Caption := 'Column 2';
+ LVColumn.Width := 100;
+ LVColumn.Height := 50;
+ //LVColumn.Visible := False;
+ FListView.Columns.Add(LVColumn);
+ //TmpListView.Columns.Add(LVColumn);
+
+ LVColumn := TfpgLVColumn.Create(FListView.Columns);
+ LVColumn.Caption := 'Column 3';
+ LVColumn.Width := 200;
+ LVColumn.Height := 50;
+ //LVColumn.Visible := False;
+ FListView.Columns.Add(LVColumn);
+ TmpListView.Columns.Add(LVColumn);
+ LVColumn.ColumnIndex := 2;
+
+
+ FEdit := TfpgEdit.Create(Self);
+ with FEdit do begin
+ Parent := Self;
+ Top := 420;
+ Left := 10;
+ Width := 100;
+ end;
+
+ FAddButton := TfpgButton.Create(Self);
+ with FAddButton do begin
+ Parent := Self;
+ Top := 420;
+ Left := 120;
+ Width := 80;
+ Text := 'Add';
+ OnClick := @AddBttn;
+ end;
+
+ FQuitButton := TfpgButton.Create(Self);
+ with FQuitButton do begin
+ Parent := Self;
+ Top := 420;
+ Left := 210;
+ Width := 80;
+ Text := 'Quit';
+ OnClick := @CloseBttn;
+ end;
+
+ FCheck := TfpgCheckBox.Create(Self);
+ with FCheck do begin
+ Parent := Self;
+ Top := 420;
+ Left := 290;
+ Width := 110;
+ Checked := True;
+ Text := 'ShowHeaders';
+ OnChange := @ShowHeadersChange;
+ end;
+
+end;
+
+destructor TMainForm.Destroy;
+begin
+ inherited Destroy;
+end;
+
+begin
+ fpgApplication.Initialize;
+ with TMainForm.Create(nil) do begin
+ Show;
+ fpgApplication.Run;
+ Free;
+ end;
+end.
+
diff --git a/src/corelib/gfxbase.pas b/src/corelib/gfxbase.pas
index 684391f5..2929c803 100644
--- a/src/corelib/gfxbase.pas
+++ b/src/corelib/gfxbase.pas
@@ -284,8 +284,8 @@ type
procedure EndDraw(x, y, w, h: TfpgCoord); overload;
procedure EndDraw; overload;
procedure FreeResources;
- property Color: TfpgColor read FColor;
- property TextColor: TfpgColor read FTextColor;
+ property Color: TfpgColor read FColor write SetColor;
+ property TextColor: TfpgColor read FTextColor write SetTextColor;
property Font: TfpgFontBase read FFont write SetFont;
property Pixels[X, Y: integer]: TfpgColor read GetPixel write SetPixel;
property InterpolationFilter: TfpgCustomInterpolation read FInterpolation write SetInterpolation;
diff --git a/src/gui/fpgui_package.lpk b/src/gui/fpgui_package.lpk
index 216e136b..ba93515f 100644
--- a/src/gui/fpgui_package.lpk
+++ b/src/gui/fpgui_package.lpk
@@ -18,7 +18,7 @@
<Description Value="fpGUI - multi-handle redesign"/>
<License Value="Modified LGPL"/>
<Version Minor="5"/>
- <Files Count="16">
+ <Files Count="17">
<Item1>
<Filename Value="gui_button.pas"/>
<UnitName Value="gui_button"/>
@@ -83,6 +83,9 @@
<Filename Value="gui_grid.pas"/>
<UnitName Value="gui_grid"/>
</Item16>
+ <Item17>
+ <Filename Value="gui_listview.pas"/>
+ </Item17>
</Files>
<RequiredPkgs Count="2">
<Item1>
diff --git a/src/gui/fpgui_package.pas b/src/gui/fpgui_package.pas
index 98749904..287708f8 100644
--- a/src/gui/fpgui_package.pas
+++ b/src/gui/fpgui_package.pas
@@ -9,7 +9,8 @@ interface
uses
gui_button, gui_combobox, gui_dialogs, gui_edit, gui_form, gui_label,
gui_listbox, gui_memo, gui_popupwindow, gui_scrollbar, gui_bevel,
- gui_checkbox, gui_radiobutton, gui_trackbar, gui_tab, gui_grid;
+ gui_checkbox, gui_radiobutton, gui_trackbar, gui_tab, gui_grid,
+ gui_listview;
implementation
diff --git a/src/gui/gui_listview.pas b/src/gui/gui_listview.pas
new file mode 100644
index 00000000..926538e6
--- /dev/null
+++ b/src/gui/gui_listview.pas
@@ -0,0 +1,799 @@
+unit gui_listview;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes,
+ SysUtils,
+ gfxbase,
+ fpgfx,
+ gfx_widget,
+ gui_scrollbar;
+
+type
+ TfpgListView = class;
+ TfpgLVItem = class;
+ TfpgLVColumns = class;
+
+ { TfpgLVColumn }
+
+ TfpgLVColumn = class(TComponent)
+ private
+ FAutoSize: Boolean;
+ FCaption: String;
+ FColumnIndex: Integer;
+ FHeight: Integer;
+ FVisible: Boolean;
+ FWidth: Integer;
+ procedure SetAutoSize(const AValue: Boolean);
+ procedure SetCaption(const AValue: String);
+ procedure SetColumnIndex(const AValue: Integer);
+ procedure SetHeight(const AValue: Integer);
+ procedure SetVisible(const AValue: Boolean);
+ procedure SetWidth(const AValue: Integer);
+ public
+ constructor Create(AColumns: TfpgLVColumns);
+ destructor Destroy; override;
+ property Caption: String read FCaption write SetCaption;
+ property AutoSize: Boolean read FAutoSize write SetAutoSize;
+ property Width: Integer read FWidth write SetWidth;
+ property Height: Integer read FHeight write SetHeight;
+ property Visible: Boolean read FVisible write SetVisible;
+ property ColumnIndex: Integer read FColumnIndex write SetColumnIndex;
+ end;
+
+ { TfpgLVColumns }
+
+ TfpgLVColumns = class(TPersistent)
+ private
+ FListView: TfpgListView;
+ FColumns: TList;
+ function GetColumn(AIndex: Integer): TfpgLVColumn;
+ procedure SetColumn(AIndex: Integer; const AValue: TfpgLVColumn);
+ public
+ constructor Create(AListView: TfpgListView);
+ destructor Destroy; override;
+ function Add(AColumn: TfpgLVColumn): Integer;
+ procedure Delete(AIndex: Integer);
+ procedure Insert(AColumn: TfpgLVColumn; AIndex: Integer);
+ function Count: Integer;
+ property Column[AIndex: Integer]: TfpgLVColumn read GetColumn write SetColumn;
+ end;
+
+ TfpgLVItemState = set of (lisFocused, lisSelected, lisHotTrack);
+
+ TfpgLVItemPaintPart = set of (lvppBackground, lvppIcon, lvppText, lvppFocused);
+
+ TfpgLVPaintItemEvent = procedure(ListView: TfpgListView; Canvas: TfpgCanvas; Item: TfpgLVItem;
+ Area:TRect; var PaintPart: TfpgLVItemPaintPart) of object;
+
+
+ IfpgLVItemViewer = interface
+ procedure ItemDeleted(AIndex: Integer);
+ procedure ItemAdded(AIndex: Integer);
+ procedure ItemChanged(AIndex: Integer);
+ end;
+
+ { TfpgLVItems }
+
+ TfpgLVItems = class(TObject)
+ private
+ FColumns: TfpgLVColumns;
+ FViewers: TList;
+ FItems: TList;
+ function GetItem(AIndex: Integer): TfpgLVItem;
+ procedure SetItem(AIndex: Integer; const AValue: TfpgLVItem);
+ procedure AddViewer(AValue: IfpgLVItemViewer);
+ procedure DeleteViewer(AValue: IfpgLVItemViewer);
+
+ procedure DoChange(AItem: TfpgLVItem);
+ procedure DoAdd(AItem: TfpgLVItem);
+ procedure DoDelete(AItem: TfpgLVItem);
+ protected
+ public
+ constructor Create(AViewer: IfpgLVItemViewer);
+ destructor Destroy; override;
+ function Add(AItem: TfpgLVItem): Integer;
+ function Count: Integer;
+ procedure Delete(AIndex: Integer);
+ function IndexOf(AItem: TfpgLVItem): Integer;
+ procedure InsertItem(AItem: TfpgLVItem; AIndex: Integer);
+
+ property Columns: TfpgLVColumns read FColumns;
+ property Item[AIndex: Integer]: TfpgLVItem read GetItem write SetItem;
+ end;
+
+ TfpgLVItem = class(TObject)
+ private
+ FCaption: String;
+ FItems: TfpgLVItems;
+ FSubItems: TStrings;
+ function GetSelected(ListView: TfpgListView): Boolean;
+ procedure SetCaption(const AValue: String);
+ procedure SetSelected(ListView: TfpgListView; const AValue: Boolean);
+ procedure SubItemsChanged(Sender: TObject);
+ public
+ constructor Create(Items: TfpgLVItems); virtual;
+ destructor Destroy; override;
+ property Caption: String read FCaption write SetCaption;
+ property SubItems: TStrings read FSubItems;
+ property Selected[ListView: TfpgListView]: Boolean read GetSelected write SetSelected;
+ end;
+
+
+ { TfpgListView }
+
+ TfpgListView = class(TfpgWidget, IfpgLVItemViewer)
+ private
+ FItemIndex: Integer;
+ FMultiSelect: Boolean;
+ FSelected: TList;
+ FUpdateCount: Integer;
+ FVScrollBar,
+ FHScrollBar: TfpgScrollBar;
+ FColumns: TfpgLVColumns;
+ FItems: TfpgLVItems;
+ FOnPaintItem: TfpgLVPaintItemEvent;
+ FShowHeaders: Boolean;
+ function GetItemHeight: Integer;
+ procedure
+ SetItemIndex(const AValue: Integer);
+ procedure SetItems(const AValue: TfpgLVItems);
+ procedure SetMultiSelect(const AValue: Boolean);
+ procedure SetShowHeaders(const AValue: Boolean);
+ procedure VScrollChange(Sender: TObject; Position: Integer);
+ procedure HScrollChange(Sender: TObject; Position: Integer);
+ // interface methods
+ procedure ItemDeleted(AIndex: Integer);
+ procedure ItemAdded(AIndex: Integer);
+ procedure ItemChanged(AIndex: Integer);
+
+ function ItemGetSelected(const AItem: TfpgLVItem): Boolean;
+ procedure ItemSetSelected(const AItem: TfpgLVItem; const AValue: Boolean);
+ function ItemGetFromPoint(const X, Y: Integer): TfpgLVItem;
+ function ItemGetRect(AIndex: Integer): TRect;
+ function HeaderHeight: Integer;
+ procedure DoRepaint;
+ protected
+ procedure HandleMouseScroll(x, y: integer; shiftstate: TShiftState; delta: smallint); override;
+ procedure HandleLMouseDown(x, y: integer; shiftstate: TShiftState); override;
+ procedure HandlePaint; override;
+ procedure HandleResize(awidth, aheight: TfpgCoord); override;
+ procedure PaintHeaders; virtual;
+ procedure PaintItems; virtual;
+ procedure UpdateScrollBarPositions; virtual;
+ public
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure BeginUpdate;
+ procedure EndUpdate;
+ function ItemAdd: TfpgLVItem;
+ property Columns: TfpgLVColumns read FColumns;
+ property Items: TfpgLVItems read FItems write SetItems;
+ property OnPaintItem: TfpgLVPaintItemEvent read FOnPaintItem write FOnPaintItem;
+ property ShowHeaders: Boolean read FShowHeaders write SetShowHeaders;
+ property MultiSelect: Boolean read FMultiSelect write SetMultiSelect;
+ property VScrollBar: TfpgScrollBar read FVScrollBar;
+ property HScrollBar: TfpgScrollBar read FHScrollBar;
+ property ItemHeight: Integer read GetItemHeight;
+ property ItemIndex: Integer read FItemIndex write SetItemIndex;
+ end;
+implementation
+
+{ TfpgLVItems }
+
+function TfpgLVItems.GetItem(AIndex: Integer): TfpgLVItem;
+begin
+ Result := TfpgLVItem(FItems.Items[AIndex]);
+end;
+
+procedure TfpgLVItems.SetItem(AIndex: Integer; const AValue: TfpgLVItem);
+begin
+ FItems.Items[AIndex] := AValue;
+end;
+
+procedure TfpgLVItems.AddViewer(AValue: IfpgLVItemViewer);
+begin
+ if AValue <> nil then
+ FViewers.Add(AValue);
+end;
+
+procedure TfpgLVItems.DeleteViewer(AValue: IfpgLVItemViewer);
+var
+ AIndex: Integer;
+begin
+ AIndex := FViewers.IndexOf(AValue);
+ if AIndex > -1 then begin
+ FViewers.Delete(AIndex);
+ end;
+ if FViewers.Count = 0 then Free;
+end;
+
+procedure TfpgLVItems.DoChange(AItem: TfpgLVItem);
+var
+ I: Integer;
+ AIndex: Integer;
+begin
+ AIndex := IndexOf(AItem);
+ for I := 0 to FViewers.Count -1 do begin
+ IfpgLVItemViewer(FViewers.Items[I]).ItemChanged(AIndex);
+ end;
+end;
+
+procedure TfpgLVItems.DoAdd(AItem: TfpgLVItem);
+var
+ I: Integer;
+ AIndex: Integer;
+begin
+ AIndex := IndexOf(AItem);
+ for I := 0 to FViewers.Count -1 do begin
+ IfpgLVItemViewer(FViewers.Items[I]).ItemAdded(AIndex);
+ end;
+end;
+
+procedure TfpgLVItems.DoDelete(AItem: TfpgLVItem);
+var
+ I: Integer;
+ AIndex: Integer;
+begin
+ AIndex := IndexOf(AItem);
+ for I := 0 to FViewers.Count -1 do begin
+ IfpgLVItemViewer(FViewers.Items[I]).ItemDeleted(AIndex);
+ end;
+end;
+
+constructor TfpgLVItems.Create(AViewer: IfpgLVItemViewer);
+begin
+ FItems := TList.Create;
+ FViewers := TList.Create;
+ AddViewer(AViewer);
+end;
+
+destructor TfpgLVItems.Destroy;
+begin
+ FItems.Free;
+ FViewers.Free;
+ inherited Destroy;
+end;
+
+function TfpgLVItems.Add(AItem: TfpgLVItem): Integer;
+begin
+ Result := Count;
+ InsertItem(AItem, Count);
+ DoAdd(AItem);
+end;
+
+function TfpgLVItems.Count: Integer;
+begin
+ Result := FItems.Count;
+end;
+
+procedure TfpgLVItems.Delete(AIndex: Integer);
+begin
+ DoDelete(GetItem(AIndex));
+ FItems.Delete(AIndex);
+end;
+
+function TfpgLVItems.IndexOf(AItem: TfpgLVItem): Integer;
+begin
+ Result := FItems.IndexOf(AItem);
+end;
+
+procedure TfpgLVItems.InsertItem(AItem: TfpgLVItem; AIndex: Integer);
+begin
+ if AItem.InheritsFrom(TfpgLVItem) then
+ FItems.Insert(AIndex, AItem)
+ else
+ raise Exception.Create('Item is not of TfpgLVItem type!');
+end;
+{ TfpgLVItem }
+
+procedure TfpgLVItem.SetCaption(const AValue: String);
+begin
+ if FCaption=AValue then exit;
+ FCaption:=AValue;
+ if Assigned(FItems) then FItems.DoChange(Self);
+end;
+
+function TfpgLVItem.GetSelected(ListView: TfpgListView): Boolean;
+begin
+ Result := ListView.ItemGetSelected(Self);
+end;
+
+procedure TfpgLVItem.SetSelected(ListView: TfpgListView; const AValue: Boolean);
+begin
+ ListView.ItemSetSelected(Self, AValue);
+end;
+
+procedure TfpgLVItem.SubItemsChanged(Sender: TObject);
+begin
+ if Assigned(FItems) then
+ FItems.DoChange(Self);
+end;
+
+constructor TfpgLVItem.Create(Items: TfpgLVItems);
+begin
+ FItems := Items;
+ FSubItems := TStringList.Create;
+ TStringList(FSubItems).OnChange := @SubItemsChanged;
+end;
+
+destructor TfpgLVItem.Destroy;
+begin
+ FSubItems.Free;
+ inherited Destroy;
+end;
+
+{ TfpgListView }
+
+
+procedure TfpgListView.SetShowHeaders(const AValue: Boolean);
+begin
+ if FShowHeaders=AValue then exit;
+ FShowHeaders:=AValue;
+ DoRePaint;
+end;
+
+
+procedure TfpgListView.VScrollChange(Sender: TObject; Position: Integer);
+begin
+ DoRepaint;
+end;
+
+procedure TfpgListView.HScrollChange(Sender: TObject; Position: Integer);
+begin
+ DoRepaint;
+end;
+
+procedure TfpgListView.SetItems(const AValue: TfpgLVItems);
+begin
+ if AValue = FItems then Exit;
+ AValue.AddViewer(Self);
+ FItems.DeleteViewer(Self);
+ Fitems := AValue;
+end;
+
+procedure TfpgListView.SetMultiSelect(const AValue: Boolean);
+begin
+ if FMultiSelect=AValue then exit;
+ FMultiSelect:=AValue;
+end;
+
+function TfpgListView.GetItemHeight: Integer;
+begin
+ Result := Canvas.Font.Height + 4;
+end;
+
+procedure TfpgListView.SetItemIndex(const AValue: Integer);
+begin
+ if FItemIndex=AValue then exit;
+ FItemIndex:=AValue;
+end;
+
+procedure TfpgListView.ItemDeleted(AIndex: Integer);
+begin
+ if FUpdateCount = 0 then DoRePaint;
+end;
+
+procedure TfpgListView.ItemAdded(AIndex: Integer);
+begin
+ if FUpdateCount = 0 then DoRePaint;
+end;
+
+procedure TfpgListView.ItemChanged(AIndex: Integer);
+begin
+ if FUpdateCount = 0 then DoRePaint;
+ // TODO
+end;
+
+function TfpgListView.ItemGetSelected(const AItem: TfpgLVItem): Boolean;
+begin
+ Result := FSelected.IndexOf(AItem) > -1;
+end;
+
+procedure TfpgListView.ItemSetSelected(const AItem: TfpgLVItem; const AValue: Boolean);
+var
+ Index: Integer;
+begin
+ Index := FSelected.IndexOf(AItem);
+
+ if AValue and (Index = -1) then
+ FSelected.Add(AItem);
+ if (AValue = False) and (Index <> -1) then
+ FSelected.Delete(Index);
+end;
+
+function TfpgListView.ItemGetFromPoint(const X, Y: Integer): TfpgLVItem;
+var
+ Index: Integer;
+ ItemTop: Integer;
+begin
+ Result := nil;
+ ItemTop := (FVScrollBar.Position + Y) -2;
+ if ShowHeaders then Dec(ItemTop, HeaderHeight);
+ Index := ItemTop div ItemHeight;
+ if Index < 0 then Exit;
+ if Index >= FItems.Count then Exit;
+
+ Result := FItems.Item[Index];
+end;
+
+function TfpgListView.ItemGetRect(AIndex: Integer): TRect;
+begin
+ Result.Top := 2 + (AIndex * ItemHeight) - FVScrollBar.Position;
+ if ShowHeaders then Inc(Result.Top, HeaderHeight);
+ Result.Bottom := Result.Top + ItemHeight-1;
+ Result.Left := 2 - FHScrollBar.Position;
+ Result.Right := Width - 4;
+ if FVScrollBar.Visible then Dec(Result.Right, FVScrollBar.Width);
+end;
+
+function TfpgListView.HeaderHeight: Integer;
+begin
+ Result := Canvas.Font.Height + 10;
+end;
+
+procedure TfpgListView.DoRepaint;
+begin
+ if FUpdateCount = 0 then RePaint;
+end;
+
+procedure TfpgListView.HandleMouseScroll(x, y: integer;
+ shiftstate: TShiftState; delta: smallint);
+begin
+ // Yes this is a dirty dirty hack
+ TfpgListView(FVScrollBar).HandleMouseScroll(x, y, shiftstate, delta);
+end;
+
+procedure TfpgListView.HandleLMouseDown(x, y: integer; shiftstate: TShiftState
+ );
+var
+ Item: TfpgLVItem;
+begin
+ inherited HandleLMouseDown(x, y, shiftstate);
+ Item := ItemGetFromPoint(X, Y);
+ if not FMultiSelect then FSelected.Clear;
+ if Item <> nil then begin
+ //WriteLn('Got ITem: ', Item.Caption);
+ FItemIndex := FItems.IndexOf(Item);
+ if FMultiSelect then begin
+ if not ((ssCtrl in shiftstate) or (ssShift in shiftstate)) then begin
+ FSelected.Clear;
+ ItemSetSelected(Item, True);
+ end
+ else begin
+ if ssCtrl in shiftstate then
+ ItemSetSelected(Item, not ItemGetSelected(Item));
+ if ssShift in shiftstate then ;
+ end
+ end
+ else ItemSetSelected(Item, True);
+ end;
+ DoRepaint;
+end;
+
+
+procedure TfpgListView.HandlePaint;
+begin
+ if FUpdateCount > 0 then Exit;
+
+ Canvas.BeginDraw;
+
+ UpdateScrollBarPositions;
+
+ Canvas.Clear(clListBox);
+
+ PaintItems;
+ if ShowHeaders then
+ PaintHeaders;
+
+
+ fpgStyle.DrawControlFrame(Canvas, 0,0,Width,Height);
+
+ Canvas.EndDraw;
+end;
+
+procedure TfpgListView.HandleResize(awidth, aheight: TfpgCoord);
+begin
+ inherited HandleResize(awidth, aheight);
+
+ UpdateScrollBarPositions;
+end;
+
+procedure TfpgListView.PaintHeaders;
+var
+ I: Integer;
+ cLeft,
+ cTop: Integer;
+ Column: TfpgLVColumn;
+begin
+ cLeft := 2;
+ if FHScrollBar.Visible then Dec(cLeft, FHScrollBar.Position);
+ cTop := 2;
+ for I := 0 to Columns.Count-1 do begin
+ Column := Columns.Column[I];
+ if Column.Visible then begin
+ fpgStyle.DrawButtonFace(Canvas,cLeft, cTop, cLeft+Column.Width, Canvas.Font.Height+10, [btnIsEmbedded]);
+ fpgStyle.DrawString(Canvas, cLeft+5, cTop+5, Column.Caption, Enabled);
+ Inc(cLeft, Column.Width);
+ end;
+ end;
+ if cLeft < FWidth-2 then begin
+ fpgStyle.DrawButtonFace(Canvas,cLeft, cTop, cLeft+(Width-2-cLeft), Canvas.Font.Height+10, [btnIsEmbedded, btnIsPressed]);
+ end;
+end;
+
+procedure TfpgListView.PaintItems;
+var
+ //ItemRect: TfpgRect;
+ VisibleItem: TfpgLVItem;
+ FirstIndex,
+ LastIndex: Integer;
+ I, J : Integer;
+ PaintPart: TfpgLVItemPaintPart;
+ ItemRect: TRect;
+ ItemState: TfpgLVItemState;
+ Item: TfpgLVItem;
+ TheText: String;
+ TextColor: TfpgColor;
+ ColumnIndex: Integer;
+begin
+ FirstIndex := (FVScrollBar.Position) div ItemHeight;
+ LastIndex := (FVScrollBar.Position+(Height-4)) div ItemHeight;
+
+ if LastIndex > Fitems.Count-1 then LastIndex := FItems.Count-1;
+
+ //WriteLn('FirstIndex = ', FirstIndex, ' LastIndex = ', LastIndex);
+
+ for I := FirstIndex to LastIndex do begin
+ ItemState := [];
+ PaintPart := [lvppBackground, lvppIcon, lvppText];
+ ItemRect := ItemGetRect(I);
+ Item := FItems.Item[I];
+ if Item.Selected[Self] then Include(ItemState, lisSelected);
+ if FItemIndex = I then begin
+ Include(ItemState, lisFocused);
+ Include(PaintPart, lvppFocused);
+ end;
+
+ if lisSelected in (ItemState) then begin
+ Canvas.Color := clBlue;
+ end
+ else Canvas.Color := clListBox;
+
+
+
+ Canvas.FillRectangle(ItemRect);
+ Exclude(PaintPart, lvppBackground);
+ TextColor := Canvas.TextColor;
+ if Assigned(FOnPaintItem) then FOnPaintItem(Self, Canvas, Item, ItemRect, PaintPart);
+
+ if lvppIcon in PaintPart then begin
+ // TODO paint icon
+ end;
+
+ if lvppFocused in PaintPart then begin
+ Canvas.Color := clBlack;
+ canvas.DrawRectangle(ItemRect);
+ end;
+
+ if lvppText in PaintPart then begin
+ if lisSelected in ItemState then Canvas.TextColor := clwhite;//Canvas.Color xor Canvas.Color;
+ for J := 0 to FColumns.Count -1 do begin;
+ if FColumns.Column[J].Visible then begin
+ if FColumns.Column[J].ColumnIndex <> -1 then
+ ColumnIndex := FColumns.Column[J].ColumnIndex
+ else ColumnIndex := J;
+ if ColumnIndex = 0 then
+ TheText := Item.Caption
+ else if item.SubItems.Count > ColumnIndex then
+ TheText := Item.SubItems.Strings[ColumnIndex-1]
+ else
+ TheText := '';
+
+ fpgStyle.DrawString(Canvas, ItemRect.Left+5, ItemRect.Top+2, TheText, Enabled);
+ Inc(ItemRect.Left, FColumns.Column[J].Width);
+ //WriteLn(ItemRect.Left,' ', ItemRect.Top, ' ', ItemRect.Right, ' ', ItemRect.Bottom);
+ end;
+ end;
+ end;
+ Canvas.TextColor := TextColor;
+ end;
+
+
+end;
+
+procedure TfpgListView.UpdateScrollBarPositions;
+var
+ BevelSize: Integer;
+ I: Integer;
+ MaxH,
+ MaxV: Integer;
+begin
+ MaxH := 0;
+ MaxV := 0;
+ BevelSize := 2;
+
+ for I := 0 to Columns.Count -1 do begin
+ if Columns.Column[I].Visible then
+ Inc(MaxH, Columns.Column[I].Width);
+ end;
+
+ MaxV := (FItems.Count+1) * 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
+ FVScrollBar.Top := BevelSize;
+ if ShowHeaders then FVScrollBar.Top := FVScrollBar.Top + HeaderHeight;
+ FVScrollBar.Left := Width - FVScrollBar.Width - (BevelSize );
+ FVScrollBar.Height := Height - FVScrollBar.Top - BevelSize;
+ end;
+
+ if FVScrollBar.Visible and FHScrollBar.Visible then begin
+ FHScrollBar.Width := FHScrollBar.Width - FVScrollBar.Width;
+ FVScrollBar.Height := FVScrollBar.Height - FHScrollBar.Height;
+ end;
+
+
+ FHScrollBar.Max := MaxH-(Width-(BevelSize * 2));
+ FVScrollBar.Max := MaxV;
+
+ FHScrollBar.UpdateWindowPosition;
+ FVScrollBar.UpdateWindowPosition;
+end;
+
+constructor TfpgListView.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ ShowHeaders := True;
+
+ FVScrollBar := TfpgScrollBar.Create(Self);
+ FVScrollBar.Orientation := orVertical;
+ FVScrollBar.OnScroll := @VScrollChange;
+ FVScrollBar.ScrollStep := 5;
+ FVScrollBar.Position := 0;
+
+ FHScrollBar := TfpgScrollBar.Create(Self);
+ FHScrollBar.Orientation := orHorizontal;
+ FHScrollBar.OnScroll := @HScrollChange;
+ FHScrollBar.ScrollStep := 5;
+ FHScrollBar.Position := 0;
+
+ FColumns := TfpgLVColumns.Create(Self);
+
+ FItems := TfpgLVItems.Create(Self);
+ FSelected := TList.Create;
+end;
+
+destructor TfpgListView.Destroy;
+begin
+ FItems.DeleteViewer(Self);
+ FSelected.Free;
+ inherited Destroy;
+end;
+
+procedure TfpgListView.BeginUpdate;
+begin
+ Inc(FUpdateCount);
+end;
+
+procedure TfpgListView.EndUpdate;
+begin
+ Dec(FUpdateCount);
+ if FUpdateCount < 0 then FUpdateCount := 0;
+ if FUpdateCount = 0 then DoRePaint;
+end;
+
+function TfpgListView.ItemAdd: TfpgLVItem;
+begin
+ Result := TfpgLVItem.Create(FItems);
+ FItems.Add(Result);
+end;
+
+{ TfpgLVColumns }
+
+function TfpgLVColumns.GetColumn(AIndex: Integer): TfpgLVColumn;
+begin
+ Result := TfpgLVColumn(FColumns.Items[AIndex]);
+end;
+
+procedure TfpgLVColumns.SetColumn(AIndex: Integer; const AValue: TfpgLVColumn);
+begin
+ FColumns.Items[AIndex] := AValue;
+end;
+
+constructor TfpgLVColumns.Create(AListView: TfpgListView);
+begin
+ FListView := AListView;
+ FColumns := TList.Create;
+end;
+
+destructor TfpgLVColumns.Destroy;
+begin
+ FColumns.Free;
+ inherited Destroy;
+end;
+
+function TfpgLVColumns.Add(AColumn: TfpgLVColumn): Integer;
+begin
+ Result := Count;
+ Insert(AColumn, Count);
+end;
+
+procedure TfpgLVColumns.Delete(AIndex: Integer);
+begin
+ FColumns.Delete(AIndex);
+end;
+
+procedure TfpgLVColumns.Insert(AColumn: TfpgLVColumn; AIndex: Integer);
+begin
+ FColumns.Insert(AIndex, AColumn);
+end;
+
+function TfpgLVColumns.Count: Integer;
+begin
+ Result := FColumns.Count;
+end;
+
+{ TfpgLVColumn }
+
+procedure TfpgLVColumn.SetCaption(const AValue: String);
+begin
+ if FCaption=AValue then exit;
+ FCaption:=AValue;
+end;
+
+procedure TfpgLVColumn.SetColumnIndex(const AValue: Integer);
+begin
+ if FColumnIndex=AValue then exit;
+ FColumnIndex:=AValue;
+end;
+
+procedure TfpgLVColumn.SetHeight(const AValue: Integer);
+begin
+ if FHeight=AValue then exit;
+ FHeight:=AValue;
+end;
+
+procedure TfpgLVColumn.SetVisible(const AValue: Boolean);
+begin
+ if FVisible=AValue then exit;
+ FVisible:=AValue;
+end;
+
+procedure TfpgLVColumn.SetAutoSize(const AValue: Boolean);
+begin
+ if FAutoSize=AValue then exit;
+ FAutoSize:=AValue;
+end;
+
+procedure TfpgLVColumn.SetWidth(const AValue: Integer);
+begin
+ if FWidth=AValue then exit;
+ FWidth:=AValue;
+end;
+
+constructor TfpgLVColumn.Create(AColumns: TfpgLVColumns);
+begin
+ FVisible := True;
+ FColumnIndex := -1;
+end;
+
+destructor TfpgLVColumn.Destroy;
+begin
+ inherited Destroy;
+end;
+
+end.
diff --git a/src/gui/gui_scrollbar.pas b/src/gui/gui_scrollbar.pas
index 67716276..56baa257 100644
--- a/src/gui/gui_scrollbar.pas
+++ b/src/gui/gui_scrollbar.pas
@@ -31,6 +31,9 @@ type
FOnScroll: TScrollNotifyEvent;
FPosition: integer;
FScrollStep: integer;
+ procedure SetMax(const AValue: integer);
+ procedure SetMin(const AValue: integer);
+ procedure SetPosition(const AValue: integer);
protected
FSliderPos: TfpgCoord;
FSliderLength: TfpgCoord;
@@ -57,10 +60,10 @@ type
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure RepaintSlider;
- property Position: integer read FPosition write FPosition default 10;
+ property Position: integer read FPosition write SetPosition default 10;
property ScrollStep: integer read FScrollStep write FScrollStep default 1;
- property Min: integer read FMin write FMin default 0;
- property Max: integer read FMax write FMax default 100;
+ property Min: integer read FMin write SetMin default 0;
+ property Max: integer read FMax write SetMax default 100;
property OnScroll: TScrollNotifyEvent read FOnScroll write FOnScroll;
end;
@@ -119,6 +122,27 @@ begin
DrawSlider(True);
end;
+procedure TfpgScrollBar.SetMax(const AValue: integer);
+begin
+ if AValue = FMax then Exit;
+ FMax := AValue;
+ if FPosition > FMax then SetPosition(FMax);
+end;
+
+procedure TfpgScrollBar.SetMin(const AValue: integer);
+begin
+ if AValue = FMin then Exit;
+ FMin := AValue;
+ if FPosition < FMin then SetPosition(FMin);
+end;
+
+procedure TfpgScrollBar.SetPosition(const AValue: integer);
+begin
+ if AValue < FMin then FPosition := FMin
+ else if AValue > FMax then FPosition := FMax
+ else FPosition := AValue;
+end;
+
procedure TfpgScrollBar.ScrollTimer(Sender: TObject);
begin
FScrollTimer.Interval := 25;
@@ -182,8 +206,11 @@ begin
FPosition := FMin;
FSliderLength := Trunc(area * SliderSize);
+ //FSliderLength := Trunc((width/area) * (fmax /area ));
if FSliderLength < 20 then
FSliderLength := 20;
+ if FSliderLength > area then
+ FSliderLength := area;
area := area - FSliderLength;
mm := FMax - FMin;
if mm = 0 then
@@ -323,7 +350,7 @@ begin
if newp <> FPosition then
begin
- FPosition := newp;
+ Position := newp;
if Assigned(FOnScroll) then
FOnScroll(self, FPosition);
end;