A.20. Progress Bar

function make_adj (low, up, step, pg_inc, pg_size)
{
  adj = new(GtkAdjustment);
  adj.lower = low;
  adj.upper = up;
  adj.step_increment = step;
  adj.page_increment = pg_inc;
  adj.page_size = pg_size;
  adj;
}

function update_value(adj, lbl)
{
  if(adj.value < 300)
    adj.set_value(adj.value +1);
  else
    adj.set_value(0);
  lbl.set_text(string("Label updated by user: ",
			int(adj.value / 300 * 100), "%"));
}

function make_option_menu(wgt1, wgt2, purpose, hist, titles...)
{
  local item, optionmenu, count = 0;
  local menu = new(GtkMenu);

  with tl in titles do
    {
      item = gtk_menu_item_new_with_label (tl);
      if(purpose == "orientation")
	item.signal("activate", `pbar_orient(@wgt1, @tl));
      else if(purpose == "bar_style")
	item.signal("activate", `pbar_style(@wgt1, @wgt2, @tl));
      menu.insert(item, count);
      count++;
    }

  optionmenu = new(GtkOptionMenu);
  optionmenu.set_menu(menu);
  optionmenu.set_history(hist);
  optionmenu.show();
  optionmenu;
}

function pbar_orient(bar, orient)
{
  switch(orient)
    {
    case "Left-Right": bar.set_orientation (GTK_PROGRESS_LEFT_TO_RIGHT);
    case "Right-Left": bar.set_orientation (GTK_PROGRESS_RIGHT_TO_LEFT);
    case "Bottom-Top": bar.set_orientation (GTK_PROGRESS_BOTTOM_TO_TOP);
    case "Top-Bottom": bar.set_orientation (GTK_PROGRESS_TOP_TO_BOTTOM);
    }
}

function pbar_style(bar, counter, style)
{
  switch(style)
    {
    case "Continuous":
      {
	bar.set_bar_style (GTK_PROGRESS_CONTINUOUS);
	counter.set_sensitive(FALSE);
      }
    case "Discrete":
      {
	bar.set_bar_style (GTK_PROGRESS_DISCRETE);
	counter.set_sensitive(TRUE);
      }
    }
}

function toggle_show_text(button, bar, entry, xalspin, yalspin)
{
  bar.set_show_text(button.get_active());
  entry.set_sensitive(button.get_active());
  xalspin.set_sensitive(button.get_active());
  yalspin.set_sensitive(button.get_active());
}

function toggle_activity_mode(button, bar, spin1, spin2)
{
  bar.set_activity_mode(button.get_active());
  spin1.set_sensitive(button.get_active());
  spin2.set_sensitive(button.get_active());
}

