Page 1 of 1

Coming to grips with Purebasic

Posted: Sun Jun 22, 2008 1:45 pm
by superjacent
Okay, I'm coming from a Realbasic background and I'm wanting to clarify a few issues.

Within RB Windows are created and within each window there's a place to write module level code. Code that only belongs to the particular window. Also variables can be created that have module level scope, each function or procedure within the window (module) can access these variables.

Relating the above to Purebasic, how is this done? My initial thoughts are that for each window it's a matter of writing separate code files which contain only the procedures and variables relevant to the particular window. I assume these separate code files would then be included at the beginning of the main start-up code file.

Any links to samples would be appreciated.

Posted: Sun Jun 22, 2008 4:07 pm
by Kaeru Gaman
in PB there is no such thing like seperated modules for multiple windows of one process structure.

have a look here:
http://www.purebasic.fr/english/viewtop ... 030#175030
http://www.purebasic.fr/english/viewtop ... 031#175031
examples to handle multiple windows from within one event-loop.

Posted: Sun Jun 22, 2008 4:23 pm
by Rook Zimbabwe
It is the gadgets on each window that you use. Make gadget names unique per window... Then when the gadget in that window is pressed you do what you need to do in that window...

A simple example:

Code: Select all


Enumeration
  #Window_1
  #Window_0
EndEnumeration

Enumeration
  #Button_REFILL_LI_1
  #Button_OPN1
  #Button_CLR_LI_1
  #ListIcon_1
  #Button_REFILL_LI_0
  #Button_OPN2
  #Button_CLR_LI_0
  #ListIcon_0
EndEnumeration

Structure VisualDesignerGadgets
  Gadget.l
  EventFunction.l
EndStructure

Global NewList EventProcedures.VisualDesignerGadgets()

; we make a simple neat procedure to fill nonsense into the Listicon gadgets that we can call by  button
; and indicate where to act!

Procedure FilltheList(where)
For x = 0 To 12 ; we are going to fill the ListIconGagdet
    jerk = Random(3)+3 ; from 3 - 6
        For h = 0 To jerk
            chrs = Random(25) + 65 ; capital letters of english alphabet
                letter$ = Chr(chrs) ; change that random into a character
                    word$ = word$ + letter$ ; add it to the word
       Next
       line$ = Str(x)
   AddGadgetItem(where, -1, word$) ; throw it on the list indicated
   word$ = "" ; simple cleanup
Next
EndProcedure

