Skip to content

Commit

Permalink
moved obtaining binding class to function
Browse files Browse the repository at this point in the history
  • Loading branch information
sglienke committed Jun 15, 2015
1 parent a12ecb1 commit bba2cae
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 19 deletions.
63 changes: 54 additions & 9 deletions SimpleMVVM.Binding.Components.pas
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,26 @@ TCommand = class(TInterfacedObject, ICommand)
constructor Create(const method: TRttiMethod; const instance: TObject);
end;

TBinding<T: TComponent> = class(TComponent)
protected
fComponent: T;
TBinding = class(TComponent)
private
fObservable: IObservable;
protected
procedure InitComponent; virtual;
function Initialize(const observable: IObservable): TFunc<TValue>; virtual;
procedure SetComponent(const component: TComponent); virtual; abstract;
public
constructor Create(const component: TComponent;
const observable: IObservable); reintroduce;
end;

TBindingClass = class of TBinding;

TBinding<T: TComponent> = class(TBinding)
protected
fComponent: T;
procedure SetComponent(const component: TComponent); override;
public
constructor Create(const component: T; const observable: IObservable); reintroduce;
constructor Create(const component: T; const observable: IObservable);
end;

TComponentBinding = class(TBinding<TComponent>)
Expand Down Expand Up @@ -80,11 +92,26 @@ TLabelBinding = class(TBinding<TLabel>)
function Initialize(const observable: IObservable): TFunc<TValue>; override;
end;

function GetBindingClass(const target: TObject; const expression: string): TBindingClass;

implementation

uses
Controls;

function GetBindingClass(const target: TObject; const expression: string): TBindingClass;
begin
// hardcode for now, build better rules later
if (target is TEdit) and SameText(expression, 'Value') then
Result := TEditBinding
else if (target is TComboBox) and SameText(expression, 'Value') then
Result := TComboBoxBinding
else if (target is TLabel) and SameText(expression, 'Text') then
Result := TLabelBinding
else
Result := nil;
end;

var
ctx: TRttiContext;

Expand Down Expand Up @@ -130,12 +157,13 @@ procedure TCommand.Execute;
{$ENDREGION}


{$REGION 'TBinding<T>'}
{$REGION 'TBinding'}

constructor TBinding<T>.Create(const component: T; const observable: IObservable);
constructor TBinding.Create(const component: TComponent;
const observable: IObservable);
begin
inherited Create(component);
fComponent := component;
SetComponent(component);
fObservable := TDependentObservable.Create(
Initialize(observable),
procedure(const value: TValue)
Expand All @@ -145,11 +173,11 @@ constructor TBinding<T>.Create(const component: T; const observable: IObservable
InitComponent;
end;

procedure TBinding<T>.InitComponent;
procedure TBinding.InitComponent;
begin
end;

function TBinding<T>.Initialize(const observable: IObservable): TFunc<TValue>;
function TBinding.Initialize(const observable: IObservable): TFunc<TValue>;
begin
Result :=
function: TValue
Expand All @@ -161,6 +189,21 @@ function TBinding<T>.Initialize(const observable: IObservable): TFunc<TValue>;
{$ENDREGION}


{$REGION 'TBinding<T>'}

constructor TBinding<T>.Create(const component: T; const observable: IObservable);
begin
inherited Create(component, observable);
end;

procedure TBinding<T>.SetComponent(const component: TComponent);
begin
fComponent := T(component);
end;

{$ENDREGION}


{$REGION 'TComponentBinding'}

constructor TComponentBinding.Create(const component: TComponent;
Expand Down Expand Up @@ -293,6 +336,8 @@ function TLabelBinding.Initialize(const observable: IObservable): TFunc<TValue>;
var
v: TValue;
begin
if observable = nil then
Exit;
v := observable.Value;
if v.IsEmpty then
fComponent.Caption := ''
Expand Down
22 changes: 12 additions & 10 deletions SimpleMVVM.Binding.pas
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ BindOptionsTextAttribute = class(TCustomAttribute)

procedure ApplyBindings(const view: TComponent; const viewModel: TObject);

procedure Bind(const target: TComponent; const targetExpression: string;
const source: TObject; const sourceExpression: string);

implementation

uses
Expand Down Expand Up @@ -153,7 +156,8 @@ procedure Bind(const target: TComponent; const targetExpression: string;
observable: IObservable;
typ: TRttiType;
method: TRttiMethod;
action: ICommand;
command: ICommand;
bindingClass: TBindingClass;
begin
observable := CreateObservable(source, sourceExpression);

Expand All @@ -162,18 +166,16 @@ procedure Bind(const target: TComponent; const targetExpression: string;
typ := ctx.GetType(source.ClassInfo);
method := typ.GetMethod(sourceExpression);
if Assigned(method) then
action := TCommand.Create(method, source);
command := TCommand.Create(method, source);
end;

// hardcode for now, build better rules later
if (target is TEdit) and SameText(targetExpression, 'Value') then
TEditBinding.Create(TEdit(target), observable)
else if (target is TComboBox) and SameText(targetExpression, 'Value') then
TComboBoxBinding.Create(TComboBox(target), observable)
else if (target is TLabel) and SameText(targetExpression, 'Text') then
TLabelBinding.Create(TLabel(target), observable)
Assert(Assigned(observable) or Assigned(command), 'expression not found: ' + sourceExpression);

bindingClass := GetBindingClass(target, targetExpression);
if Assigned(bindingClass) then
bindingClass.Create(target, observable)
else if (target is TButton) and SameText(targetExpression, 'Click') then
TButtonBinding.Create(TButton(target), action)
TButtonBinding.Create(TButton(target), command)
else
TComponentBinding.Create(target, observable, targetExpression);
end;
Expand Down

0 comments on commit bba2cae

Please sign in to comment.