Window in a Module?
Window in a Module?
Having a program with a main window open, is it possible to use a OpenWindow in a Module and get the  events  for that seconday windows gadgets to work?
I am trying to write a selfcontained module(with its own window) for general things to be reused in different project.
Another benefit would be to be able to use variable names in the module without conflicting with the main window, like for instance for common gadget names like btnClose etc.
			
			
									
									I am trying to write a selfcontained module(with its own window) for general things to be reused in different project.
Another benefit would be to be able to use variable names in the module without conflicting with the main window, like for instance for common gadget names like btnClose etc.
Former VB6 developer adventuring in a brave, new Purebasic world!
						Re: Window in a Module?
Code: Select all
; Make sure, that a module named common hold your extra mega super global definitions
; and declare it as the first module of your project.
DeclareModule common
  
  ; Enumeration of a Window 
  Enumeration enumWindows 1
    #Window_Main ; = 1
  EndEnumeration
  
EndDeclareModule
Module common
EndModule
; here your super feature module with an extra window...
DeclareModule Blabla1
  
  ; Here use the common module with your globals
  UseModule common
  
  ; and go on to enumerate your windows
  Enumeration enumWindows
    #Window_BlaBla1 ; = 2
  EndEnumeration
  
EndDeclareModule
Module Blabla1
EndModule
; and now use your globals in the main program
UseModule common
; and more enumerations....
Enumeration enumWindows
  #myWindow ; = 3
EndEnumeration
Debug #myWindow ; 3
Debug #Window_Main ; 1
Debug Blabla1::#Window_BlaBla1 ; 2
Re: Window in a Module?
That's exactly what modules are for.Ramses800 wrote:...is it possible to use a OpenWindow in a Module and get the events for that seconday windows gadgets to work?
...selfcontained module(with its own window)...
...to use variable names in the module without conflicting with the main window...
This example implements two modules, both with exactly the same gadget variables, used side by side without any naming conflicts. It utilises the UseModule/UnuseModule function to isolate their respective namespaces:
Code: Select all
DeclareModule Win1
  Define.i window, text, string, button
  Declare Init()
EndDeclareModule
DeclareModule Win2
  Define.i window, text, string, button
  Global.s forWin2_andBeyond
  Declare Init()