function create_progress_bar ()
{
  local button, vbox, vbox2, hbox, check, frame, tab, label, align,
  adj, pdata = nil;
  
  win_progress_bar = new (GtkDialog);
  win_progress_bar.signal ("destroy", #win_progress_bar = nil);
  win_progress_bar.title = "GtkProgressBar";
  win_progress_bar.set_policy(FALSE, FALSE, TRUE);
  win_progress_bar.border_width = 0;
  

  /**** Access the necessary pieces of the dialog box. ****/
  dvbox = car(win_progress_bar.children());
  separator = car(dvbox.children());
  action_area = cadr(dvbox.children());
  
  vbox = new(GtkVBox);
  vbox.spacing = 5;
  vbox.border_width = 10;
  dvbox.pack_start(vbox, FALSE, TRUE, 0);

  
  /**** Progress Frame, Progress Bar and User Label. ****/
  frame = new(GtkFrame);
  frame.label = "Progress";
  vbox.pack_start(frame, FALSE, TRUE, 0);
  
  vbox2 = new(GtkVBox);
  vbox2.border_width = 15;
  frame.add(vbox2);
  
  adj = make_adj(1, 300, 0, 0, 0);

  pbar = new(GtkProgressBar);
  pbar.adjustment = adj;
  pbar.set_format_string("%v from [%l,%u] (=%p%%)");
  pbar.set_color (1, 2, 0xffaaaa);
  vbox2.pack_start(pbar, TRUE, TRUE, 5);
  
  hbox = new(GtkHBox);
  hbox.spacing = 5;
  usrlabel = new(GtkLabel);
  hbox.pack_start(usrlabel, FALSE, TRUE, 0);
  vbox2.pack_start(hbox, TRUE, TRUE, 5);
  
  timer = every(.1, `update_value(@adj, @usrlabel));
  win_progress_bar.signal ("destroy", #cancel(timer));

  
  /**** Options Frame ****/
  frame = new(GtkFrame);
  frame.label = ("Options");
  vbox.pack_start(frame, FALSE, TRUE, 0);
  
  vbox2 = new(GtkVBox);
  vbox2.spacing = 2;
  frame.add(vbox2);
  
  tab = new(GtkTable);
  tab.n_rows = 7;
  tab.n_columns = 2;
  tab.homogeneous = FALSE;
  vbox2.pack_start(tab, FALSE, TRUE, 0);

  
  /**** Orientation ****/
  label = new(GtkLabel);
  label.set_text("Orientation :");
  tab.attach(label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 5, 5);
  label.set_alignment(0, 0.5);


  options = make_option_menu(pbar, nil, "orientation", 0, "Left-Right",
			     "Right-Left", "Bottom-Top", "Top-Bottom");

  tab.attach(options, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 5, 0);

  
  /**** Text ****/
  check = new(GtkCheckButton);
  check.label = "Show text";
  tab.attach(check, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 5, 5);
  
  hbox = new(GtkHBox);
  tab.attach(hbox, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 5, 5);
  
  label = new(GtkLabel);
  label.set_text("Format : ");
  hbox.pack_start(label, FALSE, TRUE, 0);

  entry = new(GtkEntry);
  hbox.pack_start(entry, TRUE, TRUE, 0);
  entry.set_text("%v from [%l,%u] (=%p%%)");
  entry.set_usize(100, -1);
  entry.set_sensitive(FALSE);
  
  label = new(GtkLabel);
  label.set_text("Text align :");
  tab.attach(label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 5, 5);
  label.set_alignment(0, 0.5);
  
  hbox = new(GtkHBox);
  tab.attach(hbox, 1, 2, 2, 3, GTK_FILL, GTK_FILL, 5, 5);
  
  label = new(GtkLabel);
  label.set_text("x :");
  hbox.pack_start(label, FALSE, TRUE, 5);
  
  adj = make_adj(0, 1, 0.1, 0.1, 0);
  adj.set_value(0.5);
  x_align = new(GtkSpinButton);
  x_align.configure(adj, 0, 1);
  hbox.pack_start(x_align, FALSE, TRUE, 0);
  x_align.set_sensitive(FALSE);
  
  label = new(GtkLabel);
  label.set_text("y :");
  hbox.pack_start(label, FALSE, TRUE, 5);
  
  adj = make_adj(0, 1, 0.1, 0.1, 0);
  adj.set_value(0.5);
  y_align = new(GtkSpinButton);
  y_align.configure(adj, 0, 1);
  hbox.pack_start(y_align, FALSE, TRUE, 0);
  y_align.set_sensitive(FALSE);

  check.signal("clicked", `toggle_show_text(@check, @pbar, @entry,
					    @x_align, @y_align));
  entry.signal("changed", `(@pbar).set_format_string((@entry).get_text()));
  x_align.signal("changed", `(@pbar).set_text_alignment((@x_align).get_value_as_float(),
							(@y_align).get_value_as_float()));
  y_align.signal("changed", `(@pbar).set_text_alignment((@x_align).get_value_as_float(),
							(@y_align).get_value_as_float()));

  
  /**** Bar Style ****/
  label = new(GtkLabel);
  label.set_text("Bar Style :");
  tab.attach(label, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 5, 5);
  label.set_alignment(0, 0.5);
  
  label = new(GtkLabel);
  label.set_text("Block count :");
  tab.attach(label, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 5, 5);
  label.set_alignment(0, 0.5);
  
  hbox = new(GtkHBox);
  tab.attach(hbox, 1, 2, 4, 5, GTK_FILL, GTK_FILL, 5, 5);
  adj = make_adj(2, 20, 1, 5, 0);
  adj.set_value(10);
  block_spin = new(GtkSpinButton);
  block_spin.configure(adj, 0, 0);
  block_spin.signal("changed",
		    `(@pbar).set_discrete_blocks((@block_spin).get_value_as_int()));
  hbox.pack_start(block_spin, FALSE, TRUE, 0);
  block_spin.set_sensitive(FALSE);

  options = make_option_menu(pbar, block_spin, "bar_style", 0, "Continuous", "Discrete");
  tab.attach(options, 1, 2, 3, 4, GTK_FILL, GTK_FILL, 5, 0);

  
  /**** Activity Mode ****/
  check = new(GtkCheckButton);
  check.label = "Activity mode";
  tab.attach(check, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 5, 5);
  
  hbox = new(GtkHBox);
  tab.attach(hbox, 1, 2, 5, 6, GTK_FILL, GTK_FILL, 5, 5);
  
  label = new(GtkLabel);
  label.set_text("Step size : ");
  hbox.pack_start(label, FALSE, TRUE, 0);
  
  adj = make_adj(1, 20, 1, 5, 0);
  adj.set_value(3);
  step_spin = new(GtkSpinButton);
  step_spin.configure(adj, 0, 0);
  step_spin.signal("changed",
	     `(@pbar).set_activity_step((@step_spin).get_value_as_int()));
  hbox.pack_start(step_spin, FALSE, TRUE, 0);
  step_spin.set_sensitive(FALSE);
  
  hbox = new(GtkHBox);
  tab.attach(hbox, 1, 2, 6, 7, GTK_FILL, GTK_FILL, 5, 5);
  
  label = new(GtkLabel);
  label.set_text("Blocks :     ");
  hbox.pack_start(label, FALSE, TRUE, 0);
  
  adj = make_adj(2, 10, 1, 5, 0);
  adj.set_value(5);
  blocks_spin = new(GtkSpinButton);
  blocks_spin.configure(adj, 0, 0);
  blocks_spin.signal("changed",
		     `(@pbar).set_activity_blocks((@blocks_spin).get_value_as_int()));
  hbox.pack_start(blocks_spin, FALSE, TRUE, 0);
  blocks_spin.set_sensitive(FALSE);

  check.signal("clicked", `toggle_activity_mode(@check, @pbar,
						@step_spin, @blocks_spin));
  
  button = new (GtkButton);
  button.label = "close";
  button.signal ("clicked", `(@win_progress_bar).destroy());
  action_area.pack_start (button, TRUE, TRUE, 0);
  button.can_default = TRUE;
  button.grab_default();
  
  win_progress_bar.show_all();
  win_progress_bar;
}

function main ()
{
  local window, win_progress_bar;
  TRUE=1;
  FALSE=0;
  window = create_progress_bar ();
  window.signal ("destroy", #exit_program(0));
  init_ipc("prog_bar", "prog_barq");
  gtk_main ();
}