A smooth effect with GTK+
Mike Massonnet | Posted 3 months, 6 days ago on February 18, 2006
Did you try the Beta of GAIM2 ? In the discussion window there is a nice smooth effect, when the discussion scrolls down after you get or send a message. Also in GParted there is this effect when you show or hide a panel.
Now, if you are looking on how this effect is done, read the source :)
#include <stdlib.h>
#include <gtk/gtk.h>
#define DEBUG 1
void openclose_panel(GtkWidget*, gpointer);
void open_panel();
void close_panel();
GtkWidget *pWindow;
GtkWidget *pPanel;
GtkWidget *pButton;
GtkWidget *pLabel;
int
main(int argc, char **argv)
{
/* Initialization of GTK+ */
gtk_init(&argc, &argv);
/* The window */
pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(pWindow), "¡Panned!");
gtk_window_set_default_size(GTK_WINDOW(pWindow), 450, 300);
/* Panel */
pPanel = gtk_vpaned_new();
gtk_container_add(GTK_CONTAINER(pWindow), pPanel);
/* Button */
pButton=gtk_button_new_with_label("Close the panel");
gtk_paned_pack1(GTK_PANED(pPanel), pButton, FALSE, FALSE);
/* Label */
pLabel = gtk_label_new( "Hello" );
gtk_paned_pack2(GTK_PANED(pPanel), pLabel, TRUE, FALSE);
/* Show */
gtk_widget_show_all(pWindow);
/* Callbacks */
g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(pButton), "clicked", G_CALLBACK(openclose_panel), NULL);
/* Cycle loop and so on */
gtk_main();
return EXIT_SUCCESS;
}
void
openclose_panel(GtkWidget *pWidget, gpointer pData)
{
gboolean is_hiden = !(GTK_WIDGET_FLAGS (pLabel) & GTK_VISIBLE);
if (DEBUG) printf("is_hiden:%d\n", is_hiden);
if (is_hiden)
{
gtk_widget_show(pLabel);
gtk_label_set_text(GTK_LABEL(pLabel), "Hello");
open_panel();
gtk_button_set_label(GTK_BUTTON(pButton), "Close the panel");
}
else
{
gtk_label_set_text(GTK_LABEL(pLabel), "Bye");
close_panel();
gtk_widget_hide(pLabel);
gtk_button_set_label(GTK_BUTTON(pButton), "Open the panel");
}
}
void
open_panel()
{
gint pos = gtk_paned_get_position(GTK_PANED(pPanel));
if (DEBUG)
{
gint width,height;
gtk_window_get_size(GTK_WINDOW(pWindow), &width, &height);
printf("div_pos:%d/%d\n", gtk_paned_get_position(GTK_PANED(pPanel)) , \
height);
}
/* * * * * * * */
/* Start the resizing */
/* * * * * * * */
while (pos > 0)
{
pos -= 5;
gtk_paned_set_position(GTK_PANED(pPanel), pos);
while (gtk_events_pending())
{
gtk_main_iteration();
}
}
}
void
close_panel()
{
gint pos = gtk_paned_get_position(GTK_PANED(pPanel));
gint width,height;
gtk_window_get_size(GTK_WINDOW(pWindow), &width, &height);
if (DEBUG) printf("div_pos:%d/%d\n", gtk_paned_get_position(GTK_PANED(pPanel)) , \
height);
/* * * * * * * */
/* Start the resizing */
/* * * * * * * */
while (pos < height)
{
pos += 5;
gtk_paned_set_position(GTK_PANED(pPanel), pos);
while (gtk_events_pending())
{
gtk_main_iteration();
}
}
}
The important part is the resizing where you reduce or expand the size of a widget in a loop, and each time you set the new size in the loop, you need to get into another loop to be able to see the effect:
while (gtk_events_pending())
{
gtk_main_iteration();
}
It is really easy and gives the application a nice impression :)