Recent

Author Topic: FPOObservedChanged  (Read 4298 times)

Weitentaaal

  • Sr. Member
  • ****
  • Posts: 367
  • Weitental is a very beautiful garbage depot.
FPOObservedChanged
« on: December 02, 2021, 11:20:55 am »
Hello Guys,

Attached a small Project, in which i played a bit with Observers. i  understand what Observers do but i cant get how you handle this certain Function (FPOObservedChanged).

Could you guys tell me what i am doing wrong and what i should do instead ? I got another Project in which i wanted to implement Observers. Its Huge so i wanna be careful with those Observers.

For Example if i have 3 edits and all do notify my ViewModel via this Procedure. How do i know where i get my Data from ? was it send by Edit1 or Edit2 ?
Code: Pascal  [Select][+][-]
  1. procedure TMyObserver.FPOObservedChanged(ASender: TObject;
  2.    Operation: TFPObservedOperation; Data: Pointer);
  3. var
  4.   intf: IFPObserved;
  5. begin
  6.   case Operation of
  7.     ooFree: if Supports(ASender, IFPObserved, intf) then
  8.               intf.FPODetachObserver(Self);
  9.     ooCustom: begin
  10.        If Assigned(Data) then begin
  11.           case ASender.ClassName of //i know this wont work. what do i do here ?
  12.              'Edit1': SomStr :=  String(Data);
  13.              'Edit2': Num1 := Integer(Data);
  14.              'Edit3': Num1 := Integer(Data);
  15.              'ComboBox1': begin
  16.                 Case Integer(Data) of
  17.                    0: fNewColor:= clBlue;
  18.                    1: fNewColor:= clGreen;
  19.                    2: fNewColor:= clYellow;
  20.                    3: fNewColor:= clRed;
  21.                    4: fNewColor:= clWhite;
  22.                    5: fNewColor:= clBlack;
  23.                    6: fNewColor:= clAqua;
  24.                 end;
  25.              end;
  26.           end;
  27.        end;
  28.     end;
  29.   end;
  30. end;
  31.  

and if i have more than 1 Components of the Same type, lets say TEdit, can i create an Observer which observes all of those Edit's ? then again how do i know from who i got the data from ?

Thanks in advance :)
« Last Edit: December 02, 2021, 01:27:31 pm by Weitentaaal »
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.0

AlexTP

  • Hero Member
  • *****
  • Posts: 1761
    • UVviewsoft
Re: FPOObservedChanged
« Reply #1 on: December 02, 2021, 11:30:58 am »
Perhaps, you may check the ASender and compare it with Edit1, Edit2. Also you may test 'if ASender is TEdit'.

Weitentaaal

  • Sr. Member
  • ****
  • Posts: 367
  • Weitental is a very beautiful garbage depot.
Re: FPOObservedChanged
« Reply #2 on: December 02, 2021, 12:35:46 pm »
Perhaps, you may check the ASender and compare it with Edit1, Edit2. Also you may test 'if ASender is TEdit'.

Thanks for your Reply. i was about to decouple my GUI from my Logic (to improve legibility and Maintenance). If there is no other way, then i will go with that, but after me, the Code will get a bit messy when using it like this.

Edit: If the code i have Shown is pointless(because its not done like this or whatever) then please tell me :)
« Last Edit: December 02, 2021, 12:41:15 pm by Weitentaaal »
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.0

AlexTP

  • Hero Member
  • *****
  • Posts: 1761
    • UVviewsoft
Re: FPOObservedChanged
« Reply #3 on: December 02, 2021, 12:59:24 pm »
You can also assign Tag property of TEdit's, then in the observer:
Code: Pascal  [Select][+][-]
  1. if ASender is TComponent then
  2. begin
  3.   NTag:= TComponent(ASender).Tag;
  4.   ...
  5. end

Weitentaaal

  • Sr. Member
  • ****
  • Posts: 367
  • Weitental is a very beautiful garbage depot.
Re: FPOObservedChanged
« Reply #4 on: December 02, 2021, 01:05:28 pm »
You can also assign Tag property of TEdit's, then in the observer:
Code: Pascal  [Select][+][-]
  1. if ASender is TComponent then
  2. begin
  3.   NTag:= TComponent(ASender).Tag;
  4.   ...
  5. end

was thinking about this but some of my Components (TListBoxes) do already have the Tag Property Occupied. So i would have to create maybe a record to store in them and then it is getting complex again. But this is probably the best way to do this i guess.

Thank you @Alextp

Keep me updated if any1 has another Solution.

