Objects added two times: problem o misunderstanding?

Moderator: Rathinagiri

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

Re: Objects added two times: problem o misunderstanding?

Post by l3whmg » Wed Jun 15, 2011 10:07 am

Hi to everyone.
1) about name. I think it's a good thing to remove this syntax ":Name := " because can create a lot of problem; on the other hand A) we treat the name in the New method (see the automatic procedure), B) ":Name" take effect when we execute "End With", C) with preprocessor we can handle very easy:

Code: Select all

WITH OBJECT Button():New( cName )
it will be

Code: Select all

DEFINE BUTTON <ObjectName>  ===> WITH OBJECT Button():New( ObjectName )
or

Code: Select all

DEFINE BUTTON <ObjectName>  ===> WITH OBJECT <ObjectName> := Button():New( ObjectName )
2) in my opinion, we can add an array (childs) and use it when we add (AddData method) object to its parent, to havee this syntax:

Code: Select all

ParentControl:ChildControl:Value
So, when we use "__objAddData( Self, cObjname)" we can add the object we do the same to the array; with some functions we can test if exists a control with the given name ( and for this, take a look to problem 1)).
Unfortunately, I never could use the statement "__ObjDelData" because create me problem (I don't know why, but read harbour changelog); I always use <cObjectName>:= NIL. This statement clears the object, but don't remove object from its parent! With arrary, I remove the name et voilà: I can test its presence and recreate.
N.B. if we have a SuperParent, we can use the same method to control window: it's already defined, order creation and so on....
The last but not the least, we can get a list of childs:

Code: Select all

METHOD ChildList            INLINE aChilds
P.S. perhaps we can also use aControls array.

IMHO, I don't know if it's a good future recreate an object with the same name: before "button1" was a button after will be a label: mmmmh!

Best regards
Luigi from Italy
www.L3W.it

User avatar
concentra
Posts: 256
Joined: Fri Nov 26, 2010 11:31 am
Location: Piracicaba - Brasil

Post by concentra » Wed Jun 15, 2011 12:00 pm

Hi.
l3whmg wrote: 1) about name. I think it's a good thing to remove this syntax ":Name := "
I am not sure, but isn´t this break HMG3 compatibility ?
C) with preprocessor we can handle very easy:

Code: Select all

WITH OBJECT Button():New( cName )
it will be

Code: Select all

DEFINE BUTTON <ObjectName>  ===> WITH OBJECT Button():New( ObjectName )
or

Code: Select all

DEFINE BUTTON <ObjectName>  ===> WITH OBJECT <ObjectName> := Button():New( ObjectName )
Agree. Lets start this ?
2) in my opinion, we can add an array (childs) and use it when we add (AddData method) object to its parent, to havee this syntax:

Code: Select all

ParentControl:ChildControl:Value
So, when we use "__objAddData( Self, cObjname)" we can add the object we do the same to the array;
Didn´t get it... How can we do ParentControl:ChildControl:Value using an array ? Could you sample some code please ?
with some functions we can test if exists a control with the given name ( and for this, take a look to problem 1)).
This is already possible, using Harbour __Obj functions, we can code a runtime error message when a duplicated name is used.
Unfortunately, I never could use the statement "__ObjDelData" because create me problem (I don't know why, but read harbour changelog)
Luigi I wasn´t aware of this problems and coded ( and committed ) removing old names from the parents when renaming, using __ObjDelData . Tested all demos and they worked fine.
Could you get more information on this problems because if they exists we need to remove it from the code...

IMHO, I don't know if it's a good future recreate an object with the same name: before "button1" was a button after will be a label: mmmmh!
Again, we can code a runtime error message when a duplicated name is used.
[[]] Mauricio Ventura Faria

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

Post by l3whmg » Wed Jun 15, 2011 2:00 pm

Hi Mauricio.

1) about name. HMG3 compatibility require the ability to assign a name to the object. This ":Name" is been introduced with startup of HMG4 development and I think (at that moment) was the best solution. HMG3 handle in different way because it's different. The most important thing is to assign the name. When? IMHO when I create/define the object. How to? IMHO with a parameter in the New() method.
ie button

Code: Select all

OOP Style
WITH OBJECT button():New( cName )
....
END WITH

Code: Select all

XBASE style
#xcommand DEFINE BUTTON <ButtonName> => WITH OBJECT button():New( <"ButtonName"> )
n.b. Also, with previous syntax (WITH OBJECT) it's most relevant the order; the values assigned are "stable" only when reaching the END WITH
ie button

Code: Select all

WITH OBJECT button():New()
...
:Name := xxxx
END WITH
When New() method is execute, cName is empty. When END WITH is execute cName is xxxx.

