(***********************************************************************
   This file is part of GTKpas, an OOP wrapper for GTK+ written
   for Pascal.

   Copyright (C) 2000 by Johann Glaser <Johann.Glaser@gmx.at>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program in the file COPYING; if not, write to the 
   Free Software Foundation, Inc., 
   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
***********************************************************************)
Program PackboxExample;
{$MODE OBJFPC}
Uses GLib,GDK,GTK,GTKpas,Strings;

Type CPackBox = Class(CWindow)
                  Function DeleteEventImpl(aEvent:PGdkEventAny):Gint; virtual; override;
                  Procedure Destroy_; virtual; override;
                  Function OnQuitButtonClicked(Sender:CButton;Data:GPointer):GBoolean;
                End;

Var Kit    : CMain;
    Window : CWindow;
    Button : CButton;

(* You should always remember to connect the delete_event signal
 * to the main window. This is very important for proper intuitive
 * behavior *)
Function CPackBox.DeleteEventImpl(aEvent:PGdkEventAny):Gint;
Begin
  inherited DeleteEventImpl(aEvent);
  Kit.Quit;
  DeleteEventImpl := 0;
End;
Procedure CPackBox.Destroy_;
Begin
  inherited Destroy_;
  WriteLn('Destroy_');
  Kit.Quit;
End;

(* Setup the signal to terminate the program when the button is clicked *)
Function CPackBox.OnQuitButtonClicked(Sender:CButton;Data:GPointer):GBoolean;
Begin
  Window.Destroy_;
End;

(* Make a new hbox filled with button-labels. Arguments for the
 * variables we're interested are passed in to this function. 
 * We do not show the box, but do show everything inside. *)
Function MakeBox( homogeneous : GBoolean;
                  spacing : GInt;
                  expand : GBoolean;
                  fill : GBoolean;
                  padding:GInt) : CBox;
Var Box    : CBox;
    Button : CWidget;
    PadStr : Array[0..79] of Char;
    St     : String;
Begin
  (* Create a new hbox with the appropriate homogeneous
   * and spacing settings *)
  Box := CHBox.Create(homogeneous, spacing);
  
  (* Create a series of buttons with the appropriate settings *)
  Button := CButton.Create('Box.PackStart');
  Box.PackStart(Button, expand, fill, padding);
  Button.Show;
  
  Button := CButton.Create('(button,');
  Box.PackStart(Button, expand, fill, padding);
  Button.Show;
  
  (* Create a button with the label depending on the value of
   * expand. *)
  if expand = True then Button := CButton.Create('True,')
  else                  Button := CButton.Create('False,');
  Box.PackStart(Button, expand, fill, padding);
  Button.Show;

  (* This is the same as the button creation for 'expand'
   * above, but uses the shorthand form. *)
  if Fill = True then Button := CButton.Create('True,')
  else                Button := CButton.Create('False,');
  Box.PackStart(Button, expand, fill, padding);
  Button.Show;
  
  Str(padding,St);
  StrPCopy(padstr, St+');');
  Button := CButton.Create(padstr);
  Box.PackStart(Button, expand, fill, padding);
  Button.Show;
  MakeBox := Box;
End;


Var I         : Integer;
    Which     : Integer;
    Box1      : CBox;
    Box2      : CBox;
    QuitBox   : CBox;
    TheLabel  : CLabel;
    Separator : CSeparator;

