xsharp.eu • We need your input on how to migrate FoxPro forms - Page 4
Page 4 of 4

We need your input on how to migrate FoxPro forms

Posted: Mon Jan 13, 2020 3:45 pm
by atlopes
Robert, I'll dare to think that I understood what you said. At least the core of it... So, maybe not completely...

My points are

a) the problem you're addressing is not specific to VFP forms and to the Form Designer, which is nothing more than a specialized class editor (;) @pluisje). And yes, you don't need the Form Designer to build fully operational and complex forms in VFP, a simple text editor like Notepad will do. But the problem of allowing objects to carry or not their un-subclassed methods potentially affects all VFP classes (Thomas, you are right - as usual! - some of my previous statements should have been put in better context).

b) getting away from the way VFP operates will difficult the port and conversion of the accumulated VFP material (I won't say this is a bad thing per se, it's only something to be reasonably expected).

At the end of the day, it will a decision that will impact how X# will be perceived by the VFP community. I can speak for no one but me but will assume that the greater the distance from how VFP does its things, the stronger the resistance.

We need your input on how to migrate FoxPro forms

Posted: Mon Jan 13, 2020 5:34 pm
by atlopes
Coming back to your post, Chris
2) Use some compiler trickery and possibly some leading code inside the event methods to do the translating between WinForms and VFP style
This works in VFP, don't know how would it go in X# (method names aside).

Code: Select all

LOCAL DemoForm AS Demo

m.DemoForm = CREATEOBJECT("Demo")
m.DemoForm.Show(1)

DEFINE CLASS Demo AS Form

	ADD OBJECT Button AS CommandButton
	ADD OBJECT AltButton AS CommandButton WITH TOP = 20
	ADD OBJECT MyLabel AS DemoLabel WITH Top = 50

	PROCEDURE Button.Click
* some auto-generated header
#IFDEF This
#UNDEF This
#ENDIF

#DEFINE This Thisform.Button
* end of header

		This.Caption = "Ouch!"
		This.Parent.Caption = "The button was clicked!"
		This.Parent.MyLabel.Set("I confirm that!")
		This.Parent.AltButton.MyMethod()

* some auto-generated footer
#UNDEF This
* end of footer

	PROCEDURE AltButton.MyMethod
* some auto-generated header
#IFDEF This
#UNDEF This
#ENDIF

#DEFINE This Thisform.AltButton
* end of header

		This.Caption = "Replika!"

* some auto-generated footer
#UNDEF This
* end of footer
ENDDEFINE

DEFINE CLASS DemoLabel AS Label

	PROCEDURE Set (LabelCaption AS String)

		This.Caption = m.LabelCaption

	ENDPROC

ENDDEFINE

We need your input on how to migrate FoxPro forms

Posted: Mon Jan 13, 2020 5:48 pm
by FoxProMatt
Robert said:
If you look at the designed VFP form then the form itself represents a class. You can see that also if you generate the source version of this with FoxBin2Prg. The Data environment is also a class.
Robert - You probably know this already, but just so I can state this, FoxBin2Prg is not a native out-of-the-box FoxPro tool, it is just a (rather recently) developed and released community tool that was primarily written to generate a text version of the SCX/VCX/FRX files in a VFP project to a text format for the purpose of easier/better use in source code repo system.

It also has the ability to reverse the text file back the original SCX/VCX/FRX file, and I have to expects that the structure of the text file is basically self-serving for these purposes, and I just want to point out that while we can probably see a lot of VFP intelligence and apparent structure in there, we can't give it too much proof or authority of how the real VFP underpinning do or must work.

So, just because FoxBin2Prg generates it that way, we have to take that with a grain of salt...

Example:

Output from FoxBin2Prg:

Code: Select all

PROCEDURE btnFirst.Click
		this.Caption = "I was clicked"
ENDPROC

Well, If I open the actual SCX file, you will NOT see this code on the Form row in the SCX file (near the top row or two), but if you scroll down and find the row in the SCX file for the actual BUTTON, you will see the code in the BUTTON itself in the field called METHODS in the SCX. So from this native VFP architecture, one can argue that the method code for the Button is indeed stored in the Button and not the Form.


See screenshot of SCX file: Notice this Button has 2 methods defined in its METHODS field, and notice they do not start navigating from the Form...:

Code: Select all

