|
From: <na...@us...> - 2009-08-20 09:27:21
|
Revision: 855
http://instantobjects.svn.sourceforge.net/instantobjects/revision/?rev=855&view=rev
Author: nandod
Date: 2009-08-20 09:27:11 +0000 (Thu, 20 Aug 2009)
Log Message:
-----------
* InstantExplorer enhancements:
* use checkboxes for boolean fields
* use comboboxes for string fields if an event handler provides a picklist.
* ability to order fields and hide specific fields in the object editor through an event.
* Automatic labels from CamelCaps property names.
Modified Paths:
--------------
trunk/Source/Core/InstantExplorer.pas
Modified: trunk/Source/Core/InstantExplorer.pas
===================================================================
--- trunk/Source/Core/InstantExplorer.pas 2009-08-20 09:23:30 UTC (rev 854)
+++ trunk/Source/Core/InstantExplorer.pas 2009-08-20 09:27:11 UTC (rev 855)
@@ -46,7 +46,7 @@
{$IFDEF LINUX}
QControls, QForms, QComCtrls, QExtCtrls, QDBGrids, QImgList,
{$ENDIF}
- Classes, Db, InstantPersistence, InstantPresentation;
+ Classes, DB, TypInfo, InstantPersistence, InstantPresentation, DbCtrls;
type
TInstantExplorer = class;
@@ -87,13 +87,45 @@
const Value: string; var NodeData: TInstantExplorerNodeData) of object;
TInstantExplorerGetNodeTextEvent = procedure(Sender: TInstantExplorer;
NodeData: TInstantExplorerNodeData; var Text: string) of object;
-
+ TInstantExplorerGetAllowedValuesEvent = procedure (Sender: TInstantExplorer;
+ const AObject: TObject; const APropName: string;
+ const AAllowedValues: TStrings) of object;
+ TInstantExplorerGetFieldNamesEvent = procedure (Sender: TInstantExplorer;
+ const AObject: TObject; const AFieldNames: TStrings) of object;
+
TInstantExplorerLayout = (loTreeOnly, loDetailOnly, loVertical, loHorizontal);
+ TInstantExplorerDBComboBox = class(TDBComboBox)
+ private
+ procedure ApplyToRecord;
+ protected
+ procedure Change; override;
+ procedure Click; override;
+ end;
+
+ TInstantExplorerDBGrid = class(TDBGrid)
+ private
+ procedure UpdateLastColumnWidth;
+ protected
+ procedure Resize; override;
+ end;
+
+ TInstantExplorerContentEditor = class(TPanel)
+ private
+ FGrid: TInstantExplorerDBGrid;
+ function GetDataSource: TDataSource;
+ procedure SetDataSource(const AValue: TDataSource);
+ function GetGrid: TDBGrid;
+ public
+ constructor Create(AOwner: TComponent); override;
+ property Grid: TDBGrid read GetGrid;
+ property DataSource: TDataSource read GetDataSource write SetDataSource;
+ end;
+
TInstantExplorer = class(TCustomControl)
private
FAutoAdjust: Boolean;
- FContentEditor: TDBGrid;
+ FContentEditor: TInstantExplorerContentEditor;
FContentView: TPanel;
FDetailPanel: TPanel;
FDetailView: TPanel;
@@ -115,6 +147,8 @@
FOnGetImageIndex: TInstantExplorerNodeEvent;
FOnGetNodeText: TInstantExplorerGetNodeTextEvent;
FOnIncludeNode: TInstantExplorerIncludeNodeEvent;
+ FOnGetAllowedValues: TInstantExplorerGetAllowedValuesEvent;
+ FOnGetFieldNames: TInstantExplorerGetFieldNamesEvent;
function AddNode(NodeType: TInstantExplorerNodeType; Parent: TTreeNode;
Name: string; AObject: TObject; Value: string = ''): TTreeNode;
procedure ArrangeControls;
@@ -130,12 +164,15 @@
procedure DestroyObjectEditor;
procedure ExpandNode(Node: TTreeNode);
function GetCurrentObject: TObject;
+ procedure GetAllowedValues(const AObject: TObject;
+ const APropName: string; const AAllowedValues: TStrings);
function GetImages: TCustomImageList;
procedure LoadContainerNode(Node: TTreeNode; Container: TInstantContainer);
procedure LoadNode(Node: TTreeNode; LoadChildren: Boolean);
procedure LoadObjectNode(Node: TTreeNode; Instance: TObject;
var ChildCount: Integer; LoadChildren: Boolean);
function NodeIsLoaded(Node: TTreeNode): Boolean;
+ procedure ObjectExposerAfterDelete(Sender: TDataSet);
procedure ObjectExposerAfterPost(Sender: TDataSet);
procedure ResizeControls;
procedure SetAutoAdjust(const Value: Boolean);
@@ -146,10 +183,13 @@
var AllowExpansion: Boolean);
procedure TreeViewGetImageIndex(Sender: TObject; Node: TTreeNode);
procedure TreeViewNodeDeletion(Sender: TObject; Node: TTreeNode);
+ procedure SetCurrentObject(const AValue: TObject);
+ function GetContentEditor: TWinControl;
+ function CreateFieldList: TStrings;
protected
procedure ChangeNode(Node: TTreeNode); virtual;
function CreateContentEditor(AOwner: TComponent;
- DataSource: TDataSource): TDBGrid; virtual;
+ DataSource: TDataSource): TInstantExplorerContentEditor; virtual;
function CreateExposer: TInstantExposer; virtual;
function CreateNode(Nodes: TTreeNodes; Parent: TTreeNode;
NodeData: TInstantExplorerNodeData): TTreeNode; virtual;
@@ -170,13 +210,15 @@
procedure SetRootObject(const Value: TObject); virtual;
procedure UpdateDetails;
public
+ procedure SetupContentEditor;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Clear;
procedure Refresh;
procedure RefreshNode(Node: TTreeNode);
+ property ContentEditor: TWinControl read GetContentEditor;
property ContentView: TPanel read FContentView;
- property CurrentObject: TObject read GetCurrentObject;
+ property CurrentObject: TObject read GetCurrentObject write SetCurrentObject;
property DetailPanel: TPanel read FDetailPanel;
property DetailView: TPanel read FDetailView write SetDetailView;
property ObjectExposer: TInstantExposer read FObjectExposer;
@@ -206,6 +248,10 @@
property OnCreateNodeData: TInstantExplorerCreateNodeDataEvent read FOnCreateNodeData write FOnCreateNodeData;
property OnClick;
property OnDblClick;
+ property OnGetAllowedValues: TInstantExplorerGetAllowedValuesEvent
+ read FOnGetAllowedValues write FOnGetAllowedValues;
+ property OnGetFieldNames: TInstantExplorerGetFieldNamesEvent
+ read FOnGetFieldNames write FOnGetFieldNames;
property OnGetImageIndex: TInstantExplorerNodeEvent read FOnGetImageIndex write FOnGetImageIndex;
property OnGetNodeText: TInstantExplorerGetNodeTextEvent read FOnGetNodeText write FOnGetNodeText;
property OnIncludeNode: TInstantExplorerIncludeNodeEvent read FOnIncludeNode write FOnIncludeNode;
@@ -220,10 +266,10 @@
implementation
uses
- SysUtils, InstantClasses, InstantRtti, TypInfo, InstantMetadata,
+ SysUtils, Math, InstantClasses, InstantRtti, InstantMetadata,
InstantTypes,
{$IFDEF MSWINDOWS}
- Graphics, StdCtrls, DbCtrls, Windows;
+ Graphics, StdCtrls, Windows;
{$ENDIF}
{$IFDEF LINUX}
QGraphics, QStdCtrls, QDbCtrls;
@@ -232,6 +278,8 @@
const
NotLoaded = Pointer(-1);
+ MAX_DROPDOWN_ITEMS = 10;
+
procedure InstantExploreObject(AObject: TObject);
var
Form: TForm;
@@ -261,6 +309,28 @@
end;
end;
+// Converts CamelCaps to words with spaces among them.
+function Beautify(const APropName: string): string;
+var
+ LCharIndex: Integer;
+ LLastWasSpace: Boolean;
+begin
+ Result := '';
+ LLastWasSpace := False;
+ for LCharIndex := 1 to Length(APropName) do
+ begin
+ if (APropName[LCharIndex] = AnsiUpperCase(APropName[LCharIndex])[1]) and not LLastWasSpace then
+ begin
+ Result := Result + ' ';
+ LLastWasSpace := True;
+ end
+ else
+ LLastWasSpace := False;
+ Result := Result + APropName[LCharIndex];
+ end;
+end;
+
+
{ TInstantExplorerNodeData }
constructor TInstantExplorerNodeData.Create(ANodeType: TInstantExplorerNodeType;
@@ -394,21 +464,19 @@
procedure TInstantExplorer.AssignRootObject(Value: TObject);
var
Node: TTreeNode;
- ItemIndex: Integer;
+ LCurrentObject: TObject;
SaveOnChange: TTVChangedEvent;
ChildCount: Integer;
-
begin
- ItemIndex := 0;
+ LCurrentObject := nil;
with TreeView do
begin
SaveOnChange := OnChange;
OnChange := nil;
Items.BeginUpdate;
try
-
if Assigned(Selected) then
- ItemIndex := Selected.AbsoluteIndex;
+ LCurrentObject := TinstantExplorerNodeData(Selected.Data).Instance;
Items.Clear;
FRootObject := Value;
if Assigned(FRootObject) then
@@ -427,12 +495,8 @@
finally
Items.EndUpdate;
OnChange := SaveOnChange;
- if Items.Count > ItemIndex then
- Selected := Items[ItemIndex]
- else begin
- Selected := nil;
- TreeViewChange(TreeView, nil);
- end;
+ CurrentObject := LCurrentObject;
+ TreeView.FullExpand;
end;
end;
end;
@@ -466,26 +530,22 @@
end;
function TInstantExplorer.CreateContentEditor(AOwner: TComponent;
- DataSource: TDataSource): TDBGrid;
-var
- Grid: TDBGrid;
+ DataSource: TDataSource): TInstantExplorerContentEditor;
begin
- Grid := TDBGrid.Create(AOwner);
- Grid.DataSource := DataSource;
- Grid.BorderStyle := bsNone;
- Result := Grid;
+ Result := TInstantExplorerContentEditor.Create(AOwner);
+ Result.DataSource := DataSource;
end;
procedure TInstantExplorer.CreateContentView;
begin
FContentView := CreatePanel(Self);
+ FContentView.Parent := DetailPanel;
FContentEditor := CreateContentEditor(FContentView, ObjectSource);
if Assigned(FContentEditor) then
with FContentEditor do
begin
Align := alClient;
Parent := FContentView;
- Show;
end;
end;
@@ -494,6 +554,7 @@
FDetailPanel := CreatePanel(Self);
with FDetailPanel do
begin
+ Parent := Self;
BorderStyle := bsSingle;
Height := Self.Height div 2;
Align := alClient;
@@ -545,74 +606,170 @@
function TInstantExplorer.CreateObjectEditor(AOwner: TComponent;
DataSource: TDataSource): TControl;
+const
+ LABEL_WIDTH = 132;
+ LABEL_LEFT = 8;
+ VERT_SPACING = 4;
+ MIN_CONTROL_WIDTH = 24;
procedure CreateEditControl(AParent: TWinControl; var ATop: Integer;
PropInfo: PPropInfo; ADataSource: TDataSource);
var
- Edit: TDBEdit;
+ LControl: TWinControl;
+ LAllowedValues: TStrings;
begin
- Edit := TDBEdit.Create(AParent);
- with Edit do
- begin
- Left := 108;
- Top := ATop;
- Anchors := [akLeft, akTop, akRight];
- Constraints.MinWidth := 8;
- Width := AParent.Width - Left - 8;
- Anchors := [akLeft, akTop, akRight];
- Parent := AParent;
- DataField := InstantGetPropName(PropInfo);
- DataSource := ADataSource;
- if not Assigned(PropInfo.SetProc) then
+ case DataSource.DataSet.FieldByName(InstantGetPropName(PropInfo)).DataType of
+ ftMemo:
begin
- ReadOnly := True;
- Color := clBtnFace;
+ LControl := TDBMemo.Create(AParent);
+ with TDBMemo(LControl) do
+ begin
+ Left := LABEL_LEFT + LABEL_WIDTH;
+ Top := ATop;
+ Anchors := [akLeft, akTop, akRight];
+ Constraints.MinWidth := MIN_CONTROL_WIDTH;
+ Parent := AParent;
+ Anchors := [akLeft, akTop, akRight];
+ Width := Parent.Width - Left - 8;
+ DataField := InstantGetPropName(PropInfo);
+ DataSource := ADataSource;
+ if not Assigned(PropInfo.SetProc) then
+ begin
+ ReadOnly := True;
+ Color := clBtnFace;
+ end;
+ end;
end;
+ ftBoolean:
+ begin
+ LControl := TDBCheckBox.Create(AParent);
+ with TDBCheckBox(LControl) do
+ begin
+ Left := LABEL_LEFT + LABEL_WIDTH;
+ Top := ATop;
+ Width := 16;
+ Parent := AParent;
+ DataField := InstantGetPropName(PropInfo);
+ DataSource := ADataSource;
+ if not Assigned(PropInfo.SetProc) then
+ begin
+ ReadOnly := True;
+ Color := clBtnFace;
+ end;
+ end;
+ end
+ else
+ begin
+ LAllowedValues := TStringList.Create;
+ try
+ GetAllowedValues(ObjectExposer.CurrentObject, InstantGetPropName(PropInfo), LAllowedValues);
+ if LAllowedValues.Count > 0 then
+ begin
+ LControl := TInstantExplorerDBComboBox.Create(AParent);
+ with TInstantExplorerDBComboBox(LControl) do
+ begin
+ Left := LABEL_LEFT + LABEL_WIDTH;
+ Top := ATop;
+ Anchors := [akLeft, akTop, akRight];
+ Constraints.MinWidth := MIN_CONTROL_WIDTH;
+ Width := AParent.Width - Left - 8;
+ Anchors := [akLeft, akTop, akRight];
+ Parent := AParent;
+ Items := LAllowedValues;
+ Style := csDropDownList;
+ DataField := InstantGetPropName(PropInfo);
+ DataSource := ADataSource;
+ if not Assigned(PropInfo.SetProc) then
+ begin
+ ReadOnly := True;
+ Color := clBtnFace;
+ end;
+ end;
+ end
+ else
+ begin
+ LControl := TDBEdit.Create(AParent);
+ with TDBEdit(LControl) do
+ begin
+ Left := LABEL_LEFT + LABEL_WIDTH;
+ Top := ATop;
+ Anchors := [akLeft, akTop, akRight];
+ Constraints.MinWidth := MIN_CONTROL_WIDTH;
+ Width := AParent.Width - Left - 8;
+ Anchors := [akLeft, akTop, akRight];
+ Parent := AParent;
+ DataField := InstantGetPropName(PropInfo);
+ DataSource := ADataSource;
+ if not Assigned(PropInfo.SetProc) then
+ begin
+ ReadOnly := True;
+ Color := clBtnFace;
+ end;
+ end;
+ end;
+ finally
+ FreeAndNil(LAllowedValues);
+ end;
+ end;
end;
+
with TLabel.Create(AParent) do
begin
- Left := 8;
+ Left := LABEL_LEFT;
Top := ATop + 3;
Parent := AParent;
- Caption := InstantGetPropName(PropInfo);
- FocusControl := Edit;
+ Caption := Beautify(InstantGetPropName(PropInfo));
+ FocusControl := LControl;
end;
- Inc(ATop, Edit.Height);
+ Inc(ATop, LControl.Height);
end;
var
I, Top: Integer;
AObject: TObject;
Editor: TScrollBox;
+ LProperties: TInstantProperties;
+ LFieldNames: TStrings;
+ LFieldIndex: Integer;
begin
Editor := TScrollBox.Create(AOwner);
with Editor do
begin
BorderStyle := bsNone;
Align := alClient;
+ Parent := ObjectView;
end;
AObject := ObjectExposer.CurrentObject;
- Top := 4;
- with TInstantProperties.Create(AObject) do
+ Top := VERT_SPACING;
+ LProperties := TInstantProperties.Create(AObject);
try
- for I := 0 to Pred(Count) do
- if Types[I] <> tkClass then
+ LFieldNames := CreateFieldList;
+ try
+ for LFieldIndex := 0 to LFieldNames.Count - 1 do
begin
- Inc(Top, 4);
- CreateEditControl(Editor, Top, PropInfos[I], DataSource);
+ for I := 0 to Pred(LProperties.Count) do
+ begin
+ if (LProperties.Types[I] <> tkClass) and (LProperties.Names[I] = LFieldNames[LFieldIndex]) then
+ begin
+ Inc(Top, VERT_SPACING);
+ CreateEditControl(Editor, Top, LProperties.PropInfos[I], DataSource);
+ end;
+ end;
end;
+ finally
+ LFieldNames.Free;
+ end;
finally
- Free;
+ LProperties.Free;
end;
- Editor.Parent := ObjectView;
Result := Editor;
end;
procedure TInstantExplorer.CreateObjectExposer;
begin
FObjectExposer := CreateExposer;
- if Assigned(FObjectExposer) then
- FObjectExposer.AfterPost := ObjectExposerAfterPost;
+ FObjectExposer.AfterPost := ObjectExposerAfterPost;
+ FObjectExposer.AfterDelete := ObjectExposerAfterDelete;
FObjectSource := TDataSource.Create(Self);
FObjectSource.DataSet := FObjectExposer;
end;
@@ -620,6 +777,7 @@
procedure TInstantExplorer.CreateObjectView;
begin
FObjectView := CreatePanel(Self);
+ FObjectView.Parent := DetailPanel;
end;
function TInstantExplorer.CreatePanel(AOwner: TComponent): TPanel;
@@ -634,6 +792,9 @@
FSplitter := TSplitter.Create(Self);
with FSplitter do
begin
+ Parent := Self;
+ AutoSnap := False;
+ MinSize := 30;
Top := FTreePanel.Top + FTreePanel.Height + 1;
Align := alTop;
end;
@@ -644,6 +805,7 @@
FTreePanel := CreatePanel(Self);
with FTreePanel do
begin
+ Parent := Self;
Align := alTop;
FTreeView := CreateTreeView(FTreePanel);
with FTreeView do
@@ -689,6 +851,18 @@
LoadNode(Node, True);
end;
+procedure TInstantExplorer.GetAllowedValues(const AObject: TObject;
+ const APropName: string; const AAllowedValues: TStrings);
+begin
+ if Assigned(FOnGetAllowedValues) then
+ FOnGetAllowedValues(Self, AObject, APropName, AAllowedValues);
+end;
+
+function TInstantExplorer.GetContentEditor: TWinControl;
+begin
+ Result := FContentEditor;
+end;
+
function TInstantExplorer.GetCurrentObject: TObject;
begin
with TreeView do
@@ -855,9 +1029,14 @@
procedure TInstantExplorer.ObjectExposerAfterPost(Sender: TDataSet);
begin
- RefreshNode(TreeView.Selected);
+ Refresh;
end;
+procedure TInstantExplorer.ObjectExposerAfterDelete(Sender: TDataSet);
+begin
+ Refresh;
+end;
+
procedure TInstantExplorer.Refresh;
begin
AssignRootObject(FRootObject);
@@ -902,21 +1081,32 @@
end;
end;
+procedure TInstantExplorer.SetCurrentObject(const AValue: TObject);
+var
+ LNodeIndex: Integer;
+begin
+ for LNodeIndex := 0 to TreeView.Items.Count - 1 do
+ begin
+ if Integer(TreeView.Items[LNodeIndex].Data) > 0 then
+ if TInstantExplorerNodeData(TreeView.Items[LNodeIndex].Data).Instance = AValue then
+ begin
+ TreeView.Selected := TreeView.Items[LNodeIndex];
+ Break;
+ end;
+ end;
+end;
+
procedure TInstantExplorer.SetDetailView(const Value: TPanel);
begin
if Value <> FDetailView then
begin
if Assigned(FDetailView) then
- begin
- FDetailView.Hide;
- FDetailView.Parent := nil;
- end;
+ FDetailView.Visible := False;
FDetailView := Value;
if Assigned(FDetailView) then
begin
FDetailView.Align := alClient;
- FDetailView.Parent := DetailPanel;
- FDetailView.Show;
+ FDetailView.Visible := True;
end;
end;
end;
@@ -1007,7 +1197,9 @@
ObjectExposer.ContainerName := Container.Name;
ObjectExposer.Subject := Container.Owner;
DetailView := ContentView;
- end else if Assigned(AObject) then
+ SetupContentEditor;
+ end
+ else if Assigned(AObject) then
begin
if AObject.ClassType <> ObjectExposer.ObjectClass then
DestroyObjectEditor;
@@ -1023,6 +1215,156 @@
ObjectExposer.Subject := nil;
DetailView := nil;
end;
+ // Reduces a treeview painting problem in D2007 with runtime themes enabled
+ // and checkboxes in the object editor.
+ Update;
end;
+procedure TInstantExplorer.SetupContentEditor;
+var
+ LColumnIndex: Integer;
+ LField: TField;
+ LFieldNames: TStrings;
+ LFieldIndex: Integer;
+
+begin
+ // Arrange columns.
+ LFieldNames := CreateFieldList;
+ try
+ FContentEditor.Grid.Columns.Clear;
+ for LFieldIndex := 0 to LFieldNames.Count - 1 do
+ with FContentEditor.Grid.Columns.Add do
+ begin
+ FieldName := LFieldNames[LFieldIndex];
+ Width := DefaultWidth;
+ end;
+ finally
+ LFieldNames.Free;
+ end;
+
+ for LColumnIndex := 0 to FContentEditor.Grid.Columns.Count - 1 do
+ begin
+ LField := FContentEditor.Grid.Columns[LColumnIndex].Field;
+ // Beautify caption.
+ FContentEditor.Grid.Columns[LColumnIndex].Title.Caption := Beautify(LField.DisplayLabel);
+ // Add combo box for boolean fields.
+ if LField.DataType = ftBoolean then
+ begin
+ FContentEditor.Grid.Columns[LColumnIndex].PickList.Clear;
+ FContentEditor.Grid.Columns[LColumnIndex].PickList.Add(BoolToStr(True, True));
+ FContentEditor.Grid.Columns[LColumnIndex].PickList.Add(BoolToStr(False, True));
+ end
+ else
+ // Add picklist for all columns.
+ begin
+ FContentEditor.Grid.Columns[LColumnIndex].PickList.Clear;
+ GetAllowedValues(ObjectExposer.CurrentObject,
+ FContentEditor.Grid.Columns[LColumnIndex].FieldName,
+ FContentEditor.Grid.Columns[LColumnIndex].PickList);
+ end;
+ FContentEditor.Grid.Columns[LColumnIndex].DropDownRows :=
+ Min(MAX_DROPDOWN_ITEMS, FContentEditor.Grid.Columns[LColumnIndex].PickList.Count);
+ // Hide detail and memo columns, useless in standard grids.
+ if LField.DataType in [ftBlob, ftMemo, ftDataSet] then
+ FContentEditor.Grid.Columns[LColumnIndex].Visible := False;
+ end;
+end;
+
+function TInstantExplorer.CreateFieldList: TStrings;
+var
+ LFieldIndex: Integer;
+begin
+ Result := TStringList.Create;
+ try
+ for LFieldIndex := 0 to FObjectExposer.FieldCount - 1 do
+ Result.Add(FObjectExposer.Fields[LFieldIndex].FieldName);
+ if Assigned(FOnGetFieldNames) then
+ FOnGetFieldNames(Self, ObjectExposer.CurrentObject, Result);
+ except
+ Result.Free;
+ raise;
+ end;
+end;
+
+{ TInstantExplorerDBGrid }
+
+procedure TInstantExplorerDBGrid.Resize;
+begin
+ inherited;
+ UpdateLastColumnWidth;
+end;
+
+procedure TInstantExplorerDBGrid.UpdateLastColumnWidth;
+
+ function GetAllColumnsWidth(const AMinus: Integer): Integer;
+ var
+ LColumnIndex: Integer;
+ begin
+ Result := 0;
+ for LColumnIndex := 0 to Columns.Count - 1 - AMinus do
+ Inc(Result, Columns[LColumnIndex].Width);
+ end;
+
+begin
+ if Columns.Count >= 1 then
+ Columns[Columns.Count - 1].Width := ClientWidth - GetAllColumnsWidth(1);
+end;
+
+{ TInstantExplorerContentEditor }
+
+constructor TInstantExplorerContentEditor.Create(AOwner: TComponent);
+begin
+ inherited;
+ BevelInner := bvNone;
+ BevelOuter := bvNone;
+
+ FGrid := TInstantExplorerDBGrid.Create(Self);
+ FGrid.Parent := Self;
+ FGrid.Align := alClient;
+end;
+
+function TInstantExplorerContentEditor.GetDataSource: TDataSource;
+begin
+ Result := FGrid.DataSource;
+end;
+
+function TInstantExplorerContentEditor.GetGrid: TDBGrid;
+begin
+ Result := FGrid;
+end;
+
+procedure TInstantExplorerContentEditor.SetDataSource(const AValue: TDataSource);
+begin
+ FGrid.DataSource := AValue;
+end;
+
+{ TInstantExplorerDBComboBox }
+
+procedure TInstantExplorerDBComboBox.ApplyToRecord;
+var
+ LDataLink: TDataLink;
+begin
+ // Provides the auto-apply feature.
+ LDataLink := TDataLink(Perform(CM_GETDATALINK, 0, 0));
+ try
+ LDataLink.UpdateRecord;
+ except
+ SelectAll;
+ SetFocus;
+ raise;
+ end;
+end;
+
+procedure TInstantExplorerDBComboBox.Change;
+begin
+ inherited;
+ ApplyToRecord;
+end;
+
+procedure TInstantExplorerDBComboBox.Click;
+begin
+ inherited;
+ ApplyToRecord;
+end;
+
end.
|