Page 1 of 2

iterate enumeration

Posted: Tue Mar 12, 2019 9:40 am
by A.D.
i wish we could iterate enumerations like this:

Code: Select all

 
Enumeration Gadgets
 #GadgetInfo 
 #GadgetText 
 #GadgetOK  
EndEnumeration
  
ForEach Gadgets
 Debug "enumeration value: " + #PB_Compiler_EnumerationValue
Next  

Re: iterate enumeration

Posted: Tue Mar 12, 2019 10:03 am
by wombats
Out of interest, what would this be useful for?

Re: iterate enumeration

Posted: Tue Mar 12, 2019 10:21 am
by Dude
A.D. wrote:i wish we could iterate enumerations like this:

Code: Select all

Enumeration Gadgets
 #GadgetInfo 
 #GadgetText 
 #GadgetOK  
EndEnumeration
  
ForEach Gadgets
 Debug "enumeration value: " + #PB_Compiler_EnumerationValue
Next  
You can already do it:

Code: Select all

Enumeration
  #GadgetInfo
  #GadgetText
  #GadgetOK 
EndEnumeration

For v = #GadgetInfo To #GadgetOK
  Debug "enumeration value: " + v
Next

Re: iterate enumeration

Posted: Tue Mar 12, 2019 10:35 am
by A.D.

Code: Select all

For v = #GadgetInfo To #GadgetOK
  Debug "enumeration value: " + v
Next
That's not what i want to do. I want to enumerate each Enumerationlist i want to with ForEach Enumerationlist!

Re: iterate enumeration

Posted: Tue Mar 12, 2019 10:38 am
by Dude
A.D. wrote:I want to enumerate each Enumerationlist i want to with ForEach Enumerationlist!
Maybe I misunderstood. Didn't you want to show what the enumerated value of each constant was?

Re: iterate enumeration

Posted: Tue Mar 12, 2019 10:52 am
by A.D.
well, i'm not sure if my request is really needed as it can be done with a simple loop like you said. (i just wanted to iterate trough every gadget)

Re: iterate enumeration

Posted: Tue Mar 12, 2019 11:10 am
by wombats
Since you are the one creating the gadgets, can't you just store their numbers in a list and iterate through that?

Re: iterate enumeration

Posted: Tue Mar 12, 2019 11:34 am
by TI-994A
A.D. wrote:...i just wanted to iterate trough every gadget
Assuming that the named enumerations consist of valid PureBasic objects, this might do the trick:

Code: Select all

Enumeration Windows
  #Window1
  #Window2
EndEnumeration

Enumeration Gadgets
  #Gadget1
  #Gadget2
  #Gadget3
EndEnumeration

Enumeration Fonts
  #Font1
  #Font2
  #Font3
  #Font4
EndEnumeration

Enumeration Images
  #Image1
  #Image2
  #Image3
  #Image4
  #Image5
EndEnumeration

Macro NextEnumeration(e, name)
  Enumeration name 
  EndEnumeration
  e = #PB_Compiler_EnumerationValue
EndMacro

Procedure EnumerateGroup(objectType.s, lastEnumeration)
  Debug objectType + ":"
  For i = 0 To lastEnumeration
    Select objectType
      Case "windows":        
        If IsWindow(i)
          Debug "#Window" + Str(i + 1) + " is in use."
        EndIf
      Case "gadgets": 
        If IsGadget(i)
          Debug "#Gadget" + Str(i + 1) + " is in use."
        EndIf        
      Case "fonts":        
        If IsFont(i)
          Debug "#Font" + Str(i + 1) + " is in use."
        EndIf        
      Case "images":
        If IsImage(i)
          Debug "#Image" + Str(i + 1) + " is in use."
        EndIf        
    EndSelect    
  Next i      
  Debug "---"
