Demo Gnoga – Click Me!

Description

Click Me! is a simple multi user Gnoga application.

This tutorial is designed to introduce:

  • Gnoga.Application.Multi_Connect – Initialize connectivity in a multi-usre context.
  • User app specific data.
  • Multiple URL paths

 

Download Gnoga for more tutorials and demos.

Source code

--  In the previous tutorials we created Singletons applications where there
--  is no issue of concurrency outside of events from the same user. This
--  allowed for programming in the familiar sequential patterns of regular
--  console applications. In this tutorial we will create an application that
--  will allow for multiple connections on the same machine, network or across
--  the globe on the internet.
--
--  In order to help see the different approach to setting up the application
--  we will do something similar to the previous tutorial.

with Gnoga.Application.Multi_Connect;
with Gnoga.Gui.Base;
with Gnoga.Gui.Window;
with Gnoga.Gui.View;
with Gnoga.Gui.Element.Common;

with Gnoga.Types;
--  Gnoga special types are found in Gnoga.Types.

procedure Tutorial_03 is
   use all type Gnoga.String;

   --  Since this application will be used by multiple connections, we need to
   --  track and access that connection's specific data. To do this we create
   --  a derivative of Gnoga.Types.Connection_Data_Type that will be accessible
   --  to any object on a connection.

   type App_Data is new Gnoga.Types.Connection_Data_Type with record
      My_Window : Gnoga.Gui.Window.Pointer_To_Window_Class;
      My_View   : Gnoga.Gui.View.View_Type;
      My_Button : Gnoga.Gui.Element.Common.Button_Type;
      My_Exit   : Gnoga.Gui.Element.Common.Button_Type;
   end record;
   type App_Access is access all App_Data;

   procedure On_Click (Object : in out Gnoga.Gui.Base.Base_Type'Class);
   procedure On_Exit (Object : in out Gnoga.Gui.Base.Base_Type'Class);
   --  Events for our application. The implementation is almost identical
   --  to our previous tutorial. However we access the elements through our
   --  App_Data data structure associated with the connection instead of
   --  globally.

   procedure On_Click (Object : in out Gnoga.Gui.Base.Base_Type'Class) is
      App : constant App_Access := App_Access (Object.Connection_Data);
   begin
      App.My_View.New_Line;
      App.My_View.Put_Line ("I've been clicked!");
   end On_Click;

   procedure On_Exit (Object : in out Gnoga.Gui.Base.Base_Type'Class) is
      App  : constant App_Access := App_Access (Object.Connection_Data);
      View : Gnoga.Gui.View.View_Type;
   begin
      App.My_View.Remove;
      View.Create (App.My_Window.all);
      View.Put_Line ("Application exited.");
      App.My_Window.Close_Connection;
   exception
      when E : others =>
         Gnoga.Log (Message => "On_Exit: ", Occurrence => E);
   end On_Exit;

   procedure On_Connect
     (Main_Window : in out Gnoga.Gui.Window.Window_Type'Class;
      Connection  :        access Gnoga.Application.Multi_Connect.Connection_Holder_Type);
   --  Instead of creating and setting up our GUI in the main body of the
   --  application, we now set up the GUI in a connection event handler.
   --  The implementation is almost identical to the last tutorial except we
   --  place our GUI element variables within the App_Data data structure
   --  that will be associated with the connection.

   procedure On_Connect
     (Main_Window : in out Gnoga.Gui.Window.Window_Type'Class;
      Connection  :        access Gnoga.Application.Multi_Connect.Connection_Holder_Type)
   is
      pragma Unreferenced (Connection);
      App : constant App_Access := new App_Data;
   begin
      App.My_Window := Main_Window'Unchecked_Access;
      Main_Window.Connection_Data (App);
      --  This associates our application data to this connection. Now any
      --  object created on it has access to it using its Connection_Data
      --  property. When the connection is done it will deallocate the memory
      --  used.

      App.My_View.Create (Main_Window);

      App.My_Button.Create (App.My_View, "Click Me!");
      App.My_Button.On_Click_Handler (On_Click'Unrestricted_Access);

      App.My_Exit.Create (App.My_View, "Exit App");
      App.My_Exit.On_Click_Handler (On_Exit'Unrestricted_Access);

      App.My_View.Horizontal_Rule;
   end On_Connect;

begin
   Gnoga.Application.Title ("Tutorial 03");

   Gnoga.Application.HTML_On_Close ("Application ended.");

   Gnoga.Application.Multi_Connect.Initialize;

   Gnoga.Application.Multi_Connect.On_Connect_Handler (Event => On_Connect'Unrestricted_Access, Path => "default");
   --  With a Multi_Connect application it is possible to have different
   --  URL paths start different Connection Event Handlers. This allows
   --  for the creation of Web Apps that appear as larger web sites or as
   --  multiple applications to the user. Setting Path to "default" means
   --  that any unmatched URL path will start that event handler. A URL path
   --  is the path following the host and port. For example:
   --  http://localhost:8080/test/me
   --  The Path would be "/test/me". In Gnoga the path can even appear to be
   --  a file name "/test/me.html". However if you have a file of the same
   --  name in the html directory it will be served instead.

   Gnoga.Application.Multi_Connect.Message_Loop;
end Tutorial_03;

Project file

with "settings.gpr";
with "gnoga.gpr";

project Tutorial_03 is

   for Object_Dir use Settings.Obj_Dir;
   for Exec_Dir use Settings.Exe_Dir;
   for Main use ("tutorial_03.adb");
   for Create_Missing_Dirs use Settings'Create_Missing_Dirs;

   package Compiler renames Settings.Compiler;
   package Binder renames Settings.Binder;
   package Linker renames Settings.Linker;
   package Pretty_Printer renames Settings.Pretty_Printer;

end Tutorial_03;