PROCEDURE Click
This.Parent.txtJobNo.Enabled = .t.
This.Parent.txtjobNo.SetFocus()

ENDPROC


PROCEDURE Refresh

*-- Hide this button if we are running in an EXE.
*-- Not ready to release it yet, so only want to see it in dev mode.

This.Enabled = Thisform.lEditMode and !Empty(Thisform.oMainObject.PK)

ENDPROC
2020-01-13_11-46-50.png
2020-01-13_11-46-50.png (283.21 KiB) Viewed 580 times

We need your input on how to migrate FoxPro forms

Posted: Mon Jan 13, 2020 7:14 pm
by robert
Matt,

I know how and where the methods are stored. But that is not the point.
The point is that the PROCEDURE Click and PROCEDURE Refresh from your example can access the control with "This".
That means that they are not "stand alone" procedures but members of a class.
And to access the button with the "This" keyword they have to be members of a class in the control hierarchy.
.Net does not allow you to define methods for code that you (the form) don't 'own' so these methods must be either added to the form or to a new subclass of the control.


Robert

Robert

We need your input on how to migrate FoxPro forms

Posted: Mon Jan 13, 2020 7:38 pm
by FoxProMatt
Robert said:
If we would have to keep the code unchanged, so if the event would still refer to the button as 'This' then we would generate an extra class (nested inside the DEFINE CLASS form1) and would move the code for the Click event inside this class:

Code: Select all

DEFINE CLASS btnFirst
        PROCEDURE Click
		this.Caption = "I was clicked"
	ENDPROC
END DEFINE

Robert - I can clearly see that this is a necessary approach, and it makes perfect sense.

Yes, yes... I see that essentially we have been creating all these "custom classes" in each Form all along, it's just that the VFP IDE has been nicely hiding them for us all this time, tucking the wanna-be (should-have-been) classes in the rows of the SCX and it (or, we) conveniently didn't have to give them a name or formal separate existence in our Projects.

I could live with this. I get it. In fact, I even like it, a lot, if we can address these two concerns:


1. The naming convention of each class will require some work, perhaps with Namespaces, because even if you generate the control class code inside the Form code file, you can still have naming conflicts across a Project, as many forms may contain a button control named "btnFirst", so you cannot just use that name alone (I know you already know this...) , without some complex or verbose naming prefixes, and/or Namespace(s(). Heck, even many Containers on the same Form could contain "btnFirst" as a control name. This part makes me think the generated class code is gonna get ugly... A Button in a Container on Page in a Pageframe.... That's a lot of nesting, and when that UI control has to become a free-standing class, it's going to have an ugly name.


2. We are very spoiled in VFP form editor that we can double-click on any control in the Form or Container(s) and the method/event code for that one control immediately pop up in the code editor, and the Properties for it appear in scope of the Property editor. So in the Visual Studio IDE we'll hope there can be some tools there to quickly and easily open the control class in a separate edit window, but that sounds hard to do in the VS IDE.

We need your input on how to migrate FoxPro forms

Posted: Tue Jan 14, 2020 1:05 pm
by mainhatten
FoxProMatt_MattSlay wrote:Well, If I open the actual SCX file, you will NOT see this code on the Form row in the SCX file (near the top row or two), but if you scroll down and find the row in the SCX file for the actual BUTTON, you will see the code in the BUTTON itself in the field called METHODS in the SCX. So from this native VFP architecture, one can argue that the method code for the Button is indeed stored in the Button and not the Form.

See screenshot of SCX file: Notice this Button has 2 methods defined in its METHODS field, and notice they do not start navigating from the Form...:
Hi Matt,
testing with .scx you tricked yourself a bit. The "latebinding" of method code in GUI table happens
a) when overwriting method of complex class in inherited class
b) when overwriting method of complex class aggregated in further container class

A .scx by definition creates the lowest container, which then is not inherited.I created a small example .vcx, where you can witness both effects in method code - which creates a problem in classical OOP.

Check out method code for procedure names sporting dots. Simple example could be used as sanity check for coverage when comparing/testing implementation. In .?cx version first a subclass record is created and added, but as soon as that is done (further inheritance/aggregation of complex control) the problematic method names "moving" or describing method target object (==correct "this" from vfp point of view). That was the reason for my somewhat long-winded description of problematic structures - I encountered that in the Lianja screen exporting code.

Hope this clears some of the confusion

thomas

We need your input on how to migrate FoxPro forms

