i have subclassed the ProgressBar control and named it “PBunlimited”. I added a private computed property “MaxFactor”.
After adding this control to Window1 and a “Run” the following should happen:
The “Maximum” value of PBunlimited - inherited from the Super ProgressBar (=100) - should be checked if it was changed
in the Xojo Inspector
If the value was changed, the “Maximum” of PBunlimited should be calculated to a new value. Then this new value should
be set as the new PBunlimited’s new Maximum and the “MaxFactor” should also be set (as Read Only thus the “Set” is not used" .
I tried to do this by adding a “public Computed Property” and naming it just as the Supers (ProgressBar) property “Maximum”. I tried to override/shadow the “Maximum” property, but that does not work.
Can anyone tell me how i can solve that problem in any way ?
General:
A subclass of a control should be checked (after instantiating or adding to a window and running the program) if
a value of a property of the (subclass-)control was changed in Xojo inspector or in the code (changed = no more the default value)
if the changed value exceeds a limit (set by a constant) the value should be calculated to a new one
the new calculated value should be set as the new (subclass-)control property value
3a) the calculation in 2) gives also a factor that should be set as value of a new property
Example:
ProgressBar1 -> subclass “PBunlimited1”
PBunlimited1 added to Windows1
In Inspector change of “Maximum” of PBunlimited1 from 100 to 10000000
Run
[now the followin should be done automatically]
-> check if Maximum was changed and greater than 65536 => then do
divide Maximum of PBUnlimited by 65536 and set private property mMaxFactor to the next rounded-up whole number of the division
[10000000 / 65536 = 152,587890625 -> rounded up to next whole numer = 153]
divide the Maximum by mMaxFactor value and set Maximum of PBunlimited1 to the next rounded-down whole number of this division
[10000000 / 153 = 65359,47712418301 -> rounded down to next whole numer = 65359]
[PBunlimited.MaxFactor should be set to 153, PBunlimited.Maximum should be set to 65359]
About the only way to do this is to start a Timer in the control’s constructor and put your initialization code in it. The reason is that the values set in the IDE are loaded after the constructor finishes, so your constructor won’t see the new value.
Thank you, but i got no idea how to do what you suggest. On my Padlet wall you can download a “Test” project file. There you can see how i tried to solve the problem but the maximum is either reset to 0 or an exception is thrown.
First, shadowing a property like this is a bad idea. However, if you want to make it work, you need to change your Maximum.Set code to
if value > 65536 then
mMaxFactor = Ceil(value / 65536)
Progressbar(me).Maximum = floor(value / mMaxFactor )
else
Progressbar(me).Maximum = value
end if
(By “bad idea”, I mean that shadowing a property makes your code fragile. It is still possible to manipulate Maximum directly without going through your computed property.)
Thank you very much. Now i could finish my Subclassed ProgressBar example.
But can you maybe explain to me why i must use “Progressbar(me).Maximum” instead of “Me.Maximum” or “Progressbar.Maximum” or “PBunlimited.Maximum” ?? (Any link where i read about that ?)
Be aware that you can not do the following (assuming that your window contains ProgressBar and PBunlimited instances):
For i As Integer = 0 To Window1.ControlCount - 1
If Window1.Control(i) IsA ProgressBar Then
// a ProgressBar or a PBunlimited
ProgressBar(Window1(i)).Maximum = ... // This will use the code of the Maximum property of ProgressBar,
// even if it is an instance of PBunlimited
End
Next
You will have to first handle the subclass:
For i As Integer = 0 To Window1.ControlCount - 1
If Window1.Control(i) IsA PBunlimited Then
// a PBunlimited
PBunlimited(Window1(i)).Maximum = ... // This will use the code of the Maximum property of PBunlimited
ElseIf Window1.Control(i) IsA ProgressBar Then
// a ProgressBar, which is not a PBunlimited
ProgressBar(Window1(i)).Maximum = ... // This will use the code of the Maximum property of ProgressBar
End
Next
That’s one of the nasty things of not being able to override properties like in VB. NET and most of the other OOP languages.
Thanks for that hint. I’m new to programming and i haven’t to loop through controls for now but when it comes to my learning experience i will remember it.
That is the very heart of the problem with shadowing a property. The type of variable you use matters. This isn’t a problem with overriding methods, but is a big problem with shadowing properties. Methods are virtual - they are resolved at runtime and will find the correct method to call based on the type of object, regardless of the type of variable. Properties are not - they are resolved at compile time based on the type of variable, regardless of the type of object the variable holds. This can lead to very subtle, hard to find bugs. You have to be very careful when shadowing a property.