[lazarus] Questions about DB status
Andrew Johnson
acjgenius at earthlink.net
Sat Sep 13 09:00:28 EDT 2003
ah ok cool. I will look more shortly, but I have started a DataLink for
data-aware controls, I am looking at Jesus' dbgrid for examples on use
and using my old Delphi4 help files to try and make it as compatible as
possible. Once I get that "working" I will try and make a DBEdit based
around MaskEdit so we have something to use as a db navigator and an
edit. thats good enough for testing and we can start making sure the fcl
db backend is good enough fo all these backends like yours. Since this
is so low level we should make actual changes needed from delphi
dataset controls as minimal as possible, no more then from one version
of delphi to the next, so we will need to fill in the
appendrecord/insertrecord/insert, findnext/find etc routines, as well as
quite a few others( I think we may be missng a few as well as the
unimplimented ones). Once enough are working my dummy unfinished
texttable or your dxf table(if it can be compilied) can be used to
refine it further.
would you like to take my attatched dsnavigator and try and make it more
compatible with delphi's so it can be the lcl dbnavigator? it can
compile under both delphi and lazarus so you can test it and such in
delphi, with your existing stuff to compare and change. I removed the
resources so we will need images once it works from the glyphs, but I
hacked support for text in so it can have text and/or glyphs, and has
all text on my default(yes we will want localized resource string later
if we keep this as a feature).
Andrew
On Sat, 2003-09-13 at 08:27, Micha Nelissen wrote:
> Andrew Johnson wrote:
>
> > I want to get DB working in Lazarus, so I looked around in my old Delphi cruft and found a dsnavigator I wrote for some reason based on some freeware one out there. it looks a bit.... wierd and not DBNavigator compatible but it seems to work in delphi, and it can be compiled with pretty much no change in lazarus, so I figured I could start there and work forward by getting a base FieldDataLink and Edit based on MaskEdit and make a basic TextTable based on mylittlebase(which can compile with no changes whatsoever with fpc1.0.10 in delphi mode) however I discovered to my dismay that a good half of the functionality needed to implement a proper TDataset descendant has yet to be implemented. So my question would be this.. should I consider trying to get basic db aware controls "working" even though the backend dataset stuff is sorely lacking in some areas or should I try and get fcl dataset more complete(assuming I am capable). I have a texttable that sort of works in delphi
>
> b!
> > ut untill the missing functionality is taken care of in fcl it will be rather useless.
> >
> > comments ideas? people want to help?
>
> I am the author of TDbf: tdbf.sf.net which can read/write dbase files
> and read/write/use/search indexes (ndx,mdx). It now runs 'on' the VCL,
> it's a TDataSet descendant. Maybe that can be used as a backend. I never
> tried compiling it because the db-aware controls weren't present
> anyway...(sigh) and because there is much work to do on the win32
> interface too. But I am willing to help where possible.
>
> Regards,
>
> Micha.
>
>
>
>
>
>
> _________________________________________________________________
> To unsubscribe: mail lazarus-request at miraclec.com with
> "unsubscribe" as the Subject
> archives at http://www.lazarus.freepascal.org/mailarchives
unit dsnavigator;
{$IfDef FPC}
{$mode Delphi}{$H+}
{$EndIf}
interface
uses
SysUtils, Classes, Graphics, GraphType, Controls,Dialogs,
ExtCtrls, db, buttons;
Type BInt = 1..12;
const
DSBFirst : BInt = 1;
DSBPrior : BInt = 2;
DSBNext : BInt = 3;
DSBLast : BInt = 4;
DSBInsert : BInt = 5;
DSBDelete : BInt = 6;
DSBEdit : BInt = 7;
DSBPost : BInt = 8;
DSBCancel : BInt = 9;
DSBRefresh : BInt = 10;
DSBBookmark : BInt = 11;
DSBGotoBookmark : BInt = 12;
type
TDSButton = (ubFirst, ubPrior, ubNext, ubLast, ubInsert, ubDelete, ubEdit, ubPost,
ubCancel, ubRefresh, ubBookmark, ubGotoBookmark);
TDSButtons = Set of TDSButton;
TDSTypeInsert = (tiAppend, tiInsert);
TDSRefreshAction = (raRefresh, raCloseOpen);
TDSNavigator = class;
TDSDataLink = Class(TDataLink)
private
FNavigator: TDSNavigator;
protected
procedure EditingChanged; override;
procedure DataSetChanged; override;
procedure ActiveChanged; override;
public
constructor Create(ANav: TDSNavigator);
destructor Destroy; override;
end;
TDSNavButton = class(TSpeedButton)
private
FRepeatTimer: TTimer;
procedure TimerExpired(Sender: TObject);
protected
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
public
destructor Destroy; override;
end;
TButtonStrings = Array[1..12] of string;
TDSNavigator = class(TCustomPanel)
private
FLayout : TButtonLayout;
BM: TBookmark;
NavOwner: TComponent;
FDataSource: TDataSource;
VVisibleButtonCount: Integer;
VButtons: Array[1..12] of TDSNavButton;
VDataLink: TDSDataLink;
FFlat: Boolean;
resizing : boolean;
FCaptions : TButtonStrings;
FAfterClick : TNotifyEvent;
FConfirmDeleteString: String;
FOverrideFirstButton: TNotifyEvent;
FOverrideInsertButton: TNotifyEvent;
FOverrideCancelButton: TNotifyEvent;
FOverrideGotoBookmarkButton: TNotifyEvent;
FOverridePostButton: TNotifyEvent;
FOverrideBookmarkButton: TNotifyEvent;
FOverrideLastButton: TNotifyEvent;
FOverrideNextButton: TNotifyEvent;
FOverridePriorButton: TNotifyEvent;
FOverrideEditButton: TNotifyEvent;
FOverrideDeleteButton: TNotifyEvent;
FOverrideRefreshButton: TNotifyEvent;
FInsertType: TDSTypeInsert;
FRefreshAction: TDSRefreshAction;
FDeleteConfirmation: Boolean;
FVisibleButtons,
FButtonCaptions,
FButtonGlyphs: TDSButtons;
Procedure CreateButton(Num : integer);
Function GetCaptions(index: Bint) : string;
procedure SetDataSource(const Value: TDataSource);
procedure SetFlat(const Value: Boolean);
procedure SetDeleteConfirmation(const Value: Boolean);
procedure SetVisibleButtons(const Value: TDSButtons);
procedure SetButtonCaptions(const Value: TDSButtons);
procedure SetButtonGlyphs(const Value: TDSButtons);
procedure SetLayout(Value : TButtonLayout);
procedure SetCaptions(index: Bint; Value : string);
Procedure AftClick;
protected
procedure ButtonState;
public
procedure FirstClick(Sender: TObject);
procedure LastClick(Sender: TObject);
procedure PriorClick(Sender: TObject);
procedure NextClick(Sender: TObject);
procedure InsertClick(Sender: TObject);
procedure EditClick(Sender: TObject);
procedure DeleteClick(Sender: TObject);
procedure RefreshClick(Sender: TObject);
procedure PostClick(Sender: TObject);
procedure CancelClick(Sender: TObject);
procedure BookmarkClick(Sender: TObject);
procedure GotoBookmarkClick(Sender: TObject);
procedure Resize; override;
procedure Paint; override;
constructor Create(Owner: Tcomponent); Override;
destructor destroy; override;
property Captions[index : Bint] : string read GetCaptions write SetCaptions;
published
// Properties
property DeleteConfirmation: Boolean read FDeleteConfirmation write SetDeleteConfirmation;
property Align;
property Anchors;
property ConfirmDeleteString: String read FConfirmDeleteString write FConfirmDeleteString;
property Constraints;
property DataSource: TDataSource read FDataSource write SetDataSource;
property Enabled;
property Flat: Boolean read FFlat write SetFlat;
property InsertType: TDSTypeInsert read FInsertType write FInsertType
default tiInsert;
property ParentShowHint;
property PopupMenu;
property RefreshAction: TDSRefreshAction read FRefreshAction write FRefreshAction default raRefresh;
property ShowHint;
property TabOrder;
property TabStop;
property Visible;
property ButtonsLayout : TButtonLayout read FLayout write SetLayout;
property VisibleButtons: TDSButtons read FVisibleButtons write SetVisibleButtons default
[ubFirst, ubPrior, ubNext, ubLast, ubInsert, ubDelete,
ubEdit, ubPost, ubCancel, ubRefresh];
property ButtonCaptions: TDSButtons read FButtonCaptions
write SetButtonCaptions default [ubInsert, ubDelete,
ubEdit, ubPost, ubCancel, ubRefresh];
property ButtonGlyphs: TDSButtons read FButtonGlyphs
write SetButtonGlyphs default [ubFirst, ubPrior, ubNext,
ubLast, ubInsert, ubDelete, ubEdit, ubPost, ubCancel, ubRefresh];
// Standard Events
property AfterClick : TNotifyEvent read FAfterClick write FAfterClick;
property OnClick;
property OnDblClick;
property OnEnter;
property OnExit;
property OnResize;
// Override Events
property OverrideFirstButton: TNotifyEvent read FOverrideFirstButton write FOverrideFirstButton;
property OverridePriorButton: TNotifyEvent read FOverridePriorButton write FOverridePriorButton;
property OverrideNextButton: TNotifyEvent read FOverrideNextButton write FOverrideNextButton;
property OverrideLastButton: TNotifyEvent read FOverrideLastButton write FOverrideLastButton;
property OverrideInsertButton: TNotifyEvent read FOverrideInsertButton write FOverrideInsertButton;
property OverrideEditButton: TNotifyEvent read FOverrideEditButton write FOverrideEditButton;
property OverrideDeleteButton: TNotifyEvent read FOverrideDeleteButton write FOverrideDeleteButton;
property OverridePostButton: TNotifyEvent read FOverridePostButton write FOverridePostButton;
property OverrideCancelButton: TNotifyEvent read FOverrideCancelButton write FOverrideCancelButton;
property OverrideBookmarkButton: TNotifyEvent read FOverrideBookmarkButton write FOverrideBookmarkButton;
property OverrideGotoBookmarkButton: TNotifyEvent read FOverrideGotoBookmarkButton write FOverrideGotoBookmarkButton;
property OverrideRefreshButton: TNotifyEvent read FOverrideRefreshButton write FOverrideRefreshButton;
end;
procedure Register;
implementation
var BtnTypeName: array[1..12] of String = ('FIRST', 'PRIOR', 'NEXT',
'LAST', 'INSERT', 'DELETE', 'EDIT', 'POST', 'CANCEL', 'REFRESH', 'BOOKMARK', 'GOTOBOOKMARK');
BtnTypeCaption: array[1..12] of String = ('First', 'Prior', 'Next',
'Last', 'Insert', 'Delete', 'Edit', 'Post', 'Cancel', 'Refresh',
'Bookmark', 'Goto Bookmark');
const ButtonArray: Array[1..12] of TDSButton = (ubFirst, ubPrior, ubNext, ubLast, ubInsert, ubDelete, ubEdit, ubPost,
ubCancel, ubRefresh, ubBookmark, ubGotoBookmark);
procedure Register;
begin
RegisterComponents('Data Controls', [TDSNavigator]);
end;
{ TDSDataLink }
procedure TDSDataLink.ActiveChanged;
begin
if FNavigator <> nil then
FNavigator.ButtonState;
end;
constructor TDSDataLink.Create(ANav: TDSNavigator);
begin
inherited Create;
FNavigator := ANav;
VisualControl := True;
end;
procedure TDSDataLink.DataSetChanged;
begin
if FNavigator <> nil then
FNavigator.ButtonState;
end;
destructor TDSDataLink.Destroy;
begin
FNavigator := nil;
inherited Destroy;
end;
procedure TDSDataLink.EditingChanged;
begin
if FNavigator <> nil then
FNavigator.ButtonState;
end;
{TDSNavButton}
destructor TDSNavButton.Destroy;
begin
if FRepeatTimer <> nil then
FRepeatTimer.Free;
inherited Destroy;
end;
procedure TDSNavButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited MouseDown (Button, Shift, X, Y);
if FRepeatTimer = nil then
FRepeatTimer := TTimer.Create(nil);
FRepeatTimer.OnTimer := TimerExpired;
FRepeatTimer.Interval := 400;
FRepeatTimer.Enabled := True;
end;
procedure TDSNavButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited MouseUp (Button, Shift, X, Y);
if FRepeatTimer <> nil then begin
FRepeatTimer.Enabled := False;
FRepeatTimer.Free;
FRepeatTimer := nil;
end;
end;
procedure TDSNavButton.TimerExpired(Sender: TObject);
begin
FRepeatTimer.Interval := 100;
if (FState = bsDown) and MouseCapture then
begin
try
Click;
except
if FRepeatTimer <> nil then begin
FRepeatTimer.Enabled := False;
FRepeatTimer.Free;
FRepeatTimer := nil;
end;
raise;
end;
end;
end;
{ TDSNavigator }
Procedure TDSNavigator.AftClick;
begin
if Assigned(FAfterClick) then
FAfterClick(Self);
end;
procedure TDSNavigator.SetCaptions(index: BInt; Value : string);
begin
FCaptions[Index] := Value;
SetButtonCaptions(FButtonCaptions);
end;
Function TDSNavigator.GetCaptions(index: Bint) : string;
begin
Result := FCaptions[Index];
end;
procedure TDSNavigator.SetLayout(Value : TButtonLayout);
var
I : integer;
begin
FLayout := Value;
For I := 1 to 12 do
If VButtons[i] <> nil then
VButtons[i].Layout := Value;
repaint;
end;
procedure TDSNavigator.SetButtonCaptions(const Value: TDSButtons);
var
I : integer;
begin
FButtonCaptions := Value;
For I := 1 to 12 do
If VButtons[I] <> nil then
If (ButtonArray[I] in Value) then begin
VButtons[I].Caption := Captions[I];
VButtons[i].Hint := Captions[I];
end
else
VButtons[I].Caption := '';
repaint;
end;
procedure TDSNavigator.SetButtonGlyphs(const Value: TDSButtons);
var
I : integer;
begin
{ FButtonGlyphs := Value;
For I := 1 to 12 do
If (ButtonArray[I] in Value) then
If VButtons[I] <> nil then
VButtons[I].Glyph.LoadFromResourceName(HInstance,
'unb_' + BtnTypeName[I]);
repaint;}
end;
constructor TDSNavigator.Create(Owner: TComponent);
var
i: Integer;
begin
inherited Create(Owner);
NavOwner := Owner;
FConfirmDeleteString := 'Delete this record?';
VDataLink := TDSDataLink.Create(Self);
FDeleteConfirmation := True;
Caption := ' ';
FInsertType := tiInsert;
FVisibleButtons := [ubFirst, ubPrior, ubNext, ubLast, ubInsert, ubDelete,
ubEdit, ubPost, ubCancel, ubRefresh];
FButtonGlyphs := [];//no lcl glyphs yet so turn this off for now
FButtonCaptions := FVisibleButtons;// and turn this on
for I := 1 to 12 do
FCaptions[I] := BtnTypeCaption[I];
for i := 1 to 12 do
CreateButton(I);
VVisibleButtonCount := 12;
SetVisibleButtons(FVisibleButtons);
ButtonState;
end;
destructor TDSNavigator.destroy;
var
i: Integer;
begin
VDataLink.Free;
for i := 1 to 12 do
if Assigned(VButtons[i]) then
VButtons[i].Free;
inherited;
end;
procedure TDSNavigator.DeleteClick(Sender: TObject);
var
S: String;
begin
Click;
if Assigned(FOverrideDeleteButton) then
OverrideDeleteButton(Self)
else begin
if FDeleteConfirmation then begin
if FConfirmDeleteString = '' then
S := 'Delete this record?'
else
S := FConfirmDeleteString;
if MessageDlg(S, mtConfirmation, [mbYes, mbNo], 0) = mrYes
then
DataSource.DataSet.Delete;
end
else
DataSource.DataSet.Delete;
end;
AftClick;
ButtonState;
end;
procedure TDSNavigator.InsertClick(Sender: TObject);
begin
Click;
if Assigned(FOverrideInsertButton) then
OverrideInsertButton(Self)
else
if FInsertType = tiAppend then
DataSource.DataSet.Append
else
DataSource.DataSet.Insert;
AftClick;
ButtonState;
end;
procedure TDSNavigator.BookmarkClick(Sender: TObject);
begin
Click;
if Assigned(FOverrideBookmarkButton) then
OverrideBookmarkButton(Self)
else
Bm := DataSource.DataSet.GetBookmark;
AftClick;
ButtonState;
end;
procedure TDSNavigator.CancelClick(Sender: TObject);
begin
Click;
if Assigned(FOverrideCancelButton) then
OverrideCancelButton(Self)
else
DataSource.DataSet.Cancel;
AftClick;
ButtonState;
end;
procedure TDSNavigator.EditClick(Sender: TObject);
begin
Click;
if Assigned(FOverrideEditButton) then
OverrideEditButton(Self)
else
DataSource.DataSet.Edit;
AftClick;
ButtonState;
end;
procedure TDSNavigator.FirstClick(Sender: TObject);
begin
Click;
if Assigned(FOverrideFirstButton) then
OverrideFirstButton(Self)
else
DataSource.DataSet.First;
AftClick;
ButtonState;
end;
procedure TDSNavigator.GotoBookmarkClick(Sender: TObject);
begin
Click;
if Assigned(FOverrideGotoBookmarkButton) then
OverrideGotoBookmarkButton(Self)
else begin
DataSource.DataSet.GotoBookmark(BM);
DataSource.DataSet.FreeBookmark(BM);
bm := nil;
end;
AftClick;
ButtonState;
end;
procedure TDSNavigator.LastClick(Sender: TObject);
begin
Click;
if Assigned(FOverrideLastButton) then
OverrideLastButton(Self)
else
DataSource.DataSet.Last;
AftClick;
ButtonState;
end;
procedure TDSNavigator.NextClick(Sender: TObject);
begin
Click;
if Assigned(FOverrideNextButton) then
OverrideNextButton(Self)
else
DataSource.DataSet.Next;
AftClick;
ButtonState;
end;
procedure TDSNavigator.PriorClick(Sender: TObject);
begin
Click;
if Assigned(FOverridePriorButton) then
OverridePriorButton(Self)
else
DataSource.DataSet.Prior;
AftClick;
ButtonState;
end;
procedure TDSNavigator.RefreshClick(Sender: TObject);
var
rec : integer;
begin
Click;
if Assigned(FOverrideRefreshButton) then
OverrideRefreshButton(Self)
else
if FRefreshAction = raRefresh then
DataSource.DataSet.Refresh
else begin
rec := DataSource.DataSet.RecNo;
DataSource.DataSet.Close;
DataSource.DataSet.Open;
DataSource.DataSet.RecNo := rec;
end;
AftClick;
ButtonState;
end;
procedure TDSNavigator.PostClick(Sender: TObject);
begin
Click;
if Assigned(FOverridePostButton) then
OverridePostButton(Self)
else
DataSource.DataSet.Post;
AftClick;
ButtonState;
end;
procedure TDSNavigator.Paint;
begin
inherited;
if not resizing then begin
resizing := true;
Resize;
end;
end;
procedure TDSNavigator.Resize;
var
H, W, ButWidth, i, btnLeft: Integer;
begin
inherited;
H := Self.Height;
W := Self.Width;
ButWidth := 25;
if (W <= 0) then
w := 100;
if VVisibleButtonCount >0 then
ButWidth := (W div VVisibleButtonCount);
btnLeft := 0;
for i := 1 to 12 do
begin
If VButtons[I] <> nil then begin
if VButtons[i].Visible then begin
VButtons[i].Parent := self;
VButtons[i].SetBounds(btnLeft, 0, ButWidth, H);
btnLeft := btnLeft + ButWidth;
end
else
VButtons[i].Parent := nil;
VButtons[i].Tag := i;
end;
end;
for i := 12 downto 1 do
begin
If VButtons[I] <> nil then begin
if VButtons[i].Visible then
begin
VButtons[i].Width := VButtons[i].Width + (W - (ButWidth * VVisibleButtonCount));
break;
end;
end;
end;
Repaint
end;
procedure TDSNavigator.ButtonState;
var
I : integer;
EOF,BOF : Boolean;
State,
AllInActive: Boolean;
begin
AllInActive := False;
if not Assigned(VDataLink.DataSource) then
begin
State := False;
AllInactive := True;
end
else begin
if not Assigned(VDataLink.DataSource.Dataset) then
begin
State := False;
AllInactive := True;
end
else begin
if not VDataLink.DataSource.Dataset.Active then
begin
State := False;
AllInactive := True;
end
else
State := (VDataLink.DataSource.DataSet.State = dsBrowse);
end;
end;
if AllInActive then begin
For I := 1 to 12 do
if VButtons[I] <> nil then
VButtons[I].Enabled := False;
end
else begin
EOF := (DataSource.DataSet.EOF) or
((DataSource.DataSet.RecNo >=
DataSource.DataSet.RecordCount) and not
DataSource.DataSet.Filtered);
BOF := (((DataSource.DataSet.BOF) or{
(DataSource.DataSet.RecNO <= 1)) or}
(DataSource.DataSet.RecordCount <= 1)));
For I := 1 to 2 do
If VButtons[I] <> nil then
VButtons[I].Enabled := (not Bof) and (State or
VDataLink.DataSource.AutoEdit);
For I := 3 to 4 do
If VButtons[I] <> nil then
VButtons[I].Enabled := (not EOF) and (State or
VDataLink.DataSource.AutoEdit);
For I := 5 to 7 do
If VButtons[I] <> nil then
VButtons[I].Enabled := State and (not VDataLink.DataSource.AutoEdit);
For I := 8 to 9 do
If VButtons[I] <> nil then
VButtons[I].Enabled := (not State) or (VDataLink.DataSource.AutoEdit);
If VButtons[10] <> nil then
VButtons[10].Enabled := State and (not VDataLink.DataSource.AutoEdit);
If VButtons[11] <> nil then
VButtons[11].Enabled := State;
If VButtons[12] <> nil then
VButtons[12].Enabled := State and Assigned(BM);
end;
SetButtonCaptions(FButtonCaptions);
end;
procedure TDSNavigator.SetDataSource(const Value: TDataSource);
begin
FDataSource := Value;
if not Assigned(FDataSource) then
Exit;
VDataLink.DataSource := FDataSource;
ButtonState;
end;
procedure TDSNavigator.SetFlat(const Value: Boolean);
var
i: Integer;
begin
FFlat := Value;
for i := 1 to 12 do
If VButtons[i] <> nil then
VButtons[i].Flat := FFlat;
if value then
BevelOuter := bvNone
else
BevelOuter := bvRaised;
end;
procedure TDSNavigator.SetDeleteConfirmation(const Value: Boolean);
begin
FDeleteConfirmation := Value;
end;
procedure TDSNavigator.SetVisibleButtons(const Value: TDSButtons);
var
I: Integer;
begin
FVisibleButtons := Value;
VVisibleButtonCount := 0;
for i := 1 to 12 do begin
If VButtons[i] <> nil then begin
VButtons[i].Visible := (ButtonArray[i] in FVisibleButtons);
if VButtons[i].Visible then
VVisibleButtonCount := VVisibleButtonCount + 1
else begin
VButtons[i].Free;
VButtons[i] := nil;
end;
end
else begin
If (ButtonArray[i] in FVisibleButtons) then
CreateButton(I);
end;
end;
Resize;
SetButtonCaptions(FButtonCaptions);
SetButtonGlyphs(FButtonGlyphs);
SetLayout(FLayout);
end;
Procedure TDSNavigator.CreateButton(Num : integer);
begin
VButtons[Num] := TDSNavButton.Create(Self);
with VButtons[Num] do begin
Hint := Captions[Num];
Caption := '';
Flat := FFlat;
Parent := Self;
NumGlyphs := 2;
Transparent := True;
layout := FLayout;
Tag := Num;
Case Num of
1:onClick := FirstClick;
2:onClick := PriorClick;
3:onClick := NextClick;
4:onClick := LastClick;
5:onClick := InsertClick;
6:onClick := DeleteClick;
7:onClick := EditClick;
8:onClick := PostClick;
9:onClick := CancelClick;
10:onClick := RefreshClick;
11:onClick := BookmarkClick;
12:onClick := GotoBookmarkClick;
end;
end;
end;
end.
More information about the Lazarus
mailing list