(***********************************************************************
   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 ProgressBarExample;
{$MODE OBJFPC}
Uses GLib,GDK,GTK,GTKpas;


Type CProgressBarWin = Class(CWindow)
                Function  DeleteEventImpl(aEvent:PGdkEventAny):Gint; virtual; override;
                Procedure Destroy_; virtual; override;
                Function  OnQuitButtonClicked(Sender:CButton;Data:GPointer):GBoolean;
                Function  ToggleShowText(Sender:CToggleButton;Data:GPointer):GBoolean;
                Function  ToggleActivityMode(Sender:CToggleButton;Data:GPointer):GBoolean;
                Function  SetContinuousMode(Sender:CToggleButton;Data:GPointer):GBoolean;
                Function  SetDiscreteMode(Sender:CToggleButton;Data:GPointer):GBoolean;
              End;

Type PProgressData = ^TProgressData;
     TProgressData = record
                       Window : CProgressBarWin;
                       PBar   : CProgressBar;
                       Timer  : LongInt;
                     End;

Var Kit : CMain;

Function CProgressBarWin.DeleteEventImpl(aEvent:PGdkEventAny):Gint;
Begin
  inherited DeleteEventImpl(aEvent);
  DeleteEventImpl := 0;
End;
Procedure CProgressBarWin.Destroy_;
Begin
  inherited Destroy_;
  Kit.Quit;
End;
Function CProgressBarWin.OnQuitButtonClicked(Sender:CButton;Data:GPointer):GBoolean;
Begin
  (* Remove the timer *)
  gtk_timeout_remove(PProgressData(Data)^.Timer);
  PProgressData(Data)^.Timer := 0;
  PProgressData(Data)^.Window := Nil;
  Destroy_;
  OnQuitButtonClicked := False;
End;
(* Callback that toggles the text display within the progress
 * bar trough *)
Function CProgressBarWin.ToggleShowText(Sender:CToggleButton;Data:GPointer):GBoolean;
Begin
  PProgressData(Data)^.PBar.ShowText := GUInt(Not Sender.Active);
  ToggleShowText := False;
End;
(* Callback that toggles the activity mode of the progress
 * bar *)
Function CProgressBarWin.ToggleActivityMode(Sender:CToggleButton;Data:GPointer):GBoolean;
Begin
  PProgressData(Data)^.PBar.ActivityMode := GUInt(Not Sender.Active);
  ToggleActivityMode := False;
End;
(* Callback that toggles the continuous mode of the progress
 * bar *)
Function CProgressBarWin.SetContinuousMode(Sender:CToggleButton;Data:GPointer):GBoolean;
Begin
  SetContinuousMode := False;
  if not Sender.Active then Exit;
  PProgressData(Data)^.PBar.BarStyle := GTK_PROGRESS_CONTINUOUS;
End;
(* Callback that toggles the discrete mode of the progress
 * bar *)
Function CProgressBarWin.SetDiscreteMode(Sender:CToggleButton;Data:GPointer):GBoolean;
Begin
  SetDiscreteMode := False;
  if not Sender.Active then Exit;
  PProgressData(Data)^.PBar.BarStyle := GTK_PROGRESS_DISCRETE;
End;

(* Update the value of the progress bar so that we get
 * some movement *)
Function ProgressTimeout(Data:GPointer):GInt; CDecl;
Var NewVal : GFloat;
    Adj    : PGtkAdjustment;
Begin
  (* Calculate the value of the progress bar using the
   * value range set in the adjustment object *)

  NewVal := CProgress(Data).Value+1;

  Adj := PGtkProgress(CProgress(Data).GtkObject)^.Adjustment;
  if NewVal > Adj^.Upper then
    NewVal := Adj^.Lower;

  (* Set the new value *)
  CProgress(Data).Value := NewVal;

  (* As this is a timeout function, return TRUE so that it
   * continues to get called *)
  ProgressTimeout := 1;
End; 


Var PData : TProgressData;
    VBox  : CBox;
    Align : CAlignment;
    Adj   : CAdjustment;
    Toggle    : CToggleButton;
    Separator : CSeparator;
    Check     : CCheckButton;
    Table     : CTable;
    Close     : CButton;

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

  With PData do
    Begin
      Window := CProgressBarWin.Create(GTK_WINDOW_TOPLEVEL);
      Window.BorderWidth := 0;
      Window.Title := 'CProgressBar';
      Window.SetPolicy(0{FALSE}, 0{FALSE}, 1{TRUE});
    
      VBox := CVBox.Create(FALSE, 5);
      VBox.BorderWidth := 10;
      Window.Add(VBox);
      VBox.Show;
      
      (* Create a centering alignment object *)
      Align := CAlignment.Create(0.5, 0.5, 0, 0);
      VBox.PackStart(Align, FALSE, FALSE, 5);
      Align.Show;
    
      (* Create a Adjusment object to hold the range of the
       * progress bar *)
      Adj := CAdjustment.Create(0, 1, 150, 0, 0, 0);
    
      (* Create the GtkProgressBar using the adjustment *)
      PBar := CProgressBar.Create(Adj);
    
      (* Set the format of the string that can be displayed in the
       * trough of the progress bar:
       * %p - percentage
       * %v - value
       * %l - lower range value
       * %u - upper range value *)
      PBar.FormatString := '%v from [%l-%u] (=%p%%)';
      Align.Add(PBar);
      PBar.Show;
    
      (* Add a timer callback to update the value of the progress bar *)
      PData.Timer := gtk_timeout_add (100, @ProgressTimeout, PData.PBar);
    
      Separator := CHSeparator.Create;
      VBox.PackStart(Separator, FALSE, FALSE, 0);
      Separator.Show;
    
      (* rows, columns, homogeneous *)
      Table := CTable.Create(2, 3, FALSE);
      VBox.PackStart(Table, FALSE, TRUE, 0);
      Table.Show;
    
      (* Add a check button to select displaying of the trough text *)
      Check := CCheckButton.Create('Show text');   { ZENTRIERT? !!! }
      Table.Attach(Check, 0, 1, 0, 1,
                   GTK_EXPAND or GTK_FILL, GTK_EXPAND or GTK_FILL,
                   5, 5);
      Check.OnClicked := @Window.ToggleShowText;
      Check.OnClickedData := @PData;
      Check.Show;
      
      (* Add a check button to toggle activity mode *)
      Check := CCheckButton.Create('Activity mode');
      Table.Attach(Check, 0, 1, 1, 2,
                   GTK_EXPAND or GTK_FILL, GTK_EXPAND or GTK_FILL,
                   5, 5);
      Check.OnClicked := @Window.ToggleActivityMode;
      Check.OnClickedData := @PData;
      Check.Show;
    
      Separator := CVSeparator.Create;
      Table.Attach(Separator, 1, 2, 0, 2,
                   GTK_EXPAND or GTK_FILL, GTK_EXPAND or GTK_FILL,
                   5, 5);
      Separator.Show;
    
      (* Add a radio button to select continuous display mode *)
      Toggle := CRadioButton.Create('Continuous');
      Table.Attach(Toggle, 2, 3, 0, 1,
                   GTK_EXPAND or GTK_FILL, GTK_EXPAND or GTK_FILL,
                   5, 5);
      Toggle.OnToggled := @Window.SetContinuousMode;
      Toggle.OnToggledData := @PData;
      Toggle.Show;
    
      (* Add a radio Toggle to select discrete display mode *)
      Toggle :=  CRadioButton.Create(gtk_radio_button_group (PGtkRadioButton(Toggle.GtkObject)),
                 'Discrete');
      Table.Attach(Toggle, 2, 3, 1, 2,
                   GTK_EXPAND or GTK_FILL, GTK_EXPAND or GTK_FILL,
                   5, 5);
      Toggle.OnToggled:= @Window.SetDiscreteMode;
      Toggle.OnToggledData := @PData;
      Toggle.Show;
      
      Separator := CHSeparator.Create;
      VBox.PackStart(Separator, FALSE, FALSE, 0);
      Separator.Show;
      
      (* Add a Button to exit the program *)
      Close := CButton.Create('close');
      Close.OnClicked := @Window.OnQuitButtonClicked;
      VBox.PackStart(Close,True,True,0);
      (* This makes it so the Button is the default. *)
      GTK_WIDGET_SET_FLAGS(PGtkWidget(Close.GtkObject),GTK_CAN_DEFAULT);
      (* This grabs this Button to be the default Button. Simply hitting
       * the 'Enter' key will cause this Button to activate. *)
      Close.GrabDefault;
      Close.Show;
    
      Window.Show;
    End;

  Kit.Run;
End.

