Page 1 of 1

#PB_Event_FirstCustomValue & #PB_Compiler_EnumerationValue

Posted: Tue Aug 09, 2016 10:24 am
by SparrowhawkMMU
Hi,

Back to trying out PB - I bought license a while back but never really used it much. After succesfully using the excellent SpiderBasic on a couple of projects, I thought I'd try it's older sibling again :)

Is the following behaviour as expected for the PB constants #PB_Event_FirstCustomValue and #PB_Compiler_EnumerationValue?

Scenario: I need to set up some custom events, and I'm using #PB_Event_FirstCustomValue to define these, but the compiler's enumeration value is then bumped up to that level - is there only a single enumeration stack/counter in the compiler?

Simplified sample code:

Code: Select all

Enumeration #PB_Event_FirstCustomValue
	#CONST_1
EndEnumeration

Enumeration #PB_Compiler_EnumerationValue
	#CONST_2
EndEnumeration

Debug "1: " + Str(#CONST_1) + ", 2: " + Str(#CONST_2)

OpenWindow(#CONST_2, 0,0,100,100, "TEST")

End
Gives the following output in the debugger:

Code: Select all

1: 65536, 2: 65537
And the program then exits when trying to execute the OpenWindow() command with the following error:

Code: Select all

[10:11:55] [ERROR] #Window object number is very high (over 5000), are You sure of that ?
Should custom events always be defined last to avoid this problem? Just seeking guidance on PB best practice when using enumerations including custom events.

Thanks

Re: #PB_Event_FirstCustomValue & #PB_Compiler_EnumerationVal

Posted: Tue Aug 09, 2016 12:02 pm
by TI-994A
SparrowhawkMMU wrote:Should custom events always be defined last to avoid this problem?
The short answer would be no.

Just don't continue enumerating from the custom values with the #PB_Compiler_EnumerationValue directive:

Code: Select all

Enumeration #PB_Event_FirstCustomValue
   #CONST_1
EndEnumeration

Enumeration   ;#PB_Compiler_EnumerationValue   <--- remove this
   #CONST_2
EndEnumeration

Debug "1: " + Str(#CONST_1) + ", 2: " + Str(#CONST_2)

OpenWindow(#CONST_2, 0,0,100,100, "TEST")

End
A good practice would be to maintain named enumerations for different object types:

Code: Select all

Enumeration Windows
  #win1
  #win2
  #win3
EndEnumeration

Enumeration Gadgets
  #gad1
  #gad2
  #gad3
EndEnumeration

Enumeration Misc
  #misc1
  #misc2
  #misc3
EndEnumeration

Debug #win1
Debug #win2
Debug #win3
Debug #gad1
Debug #gad2
Debug #gad3
Debug #misc1
Debug #misc2
Debug #misc3
The manual has more:

The PureBasic Manual - Enumerations

Re: #PB_Event_FirstCustomValue & #PB_Compiler_EnumerationVal

Posted: Tue Aug 09, 2016 12:14 pm
by Marc56us
Debug show this as Error, but it must be show as Wanning (IMHO)

Run with debug OFF or in EXE and it work

Code: Select all

 Enumeration #PB_Event_FirstCustomValue
   #CONST_1
EndEnumeration

Enumeration #PB_Compiler_EnumerationValue
   #CONST_2
EndEnumeration

Debug "1: " + Str(#CONST_1) + ", 2: " + Str(#CONST_2)

OpenWindow(#CONST_2, 0,0,100,100, "TEST")

While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend

End 
Why this message ? Simply, because if you define an object number, ie 5000, PB reserve 4999 free values before. So wast of memory space !

So with this example, you've created a table of 65537 value which unused 65536

:wink:

Re: #PB_Event_FirstCustomValue & #PB_Compiler_EnumerationVal

Posted: Tue Aug 09, 2016 12:20 pm
by SparrowhawkMMU
Hi and thanks for the information.

The problem is that I am trying to abstract my code out to modules as much as possible, so one module per window for example, each module having it's own gadget enum.

As such, I was using the #PB_Compiler_EnumerationValue to ensure no gadget clash.

A workaround I have is to set the start value for each gadget enum based on the window number, eg:

Code: Select all

	Enumeration (#WINDOW_Main + 1) * 100
		#GADGET_ValueText
		#GADGET_OpenChildButton
		#GADGET_CloseButton
	EndEnumeration
Not sure whether this is a common/good approach but it's working so far.

As you can probably tell, I'm very much at the feeling my way around PB stage at the moment. ;)

Re: #PB_Event_FirstCustomValue & #PB_Compiler_EnumerationVal

Posted: Tue Aug 09, 2016 12:33 pm
by Fred
Named enumeration is the way to go:

Code: Select all

Enumeration Gadget
  #Gadget1
  #Gadget2
EndEnumeration

Enumeration Window
  #Window1
  #Window2
EndEnumeration

Enumeration Gadget
  #Gadget3
  #Gadget4
EndEnumeration

Debug #Gadget1
Debug #Gadget2
Debug #Gadget3
Debug #Gadget4

Re: #PB_Event_FirstCustomValue & #PB_Compiler_EnumerationVal

Posted: Tue Aug 09, 2016 1:29 pm
by SparrowhawkMMU
Righto chaps - Named enumeration sit is! :)

Re: #PB_Event_FirstCustomValue & #PB_Compiler_EnumerationVal

Posted: Tue Aug 09, 2016 2:19 pm
by SparrowhawkMMU
Except... having tried it I get the same problem with gadgets - because gadget enumeration in the modules are starting from 0 now, they override each other.

I need abstraction as I want to be easily able to replace one version of a window with another - the app pulls in the various windows using a master control file that pulls in individual modules (so windows defs too), each one in its own file.

Re: #PB_Event_FirstCustomValue & #PB_Compiler_EnumerationVal

Posted: Tue Aug 09, 2016 5:02 pm
by Marc56us
What do you call a "module" ?

PB Module : https://www.purebasic.com/documentation ... odule.html ?

or an include file ? (*.pbi)

If this is only an IncludeFile, you have to do nothing, named enumeration will follow number whatever order of included files.

Re: #PB_Event_FirstCustomValue & #PB_Compiler_EnumerationVal

Posted: Tue Aug 09, 2016 5:05 pm
by ts-soft

Code: Select all

DeclareModule CommonConstants
  ; Form
  Enumeration FormWindow
  EndEnumeration
  Enumeration FormGadget
  EndEnumeration
  Enumeration FormMenu
  EndEnumeration
  Enumeration FormImage
  EndEnumeration
  Enumeration FormFont
  EndEnumeration
  ; Event
  Enumeration EventCustom #PB_Event_FirstCustomValue
  EndEnumeration
  Enumeration EventTypeCustom #PB_EventType_FirstCustomValue
  EndEnumeration
EndDeclareModule

Module CommonConstants
EndModule

; ------------
; Examples
DeclareModule Example1
  UseModule CommonConstants
  Enumeration FormGadget
    #Gadget1
  EndEnumeration
EndDeclareModule

Module Example1
 Debug #Gadget1
EndModule

DeclareModule Example2
  UseModule CommonConstants
  Enumeration FormGadget
    #Gadget2
  EndEnumeration
EndDeclareModule

Module Example2
 Debug #Gadget2
EndModule

UseModule CommonConstants

Enumeration FormGadget
  #Gadget3
EndEnumeration

Debug #Gadget3

Debug "-----------"
Debug Example2::#Gadget2

Re: #PB_Event_FirstCustomValue & #PB_Compiler_EnumerationVal

Posted: Tue Aug 09, 2016 6:46 pm
by SparrowhawkMMU
@Marc56us: A PB module, but I structure my code to one module per file (also a general module declaration file I load up front)

This makes it easier when doing version control in git as I have more flexibility.

@ts-soft. Thanks for example - That's pretty much exactly how I'm doing it. However, when I open a second window, the controls on the new windows clearly take the ids of the parent as the originals disappear!

I have an example at work. I'll post it here tomorrow.

Thanks all for your help :)

Re: #PB_Event_FirstCustomValue & #PB_Compiler_EnumerationVal

Posted: Wed Aug 10, 2016 5:26 am
by TI-994A
SparrowhawkMMU wrote:...I structure my code to one module per file (also a general module declaration file I load up front)...

...when I open a second window, the controls on the new windows clearly take the ids of the parent as the originals disappear!
The placement of the general module, and its usage in each module, is key. Here's a slightly simplified, visual version of ts-soft's example:

Code: Select all

; --- common module
;
DeclareModule generalModule
  Enumeration windows
  EndEnumeration
  Enumeration gadgets
  EndEnumeration  
EndDeclareModule

Module generalModule
EndModule

; --- module A
;
DeclareModule a
  UseModule generalModule
  Enumeration windows
    #win
  EndEnumeration
  Enumeration gadgets
    #gadget
  EndEnumeration  
  Declare openWin()
EndDeclareModule

Module a
  Procedure openWin()
    OpenWindow(#win, 160, 300, 250, 100, "Module A Window")
    ButtonGadget(#gadget, 25, 20, 200, 30, "Module A Gadget")
  EndProcedure
EndModule

; --- module B
;
DeclareModule b
  UseModule generalModule
  Enumeration windows
    #win
  EndEnumeration
  Enumeration gadgets
    #gadget
  EndEnumeration  
  Declare openWin()
EndDeclareModule

Module b
  Procedure openWin()
    OpenWindow(#win, 220, 400, 250, 100, "Module B Window")
    ButtonGadget(#gadget, 25, 20, 200, 30, "Module B Gadget ")
  EndProcedure
EndModule

; --- module C
;
DeclareModule c
  UseModule generalModule
  Enumeration windows
    #win
  EndEnumeration
  Enumeration gadgets
    #gadget
  EndEnumeration  
  Declare openWin()
EndDeclareModule

Module c
  Procedure openWin()
    OpenWindow(#win, 280, 500, 250, 100, "Module C Window")
    ButtonGadget(#gadget, 25, 20, 200, 30, "Module C Gadget")
  EndProcedure
EndModule

; --- main module
;
UseModule generalModule
Enumeration windows
  #win
  #childWin
EndEnumeration

Enumeration gadgets
  #gadget
  #childGadget
EndEnumeration  

OpenWindow(#win, 100, 200, 250, 100, "Main Window")
ButtonGadget(#gadget, 25, 20, 200, 30, "Main Gadget")
 
a::openWin()
b::openWin()
c::openWin()

OpenWindow(#childWin, 340, 600, 250, 100, "Child Window")
ButtonGadget(#childGadget, 25, 20, 200, 30, "Child Gadget")

MessageRequester("Modules", "Perfectly black-boxed - no clashes!")
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend 
Works perfectly without clash or conflict, even when each module is loaded from separate files. Furthermore, there are no worries about maintaining unique constant names, as they could be reused. The constants, #win and #gadget in this example, are used in all three modules, and also in the main module, without issue.

Hope it helps. :wink:

Re: #PB_Event_FirstCustomValue & #PB_Compiler_EnumerationVal

Posted: Wed Aug 10, 2016 9:23 am
by SparrowhawkMMU
Ah I see - I had not set an empty Gadgets enumeration in my common module. When I added that it all worked as with yours.

MANY, MANY THANKS TO YOU ALL. :)