Posted: Tue Jan 14, 2020 1:23 pm
by mainhatten
FoxProMatt_MattSlay wrote:Robert said:
Yes, yes... I see that essentially we have been creating all these "custom classes" in each Form all along, it's just that the VFP IDE has been nicely hiding them for us all this time, tucking the wanna-be (should-have-been) classes in the rows of the SCX and it (or, we) conveniently didn't have to give them a name or formal separate existence in our Projects.
As shown in previous post with attached .vcx, those custom classes are only added in a new aggregation
1. The naming convention of each class will require some work, perhaps with Namespaces, because even if you generate the control class code inside the Form code file, you can still have naming conflicts across a Project, as many forms may contain a button control named "btnFirst", so you cannot just use that name alone (I know you already know this...) , without some complex or verbose naming prefixes, and/or Namespace(s(). Heck, even many Containers on the same Form could contain "btnFirst" as a control name. This part makes me think the generated class code is gonna get ugly... A Button in a Container on Page in a Pageframe.... That's a lot of nesting, and when that UI control has to become a free-standing class, it's going to have an ugly name.
I think best way will be to replace dots with "#" for class names, as this cannot clash with vfp. Uncetain on upper length limit, but we should have that in vfp as well, and can subtracht "method name extension".
2. We are very spoiled in VFP form editor that we can double-click on any control in the Form or Container(s) and the method/event code for that one control immediately pop up in the code editor, and the Properties for it appear in scope of the Property editor. So in the Visual Studio IDE we'll hope there can be some tools there to quickly and easily open the control class in a separate edit window, but that sounds hard to do in the VS IDE.
I am more in line with Chris wishing to be able to have access to ALL Dotnet controls inside xSharp forms, which will create hassles and/or boundries for special editor of vfp-compatible WinForms. Hope I find enough time for my longer post today...

We need your input on how to migrate FoxPro forms

Posted: Tue Jan 14, 2020 2:42 pm
by mainhatten
robert wrote:This does not fit well in the way OOP is implemented in .Net.
Robert,
see my example .vcx to Matt, the problem shows up on overwriting methods of complex controls both in aggregation AND inheritance.
If we would have to keep the code unchanged, so if the event would still refer to the button as 'This' then we would generate an extra class (nested inside the DEFINE CLASS form1) and would move the code for the Click event inside this class:

Code: Select all

DEFINE CLASS btnFirst
        PROCEDURE Click
		this.Caption = "I was clicked"
	ENDPROC
END DEFINE
As I wrote earlier, this approach will work, both with inner/nested or normal classes. You prbably will have to create (sometimes empty) classes classes on every level of aggregation AND inheritance plus a factory to instantiate the correct class (name) when instantiating any level of complex class, something simple like addobject("ConstantPropertyName", "CorectClassNameAtThisLevel"), esp. if dynamic loading is thrown into the mix. Conceptually another corner, but nothing unsurmountable, although
https://social.msdn.microsoft.com/Forum ... arpgeneral
hints at ugly implementation needing orthogonal approach..

I am also not worried for runtime performance, but it could add to compile time, already tugging at vfp-spoiled nerves.
The alternative is to keep the procedure as part of the class definition and make some changes to the code. For example:

Code: Select all

      PROCEDURE btnFirst.Click
		ThisForm.btnFirst.Caption = "I was clicked"
	ENDPROC
My point of view: ONLY if everything else fails! Also unclear for me how you will point any dodefault() in WinForm click automatically to the event delegate already coded in the class hierarchy in parent class of btnFirst - but I lack a lot of expirience in WinForms.

I mentioned the prototypal implementaton of vfp before and googled a bit for equivalents of the This-Moving ABC of Javascript. Anybody not familiar with Javascripts Apply, Bind and Call functions - please google until mostly satisfied, a description tried/offered by me would probably only further consternation.

As there are a few implementations of Javascript done in Dotnet, the basic functionality has to exist somewhere. Found:
https://stackoverflow.com/questions/195 ... y-and-call
Could this be a solution to exchange the object "this" points to in the event handler ?

Re-Assigning reserved words is a no-no under most circumstances. But perhaps @This could work ? See
https://stackoverflow.com/questions/429 ... -mean-in-c

And there always is preprocessor magic... Sorry I cannot point to proven and elegant solution, but I lack Dotnet knowledge

regards
thomas