I can apply this to HMG4, but it take a while. Tell me if I can start. This is an important rule: all team members agree?

2) about the existence of an object
first about __objDelData. In my experience, this harbour function remove the object but alters the structure of parent - objects.
Perhaps, with last harbour work fine or was a problem with my test program. Anyway, if you use it and work fine very good.

I'm sorry for my bad explanation. Th problem is to check if object it's already defined, but before to show solution a little brief of my experience
with Harbour object. When you use __objAddData you add a DATA (new object) to an object (parent); in HMG4 we use this function to have syntax: Parent:Object:....
But parent have a lot of prebuild Harbour DATA and name stored (if I understand very well) are case sensitive (this is the problem to use harbour _obj functions)
My solutions are two, but REMEMBER: this at oParent level.

A) When we use function AddData (that is, when we use __objAddData) we can add cName to an array (ie Childs)

Code: Select all

METHOD AddData( cObjName, oObject )
__objAddData( Self, cObjName )
::&cObjName := oObject
AADD( ::aChilds, ALLTRIM( LOWER( cObjName ) ) )    <=====
RETURN Self
If we want check if exist, we can use:

Code: Select all

METHOD NameIsDefined( cObjName )
LOCAL nX := ASCAN( ::aChilds, LOWER( ALLTRIM( cObjName ) ) )
RETURN IIF( nX>0, .T., .F. )
IF we want a list of controls we can use

Code: Select all

METHOD ControlList INLINE ::aChilds
IF we want to remove

Code: Select all

METHOD RemoveObject( oObject, cObjName )
LOCAL nX := ASCAN( ::aChilds, LOWER( ALLTRIM( cObjName ) ) )
IF nX > 0
::aChilds := hb_adel( ::aChilds, nX, .T. )
Self:__objDelData( oObject, cObjName )
ENDIF
RETURN Self
Problem in this last method: __objDelData requires oObject and cObjName. For me, everyone can be a problem. Bu if I use

Code: Select all

METHOD RemoveObject( cObjName )
LOCAL nX := ASCAN( ::aChilds, LOWER( ALLTRIM( cObjName ) ) )
IF nX > 0
::aChilds := hb_adel( ::aChilds, nX, .T. )
Self:&cObjName := NIL
ENDIF
RETURN Self
B) we can use aControls

Code: Select all

METHOD NameIsDefined( cObjName )
LOCAL nX, lReturn := .F.
FOR nX := 1 TO LEN( ::aControls )
lReturn := IIF( LOWER( ALLTRIM( cObjName ) ) == LOWER( ALLTRIM( ::aControls:Name() ) ), .T., .F. )
RETURN lReturn
but it is dangerous. An object can not be named?

3) about my last opinion
The problem is: why I RECREATE an object? I can alter properties or I want to remove, but IMHO I never create a BUTTON with name Button1 and then
I create a FORM with name Button1. This is my question.

Best regard
Luigi from Italy
www.L3W.it

User avatar
concentra
Posts: 256
Joined: Fri Nov 26, 2010 11:31 am
Location: Piracicaba - Brasil

Post by concentra » Thu Jun 16, 2011 11:09 am

Hi Luigi.
l3whmg wrote:I can apply this to HMG4, but it take a while. Tell me if I can start. This is an important rule: all team members agree?
I do. Does anyone disagree ?
When you use __objAddData you add a DATA (new object) to an object (parent); in HMG4 we use this function to have syntax: Parent:Object:....
What I misunderstood in your previous post was that I supposed you were talking about doing Parent:Object:.... without using __objAddData, using an array.
That was why I asked for more info. But seems I was wrong, you are talking about still using __objAddData.
about the existence of an object
We can use __objHasMsg( oObject, cName ) to inspect an object and see if cName was previously added, without using an array.
first about __objDelData. In my experience, this harbour function remove the object but alters the structure of parent - objects.
Perhaps, with last harbour work fine or was a problem with my test program. Anyway, if you use it and work fine very good.
This can be dangerous. The fact that this is working now don´t tells all the story... I searched about it and found little info but Przemek talks really bad about this in 2007. And you also had bad experiences with it, so it is probably a good idea avoid it.
A) When we use function AddData (that is, when we use __objAddData) we can add cName to an array (ie Childs)
Such an array is redundant with aControls. If we will do this, we must use aControls.

I will suggest something different:
Today, AddData method always set an object to ::cName.

Code: Select all

METHOD AddData( cName , oObject ) CLASS BASIC

   __objAddData( Self , cName )

   ::&cName := oObject

   RETURN NIL
DelData method can avoid __objDelData this way:

Code: Select all

METHOD DelData( cName ) CLASS BASIC

   IF __objHasMsg( Self, cName )  // This tells that cName exists in the object.
     ::&cName := NIL
   ENDIF

   RETURN NIL