EndDeclareModule
Module Win1
  ;this GLOBAL variable IS NOT DECLARED in the module declaration
  ;so it is only available within the Win1 module (Private)
  Global.s forWin1_Only = "Win1 String (Private)"
  
  Procedure Init()
    Shared window, string, button
    window = OpenWindow(#PB_Any, 100, 200, 300, 200, "Win1 Window", #PB_Window_SystemMenu)
    text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window ends the app...")
    string = StringGadget(#PB_Any, 50, 80, 200, 30, forWin1_Only)
    button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "Win1 Button")
  EndProcedure
EndModule
Module Win2
  ;this GLOBAL variable IS DECLARED in the module declaration
  ;so it is available within & without the Win2 module (Public)
  forWin2_andBeyond = "Win2 String (Public)"
  
  Procedure Init()  
    Shared window, string, button
    window = OpenWindow(#PB_Any, 440, 200, 300, 200, "Win2 Window", #PB_Window_SystemMenu)
    text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window does not end the app...")
    string = StringGadget(#PB_Any, 50, 80, 200, 30, forWin2_andBeyond)
    button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "Press to see Win2 variable...")
  EndProcedure
EndModule
Win1::Init()
Win2::Init()
  
Repeat
  event = WaitWindowEvent()
  
  Select EventWindow()
      
    Case Win1::window      
      UseModule Win1
      Select event
        Case #PB_Event_CloseWindow
          appQuit = 1
        Case #PB_Event_Gadget
          Select EventGadget()
            Case string
              Select EventType()
                Case #PB_EventType_Change
                  SetGadgetText(button, "Typing...")
              EndSelect
            Case button
              SetGadgetText(string, "You pressed Win1::button!")
          EndSelect
        UnuseModule Win1  
      EndSelect
      
    Case Win2::window      
      UseModule Win2
      Select event
        Case #PB_Event_CloseWindow
          CloseWindow(window)
        Case #PB_Event_Gadget
          Select EventGadget()
            Case string
              Select EventType()
                Case #PB_EventType_Change
                  SetGadgetText(button, "Typing...")
              EndSelect
            Case button
              If Not seenOnce
                MessageRequester("Win2::Module", forWin2_andBeyond)
                SetGadgetText(button, "Win2 Button")
                seenOnce = #True
              Else
                SetGadgetText(string, "You pressed Win2::button!")
              EndIf 
          EndSelect
      EndSelect
      UnuseModule Win2
      
  EndSelect
Until appQuit = 1Code: Select all
DeclareModule Win1
  Define.i window, text, string, button
  Declare Init()
EndDeclareModule
DeclareModule Win2
  Define.i window, text, string, button
  Global.s forWin2_andBeyond
  Declare Init()
EndDeclareModule
Module Win1
  ;this GLOBAL variable IS NOT DECLARED in the module declaration
  ;so it is only available within the Win1 module (Private)
  Global.s forWin1_Only = "Win1 String (Private)"
  
  Procedure Init()
    Shared window, string, button
    window = OpenWindow(#PB_Any, 100, 460, 300, 200, "Win1 Window", #PB_Window_SystemMenu)
    text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window ends the app...")
    string = StringGadget(#PB_Any, 50, 80, 200, 30, forWin1_Only)
    button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "Win1 Button")
  EndProcedure
EndModule
Module Win2
  ;this GLOBAL variable IS DECLARED in the module declaration
  ;so it is available within & without the Win2 module (Public)
  forWin2_andBeyond = "Win2 String (Public)"
  
  Procedure Init()  
    Shared window, string, button      
    window = OpenWindow(#PB_Any, 440, 460, 300, 200, "Win2 Window", #PB_Window_SystemMenu)
    text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window does not end the app...")
    string = StringGadget(#PB_Any, 50, 80, 200, 30, forWin2_andBeyond)
    button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "Press to see Win2 variable...")
  EndProcedure
EndModule
Win1::Init()
Win2::Init()
Define.s forMainWindowOnly = "MainWindow String"
Define.i window = OpenWindow(#PB_Any, 250, 200, 300, 200, "MainWindow", #PB_Window_SystemMenu)
Define.i text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window ends the app...")
Define.i string = StringGadget(#PB_Any, 50, 80, 200, 30, forMainWindowOnly)
Define.i button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "MainWindow Button")
  
Repeat
  event = WaitWindowEvent()
  
  Select EventWindow()
      
    Case window      
      Select event
        Case #PB_Event_CloseWindow
          appQuit = 1
        Case #PB_Event_Gadget
          Select EventGadget()
            Case string
              Select EventType()
                Case #PB_EventType_Change
                  SetGadgetText(button, "Typing...")
              EndSelect
            Case button
              SetGadgetText(string, "You pressed MainWindow button!")
          EndSelect
      EndSelect      
      
    Case Win1::window      
      Select event
        Case #PB_Event_CloseWindow
          appQuit = 1
        Case #PB_Event_Gadget
          Select EventGadget()
            Case Win1::string
              Select EventType()
                Case #PB_EventType_Change
                  SetGadgetText(Win1::button, "Typing...")
              EndSelect
            Case Win1::button
              SetGadgetText(Win1::string, "You pressed Win1::button!")
          EndSelect
      EndSelect
      
    Case Win2::window      
      Select event
        Case #PB_Event_CloseWindow
          CloseWindow(Win2::window)
        Case #PB_Event_Gadget
          Select EventGadget()
            Case Win2::string
              Select EventType()
                Case #PB_EventType_Change
                  SetGadgetText(Win2::button, "Typing...")
              EndSelect
            Case Win2::button
              If Not seenOnce
                MessageRequester("Win2::Module", Win2::forWin2_andBeyond)
                SetGadgetText(Win2::button, "Win2 Button")
                seenOnce = #True
              Else
                SetGadgetText(Win2::string, "You pressed Win2::button!")
              EndIf 
          EndSelect
      EndSelect
      
  EndSelect
Until appQuit = 1Hope it helps.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 
						Re: Window in a Module?
@TI-994A:
You can also do the event management within the modules, so the global event loop is not required.
Quickly modified your example:
Using getWindow() only you can send messages/events to the other window via PostEvent().
			
			
									
									
						You can also do the event management within the modules, so the global event loop is not required.
Quickly modified your example:
Code: Select all
DeclareModule MainWindow
  Declare Init()
  Declare.i getWindow()
EndDeclareModule
DeclareModule ToolWindow
  Global.s forToolWindow_andBeyond
  Declare Init()
  Declare.i getWindow()
EndDeclareModule
Module MainWindow
  Global.i window, text, string, button
  ;this GLOBAL variable IS NOT DECLARED in the module declaration
  ;so it is only available within the Win1 module (Private)
  Global.s forWin1_Only = "Win1 String (Private)"
  
  ; Private
  Procedure OnCloseWindow()   : End                                                      : EndProcedure
  Procedure OnInputChange()   : SetGadgetText(button, "Typing...")                       : EndProcedure
  Procedure OnButtonClicked() : SetGadgetText(string, "You pressed MainWindow::button!") : EndProcedure
  
  ; Public
  Procedure Init()
    window = OpenWindow(#PB_Any, 100, 200, 300, 200, "MainWindow", #PB_Window_SystemMenu)
    text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window ends the app...")
    string = StringGadget(#PB_Any, 50, 80, 200, 30, forWin1_Only)
    button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "MainWindow Button")
    
    BindEvent(#PB_Event_CloseWindow,@OnCloseWindow(),window)
    BindGadgetEvent(string,@OnInputChange(),#PB_EventType_Change)
    BindGadgetEvent(button,@OnButtonClicked())
  EndProcedure
  
  Procedure.i getWindow()
      ProcedureReturn window
  EndProcedure
EndModule
Module ToolWindow
  Global.i window, text, string, button
  ;this GLOBAL variable IS DECLARED in the module declaration
  ;so it is available within & without the ToolWindow module (Public)
  forToolWindow_andBeyond = "ToolWindow String (Public)"
  
  ; Private
  Procedure OnCloseWindow() : CloseWindow(window)                : EndProcedure
  Procedure OnInputChange() : SetGadgetText(button, "Typing...") : EndProcedure
  Procedure OnButtonClicked()
    Static seenOnce
    If Not seenOnce
      MessageRequester("ToolWindow::Module", forToolWindow_andBeyond)
      SetGadgetText(button, "ToolWindow Button")
      seenOnce = #True
    Else
      SetGadgetText(string, "You pressed ToolWindow::button!")
    EndIf
  EndProcedure
  
  ; Public
  Procedure Init()
    window = OpenWindow(#PB_Any, 440, 200, 300, 200, "ToolWindow", #PB_Window_SystemMenu)
    text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window does not end the app...")
    string = StringGadget(#PB_Any, 50, 80, 200, 30, forToolWindow_andBeyond)
    button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "Press to see ToolWindow variable...")
    BindEvent(#PB_Event_CloseWindow,@OnCloseWindow(),window)
    BindGadgetEvent(string,@OnInputChange(),#PB_EventType_Change)
    BindGadgetEvent(button,@OnButtonClicked())
  EndProcedure
  
  Procedure.i getWindow()
      ProcedureReturn window
  EndProcedure
EndModule
MainWindow::Init()
ToolWindow::Init()
Repeat : WaitWindowEvent() : ForEverRe: Window in a Module?
Nice, neat, and truly modular.Danilo wrote:You can also do the event management within the modules, so the global event loop is not required.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 
						Re: Window in a Module?
@TI-994A,
@Danilo,
Excellent demo.
Couldn't have done that myself: Always nice to learn something new.
Thank you, both.
			
			
									
									@Danilo,
Excellent demo.
Couldn't have done that myself: Always nice to learn something new.
Thank you, both.
DE AA EB
						Re: Window in a Module?
Thanks for all the great advice! Off to coding it all up now....
			
			
									
									Former VB6 developer adventuring in a brave, new Purebasic world!
						Re: Window in a Module?
A followup question about BindGadgetEvent,
Is it possible to supply the Callback with a parameter? I'm thinking of keeping track of multiple windows opened from the module. Something like this(raises a syntax error)
			
			
									
									Is it possible to supply the Callback with a parameter? I'm thinking of keeping track of multiple windows opened from the module. Something like this(raises a syntax error)
Code: Select all
BindGadgetEvent(iThisCloseButton,@btnClose_Click(iThisWindow),#PB_EventType_LeftClick) Former VB6 developer adventuring in a brave, new Purebasic world!
						Re: Window in a Module?
No, but you can use EventWindow(), EventType(), etc. within your event procedure.
			
			
									
									
						Code: Select all
Procedure btnClose_Click()
    IThisWindow = EventWindow() Re: Window in a Module?
@Danilo: Great tip, just what I was looking for!
			
			
									
									Former VB6 developer adventuring in a brave, new Purebasic world!
						Re: Window in a Module?
A question for Danilo :
 
In your demo,
There has to be a compelling reason, but it escapes me so far...
			
			
													In your demo,
why go through the procedure getWindow() to reference the value of the window variable, instead of declaring the variable itself as public ?Danilo wrote:Code: Select all
DeclareModule MainWindow ... Declare.i getWindow() EndDeclareModule DeclareModule ToolWindow ... Declare.i getWindow() EndDeclareModule
There has to be a compelling reason, but it escapes me so far...
					Last edited by Blue on Thu Mar 10, 2016 6:42 pm, edited 1 time in total.
									
			
									PB Forums : Proof positive that 2 heads (or more...) are better than one 
						Re: Window in a Module?
No compelling reason. As you've pointed out, while the value could just as easily be referenced via a public variable, he has simply implemented a convenience getter function, presumably to demonstrate the private scope of global variables within a module.Blue wrote:...why go through the procedure getWindow() to reference the value of the window variable, instead of declaring the variable itself as public ?
There has to be a compelling reason, but it escapes me so far...
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 
						Re: Window in a Module?
Thank you TI-994A for clarifying that.
That's a relief; I was so sure that I was missing something important here.
			
			
									
									That's a relief; I was so sure that I was missing something important here.
PB Forums : Proof positive that 2 heads (or more...) are better than one 
						Re: Window in a Module?
Well, if you declare the variable as public, it is also write-able from outside.Blue wrote:A question for Danilo :
why go through the procedure getWindow() to reference the value of the window variable, instead of declaring the variable itself as public ?
There has to be a compelling reason, but it escapes me so far...
There is no read-only access-specifier in PB, so everybody could just overwrite it from the outside.
The Window is handled by the module internally, and to make the Window handle read-only
from the outside, I used the getter-function. Getter without Setter means read-only and
ensures encapsulation.
Re: Window in a Module?
Ah, there's the compelling reasonDanilo wrote:[...]
There is no read-only access-specifier in PB, so everybody could just overwrite it from the outside.
The Window is handled by the module internally, and to make the Window handle read-only
from the outside, I used the getter-function.
[...]
I had a strong intuition that I was missing an important point here.
Thanks for clarifying that, Danilo.
As usual, clear, concise and informative.
As for me, as always, I greatly appreciate the learning opportunity.
PB Forums : Proof positive that 2 heads (or more...) are better than one 
						
