448. How to dynamically scale a bar graph using scrollbars - Part 4 - x and y directions?

Problem

This is in response to Paamayim's post titled 'smooth scrolling for a gtkimage drawing'.

He has set up a bar graph and wants to allow the user to dynamically change the scale of the x-axis and y-axis through the scrollbars as shown below.

As there are quite a number of techniques involved, to make it easier to follow, I've spread the techniques over 5 parts:

  • Part 1 - adds the vscrollbar
  • Part 2 - aligns the graph to bottom left
  • Part 3 - adds the hscrollbar
  • Part 4 (this article) - adds both vscrollbar and hscrollbar
  • Part 5 - use only one scrollbar to control scaling of both axis

In this Part 4, we will combine the codes from Part 2 and Part 3 so that the users now have the vscrollbar for scaling the y-axis and the hscrollbar for scaling the x-axis as shown below:

How to dynamically scale a bar graph using scrollbars - Part 4 - x and y directions?


Solution

  • Please refer to Part 2 for the set up of vscrollbar.
  • Please refer to Part 3 for the set up of hscrollbar.

Sample Code

1   
2   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
15   
16   
18   
19   
20   
21   
23   
24   
25   
26   
27   
28   
29   
30   
31   
32   
33   
34   
35   
36   
37   
38   
39   
40   
41   
42   
43   
44   
45   
46   
47   
48   
49   
50   
51   
52   
53   
54   
55   
56   
57   
58   
59   
60   
61   
64   
65   
66   
67   
68   
69   
70   
76   
77   
78   
80   
81   
82   
83   
84   
85   
87   
88   
89   
92   
94   
96   
97   
98   
99   
100   
101   
102   
103   
104   
105   
106   
107   
<?php
$window = new GtkWindow();
$window->set_title($argv[0]);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->add($vbox = new GtkVBox());

// display title
$title = new GtkLabel("Dynamically scale a bar graph using scrollbars\n".
"Part 4: with both hscrollbar and vscrollbar");
$title->modify_font(new PangoFontDescription("Times New Roman Italic 10"));
$title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff"));
$title->set_size_request(-1, 40);
$title->set_justify(Gtk::JUSTIFY_CENTER);
$alignment = new GtkAlignment(0.5, 0, 0, 0);
$alignment->add($title);
$vbox->pack_start($alignment, 0, 0);
$vbox->pack_start(new GtkLabel(), 0, 0);

setup_bargraph($vbox);

$window->show_all();
Gtk::main();

function setup_bargraph($vbox) {
    global $img;
    $vbox->pack_start($hbox = new GtkHBox());
    $hbox->pack_start($vbox2 = new GtkVBox());
    $img = new GtkImage();
    $vbox2->pack_start(new GtkVBox());
    $vbox2->pack_start($hbox2 = new GtkHBox(), 0);
    $hbox2->pack_start($img, 0);

    global $hadj, $vadj;
    $vadj = new GtkAdjustment(0.87, 0.87, 2, 0.1, .5);
    $vscrollbar = new GtkVScrollbar($vadj);
    $vscrollbar->connect('value-changed', 'on_value_changed');
    $hbox->pack_start($vscrollbar, 0);

    $hadj = new GtkAdjustment(0.5, 0.5, 2, 0.01, .5);
    $hscrollbar = new GtkHScrollbar($hadj);
    $hscrollbar->connect('value-changed', 'on_value_changed');
    $vbox->pack_start($hscrollbar, 0);

    $vadj->set_value(1);
    $hadj->set_value(1);
    $vadj->value_changed();

    $hbox->set_size_request(600, 400);
}

function draw_bargraph($x_scale, $y_scale) {
    global $img;
    $max_width = 360 * $x_scale;
    $max_height = 200 * $y_scale;
    $margin = 40;
    $im = imagecreate($max_width, $max_height);
    $white = imagecolorallocate($im,255,255,255);
    $black = imagecolorallocate($im,0,0,0);
    $blue = imagecolorallocate($im,0,0,255);

    $data = array('120','160','300','240');
    imageline($im, 10, 5, 10, $max_height-$margin, $black );
    imageline($im, 10, $max_height-$margin,
                $max_width-$margin, $max_height-$margin, $black );
    imagestring($im,6,100*$x_scale,25,"Simple Bar Graph", $black);

    // what next draw the bars
    $x = 30;
    $y = $max_height - $margin;
    $w = 40*$x_scale;
    // get into some meat now, cheese for vegetarians;
    for ($i=0;$i<count($data);$i++){
        $y_ht = ($data[$i]/max($data))* 100 * $y_scale;
        imagerectangle($im,$x,$y,$x+$w,($y-$y_ht),$blue);
        imagestring($im,2,$x+10*$x_scale*$x_scale,$y+3,$data[$i],$black);
        $x = $x+$w+40*$x_scale;
    }
    $pixbuf = GdkPixbuf::new_from_gd($im);
    $img->set_from_pixbuf($pixbuf);
}

function on_value_changed($adj) {
    global $hadj, $vadj;
    $x_val = $hadj->get_value(); // note 1
    $y_val = $vadj->get_value(); // note 1
    if ($x_val==0) $x_val = 1;
    echo "on_value_changed. val = $x_val, $y_val\n";
    draw_bargraph($x_val, $y_val); // note 2
}

?>

Output

As shown above.

 

Explanation

The above code is a synthesis of the codes from Part 2 and Part 3.

  1. Note that we can handle both scrollbars with just one signal handler.
  2. Redraw the bar graph.

Note

This example serves mainly to illustrate the use of GtkAdjustment and GtkVScrollbar. I will leave it to you to optimize and polish the gd2 portion (for the display of the bar graph).

Related Links

Add comment


Security code
Refresh