EndProcedure

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(#Window2, 0, 0, 300, 50, "Named Enumerations", wFlags)
ButtonGadget(#Gadget1, 10, 10, 135, 30, "Gadget 1")
ButtonGadget(#Gadget3, 155 , 10, 135, 30, "Gadget 3")
LoadFont(#Font2, "Arial", 10)
LoadFont(#Font4, "Arial", 10)
CreateImage(#Image2, 10, 10)
CreateImage(#Image5, 10, 10)
CreateImage(#Image1, 10, 10)

NextEnumeration(x, Windows)
EnumerateGroup("windows", x)
NextEnumeration(x, Fonts)
EnumerateGroup("fonts", x)
NextEnumeration(x, Images)
EnumerateGroup("images", x)
NextEnumeration(x, Gadgets)
EnumerateGroup("gadgets", x)

While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend

Re: iterate enumeration

Posted: Tue Mar 12, 2019 1:16 pm
by #NULL
A.D. wrote:i wish we could iterate enumerations like this:

Code: Select all

 
Enumeration Gadgets
 #GadgetInfo 
 #GadgetText 
 #GadgetOK  
EndEnumeration
  
ForEach Gadgets
 Debug "enumeration value: " + #PB_Compiler_EnumerationValue
Next  
+1

Re: iterate enumeration

Posted: Tue Mar 19, 2019 10:38 pm
by Sicro
A.D. wrote:i wish we could iterate enumerations like this:

Code: Select all

 
Enumeration Gadgets
 #GadgetInfo 
 #GadgetText 
 #GadgetOK  
EndEnumeration
  
ForEach Gadgets
 Debug "enumeration value: " + #PB_Compiler_EnumerationValue
Next  
The enumeration block no longer exists after compilation.

To make iteration of the constants of an enumeration block possible at runtime, the compiler would have to insert this enumeration block into the compiled program as a list. The PB compiler simply processes the code from top to bottom and doesn't look ahead, so it would always have to insert the list into the compiled program, which is an unnecessary ballast if you don't iterate through an enumeration block in the later code.

At compile time, however, the compiler could do the following:

Code: Select all

ForEach Gadgets
 Debug "enumeration value: " + #PB_Compiler_EnumerationValue
Next
will be converted to:

Code: Select all

Debug "enumeration value: " + #GadgetInfo
Debug "enumeration value: " + #GadgetText
Debug "enumeration value: " + #GadgetOK
This variant would be fine, because no additional list of the enumeration block has to be created and integrated into the compiled program.

Re: iterate enumeration

Posted: Tue Mar 19, 2019 11:24 pm
by #NULL

Code: Select all

For v = #GadgetInfo To #GadgetOK
  Debug "enumeration value: " + v
Next
Doesn't work with irregular enums like this one:

Code: Select all

Enumeration enum
  #a    ; 0
  #b=10
  #c=10
  #d=5
  #ee   ; 6
EndEnumeration
The feature would be almost useless if we don't get also the constant name (as a string or whatever). Otherwise you could only check if a value is part of the enum set, but I would want to use it for debugging like printing the 'name' of an integer etc., I used manual name/string lists or arrays sometimes as well as the manual integer loop, but it's error prone.
<edit>
If the compiler could just generate a stringyfied list of enum names and values that would be fine. Any loop could be done with that then at runtime. But named enums can be expanded later and the compiler never knows if that's still going to happen during compilation.

Re: iterate enumeration

Posted: Fri Mar 22, 2019 2:00 pm
by Cyllceaux
I use this :)

Code: Select all


Macro IteraEnum(enum,const,val=)
	Enumeration enum
		const val
	EndEnumeration
	CompilerIf Not Defined(enum,#PB_List)
		Global NewList enum()
	CompilerEndIf
	AddElement(enum())
	enum()=#PB_Compiler_EnumerationValue - 1
EndMacro

IteraEnum(_t2,#bla1)
IteraEnum(_t2,#bla2,=2)
IteraEnum(_t2,#bla3)

ForEach _t2()
	Debug _t2()
Next

Debug #bla2

You can make a Map or a Runtime-Enum. Works with every kind of Enums and Enumvalues.

Code: Select all

IteraEnum(_t2,#bla2,= 1 << 1 )
workes, too.

Re: iterate enumeration

Posted: Fri Mar 22, 2019 2:31 pm
by mk-soft
Another way... :wink: (viewtopic.php?f=12&t=66856)

Code: Select all

;-TOP

DeclareModule System
  Declare GetParentWindowID(Gadget)
  Declare GetGadgetList(List Gadgets(), WindowID=0)
EndDeclareModule

; ---------------------------------------------------------------------------------------
Module System
  
  EnableExplicit
  
  ;-- Import internal function
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    Import ""
      PB_Object_EnumerateStart( PB_Objects )
      PB_Object_EnumerateNext( PB_Objects, *ID.Integer )
      PB_Object_EnumerateAbort( PB_Objects )
      PB_Object_GetObject( PB_Object , DynamicOrArrayID)
      PB_Window_Objects.i
      PB_Gadget_Objects.i
      PB_Image_Objects.i
      ;PB_Font_Objects.i
    EndImport
  CompilerElse
    ImportC ""
      PB_Object_EnumerateStart( PB_Objects )
      PB_Object_EnumerateNext( PB_Objects, *ID.Integer )
      PB_Object_EnumerateAbort( PB_Objects )
      PB_Object_GetObject( PB_Object , DynamicOrArrayID)
      PB_Window_Objects.i
      PB_Gadget_Objects.i
      PB_Image_Objects.i
      ;PB_Font_Objects.i
    EndImport
  CompilerEndIf
  
  CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
    ; PB Interne Struktur Gadget MacOS
    Structure sdkGadget
      *gadget
      *container
      *vt
      UserData.i
      Window.i
      Type.i
      Flags.i
    EndStructure
  CompilerEndIf
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure GetParentWindowID(Gadget)
    Protected GadgetID, GadgetWindowID
    
    If IsGadget(Gadget)
      CompilerSelect #PB_Compiler_OS
        CompilerCase #PB_OS_MacOS
          Protected *Gadget.sdkGadget = IsGadget(Gadget)
          GadgetWindowID = WindowID(*Gadget\Window)
        CompilerCase #PB_OS_Linux
          GadgetID = GadgetID(Gadget)
          GadgetWindowID = gtk_widget_get_toplevel_ (GadgetID)
        CompilerCase #PB_OS_Windows
          GadgetID = GadgetID(Gadget)
          GadgetWindowID = GetAncestor_(GadgetID, #GA_ROOT)
      CompilerEndSelect
    EndIf
    ProcedureReturn GadgetWindowID
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure GetGadgetList(List Gadgets(), WindowID=0)
    Protected object
    ClearList(Gadgets())
    PB_Object_EnumerateStart(PB_Gadget_Objects)
    While PB_Object_EnumerateNext(PB_Gadget_Objects, @object)
      If WindowID = 0 Or GetParentWindowID(object) = WindowID
        AddElement(Gadgets())
        Gadgets() = object
      EndIf
    Wend
    ProcedureReturn ListSize(Gadgets())
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
EndModule

;-Test

UseModule System

Global NewList Gadgets()

; Zeigt mögliche Flags des ButtonGadget in Aktion...
If OpenWindow(0, 0, 0, 222, 200, "ButtonGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(0, 10, 10, 200, 20, "Standard Button")
  ButtonGadget(1, 10, 40, 200, 20, "Left Button", #PB_Button_Left)
  ButtonGadget(2, 10, 70, 200, 20, "Right Button", #PB_Button_Right)
  ButtonGadget(3, 10,100, 200, 60, "Multiline Button  (längerer Text wird automatisch umgebrochen)", #PB_Button_MultiLine)
  ;ButtonGadget(4, 10,170, 200, 20, "Toggle Button", #PB_Button_Toggle)
  ButtonGadget(#PB_Any, 10,170, 200, 20, "Toggle Button", #PB_Button_Toggle)
  
  cnt = GetGadgetList(Gadgets());, WindowID(0))
  Debug "Count of gadgets = " + cnt
  ForEach Gadgets()
    Debug "Gadget-Number = " + Gadgets() + " / Text = " + GetGadgetText(Gadgets())
  Next
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Re: iterate enumeration

Posted: Sat Mar 23, 2019 9:06 am
by Bisonte
I like the code of Cyllceaux, but it's useless if you need several enumerations. Therefore the whole thing with maps :

Code: Select all

Macro DoubleQuote
  "  
EndMacro
Macro iEnum(EnumerationName, Constant, Value=)
  Enumeration EnumerationName#Enum
    Constant Value
  EndEnumeration
  CompilerIf Not Defined(LastEnum, #PB_Map)
    Global NewMap LastEnum()
  CompilerEndIf
  LastEnum(Trim(DoubleQuote#EnumerationName#DoubleQuote)) = #PB_Compiler_EnumerationValue - 1
EndMacro

iEnum(Gadget, #a, = 1)
iEnum(Gadget, #b)
iEnum(Gadget, #c)
iEnum(Gadget, #d)

iEnum(Window, #wa)
iEnum(Window, #wb)

Debug LastEnum("Gadget")
Debug LastEnum("Window")

Re: iterate enumeration

Posted: Sat Mar 23, 2019 11:27 am
by mk-soft
Everything's too expensive. Is a question of declaration...

Code: Select all

Enumeration Gadgets
  #BeginOfGadget
  #Gadget1
  #Gadget2
  #Gadget3
  #EndOfGadget
EndEnumeration

For i = #BeginOfGadget + 1 To #EndOfGadget - 1
  Debug i
Next