To all hmg4 core developers, an important proposal
Moderator: Rathinagiri
To all hmg4 core developers, an important proposal
I already told that I think that release method should be studied a bit upon.
To me, release() should never delete the window itselft and its
objects recursively. It should never call __objDelData (if I previusly
said that it should do, I was wrong).
I try to explain why:
Imagine you have class window and 2 istances, like in:
W1 := Window():New()
W2 := Window():New()
If we add a label called "label01" to W1 internally hmg4 calls
__objAddData( w1, "label01")...
unfortunately, __objAddData (that is a internal function and should
not be called directly) adds label01 TO THE CLASS and not to the
instance !!!
You can check this with ? W2:label01 that returns NIL and doen't raise
an error !!!!!!!!!!
So, this must be taken care of, it's not really a problem, everything
is working... but programmers should know that it is unreliable to
test for method/data existance to understand which object we are
dealing...
Suppose that W2 goes out of scope earlier than W1... when it goes out
of scope, and we call __objDelData recursively... ooopss, label01
disappears ?!
To me, release() should never delete the window itselft and its
objects recursively. It should never call __objDelData (if I previusly
said that it should do, I was wrong).
I try to explain why:
Imagine you have class window and 2 istances, like in:
W1 := Window():New()
W2 := Window():New()
If we add a label called "label01" to W1 internally hmg4 calls
__objAddData( w1, "label01")...
unfortunately, __objAddData (that is a internal function and should
not be called directly) adds label01 TO THE CLASS and not to the
instance !!!
You can check this with ? W2:label01 that returns NIL and doen't raise
an error !!!!!!!!!!
So, this must be taken care of, it's not really a problem, everything
is working... but programmers should know that it is unreliable to
test for method/data existance to understand which object we are
dealing...
Suppose that W2 goes out of scope earlier than W1... when it goes out
of scope, and we call __objDelData recursively... ooopss, label01
disappears ?!
Re: To all hmg4 core developers, an important proposal
What happens if I have a program with 100 windows, each one 100
objects each one named uniquely ? If I can't use delData the class
keeps growing up to 1000 members !!!!
I think that we should take a little pause and think about it for a
moment. I ask to check what I'm saying to verify - I may be wrong...
Be able to write code with syntax like
oWindow:oLabel:value := "text"
is very nice, oop style, etc etc
Be able to write code with syntax like
oWindow:oLabel:value := "text"
is very nice, oop style, etc etc
adding oLabel as a real member to oWindow has drawbacks... the only
other solution I know of is to use the ERROR HANDLER trick.
Here a snippet from hbxbp code:
Be able to write code with syntax like
oWindow:oLabel:value := "text"
is very nice, oop style, etc etc
adding oLabel as a real member to oWindow has drawbacks... the only
other solution I know of is to use the ERROR HANDLER trick.
Here a snippet from hbxbp code:
THE FORUM SOFTWARE GIVES ERROR WHEN I PAST CODE !!!! LOOK FOR
METHOD XbpWindow:onError( ... )
IN HBXBP CONTRIB DIR
when we call
Harbour VM retrieves the oWindow object, then looks for "OLABEL"
inside it. Since it is not present, it calls the CLASS error handler.
In the XbpWindow:onError( ... ) method the "message" is retrieved
(message is "OLABEL") and in this specific case the message is used as
method on another object, it works as a layer...
Since we have the "message" we can do with it what we need. My
proposal (not really mine since Luigi already did some tests
indipendently with nice results using Hash to store objects and
something I already saw used in other situations) is to use an Hash to
store the children objects.
As we said in other threads, the objects (label) is stored in 3
places. IN a variable, in a list of objects in the parent, as a data
member.
With my proposal the data member is "emulated" and the list of objects
converted from array to Hash. oWindow:oLabel syntax is still valid.
With Hashes, every object members count doesn't grow. And it's
probably way easier to handle the children objects.
There is still one problem to solve... the release() stuff...
If we want to DELETE a window we can do it without problem, Harbour VM
should take care of everything and there should be no necessity for
recursive deleting... when VM deletes the window object tha hash (that
is a member) should be deleted item by item by the VM... if it's not
the case, a destructor method will be needed...
So
should be valid and everything should made work without problems.
If we want to destroy a single (and we can't just hide it but we
should absolutely "delete it now!"), like in
in our error handler we should intercept the NIL value and do the equivalent of:
I know these changes will give us a little speed penalty... but they
will give us more power and control...
What do you think ?
objects each one named uniquely ? If I can't use delData the class
keeps growing up to 1000 members !!!!
I think that we should take a little pause and think about it for a
moment. I ask to check what I'm saying to verify - I may be wrong...
Be able to write code with syntax like
oWindow:oLabel:value := "text"
is very nice, oop style, etc etc
Be able to write code with syntax like
oWindow:oLabel:value := "text"
is very nice, oop style, etc etc
adding oLabel as a real member to oWindow has drawbacks... the only
other solution I know of is to use the ERROR HANDLER trick.
Here a snippet from hbxbp code:
Be able to write code with syntax like
oWindow:oLabel:value := "text"
is very nice, oop style, etc etc
adding oLabel as a real member to oWindow has drawbacks... the only
other solution I know of is to use the ERROR HANDLER trick.
Here a snippet from hbxbp code:
THE FORUM SOFTWARE GIVES ERROR WHEN I PAST CODE !!!! LOOK FOR
METHOD XbpWindow:onError( ... )
IN HBXBP CONTRIB DIR
when we call
Code: Select all
oWindow:oLabel:value := "text"
inside it. Since it is not present, it calls the CLASS error handler.
In the XbpWindow:onError( ... ) method the "message" is retrieved
(message is "OLABEL") and in this specific case the message is used as
method on another object, it works as a layer...
Since we have the "message" we can do with it what we need. My
proposal (not really mine since Luigi already did some tests
indipendently with nice results using Hash to store objects and
something I already saw used in other situations) is to use an Hash to
store the children objects.
As we said in other threads, the objects (label) is stored in 3
places. IN a variable, in a list of objects in the parent, as a data
member.
With my proposal the data member is "emulated" and the list of objects
converted from array to Hash. oWindow:oLabel syntax is still valid.
With Hashes, every object members count doesn't grow. And it's
probably way easier to handle the children objects.
There is still one problem to solve... the release() stuff...
If we want to DELETE a window we can do it without problem, Harbour VM
should take care of everything and there should be no necessity for
recursive deleting... when VM deletes the window object tha hash (that
is a member) should be deleted item by item by the VM... if it's not
the case, a destructor method will be needed...
So
Code: Select all
oWindow := NIL
If we want to destroy a single (and we can't just hide it but we
should absolutely "delete it now!"), like in
Code: Select all
oWindow:oLabel := NIL
Code: Select all
::aHash[ "OLABEL" ] := NIL // to force object orderly delete
HDel( ::aHash, "OLABEL" ) // delete the key from the hash
I know these changes will give us a little speed penalty... but they
will give us more power and control...
What do you think ?
- Rathinagiri
- Posts: 5471
- Joined: Tue Jul 29, 2008 6:30 pm
- DBs Used: MariaDB, SQLite, SQLCipher and MySQL
- Location: Sivakasi, India
- Contact:
Re: To all hmg4 core developers, an important proposal
Hi Francesco,
The forum software has some bugs regarding posting some codes. Especially s u b s t r () and other functions.
I think it is not allowed to post that code because of PHP security reasons !!!
The forum software has some bugs regarding posting some codes. Especially s u b s t r () and other functions.
I think it is not allowed to post that code because of PHP security reasons !!!
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.
South or North HMG is worth.
...the possibilities are endless.
- Rathinagiri
- Posts: 5471
- Joined: Tue Jul 29, 2008 6:30 pm
- DBs Used: MariaDB, SQLite, SQLCipher and MySQL
- Location: Sivakasi, India
- Contact:
Re: To all hmg4 core developers, an important proposal
I understand the problem.
The child objects should be added to instance only and not to the class.
I think it can be done via an array of child objects as DATA.
The child objects should be added to instance only and not to the class.
I think it can be done via an array of child objects as DATA.
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.
South or North HMG is worth.
...the possibilities are endless.
Re: To all hmg4 core developers, an important proposal
Today I and Luigi started working on this idea and Luigi produced some nice code. This evening we refined it a bit and implemented in hmg4 the new system based on HASHes...
I attach a basic.prg that you should AS A TEST copy over the one in your directory. Then add the line
to window():New() method, as the first line.
You will find the changes in addData and delData. Hash based implementation is at the bottom of basic.prg.
In this sample the added methods are public but they will be made protected.
The ::StartHash() line should be added to all widget source code whose New() method is overloaded and the super:new() method from basic.prg is not called (like in window.prg, where super:new() is not called...).
I tested it only on samples\slider\demo_1.prg and it is too late to do other tests. It should work on several other simple samples whose widgets call the new() of basic class, otherwise you need to add the ::StartHash() line...
Please read the code, test and report.
thanks
Francesco and Luigi
I attach a basic.prg that you should AS A TEST copy over the one in your directory. Then add the line
Code: Select all
::StartHash()
You will find the changes in addData and delData. Hash based implementation is at the bottom of basic.prg.
In this sample the added methods are public but they will be made protected.
The ::StartHash() line should be added to all widget source code whose New() method is overloaded and the super:new() method from basic.prg is not called (like in window.prg, where super:new() is not called...).
I tested it only on samples\slider\demo_1.prg and it is too late to do other tests. It should work on several other simple samples whose widgets call the new() of basic class, otherwise you need to add the ::StartHash() line...
Please read the code, test and report.
thanks
Francesco and Luigi
- Attachments
-
- basic.zip
- (5.05 KiB) Downloaded 244 times
- Rathinagiri
- Posts: 5471
- Joined: Tue Jul 29, 2008 6:30 pm
- DBs Used: MariaDB, SQLite, SQLCipher and MySQL
- Location: Sivakasi, India
- Contact:
Re: To all hmg4 core developers, an important proposal
Thanks a lot Francesco. I will check and come back.
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.
South or North HMG is worth.
...the possibilities are endless.
Re: To all hmg4 core developers, an important proposal
Hi my friends.
For work reasons, I can spend little time to HMG and I'm very disappointed but I would like to leave a constructive contribution.
I hope that my words are not misinterpreted and that my English can rise to the occasion
I believe that the structure, stability and performance of the current HMG4 version is not satisfactory.
As all of you know, to propose solutions for HMG4, I developed a small fork.
It has limitations too and has various problems, but I hope that these ideas/suggestions are useful to improve HMG4.
first item: the layout of classes
I believe we must carefully observe the structure of Qt. create the necessary classes, but maintaining a flexible structure that adapts to our project. For example, I remind you what we found - Francesco and me - about the replacement of aControls.
I believe that the structure of the classes should be like or about or very similar to this There are many similarities with the current, but be careful "BasicQt", the two groups "A" and "B", and groups of classes based on some similarities
I believe that, in the class "BasicQt" must be included (some and useful) methods and properties of QObject and QWidget.
see( http://doc.qt.nokia.com/latest/qobject.html e http://doc.qt.nokia.com/latest/qwidget.html )
for example: the data nCol, but its method is simply "RETURN:: oQtObject: x ()". The data lEnabled, in this case QT considers this property fundamental and then the method will be
second element: maintain a consistent programming style. Or use OOP or XBase classic style.
Examples currently included with HMG4 are a mixture of these styles and I believe no one thinks to write their own programs as well.
This topic is complex and takes time to be described, I believe that the examples will clarify my thoughts: they are all real.
HMG4 StatusBar
My fork StatusBar: no local vars are declared
HMG4 MainMenu
My fork MainMenu: no local vars are declared
HMG4 include file
My fork include file: no vars are used
These are brief examples of both: HMG4 and a different pow.
I repeat.
My words must be considered as constructive criticism for the good of the project HMG4, to which many of us have contributed and spent their free time.
please, think about what I have given you before you shoot me
Viva HMGx, viva Clipper
Cheers
Luigi
For work reasons, I can spend little time to HMG and I'm very disappointed but I would like to leave a constructive contribution.
I hope that my words are not misinterpreted and that my English can rise to the occasion
I believe that the structure, stability and performance of the current HMG4 version is not satisfactory.
As all of you know, to propose solutions for HMG4, I developed a small fork.
It has limitations too and has various problems, but I hope that these ideas/suggestions are useful to improve HMG4.
first item: the layout of classes
I believe we must carefully observe the structure of Qt. create the necessary classes, but maintaining a flexible structure that adapts to our project. For example, I remind you what we found - Francesco and me - about the replacement of aControls.
I believe that the structure of the classes should be like or about or very similar to this There are many similarities with the current, but be careful "BasicQt", the two groups "A" and "B", and groups of classes based on some similarities
I believe that, in the class "BasicQt" must be included (some and useful) methods and properties of QObject and QWidget.
see( http://doc.qt.nokia.com/latest/qobject.html e http://doc.qt.nokia.com/latest/qwidget.html )
for example: the data nCol, but its method is simply "RETURN:: oQtObject: x ()". The data lEnabled, in this case QT considers this property fundamental and then the method will be
Code: Select all
METHOD Enabled( lValue ) CLASS BASICQT
IF PCOUNT() == 0
::lEnabled := ::oQtObject:isEnabled()
RETURN ::lEnabled
ELSEIF hb_IsLogical( lValue ) == .T.
::lEnabled := lValue
::oQtObject:setEnabled( ::lEnabled )
ENDIF
RETURN Self
Examples currently included with HMG4 are a mixture of these styles and I believe no one thinks to write their own programs as well.
This topic is complex and takes time to be described, I believe that the examples will clarify my thoughts: they are all real.
HMG4 StatusBar
Code: Select all
FUNCTION Main
LOCAL oButton1
LOCAL oButton2
LOCAL oButton3
LOCAL oButton4
LOCAL oStatusBar
PRIVATE oWindow
HBQT_ERRORSYS()
WITH OBJECT oWindow := Window():New()
:Row := 10
:Col := 10
:Width := 500
:Height := 500
:Title := 'Status Bar management'
:Type := WND_MAIN
:OnInit := { || oWindow:Center() }
WITH OBJECT oButton1 := Button():New()
:Row := 40
:Col := 40
:Width := 250
:Caption := 'Click TO change text'
:OnClick := { || Button1Click( 1 ) }
END WITH
WITH OBJECT oButton2 := Button():New()
:Row := 80
:Col := 40
:Width := 250
:Caption := 'Click TO change icon'
:OnClick := { || Button1Click( 2 ) }
END WITH
WITH OBJECT oButton3 := Button():New()
:Row := 120
:Col := 40
:Width := 250
:Caption := 'Click TO remove icon'
:OnClick := { || Button1Click( 3 ) }
END WITH
WITH OBJECT oButton4 := Button():New()
:Row := 160
:Col := 40
:Width := 250
:Caption := 'Click TO add icon'
:OnClick := { || Button1Click( 4 ) }
END WITH
WITH OBJECT oStatusBar := StatusBar():New("oStatusBar")
:FontName := "Arial"
:FontSize := 12 ; ;
:StatusItemAdd("Example OF test",200,,":BTN_LOGIN",.F.,.T.,)
:StatusBarTimersAdd(100,,.F.,.F.,,"C")
:StatusBarTimersAdd(100,,.F.,.F.,,"D")
END
END WITH
oWindow:Activate()
Code: Select all
WITH OBJECT MainForm := WINDOW():New( "MainForm" )
:Row := 10
:Col := 10
:Width := 600
:Height := 600
:Title := "Form title: OOP syntax"
:Icon := ":L3W_ICO"
:WinType := WND_MAIN
:OnInit := {|| MainFrmOnInit() }
:ToolTip := "This is MainForm tooltip"
WITH OBJECT StatusBar():New( "StatusBar1" )
:FontFamily := "Arial"
:FontSize := 12
WITH OBJECT StatusItem():New( "StatusItem1" )
:Width := 150
:Caption := "Put Text Here"
:ToolTip := "Click hover me"
:OnClick := {|| MsgStop("Clicked me") }
END WITH
WITH OBJECT StatusItem():New( "StatusItem2" )
:Width := 150
:ToolTip := "ToolTip Item2"
:Caption := "texture"
:Height := 18 // this is required to merge icon with text, but unusefull about height of statusbar
:IconHeight := 12
:IconWidth := 12
:Icon := ":L3W_IMOVNEXT"
END WITH
WITH OBJECT StatusKeyb():New( "StatusKeyBoard" )
:Width := 100
:ToolTip := "KeyBoard Status"
END WITH
WITH OBJECT StatusDate():New( "StatusDate" )
:Width := 100
:ToolTip := "Current Date"
:OnClick := {|| InstantDate() }
END WITH
WITH OBJECT StatusClock():New( "StatusClock" )
:Width := 100
:ToolTip := "Current Time"
:OnClick := {|| InstantTime() }
END WITH
END WITH
END WITH
MainForm:Activate()
Code: Select all
LOCAL oMain
LOCAL oMainMenu
LOCAL oPopupFile
LOCAL oPopupHelp
LOCAL oPopupMore
LOCAL oPopupEdit
LOCAL oItemOpen
LOCAL oItemClose
LOCAL oItemMore1
LOCAL oItemMore2
LOCAL oItemMore3
LOCAL oItemCut
LOCAL oItemCopy
LOCAL oItemPaste
LOCAL oItemAbout
LOCAL oItemSave
LOCAL oButton1
LOCAL oButton2
LOCAL oButton3
LOCAL oButton4
LOCAL oButton5
LOCAL oButton6
LOCAL oButton7
LOCAL oButton8
LOCAL oButton9
LOCAL oButton10
HbQt_ErrorSys()
WITH OBJECT oMain := Window():New()
:Row := 10
:Col := 10
:Width := 400
:Height := 400
:Title := 'Nice OOP Demo!!!'
:Type := WND_MAIN
:OnInit := { || oMain:Center() }
* TO make the code more compact you can alternatively SET
* MenuItem properties as parameters ON 'new' method.
* Here the two ways will be shown
* MenuItem 'New' method parameters:
* ( cCaption , bOnClick , cImage , lChecked , lEnabled , lVisible )
WITH OBJECT oMainMenu := MainMenu():New()
WITH OBJECT oPopupFile := MenuPopup():New( 'oPopupFile',, 'File' )
oItemOpen := MenuItem():New( 'oItemOpen' ,, 'Open' , { || MsgInfo( 'Open' ) } )
oItemClose := MenuItem():New( 'oItemClose',, 'Close' , { || MsgInfo( 'Close' ) } )
WITH OBJECT oPopupMore := MenuPopup():New( 'oPopupMore',, 'More...' )
oItemMore1 := MenuItem():New( 'oItemMore1',, 'More 1!' , { || MsgInfo( 'More 1' ) } )
oItemMore2 := MenuItem():New( 'oItemMore2',, 'More 2!' , { || MsgInfo( 'More 2' ) } )
oItemMore3 := MenuItem():New( 'oItemMore3',, 'More 3!' , { || MsgInfo( 'More 3' ) } )
END WITH
oItemSave := MenuItem():New( 'oItemSave',, 'Save' , { || MsgInfo( 'Save' ) } , , .T. )
END WITH
WITH OBJECT oPopupEdit := MenuPopup():New( 'oPopupEdit',, 'Edit' )
oItemCut := MenuItem():New( 'oItemCut' ,, 'Cut' , { || MsgInfo( 'Cut' ) } , 'cut.png' )
oItemCopy := MenuItem():New( 'oItemCopy' ,, 'Copy' , { || MsgInfo( 'Copy' ) } , 'copy.png' )
oItemPaste := MenuItem():New( 'oItemPaste',, 'Paste' , { || MsgInfo( 'Paste' ) } , 'paste.png' , , .F. )
END WITH
WITH OBJECT oPopupHelp := MenuPopup():New( 'oPopupHelp',, 'Help' )
WITH OBJECT oItemAbout := MenuItem():New( 'oItemAbout' )
:Caption := 'Help'
:Image := 'Help.bmp'
:OnClick := { || MsgInfo( 'About' ) }
END WITH
END WITH
END WITH
Code: Select all
WITH OBJECT MainForm := WINDOW():New( "MainForm" )
:Row := 10
:Col := 10
:Width := 600
:Height := 600
:Title := "Form title: OOP syntax"
:Icon := ":L3W_ICO"
:WinType := WND_MAIN
:ToolTip := "This is MainForm tooltip"
:OnInit := {|| MainFrmOnInit() }
// :EnterLikeTab := .T. don't work properly
WITH OBJECT MAINMENU():New( "MainMenu" )
:FontSize := 12
WITH OBJECT MENUPOPUP():New( "PopUp1" )
:Title := "&File"
:ToolTip := "PopUp1 tooltip"
WITH OBJECT MENUITEM():New( "Action1" )
:Caption := "&1 Action"
:Icon := ":L3W_IMOVFW"
:OnClick := {|| MsgStop("QUI") }
END WITH
:AddSeparator()
WITH OBJECT MENUPOPUP():New( "PopUp2" )
:Title := "&Altro"
:Icon := ":L3W_IMOVNEXT"
:ToolTip := "Altro tooltip"
WITH OBJECT MENUITEM():New( "Action3" )
:Caption := "&Close"
:Icon := ":L3W_IMOVEJECT"
:OnClick := {|| MsgStop("QUA") }
END WITH
WITH OBJECT MENUITEM():New( "Action5" )
:Caption := "&Reset"
:OnClick := {|| MsgStop("XXX") }
:Enabled := .F.
END WITH
WITH OBJECT MENUITEM():New( "Action6" )
:Caption := "&6 Action"
:OnClick := {|| OnAction6() }
END WITH
WITH OBJECT MENUITEM():New( "Action7" )
:Caption := "&Print"
:OnClick := {|| MsgStop("ZZZ") }
:Visible := .F.
END WITH
:EndMenu()
END WITH // end PopUp2
:AddSeparator()
WITH OBJECT MENUITEM():New( "Action2" )
:Caption := "&Open"
:Icon := ":L3W_IMOVBW"
:OnClick := {|| MsgStop("QUO") }
END WITH
:AddSeparator()
WITH OBJECT MENUITEM():New( "Action4" )
:Caption := "e&Xit"
:Icon := ":L3W_IEXIT"
// :OnClick := {|| THISWINDOW:Close() }
:OnClick := {|| THISWINDOW:Release() }
END WITH
:EndMenu()
END WITH // end PopUp1
END WITH
END WITH
MainForm:Activate()
Code: Select all
// Main Menu
#xcommand DEFINE MAIN MENU [ <dummy1: OF, PARENT> <oParent> ] ;
=> ;
With Object :s_oMainMenu := MainMenu():New( "s_oMainMenu" [, <oParent> ] )
#xcommand DEFINE MAINMENU [ <dummy1: OF, PARENT> <oParent> ] ;
=> ;
With Object :s_oMainMenu := MainMenu():New( "s_oMainMenu" [, <oParent> ] )
#xcommand END MENU ;
=> ;
End With
// Popup - not named
#xcommand [ DEFINE ] [ MENU ] POPUP [ CAPTION ] [ <cCaption> ] ;
=> ;
:s_cNewPopUpMenuName := :s_oMainMenu:GetPopupVarName() ;;
With Object MEMVAR->&(:s_cNewPopUpMenuName) := MenuPopup():New( :s_cNewPopUpMenuName, , [<cCaption>] )
Code: Select all
// BarMenu
#xcommand DEFINE MAINMENU <oObj>[ <dummy1: OF, PARENT> <oParent> ] => ;
WITH OBJECT MAINMENU():New( <"oObj"> [, <oParent> ] )
#xcommand END MAINMENU => END WITH
// Menu
#xcommand DEFINE POPUP <oObj>[ <dummy1: OF, PARENT> <oParent> ] => ;
WITH OBJECT MENUPOPUP():New( <"oObj"> [, <oParent> ] )
#xcommand END POPUP => :EndMenu() ; END WITH
// Action
#xcommand DEFINE MENUITEM <oObj>[ <dummy1: OF, PARENT> <oParent> ] => ;
WITH OBJECT MENUITEM():New( <"oObj"> [, <oParent> ] )
#xcommand END MENUITEM => END WITH
I repeat.
My words must be considered as constructive criticism for the good of the project HMG4, to which many of us have contributed and spent their free time.
please, think about what I have given you before you shoot me
Viva HMGx, viva Clipper
Cheers
Luigi
Luigi from Italy
www.L3W.it
www.L3W.it
Re: To all hmg4 core developers, an important proposal
Luigi is right. We can freely mix OOP and xBase style.l3whmg wrote: second element: maintain a consistent programming style. Or use OOP or XBase classic style.
OOP style is WITH OBJECT xx := window():New()
xBase style is DEFINE WINDOW xx
variant of xBase style is the one with ; at the end of the line and one without... so we need to have multiple definition... and keep them in sync !!!!
This can lead to problems. For example look at DEFINE WINDOW in hmg.ch... it is translate to (partial)
Code: Select all
With Object <oObj> := Window():New( <"oObj"> [, <oParent> ] ) ; :s_oParentWindow := <oObj> ;;
Code: Select all
With Object :s_oParentWindow:oStatusBar := StatusBar():New( "oStatusBar" [, <oParent> ] );;
Luigi is not 100% correct on the need of variables to keep intermediate value. I don't remember why they started to appear. There were probably problems in the past, or it was just a shortcut to be able to reference them just with variable/object name...
With recent changes done (and for the reason that started this exact thread), New() automatically adds the object name as a data member of the parent and stores a reference to self there, and also adds itself to parent aControls.
So we don't need to have a local variable to keep the object "live" since there are at least 2 references to it stored in the parent... long life to the parent... !
Do windows need to have a variable ? short answer: no. Their New() adds them to hmgapp() object... so we may retrieve them starting from hmgapp().
hmgapp() iwanted to be a singleton but it was a not-really-a-singleton. I just committed a patch to make it a real singleton. Until now every time hmgapp() was called a new instance was created and this was ok was shared data members inherited from GLOBSHARED but was a pity for the standard data members from hmgapp itself... they reset at each call !
There were a couple of ways to solve the problem but I think that a singleton is the best way, it can help in the future.
I want to thank Luigi that shared his time with me in this week trying to understand how to improve hmg4., doing some tests, experimenting solutions, writing code, providing ideas and sharing his fork with me.
Re: To all hmg4 core developers, an important proposal
Hi to everyone, my friends.
Many thanks to MrDuck for his words. For reasons about space on this forum, I can't add a lot of examples or words.
To better explain my opinion, please feel this examples.
I consider the current demo programs like a "this is the fundamental of HMG4" and used to test HMG4 library and this is a little brief:
But the same is the real program written with "XBase command style"
OOP style it's very different. Please, put a little imagination to follow this example
So what I mean is: we can't mix OOP and XBase because they need a different approach. IMHO, OOP it's very powerfull, but for a long time I write with XBase style: I like it.
Everyone can see the difference between a real OOP program (very brief explanation) and demos and differences with XBase style.
So if we want preserve the ability to write programs (end program) with XBase style using HMG4, we can't introduce any var with LOCAL or within hmg.ch and we must change the class/core code approach. If we want loose the ability to write programs with XBase style using HMG4, I think the real example is the last one not the first.
About class layout it's only a suggestion, because I found it very useful to create this forest even if it is complex to administer and can create misunderstandings or problems.
Cheers
Many thanks to MrDuck for his words. For reasons about space on this forum, I can't add a lot of examples or words.
To better explain my opinion, please feel this examples.
I consider the current demo programs like a "this is the fundamental of HMG4" and used to test HMG4 library and this is a little brief:
Code: Select all
WITH OBJECT Button():New("button1")
or
WITH OBJECT Button():New()
or
WITH OBJECT Button1 := Button():New() this need a local declaration var
or
WITH OBJECT Button1 := Button():New("button1") this need a local declaration var
and
:row := 10
.....
END WITH
Code: Select all
DEFINE BUTTON Button1
ROW 10
....
END BUTTON
Code: Select all
FUNCTION Main
LOCAL oMainForm := MyMainWindow():New()
QUIT
RETURN NIL
CLASS MyMainWindow
DATA oForm
DATA oButton1
DATA oFormRow INIT 10
DATA oButton1Row INIT 40
....
METHOD New
METHOD Run
END CLASS
METHOD New() CLASS MyMainWindow
WITH OBJECT oForm := Window():New()
or
WITH OBJECT oForm := Window():New("myform") this is an example, but with OOP unusefull
:Row := oFormRow
.........
WITH OBJECT oButton1 := Button():New() or.....but is unusefull
:Row := oButton1Row
..........
END WITH
...........
END WITH
::Run()
RETURN Self
METHOD Run()
::oForm:Activate()
RETURN Self
Everyone can see the difference between a real OOP program (very brief explanation) and demos and differences with XBase style.
So if we want preserve the ability to write programs (end program) with XBase style using HMG4, we can't introduce any var with LOCAL or within hmg.ch and we must change the class/core code approach. If we want loose the ability to write programs with XBase style using HMG4, I think the real example is the last one not the first.
About class layout it's only a suggestion, because I found it very useful to create this forest even if it is complex to administer and can create misunderstandings or problems.
Cheers
Luigi from Italy
www.L3W.it
www.L3W.it