;; Copyright (c) 2005 Jeremy Shute

;; Permission is hereby granted, free of charge, to any person obtaining a copy
;; of this software and associated documentation files (the "Software"), to
;; deal in the Software without restriction, including without limitation the
;; rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
;; sell copies of the Software, and to permit persons to whom the Software is
;; furnished to do so, subject to the following conditions:

;; The above copyright notice and this permission notice shall be included in
;; all copies or substantial portions of the Software.

;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
;; IN THE SOFTWARE.

(module test
   (include "gtk-server.sch")
   (main main))

(define (main args)
   ;; All programs using the GTK-Server binding should have all GTK-Server
   ;; calls within the (with-gtk-server ...) macro.  This sets up the
   ;; connection to GTK-Server in a safe way and introduces all the functions
   ;; you see below.  For a more complete overview, see:
   ;;   http://www.gtk.org/api/2.6/gtk/index.html
   (with-gtk-server

    ;; Here, we use the (gtk-window-new ...) function to create the main
    ;; window of our program.  Notice that we are using GTK enumerations by
    ;; their Scheme name.
    (let ((win (gtk-window-new *GTK-WINDOW-TOPLEVEL*)))

       ;; We set the title on the window object.  I've made the design decision
       ;; to stick with the GTK naming of functions instead of, for instance,
       ;; calling this function (gtk-window-title-set! ...).  This is so there
       ;; are less discrepencies between the GTK documentation and the programs
       ;; you write.
       (gtk-window-set-title win "Bigloo GTK-server demo with STDIN")

       ;; We set the default window size on the window.  GTK is pretty
       ;; inconsistent in terms of rows/columns/width/height.  Here, it's the
       ;; width first and height second.  (Screen resolutions are reported that
       ;; way, for instance 640x480.)
       (gtk-window-set-default-size win 400 200)

       ;; We set the window to appear in the center of the screen.  Notice that
       ;; we are using GTK enumerations by their Scheme name, once again.
       (gtk-window-set-position win *GTK-WIN-POS-CENTER*)

       ;; We create a table, with two rows and one column.  (Matrices are
       ;; usually indexed this way, for instance in Fortran or Matlab.)
       (let ((tbl (gtk-table-new 2 1 #t)))

          ;; We add the table layout to the window.
          (gtk-container-add win tbl)

          ;; We create two widgets that will be added to our table.  A one-line
          ;; text-entry box is created, and a button with a label.  This is a
          ;; demonstration of how events are handled and how information is
          ;; read from widgets.
          (let ((entry (gtk-entry-new))
                (but (gtk-button-new-with-label "Click to Quit")))

             ;; We attach our entry and button to the table.  The sequence here
             ;; is left, right, top, bottom.  As we have one column and two
             ;; rows, this attachment places the text entry above the button.
             (gtk-table-attach-defaults tbl entry 0 1 0 1)
             (gtk-table-attach-defaults tbl but 0 1 1 2)

             ;; We are now ready to show off our handywork.  Up until now, the
             ;; window has been in its default visibility (invisible), so that
             ;; the user doesn't have to watch as these painstaking operations
             ;; take place.
             (gtk-widget-show-all win)

             ;; We are now ready to watch for the button click.  In order to do
             ;; so, we grab the predicate corresponding to the "clicked" event
             ;; of the button.  We will use this predicate, below, to determine
             ;; whether the event we are looking at is, in fact, the button
             ;; being clicked (as all registered events are reported, not just
             ;; this one).
             (let ((clicked? (gtk-server-connect but 'clicked)))

                ;; We drop into the event-loop here.  Note that Bigloo now
                ;; includes OS thread support, which means we can be servicing
                ;; the event-loop in this thread and watching for other types
                ;; of events (such as incoming information from the network) in
                ;; another.  Here, we specify that we would like to wait until
                ;; the user interacts with the GTK interface.  If the interface
                ;; needs to respond to data coming in from another thread, you
                ;; would want to call (gtk-server-callback #f), instead.
                (let loop ((event (gtk-server-callback #t)))

                   ;; Now, we see if the event we've just caught is our button
                   ;; being clicked.
                   (if (clicked? event)

                       ;; If so, we'll just print the text in our text entry
                       ;; widget and return.  As we will then leave the
                       ;; (with-gtk-server ...) macro, our window will
                       ;; automatically close and cleanup will automatically
                       ;; take place.
                       (pp (gtk-entry-get-text entry))

                       ;; If our event was not the button being clicked, we
                       ;; wait politely for the next event.
                       (loop (gtk-server-callback #t))))))))))