Edit: Question: isn't it resource-intensive if i update All my Controls after every Change ? Should i Split the Update Procedure up on multiple Procedures to Update certain parts of my View ?
« Last Edit: December 02, 2021, 01:16:37 pm by Weitentaaal »
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.0

AlexTP

  • Hero Member
  • *****
  • Posts: 1761
    • UVviewsoft
Re: FPOObservedChanged
« Reply #5 on: December 02, 2021, 01:21:14 pm »
In my app, I use class for Tag prop:

Code: Pascal  [Select][+][-]
  1. type
  2.   TMyTag = class
  3.   public
  4.     SomeVal1, SomeVal2, SomeVal3: SomeTypes;
  5.   end;
  6.  
  7. begin
  8.   Edit1.Tag:= PntInt( TMyTag.Create(Val1, Val2, Val3) );
  9.  
« Last Edit: December 02, 2021, 01:25:32 pm by Alextp »

Weitentaaal

  • Sr. Member
  • ****
  • Posts: 367
  • Weitental is a very beautiful garbage depot.
Re: FPOObservedChanged
« Reply #6 on: December 02, 2021, 01:27:10 pm »
In my app, I use class for Tag prop:

Code: Pascal  [Select][+][-]
  1. type
  2.   TMyTag = class
  3.   public
  4.     SomeVal1, SomeVal2, SomeVal3: SomeTypes;
  5.   end;
  6.  
  7. begin
  8.   Edit1.Tag:= PntInt( TMyTag.Create(Val1, Val2, Val3) );
  9.  

This will work! Thank you @Alextp

How do you do your updates ?

Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.0

jamie

  • Hero Member
  • *****
  • Posts: 4582
Re: FPOObservedChanged
« Reply #7 on: December 02, 2021, 01:36:06 pm »
Why don't you point the same OnChange event to all the EDITS ?

In the OI you create just one and all remaining edits can point to the same OnChange event, just scroll down in the OI event creator and select it.

 You can examine the Sender there to determine which edit it is, especially if it's in the same unit and class..

If Sender = Edit1 Then etc..



The only true wisdom is knowing you know nothing

Weitentaaal

  • Sr. Member
  • ****
  • Posts: 367
  • Weitental is a very beautiful garbage depot.
Re: FPOObservedChanged
« Reply #8 on: December 02, 2021, 01:48:18 pm »
Why don't you point the same OnChange event to all the EDITS ?

In the OI you create just one and all remaining edits can point to the same OnChange event, just scroll down in the OI event creator and select it.

 You can examine the Sender there to determine which edit it is, especially if it's in the same unit and class..

If Sender = Edit1 Then etc..





I can and i did. But all i do in this Event Handlers are Graphical Changes, because i wanted to Split GUI and Logic. So i have 2 Classes, 1 Form and 1 Logic Class. I strgugle with informing my Logic class about the Changes on my GUI and with Updating my View with my Data from the Logic class. Thats why i wanted to create Some Observers to do what i wanted. With your Solution im back where i was at the begining with a realy messy Code.

Don't get me wrong... everything is working i just want to optimizie my Code for Maintenance and readability
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.0

Thaddy

  • Hero Member
  • *****
  • Posts: 11516
Re: FPOObservedChanged
« Reply #9 on: January 08, 2022, 10:51:02 am »
You can also do without tag, but with the IInterfaceComponentReference interface from TComponent. That will really decouple your code as long as it is Tcomponent derived.
See https://www.freepascal.org/docs-html/rtl/classes/iinterfacecomponentreference.html
Simplest example:
Code: Pascal  [Select][+][-]
  1. program compref;
  2. {$mode delphi}
  3. uses classes,sysutils;
  4. type
  5.   TMyComponent = class(Tcomponent)
  6.   end;
  7. var
  8.   ref:IInterfaceComponentReference;
  9. begin
  10.   ref := TMyComponent.Create(nil)  as IInterfaceComponentReference;
  11.   writeln('it is not a TComponent, but a TMyComponent!: ',(ref as TComponent).ClassName);
  12. end.
Since you now can get at the ClassType, you can create further instances of the correct type in the gui part from the TClass.classtype reference.
This code has a small leak, but it just shows the principle.
As you can see the code is fully decoupled  as long it is a Tcomponent derivative.

I mean the generic code can be simply
(ref as TComponent).ClassName
and (ref as TComponent).classtype
The latter being a TClass from which you can create more instances of the same type.
All components support this interface so there is no reason to mis-use tag.
E.g. (ref as TComponent).classtype would return class of TEdit for TEdit etc.
« Last Edit: January 08, 2022, 02:13:40 pm by Thaddy »
Путин преступник. Россияне дезинформированы.

 

TinyPortal © 2005-2018