Begin
  Val(ParamStr(1),Which,I);
  if (ParamCount <> 1) or (I <> 0) or (Which > 3) or (Which < 1) then
    Begin
      WriteLn(StdErr,'usage: packbox num, where num is 1, 2, or 3.');
      (* exit with an exit status of 1. *)
      Halt(1);
    End;

  Kit := CMain.Create(@ArgC,@ArgV,False);

  (* Create our window *)
  Window := CPackBox.Create(GTK_WINDOW_TOPLEVEL);
  Window.BorderWidth := 10;
  Window.Title := 'Packbox demo';

  (* We create a vertical box (vbox) to pack the horizontal boxes into.
   * This allows us to stack the horizontal boxes filled with buttons one
   * on top of the other in this vbox. *)
  Box1 := CVBox.Create(False,0);
  
  (* which example to show. These correspond to the pictures above. *)
  Case Which of
    1 : Begin
          (* create a new label. *)
          TheLabel := CLabel.Create('CVBox.Create(False, 0);');
          
          (* Align the label to the left side.  We'll discuss this function and 
           * others in the section on Widget Attributes. *)
          TheLabel.SetAlignment(0, 0);
          
          (* Pack the label into the vertical box (vbox box1).  Remember that 
           * widgets added to a vbox will be packed one on top of the other in
           * order. *)
          Box1.PackStart(TheLabel, FALSE, FALSE, 0);
          
          (* Show the label *)
          TheLabel.Show;
          
          (* Call our make box function - homogeneous := FALSE, spacing := 0,
           * expand := FALSE, fill := FALSE, padding := 0 *)
          Box2 := MakeBox(FALSE, 0, FALSE, FALSE, 0);
          Box1.PackStart(Box2, FALSE, FALSE, 0);
          Box2.Show;
          
          (* Call our make box function - homogeneous := FALSE, spacing := 0,
           * expand := TRUE, fill := FALSE, padding := 0 *)
          Box2 := MakeBox(FALSE, 0, TRUE, FALSE, 0);
          Box1.PackStart(Box2, FALSE, FALSE, 0);
          Box2.Show;
          
          (* Args are: homogeneous, spacing, expand, fill, padding *)
          Box2 := MakeBox(FALSE, 0, TRUE, TRUE, 0);
          Box1.PackStart(Box2, FALSE, FALSE, 0);
          Box2.Show;

          (* Creates a separator, we'll learn more about these later, 
           * but they are quite simple. *)
          Separator := CHSeparator.Create;
          
          (* Pack the separator into the vbox. Remember each of these
           * widgets is being packed into a vbox, so they'll be stacked
           * vertically. *)
          Box1.PackStart(Separator, FALSE, TRUE, 5);
          Separator.Show;
          
          (* Create another new label, and show it. *)
          TheLabel := CLabel.Create('CHBox.Create(True, 0);');
          TheLabel.SetAlignment(0, 0);
          Box1.PackStart(TheLabel, FALSE, FALSE, 0);
          TheLabel.Show;
          
          (* Args are: homogeneous, spacing, expand, fill, padding *)
          Box2 := MakeBox(TRUE, 0, TRUE, FALSE, 0);
          Box1.PackStart(Box2, FALSE, FALSE, 0);
          Box2.Show;
          
          (* Args are: homogeneous, spacing, expand, fill, padding *)
          Box2 := MakeBox(TRUE, 0, TRUE, TRUE, 0);
          Box1.PackStart(Box2, FALSE, FALSE, 0);
          Box2.Show;

          (* Another new separator. *)
          Separator := CHSeparator.Create;
          (* The last 3 arguments to gtk_box_pack_start are:
           * expand, fill, padding. *)
          Box1.PackStart(Separator, FALSE, TRUE, 5);
          Separator.Show;
        End;
    2 : Begin
          (* Create a new TheLabel, remember box1 is a vbox as created 
           * near the beginning of main() *)
          TheLabel := CLabel.Create('CHBox.Create(False, 10);');
          TheLabel.SetAlignment(0, 0);
          Box1.PackStart(TheLabel, FALSE, FALSE, 0);
          TheLabel.Show;
          
          (* Args are: homogeneous, spacing, expand, fill, padding *)
          Box2 := MakeBox(FALSE, 10, TRUE, FALSE, 0);
          Box1.PackStart(Box2, FALSE, FALSE, 0);
          Box2.Show;
          
          (* Args are: homogeneous, spacing, expand, fill, padding *)
          Box2 := MakeBox(FALSE, 10, TRUE, TRUE, 0);
          Box1.PackStart(Box2, FALSE, FALSE, 0);
          Box2.Show;

          Separator := CHSeparator.Create;
          (* The last 3 arguments to gtk_box_pack_start are:
          * expand, fill, padding. *)
          Box1.PackStart(separator, FALSE, TRUE, 5);
          Separator.Show;
          
          TheLabel := CLabel.Create('CHBox.Create(False, 0);');
          TheLabel.SetAlignment(0, 0);
          Box1.PackStart(TheLabel, FALSE, FALSE, 0);
          TheLabel.Show;
          
          (* Args are: homogeneous, spacing, expand, fill, padding *)
          Box2 := MakeBox(FALSE, 0, TRUE, FALSE, 10);
          Box1.PackStart(Box2, FALSE, FALSE, 0);
          Box2.Show;
          
          (* Args are: homogeneous, spacing, expand, fill, padding *)
          Box2 := MakeBox(FALSE, 0, TRUE, TRUE, 10);
          Box1.PackStart(Box2, FALSE, FALSE, 0);
          Box2.Show;

          Separator := CHSeparator.Create;
          (* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. *)
          Box1.PackStart(separator, FALSE, TRUE, 5);
          Separator.Show;
        End;
    3 : Begin
          (* This demonstrates the ability to use gtk_box_pack_end() to
           * right justify widgets. First, we create a new box as before. *)
          Box2 := MakeBox(FALSE, 0, FALSE, FALSE, 0);
          
          (* Create the TheLabel that will be put at the end. *)
          TheLabel := CLabel.Create('End');
          (* Pack it using gtk_box_pack_end(), so it is put on the right
           * side of the hbox created in the make_box() call. *)
          Box2.PackEnd(TheLabel, FALSE, FALSE, 0);
          (* Show the TheLabel. *)
          TheLabel.Show;
          
          (* Pack Box2 into box1 (the vbox remember ? :) *)
          Box1.PackStart(Box2, FALSE, FALSE, 0);
          Box2.Show;

          (* A separator for the bottom. *)
          Separator := CHSeparator.Create;
          (* This explicitly sets the separator to 400 pixels wide by 5 pixels
          * high. This is so the hbox we created will also be 400 pixels wide,
          * and the 'end' TheLabel will be separated from the other TheLabels in the
          * hbox. Otherwise, all the widgets in the hbox would be packed as
          * close together as possible. *)
          Separator.SetUSize(400,5);
          (* pack the separator into the vbox (box1) created near the start 
          * of main() *)
          Box1.PackStart(separator, FALSE, TRUE, 5);
          Separator.Show;
        End;
  End;
  
  (* Create another new hbox.. remember we can use as many as we need! *)
  QuitBox := CHBox.Create(FALSE, 0);
  
  (* Our quit button. *)
  Button := CButton.Create('Quit');
  Button.OnClicked := @CPackBox(Window).OnQuitButtonClicked;
  
  (* Pack the button into the quitbox.
   * The last 3 arguments to gtk_box_pack_start are:
   * expand, fill, padding. *)
  QuitBox.PackStart(button, TRUE, FALSE, 0);
  (* pack the quitbox into the vbox (box1) *)
  Box1.PackStart(quitbox, FALSE, FALSE, 0);

  (* Pack the vbox (box1) which now contains all our widgets, into the
   * main window. *)
  Window.Add(Box1);

  (* And show everything left *)
  Button.Show;
  QuitBox.Show;

  Box1.Show;
  (* Showing the window last so everything pops up at once. *)
  Window.Show;

  (* And of course, our main function. *)
  Kit.Run;
  (* Control returns here when gtk_main_quit() is called, but not when 
   * gtk_exit is used. *)
End.




