Page 1 of 2
Enumeration etiquette
Posted: Tue Aug 30, 2011 8:18 pm
by Zach
Just curious how other programmers handle Enumeration of Constants, for things like Gadgat/Window ID's etc..
Are there some things you avoid Enumerating? If so, why?
Since I've been working on the GUI portion of my game engines World Editor tool, I have realized that I will have/need a lot of constants.
I don't have very many right now, although I did go back and re-establish some naming rules for myself to make it easier to type & recognize them.
I feel it would be easier when referring to constants by name, than an arbitrary number as I would end up backtracking all the time to look something up and see what it does. So I am thinking I want to also Enumerate my MenuID's and I figure I may as well do PanelID's etc as well.
I don't want to end up with any errors though (I got errors in some code due to some Enumeration issue one time, but I think it was an isolated case)
for things like Menu and Panel ID's though I'm not sure if I need to be careful to reset the Enumeration to 0, since I know some items maintain separate ID/position stacks. For example I could have my main Application Window with the ID "1", and I could also have my first Menu item as ID "1", as well as first Panel Item, and so on..
But I think this will confuse me more when looking at code, and I'd rather have a straight Enumeration section that enumerates every handle I will use for an object.
That way it won't matter if I am adding the object for the first time, or modifying it further down, or checking for an event /passing an event to an item. I can just use its constant everywhere and it will be much easier to read.
Should I just have one single Enumeration List, or should I break them up by Components (Main Window/Gadgets, Menu/Submenus, Panels/Trees/etc.
So, What do you guys do?
Re: Enumeration etiquette
Posted: Tue Aug 30, 2011 8:42 pm
by Demivec
Zach wrote:Should I just have one single Enumeration List, or should I break them up by Components (Main Window/Gadgets, Menu/Submenus, Panels/Trees/etc.
You can do it either way. If you do it as an all in one you would still have to group the items and set the first item in each group to a constant (i.e. 0) before enumerating the rest of that group. If you used separate enumerations you would just list the items without an initial value specified. As you can see they basically look the same.
There are of other ways as well. I just don't think it makes a difference which way you do it.
Re: Enumeration etiquette
Posted: Tue Aug 30, 2011 8:52 pm
by Zach
Demivec wrote:If you do it as an all in one you would still have to group the items and set the first item in each group to a constant (i.e. 0) before enumerating the rest of that group
I'm not sure I quite understand what that means?
Are you saying I would be forced to, by the compiler or something? Because certain groups of items must always start from 0 ??
Re: Enumeration etiquette
Posted: Tue Aug 30, 2011 9:22 pm
by Rook Zimbabwe
I am completely unclear about exactly what is wrong with the current enum scheme?
Code: Select all
Enumeration
#Window_MAIN
#Window_PPAD
#Window_OPENTIK
#Window_KEYBOARD
#Window_TABLE
#Window_KITTIK
#Window_MANAGER
#Window_PAY
#Window_SPLIT
EndEnumeration
Enumeration
#Button_DINNER
#Button_LUNCH
#ResultFile
#Image_LOGO1
#Button_OPBACKMAIN
#Button_OPSCRUB
#Button_OPLOUT
#Button_OPCLEAN
#Button_POP102
#Button_POP103
#Button_POPADD
#Text_POPMENU
#Frame3D_BW0
#Button_BWIT0
#Button_BWIT1
#Button_BWIT2
#Button_BWIT3
#Button_BWIT4
EndEnumeration
;-
#ODBC_ADD_DSN = 1 ; Add Data source
#ODBC_ADD_SYS_DSN = 4 ; Add SYSTEM Data source
#ODBC_CONFIG_DSN = 2 ; Configure (edit) Data source
#ODBC_REMOVE_DSN = 3 ; Remove Data source
#ODBC_REMOVE_SYS_DSN = 6 ; Remove SYSTEM Data source
#SQL_SUCCESS = 0
#SQL_SUCCESS_WITH_INFO = 1
Both styles are supported but if you use the autoenum you just need to make sure you use LABELS you can remember or that are self explanitory... Use and ABUSE!

it is sooo much simpler than attempting to obfuscate with some sort of NUM system! You don't have to call it by number you call it by what it is... same speed!

Re: Enumeration etiquette
Posted: Tue Aug 30, 2011 9:57 pm
by Zach
I never said anything was "wrong" with the auto-enumeration setup, did I?
I like to do certain things myself though, or at least setup any automation myself/the way I want, in this case.
All I did was ask what others do
Re: Enumeration etiquette
Posted: Tue Aug 30, 2011 10:05 pm
by Demivec
Zach wrote:Demivec wrote:If you do it as an all in one you would still have to group the items and set the first item in each group to a constant (i.e. 0) before enumerating the rest of that group
I'm not sure I quite understand what that means?
Are you saying I would be forced to, by the compiler or something? Because certain groups of items must always start from 0 ??
No, there would be no forcing going on. Use whatever numbers you choose.
Zach wrote:for things like Menu and Panel ID's though I'm not sure if I need to be careful to reset the Enumeration to 0, since I know some items maintain separate ID/position stacks. For example I could have my main Application Window with the ID "1", and I could also have my first Menu item as ID "1", as well as first Panel Item, and so on..
As you said, some things use separate 'sets' of ID's. If you intermingle them and number them all sequentially as a group (i.e. gadgets 1..2..3, windows 4..5..6, panels 7..8..9, etc.) you have the potential of simply wasting memory because PureBasic reserves space for those objects as determined by the highest number used (i.e. 9000 = space for 9001 objects, 0 - 9000), even if the lower numbered object ID's are never used. It is important to note that ID's returned using #PB_Any don't fall under this guideline.
Re: Enumeration etiquette
Posted: Tue Aug 30, 2011 10:48 pm
by Thorium
I dont use constants much for objects.
In most cases i use #PB_Any, it's more flexible.
Re: Enumeration etiquette
Posted: Wed Aug 31, 2011 12:14 am
by Zach
Yeah I just realized I forgot to ask about #PB_ANY
I've never really used it, or seen it used (that I can recall, probably used in examples all over the place)
I guess I don't understand how I could use it to recall an object later though
if I added two text gadgets and wanted to change text in one....how would I reference it / get the ID without knowing its number?
Or is this a case of having to use a variable every time?
Code: Select all
Label1 = TextGadget(#PB_ANY)
Label2 = TextGadget(#PB_ANY)
SetGadgetText(Label1)
like that?
I can see instances where both methods are beneficial... but even with #PB_ANY you are still creating a list of names to run by, I prefer to do it in advance with #CONSTANTS defined at the top, for mostly static objects, I think.. But for variable changing things like a Recent Files list, and similar things of that nature, I can see the usefulness of using #PB_ANY.
Thanks for the input everyone.
Re: Enumeration etiquette
Posted: Wed Aug 31, 2011 12:32 am
by netmaestro
Yes, that's it. There are a couple of considerations for using PB_Any though. Firstly, as you reference the object# via a variable, that variable will often need to be global for use inside procedures unless it is a member of a passed structure. Secondly, using PB_Any means the Purebasic compiler will choose an object# for you from a pool it maintains. This number is going to be very high and so it can't be reused as a static object number. For example:
Code: Select all
image1 = CreateImage(#PB_Any, 64,64)
; use the image in some way
FreeImage(image1)
CreateImage(image1, 64,64) ; incorrect
; or, more commonly tried:
CopyImage(<someimage>, image1)
This represents attempts to reuse a PB_Any image# as a static image# and it's incorrect. The debugger will complain about it, and if you turn off the debugger it may well work, but you're interfering with Purebasic's management of PB_Any object#'s and, not knowing this one is gone, PB may try to use it if PB_Any is called again. That's the first reason. The second reason is that when you choose a static object#, PB will allocate memory for those objects with static object#'s from 0 up to the one you chose. Since this is going to be a very high number, you are allocating memory for thousands of images unnecessarily.
Re: Enumeration etiquette
Posted: Wed Aug 31, 2011 1:14 am
by Zach
Yeah I wouldn't try to do that anyway. I would always start with a new var= after freeing something
Re: Enumeration etiquette
Posted: Wed Aug 31, 2011 1:25 am
by Thorium
Zach wrote:
I can see instances where both methods are beneficial... but even with #PB_ANY you are still creating a list of names to run by, I prefer to do it in advance with #CONSTANTS defined at the top, for mostly static objects
#PB_Any is a must use if you dont know the count of objects. For example you write a MDI application and allow the user to open as many editing windows as he wants. There you need to use #PB_Any. And thats why i use it in most cases, because then it's easy to change my code to allow creation of multiple objects. If you used constants for all it's a lot of work if you decide later you want to allow the user to create multiple objects of the same type (like windows).
Re: Enumeration etiquette
Posted: Wed Aug 31, 2011 1:36 am
by SFSxOI
I like to group them for the final code...
Code: Select all
Enumeration ;->Enumeration Window
#WindowKey1
#WindowKey2
#WindowKey3
; etc....
EndEnumeration
Enumeration ;->Enumeration Array 1
#Array1Key1
#Array1Key2
#Array1Key3
#Array1Key4
; etc...
EndEnumeration
Enumeration ;->Enumeration Something Else
;etc....
EndEnumeration
; and sometimes for like a long procedure.....
Enumeration ;->Enumeration MyProc()
#MyProc1Key1
#MyProc1Key2
#MyProc1Key3
#MyProc1Key4
; etc...
EndEnumeration
For those occaisional use or one time use constants I may or may not place them in an enumeration for their associated process or use. If the occaisional or one time use constants are sequential for their value I sometimes do place them in an enumeration. Overall though, I try to pay attention to the needs of what i'm working on, for example - if i'm converting something from C++ code to PB use if the API calls for a constant and that constant is in an enumeration in the SDK then in my code the whole enumeration gets put in even though I may only use one or two constants from the enumeration as I may want to expand the code a little in the future and need the constants so they will already be there for use without having to stop and look them up again. I try also for the final code to arrange enumerations and constants in the order in which they are used in the code...e.g.. #MyKey1 is used in the first procedure and is used first in that procedure so that constant would go at the top of the list as one of the first constants listed, but thats just an 'organizational' thing.
Re: Enumeration etiquette
Posted: Wed Aug 31, 2011 7:53 am
by blueznl
A bit on enumeration:
http://bluez.home.xs4all.nl/purebasic/p ... numeration
A bit on #PB_Any:
http://bluez.home.xs4all.nl/purebasic/p ... htm#pb_any
Me myself I tend to throw all enumerations together, grouping them by type:
Code: Select all
Enumeration
;
; *** windows
;
#w_main_nr
#w_about_nr
;
; *** toolbars
;
#tb_main_nr
;
EndEnumeration
;
; *** windows
;
Global w_main_h.i
Global w_about_h.i
;
; *** toolbars
;
tb_main_h.i
;
A perhaps better approach would be to group them, ie. a block for window 1, a block for window 2, and so on... Be careful though as you may end op with identical numbers, so you'll have to use the PureBasic constant #PB_Compiler_EnumerationValue
Code: Select all
;
; *** main window
;
Enumeration #PB_Compiler_EnumerationValue
#w_main_nr
#tb_main_nr
EndEnumeration
;
Global w_main_h.i
Global tb_main_h.i
;
; *** about window
;
Enumeration #PB_Compiler_EnumerationValue
#w_about_nr
EndEnumeration
;
Global w_about_h.i
;
Yet, writing it that way is a pain in the but, so you might want to use a macro and end up with better readable code:
Code: Select all
Macro enumerate(constant)
Enumeration #PB_Compiler_EnumerationValue
constant
EndEnumeration
EndMacro
;
; *** main window
;
Enumerate(#w_main_nr)
Enumerate(#tb_main_nr)
Global w_main_h.i
global tb_main_h.i
;
; *** about window
;
Enumerate(#w_about_nr)
Global w_about_h.i
;
Enumerate(#test1)
Enumerate(#test2)
Re: Enumeration etiquette
Posted: Wed Aug 31, 2011 8:48 am
by Fred
You have to group the enum per object type for optimal performance: ie, one enum for window, one for gadget, one for toolbar etc. Using only one enum for every object will lead to holes into the internal arrays for each objects.
Re: Enumeration etiquette
Posted: Wed Aug 31, 2011 9:25 am
by Zach
Thanks Fred.
I think that's the most clear answer I've gotten from anyone