Procedure Button_REFILL_LI_1_Event(Window, Event, Gadget, Type)
  Debug "#Button_REFILL_LI_1"
    FilltheList(#ListIcon_1) ; call out LI Fill procedure
EndProcedure

Procedure Button_OPN1_Event(Window, Event, Gadget, Type)
  Debug "#Button_OPN1"
    HideWindow(#Window_1, 1) ; hide the second window
        HideWindow(#Window_0, 0) ; unhide firstsecond
EndProcedure

Procedure Button_CLR_LI_1_Event(Window, Event, Gadget, Type)
  Debug "#Button_CLR_LI_1"
    ClearGadgetItemList(#ListIcon_1)
EndProcedure

Procedure ListIcon_1_Event(Window, Event, Gadget, Type)
  Debug "#ListIcon_1" ; using SELECT CASE this time
    Result = GetGadgetState(#ListIcon_1) ; what row clicked on?
        Select Result
            Case -1
                ProcedureReturn -1
            Default
                Text$ = GetGadgetItemText(#ListIcon_1, Result)
                    MessageRequester("PICK","You selected: "+text$+Chr(10)+"Please press [OK] and"+Chr(10)+"do something Else!")
                        Text$ = "" ; simple cleanup
         EndSelect
EndProcedure

Procedure Button_REFILL_LI_0_Event(Window, Event, Gadget, Type)
  Debug "#Button_REFILL_LI_0"
    FilltheList(#ListIcon_0) ; call out LI Fill procedure
EndProcedure

Procedure Button_OPN2_Event(Window, Event, Gadget, Type)
  Debug "#Button_OPN2"
  HideWindow(#Window_0, 1) ; hide the first window
        HideWindow(#Window_1, 0) ; unhide the second
EndProcedure

Procedure Button_CLR_LI_0_Event(Window, Event, Gadget, Type)
  Debug "#Button_CLR_LI_0"
    ClearGadgetItemList(#ListIcon_0)
EndProcedure

Procedure ListIcon_0_Event(Window, Event, Gadget, Type)
  Debug "#ListIcon_0"
  ; you clicked on something! we can do something here like pop up a message box about what you clicked
  Result = GetGadgetState(#ListIcon_0) ; what row was clicked on
    If Result = -1
        Goto Exit_LI0_Loop ; gonna do this with SELECT CASE next time
    ElseIf Result > -1
        Text$ = GetGadgetItemText(#ListIcon_0, Result)
            MessageRequester("PICK","You selected: "+text$+Chr(10)+"Please press [OK] and"+Chr(10)+"do something Else!")
                Text$ = "" ; simple cleanup
    EndIf
Exit_LI0_Loop:
; **** just a jump out
EndProcedure

Procedure RegisterGadgetEvent(Gadget, *Function)
  
  If IsGadget(Gadget)
    AddElement(EventProcedures())
    EventProcedures()\Gadget        = Gadget
    EventProcedures()\EventFunction = *Function
  EndIf
  
EndProcedure

Procedure CallEventFunction(Window, Event, Gadget, Type)
  
  ForEach EventProcedures()
    If EventProcedures()\Gadget = Gadget
      CallFunctionFast(EventProcedures()\EventFunction, Window, Event, Gadget, Type)
      LastElement(EventProcedures())
    EndIf
  Next
  
EndProcedure

Procedure Open_Window_0()
  
  If OpenWindow(#Window_0, 5, 5, 400, 244, "Window 0",  #PB_Window_SystemMenu | #PB_Window_TitleBar )
    If CreateGadgetList(WindowID(#Window_0))
      ListIconGadget(#ListIcon_0, 15, 20, 225, 170, "Column1", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
      RegisterGadgetEvent(#ListIcon_0, @ListIcon_0_Event())
      ButtonGadget(#Button_CLR_LI_0, 15, 195, 225, 35, "CLEAR LIST 0")
      RegisterGadgetEvent(#Button_CLR_LI_0, @Button_CLR_LI_0_Event())
      ButtonGadget(#Button_OPN2, 245, 165, 145, 65, "OPEN WINDOW 1")
      RegisterGadgetEvent(#Button_OPN2, @Button_OPN2_Event())
      ButtonGadget(#Button_REFILL_LI_0, 250, 20, 140, 40, "REFILL")
      RegisterGadgetEvent(#Button_REFILL_LI_0, @Button_REFILL_LI_0_Event())
      
    EndIf
  EndIf
EndProcedure

Procedure Open_Window_1()
  If OpenWindow(#Window_1, 417, 5, 400, 243, "Window 1",  #PB_Window_Invisible | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
    If CreateGadgetList(WindowID(#Window_1))
      ListIconGadget(#ListIcon_1, 160, 15, 225, 170, "Column1", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
      RegisterGadgetEvent(#ListIcon_1, @ListIcon_1_Event())
      ButtonGadget(#Button_CLR_LI_1, 165, 195, 220, 35, "CLEAR LIST 1")
      RegisterGadgetEvent(#Button_CLR_LI_1, @Button_CLR_LI_1_Event())
      ButtonGadget(#Button_OPN1, 10, 165, 145, 65, "OPEN WINDOW 0")
      RegisterGadgetEvent(#Button_OPN1, @Button_OPN1_Event())
      ButtonGadget(#Button_REFILL_LI_1, 10, 20, 140, 40, "REFILL")
      RegisterGadgetEvent(#Button_REFILL_LI_1, @Button_REFILL_LI_1_Event())
    EndIf
  EndIf
EndProcedure

Open_Window_1()

Open_Window_0()
 
; now that the windows are open... we need to put someht8ing in our lists

FilltheList(#ListIcon_0)
FilltheList(#ListIcon_1)

Repeat
  
  Event  = WaitWindowEvent()
  Gadget = EventGadget()
  Type   = EventType()
  Window = EventWindow()
  
  Select Event
    Case #PB_Event_Gadget
      CallEventFunction(Window, Event, Gadget, Type)
      
  EndSelect
  
Until Event = #PB_Event_CloseWindow

End

8)

Seee you can't click on a control that isn't displayed... but you can call one that isn't displayed... if you know the infernal secret! :twisted:

Let us say I wanted to call the Clear LI_0 button on the first window from the second window, I could... passing parameters to it would be difficult {that means I haven't fully figured this out yet!!} but I could simply add the function call to my program and it would. I could even create a button on the second window that would emulate a press on the first.

If you need to.

This means you do not have to duplicate code. My Restaurant POS program is barely 500k just because of this!!!

8)

Posted: Sun Jun 22, 2008 6:32 pm
by blueznl
There's some stuff on events in the survival guide...

http://www.xs4all.nl/~bluez/datatalk/pure4.htm#4_events

Posted: Sun Jun 22, 2008 6:41 pm
by Kaeru Gaman
blueznl wrote:file:///F:/data/webpages/nightliv/datatalk/pure4.htm#4_events
lol?

Posted: Sun Jun 22, 2008 6:43 pm
by blueznl
Fixed. I was updating the bloody thing, and used a local link by accident. Thx. Kaeru.

http://www.xs4all.nl/~bluez/datatalk/pure4.htm#4_events

Posted: Sun Jun 22, 2008 7:52 pm
by byo
IMHO, as long as all windows belong to your application, you don't need to specify a lot of callbacks just capture the EventGadget() number and it'll work across many different windows.

Of course that you can extend PB's builtin events with your own, by retrieving a gadget (windows) individual messages. But I find myself working real easily by capturing events and using the #PB_EventType_... constants.

But Rook's example is really nice and straight-forward.

Posted: Mon Jun 23, 2008 2:32 pm
by superjacent
Thanks all, it gives me something to work with.

I'm seeing similarities with C++ where all the prototypes must be defined prior to the calling of the "main()" program, though in Purebasic's case it's the entire definition of the procedures and functions prior to calling the main loop (or starting window).

Within a PB application that is massive, is it the norm to therefore write up the functions in separate files and simply include those files at the beginning of the main loop. Purely for readability and less clutter.

Posted: Mon Jun 23, 2008 3:33 pm
by Rook Zimbabwe
I'm seeing similarities with C++ where all the prototypes must be defined prior to the calling of the "main()" program, though in Purebasic's case it's the entire definition of the procedures and functions prior to calling the main loop (or starting window).
Actually that is just me... You can DECLARE those procedures as well at the start and keep them AFTER the main loop, I prefer not to use too many DECLAREs... :D

You aren't locked in to any coding style though... It is BASIC. As long as your code is commented well and easy to understand we can help you with any of it! 8)

I saw "we" I mean some of us... more than others...
and my purpose on this board is to show people what NOT to do! :wink:

Posted: Tue Jun 24, 2008 10:36 pm
by Amiga5k
Also, I believe RealBasic could be called an object oriented language, whereas PB is 95% free of such craziness ;)

But seriously, PB can do it...but in its own way (and almost always producing smaller and faster code as the result).

It takes some getting used to if you're coming from an OOP background, but in the end I think you'll find that it is well worth it. However, if you are planning on writing very very large programs with several persons sharing code, etc. an OOP language may be the best way to go in many cases, simply because of encapsulation and other weird sounding concepts... :D

For games, though, there really is only one way to go: Commodore 64 Basic!! (Just kidding) ;)

Russell