XSharpPublic icon indicating copy to clipboard operation
XSharpPublic copied to clipboard

XSharp.VOGUIClasses: revise DataWindow:Close() method

Open wriedmann opened this issue 2 years ago • 6 comments

In VO, code like this is normally used:

method Close( oEvent )
local lClose as logic
 lClose := super:Close( oEvent )
if lClose
  oApp:UnregisterWindow( self )
endif
return lClose

In X#, using the XSharp.GUIClasses, the method declaration throws an error:

error XS9042: Override of virtual method 'Close' in child class has CLIPPER calling convention but overridden method in parent class is STRICT.

wriedmann avatar Aug 29 '23 06:08 wriedmann

I have typed the parameters to most Windows Events in the typed SDK for performance. I can remove that typing, but that will make the code slower. Or should I only type the properties and leave the signatures of the Event Handlers unchanged?

RobertvanderHulst avatar Aug 29 '23 10:08 RobertvanderHulst

Hi Robert, I agree that events should be typed for performance, but it does not helps anything if applications then need a lot of work to be moved. Would it be possible to define both an untyped Handler() and a typed HandlerEx() method? The SDK should call only the typed ones, and the untyped should only pass the call to the typed version. Then user code is movable and can be adjusted when required. (my code is full of event handlers where I'm typing the event parameter inside of the method itself).

wriedmann avatar Aug 29 '23 11:08 wriedmann

So in this case we would have:

METHOD CloseEx(oEvent as Event)
   // original implementation of the Close event
METHOD Close(oEvent)
RETURN SELF:CloseEx(oEvent)

But what about event handles like EditChange ? These are called by the SDK classes themselves.

I can imagine EditChangeEx() and EditChange() There are implementations of EditChange inside the SDK, for DataWindow for example.

This method is called for example from the OnTextChanged event handler of the TextBox control. Should the EditChangeEx then call EditChange? But you may want to override the normal editchange and NOT call super:EditChange() If EditChange is called from EditChangeEx then the super:EditChange code has already been executed.

Or should I make EditChange untyped inside the SDK?

RobertvanderHulst avatar Aug 29 '23 12:08 RobertvanderHulst

Basically I was thinking something similar like this: the SDK classes should call only the typed methods with the new names. The untyped methods are there only for compatibility. This way we have the performance of the typed methods and the compatibility of the untyped ones.

But you are right: this is a tricky issue, and it would be a pity to discard strong typing. But on the other side, I don't think anyone will change to these classes if he has to change many method signatures. In my AlpiFakt application I have 30 EditFocusChange event handlers, 96 Close event handlers and 101 ListViewMouseButtonDoubleClick event handlers.

Maybe you have a better idea than me.....

wriedmann avatar Aug 29 '23 13:08 wriedmann

Wolfgang, My original plan was to let the compiler take care of this. I have already marked most classes in the typed SDK with the [XSharp.Internal.TypesChanged] attribute. What I wanted to do (but have not found the time to do yet) is that when I detect that a subclass has an untyped method and the parent class has a method with the same name, but typed AND when the class was marked with this attribute, then automatically (in the compiler backend) adjust the parameters of the method in the subclass (i.o.w. make the method typed). That would only work if the subclass had the same # of parameters. I also wanted to do the same for properties: when the subclass for example has an untyped Caption property and the property in the parent class is typed, then automatically change the type of the property in the subclass. The reason that I have not done this yet is the following: in Roslyn, the nodes in a parse tree are immutable. To change this, I need to change the nodes that were generated by the parser, and that can be very tricky, Especially if your code has several layers of subclasses that inherit from each other and ultimately from one of the SDK classes. I may need to traverse several layers of classes for this.

It is probably easier to create a special tool that inspects a folder tree and to automatically adjust the parameter declarations in the source code. The code in this tool does not have to very complicated. It can be controlled by a text file / json file with the method names and the new parameter types and return types. To prevent breaking your code, it could even use conditional compilation

#ifdef TYPED_SDK
METHOD EditChange(oControlEvent as ControlEvent) AS USUAL
#else
METHOD EditChange(oControlEvent) 
#endif

The only tricky part is that this tool also needs to figure out if the "EditChange" method is part of the GUI hierarchy, or if you have created an EditChange method in your own (non GUI) class tree. For EditChange it is very likely that you are inheriting from a window, but a Close() method can also be part of a file class or something like that. So the tool needs to build a class tree first (using the source code and reflection on the referenced assemblies) and can then determine if the class tree needs to be adjusted or not. The new attribute could then also be useful.

RobertvanderHulst avatar Aug 29 '23 14:08 RobertvanderHulst

I think you are right and an XPorter tool would be a better and more transparent solution than change the SDK and/or the compiler. But such a tool should understand some simple instructions that are put in the lines as comments, for example to not touch a code line. It would be better so have this as external tool that changes all prg files in a hierarchy so it can work with XIDE and Visual Studio projects.

wriedmann avatar Aug 29 '23 14:08 wriedmann