And if needed, NameIsDefined() could be:

Code: Select all

METHOD NameIsDefined( cName )

   RETURN ! __objHasMsg( Self, cName ) .OR. HB_IsNil( ::&cName )
These will work because if ::cName is an object it was previously added and not deleted and if its NIL its still there or don´t exists at all.
This is simpler and do not need extra array control stuff.
[[]] Mauricio Ventura Faria

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

Post by l3whmg » Thu Jun 16, 2011 11:51 am

Hi Mauricio,
ok we are in agreement and you understand my bad english ;)
About obj functions I have a little question: when a programmer write his program can do "mistake" :shock:
I can write this
With Object Button():New( "Button1" ) <=== take a look to the name
Then I can use MAINFORM:BUTTON1:Value <=== take a look to the name
Then somwhere I want DelData( "BUTTON1" ) <=== take a look to the name
I think the last one fails, because (if I remember well) Harbour obj functions are case sensitive. For this reason a loop inside ::aControls can solve the problem; ie like this source code

Code: Select all

METHOD RemoveObject( cObjName )
LOCAL nX, nY
FOR nX := 1 TO LEN( ::aControls )
IF LOWER(ALLTRIM(::aControls:Name())) == LOWER( ALLTRIM( cObjName ) ) )
 nY := nX
ENDIF
NEXT nX
IF VALTYPE( nY ) == "N"
::aControls[nY] := NIL
::aControls:=hb_adel(::aControls, nY, .T.)
ENDIF
RETURN Self
Any way, I do some test and give you my experience. I'll do with HMG3 new version :mrgreen:

About mod to the name, I will wait a while and then I communicate the beginning. Unfortunately, this change involves both the core code that the examples.

Best regards
Luigi from Italy
www.L3W.it

User avatar
concentra
Posts: 256
Joined: Fri Nov 26, 2010 11:31 am
Location: Piracicaba - Brasil

Post by concentra » Thu Jun 16, 2011 12:11 pm

l3whmg wrote: With Object Button():New( "Button1" ) <=== take a look to the name
Then somwhere I want DelData( "BUTTON1" ) <=== take a look to the name
Understood... But isn´t simpler to lower names ?

Code: Select all

METHOD AddData( cName , oObject ) CLASS BASIC

   __objAddData( Self , LOWER(cName) )

   ::&cName := oObject

   RETURN NIL

Code: Select all

METHOD DelData( cName ) CLASS BASIC

   IF __objHasMsg( Self, LOWER(cName) )  // This tells that cName exists in the object.
     ::&cName := NIL
   ENDIF

   RETURN NIL
[[]] Mauricio Ventura Faria

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

Post by l3whmg » Thu Jun 16, 2011 12:23 pm

Hi Mauricio.
You are a demon! It's good your code. My intention was: don't change old code and create new functions with tricks!
Best regards.
Luigi from Italy
www.L3W.it

User avatar
concentra
Posts: 256
Joined: Fri Nov 26, 2010 11:31 am
Location: Piracicaba - Brasil

Post by concentra » Thu Jun 16, 2011 12:28 pm

Ok. :twisted:
So, I will commit this.
[[]] Mauricio Ventura Faria

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

Post by l3whmg » Thu Jun 16, 2011 12:43 pm

Hi.
Only one note (in this moment I don't remember very good):

the function is "__objHasMsg( cName )" or "__objHasData( cName )" ?
Because we use __objAddData"

Best regards.
Luigi from Italy
www.L3W.it

User avatar
concentra
Posts: 256
Joined: Fri Nov 26, 2010 11:31 am
Location: Piracicaba - Brasil

Post by concentra » Thu Jun 16, 2011 1:14 pm

Please see this, extracted from \harbour\src\rtl\objfunc.prg:

Code: Select all

FUNCTION __objAddData( oObject, cSymbol )
   LOCAL nSeq, hClass

   IF ! ISOBJECT( oObject ) .OR. ! ISCHARACTER( cSymbol )
      __errRT_BASE( EG_ARG, 3101, NIL, ProcName( 0 ) )
   ELSEIF !__objHasMsg( oObject, cSymbol ) .AND. !__objHasMsg( oObject, "_" + cSymbol )
      hClass := oObject:ClassH
      nSeq   := __cls_IncData( hClass )         // Allocate new Seq#
      __clsAddMsg( hClass,       cSymbol, nSeq, HB_OO_MSG_ACCESS, NIL, 1 )
      __clsAddMsg( hClass, "_" + cSymbol, nSeq, HB_OO_MSG_ASSIGN, NIL, 1 )
   ENDIF

   RETURN oObject
[[]] Mauricio Ventura Faria

Post Reply