Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

proper way to give many controls same custom method

Status
Not open for further replies.

Nifrabar

Programmer
Mar 16, 2003
1,343
NL
Hi!

One of my users asked to provide facility to manage colors himself.

I am having an application object [oApp] and thought that's the right place to store these settings.

Just as an example:
Than I have in the init-method of controls in custom-base-class some like:
Code:
if vartype(oApp) = "O" and !isnull(oApp)
	this.disabledbackcolor = oApp.cDisabledBackcolor
endif 
this will be repeated for forecolor, backcolor etc.
My Q: what is best way to have all concerned controls such a custom method?
A solution might be hardcoding in every concerned control from my custom-base-class but from OOP vision I feel, but don't know how to, this must be possible with a single piece of code which will be valid for all controls it concerns.

Any suggestion?

-Bart
 
Unfortunatly there is no main base class all base controls inherit from, where you centrally could set this.

So for example: Even though both textbox and editbox have a disabledbackcolor you have to add your code to every single of your custom-base-classes (I assume you mean your own vcx of the foxpro base classes subclassed for adding central changes).

I would take your idea and transform it a bit:

1. Checking for vartype "O" just checks oApp is an object, this code does not guarantee the oApp object has a cDisabledBackcolor, use PEMSTATUS() to check that. I also mention GetPEM(), and I use bith in my solution below.

2. The custom property would not be called cDisabledbackcolor in the normal foxpro naming conventions "c" denotes a character property, native properties have no such prefix, but if you'd add it, it would be i in case of a color, as RGB() returns an integer. In this case I would just work with an empty object and add the property names 1:1, having SCATTER ADDITIVE in the back of my mind.

3. You can make the process to have a template for all your controls a bit easier this way:

Add a subobject oSettings to oApp, this way in oApp init:
Code:
Addproperty(oApp,"oDefaults",Createobject("empty"))
Addproperty(oApp.oDefaults,"DisabledBackcolor",RGB(128,128,128)) && might also read the concrete values from a config.dbf
* etc, etc.

Then add a method to oApp called SetControlDefaults
Code:
* SetControlDefaults
Lparameters toControl
Local lnCounter, lcProperty, laProperties[1]
If VarType(oApp) = "O" and PEMStatus(oApp,"oSettings",5)
   For lnCounter = 1 To AMEMBERS(laProperties,oApp.oDefaults)
      lcProperty = "toControl."+laPoperties[lnCounter]
      Try
         Store GetPEM(oSettings,laPoperties[lnCounter]) To (lcProperty)
      Catch
         *
      EndTry
   Endfor    
EndIf

Then in controls Init you need to add:
Code:
If Vartype(oApp) = "O" and PEMStatus(oApp,"SetControlDefaults",5)
   oApp.SetControlDefaults(THIS)
Endif

Bye, Olaf.
 
errata: Line 4 of the second CODE block should be
Code:
If VarType(oApp) = "O" and PEMStatus(oApp,"[u]oDefaults[/u]",5)

Settings was the name I initially thought about, then thought Defaults would describe the efault values better.

Bye, Olaf.
 
...and two other things should be changed. I should make use of Search & Replace :)

AMEMBERS(laProperties,oApp.oDefaults) --change-to--> AMEMBERS(laProperties,This.oDefaults)

GetPEM(oSettings... --change-to--> GetPEM(This.oDefaults,...)

Bye, Olaf.
 
Bart,

Have you got such a thing as "root class library"? This is a class library (VCX file) that contains a basic sub-class of each of the built-in classes. Each sub-class has the minimum of changes to its properties and methods.

This is quite a common arrangement, and one that I would recommend.

The purpose of this library is to act as the ultimate parent on which all your sub-classes are based. In other words, you never directly sub-class the built-in classes. You always use this root library as your starting point.

My point is that, if you do have such a library, it becomes an easy matter to add the custom method to every one of your classes. You could write a program to do it, but an easier way might be to use the macro recorder.

Essentially, you write a macro that opens a class in the class designer, adds the required method, inserts code into the method, and saves and closes the class. You then run that macro repeatedly for each class in turn.

In my own class libraries, every class has a method named Documentation, which contains notes on the purpose of the class, how to use it, etc. I created those methods using the system described above.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Hi Olaf,
custom-base-classes (I assume you mean your own vcx of the foxpro base classes subclassed for adding central changes)
Yes, that's what I do.
Once when I switched from DOS to visual foxpro Anders Altberg taught me a lot to 'take' the learning curve.
So I am having a VCX holding all base-classes. Than subclassed that to have my 'own' base class. That's where I put the general stuff.
The way you are adding and setting properties is about what I looked for. So going to give that a try.

And Olaf, you'r right re. the disabledbackcolor-type being numeric. I was influenzed by the property setting xxx,yyy,zzz which I faulty interpreted as a characterstring.
To my knowledge the numeric will be : xxx*255*255 + yyy*255 + zzzz


Mike,
I think Olaf's solution is asking less efforts as at least every control's init just asks for a 3-line piece of code to set all color-properties. Ar eyou with me at that point?
I am with you that the documentation method of whatever name you give to that is very worthfull. Especially once you want te resuse controls the other months.. ;) Our memory is no longer as it was 30yrs ago...

Anyway, as usual
thanks for your thoughts!
-Bart

 
Bart,

Yes, you're probably right that Olaf's method is less effort. My method has the advantage (or disadvantage?) of being a one-off action. Once you've done it for your root class library, it's done for everything. But the main thing is for you to find a solution that you're comfortable with.

By the way, some years ago, one of the Fox regulars (I think it was Tamar, but can't be sure) published a tip in FoxPro Advisor that might be relevant. She showed how to write a program to automatically create a root library and populate it with a basic sub-class of each of the native controls, and then to add a custom property or method to every sub-class. I think she used (_foxcode) to determine the names of all the base classes.

You say "Our memory is no longer as it was 30yrs ago". In my cases, that should be 30 days.

Veel succes met dit probleem,

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Mike,

I indeed think a method to create some meta base class and some code to put it's methods into a library of base classes is cleaner than putting these methods into an app class, indeed.

An elegant solution is not given by the nature of the foxpro base classes. Internally I think many common properties like the color properties actually have a base C++ clas, but one we don't get to see and are not able to subclass from. This is a bit of a pity.

My way keeps the code you need to put in each control a minimum and also centralises the code to be able to make changes "inherited" (kind of) from oApp by controls making an oApp call. But it also has a disadvantage you need to know: Any object, also oApp, is instanciated in some datasession (despite the session class spawning a new datasession of course) and so calls made into oApp switch to oApps datasession. If you centralise anything having to do with aliases, then stay away from putting this into an app class, this is better put into each individual base class.

So I like this methodology of Tamar. You can easily get a list of base classes via ALANGUAGE(laBaseClasses,3)., should only skip ActiveDoc and nonvisual classes, as Session and of course Empty.

Bye, Olaf.

 
You could also turn things around: If you add some code to each base class to instanciate an event handler class (eg custom) for once and then connect THIS to that event handler via bindevents you could even extend control events in a generic way, without the need to copy the code into base classes.

The only event you obviously can't bind to is Init, but that's where you create the eventhandler anyway and could call some default init code, too, of course.

Bye, Olaf.
 
Hi Bart,
Today your customer wants his own colours, tomorrow an other customer wants his own fontstyle and the day after tomorrow....

Greg L. Reinart has constructed a class Style.vcx which you can download at his site with this class users can create there own GUI.
Piece of advise: extend the class with a MyDodefault method to reset the GUI to the original status in case users have fooled around with the GUI and your application has become a mess.

Groet,

Koen
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top