claws-mail/src/gtk/gtkvscrollbutton.c
Colin Leroy 8dc0029409 2008-09-09 [colin] 3.5.0cvs96
* src/action.h
	* src/addr_compl.c
	* src/addressadd.c
	* src/addressbook.h
	* src/addressbook_foldersel.c
	* src/addressitem.h
	* src/addrgather.c
	* src/alertpanel.c
	* src/browseldap.c
	* src/editaddress.c
	* src/editaddress_other_attributes_ldap.h
	* src/editbook.c
	* src/editjpilot.c
	* src/editldap.c
	* src/editldap_basedn.c
	* src/editvcard.c
	* src/exphtmldlg.c
	* src/expldifdlg.c
	* src/export.c
	* src/foldersel.c
	* src/foldersel.h
	* src/gedit-print.c
	* src/gedit-print.h
	* src/grouplistdialog.c
	* src/headerview.c
	* src/headerview.h
	* src/image_viewer.c
	* src/import.c
	* src/importldif.c
	* src/importmutt.c
	* src/importpine.c
	* src/inc.c
	* src/main.c
	* src/main.h
	* src/messageview.c
	* src/messageview.h
	* src/noticeview.c
	* src/prefs_actions.c
	* src/prefs_filtering.c
	* src/prefs_folder_column.c
	* src/prefs_gtk.h
	* src/prefs_summary_column.c
	* src/prefs_toolbar.c
	* src/send_message.c
	* src/setup.c
	* src/sourcewindow.c
	* src/sourcewindow.h
	* src/ssl_manager.c
	* src/statusbar.c
	* src/statusbar.h
	* src/stock_pixmap.c
	* src/stock_pixmap.h
	* src/summaryview.c
	* src/textview.c
	* src/textview.h
	* src/undo.h
	* src/uri_opener.c
	* src/wizard.c
	* src/wizard.h
	* src/common/ssl.h
	* src/common/utils.c
	* src/gtk/about.c
	* src/gtk/colorlabel.c
	* src/gtk/colorlabel.h
	* src/gtk/combobox.h
	* src/gtk/description_window.c
	* src/gtk/filesel.c
	* src/gtk/gtkaspell.c
	* src/gtk/gtkaspell.h
	* src/gtk/gtkcmclist.c
	* src/gtk/gtkcmclist.h
	* src/gtk/gtkcmctree.c
	* src/gtk/gtkcmctree.h
	* src/gtk/gtkcmoptionmenu.h
	* src/gtk/gtksctree.c
	* src/gtk/gtksctree.h
	* src/gtk/gtkshruler.c
	* src/gtk/gtkshruler.h
	* src/gtk/gtksourceprintjob.c
	* src/gtk/gtksourceprintjob.h
	* src/gtk/gtkutils.c
	* src/gtk/gtkutils.h
	* src/gtk/gtkvscrollbutton.c
	* src/gtk/gtkvscrollbutton.h
	* src/gtk/icon_legend.c
	* src/gtk/inputdialog.c
	* src/gtk/logwindow.c
	* src/gtk/logwindow.h
	* src/gtk/manage_window.c
	* src/gtk/manage_window.h
	* src/gtk/menu.c
	* src/gtk/prefswindow.c
	* src/gtk/progressdialog.c
	* src/gtk/progressdialog.h
	* src/plugins/bogofilter/bogofilter_gtk.c
	* src/plugins/pgpcore/passphrase.c
	* src/plugins/spamassassin/spamassassin_gtk.c
	* src/plugins/trayicon/trayicon.c
	* src/plugins/trayicon/libeggtrayicon/eggtrayicon.c
	* src/plugins/trayicon/libeggtrayicon/eggtrayicon.h
	* src/plugins/trayicon/libeggtrayicon/gtk2-funcs.c
	* src/plugins/trayicon/libeggtrayicon/gtkplugxembed.c
	* src/plugins/trayicon/libeggtrayicon/gtkplugxembed.h
		Complete GTK+ 2.14 undeprecation
2008-09-09 16:40:59 +00:00

431 lines
13 KiB
C

/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
/*
* Simple composite widget to provide vertical scrolling, based
* on GtkRange widget code.
* Modified by the Sylpheed Team and others 2003
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glib.h>
#include <gtk/gtk.h>
#include "gtkvscrollbutton.h"
#define SCROLL_TIMER_LENGTH 20
#define SCROLL_INITIAL_DELAY 100 /* must hold button this long before ... */
#define SCROLL_LATER_DELAY 20 /* ... it starts repeating at this rate */
#define SCROLL_DELAY_LENGTH 300
enum {
ARG_0,
ARG_ADJUSTMENT
};
static void gtk_vscrollbutton_class_init(GtkVScrollbuttonClass * klass);
static void gtk_vscrollbutton_init(GtkVScrollbutton * vscrollbutton);
GType gtk_vscrollbutton_get_type (void);
GtkWidget *gtk_vscrollbutton_new (GtkAdjustment *adjustment);
static gint gtk_vscrollbutton_button_release (GtkWidget *widget,
GdkEventButton *event,
GtkVScrollbutton *scrollbutton);
static void gtk_vscrollbutton_set_adjustment (GtkVScrollbutton *scrollbutton,
GtkAdjustment *adjustment);
static gint gtk_vscrollbutton_button_press (GtkWidget *widget,
GdkEventButton *event,
GtkVScrollbutton *scrollbutton);
static gint gtk_vscrollbutton_button_release (GtkWidget *widget,
GdkEventButton *event,
GtkVScrollbutton *scrollbutton);
gint gtk_vscrollbutton_scroll (GtkVScrollbutton *scrollbutton);
static gboolean gtk_vscrollbutton_timer_1st_time(GtkVScrollbutton *scrollbutton);
static void gtk_vscrollbutton_add_timer (GtkVScrollbutton *scrollbutton);
static void gtk_vscrollbutton_remove_timer (GtkVScrollbutton *scrollbutton);
static gint gtk_real_vscrollbutton_timer (GtkVScrollbutton *scrollbutton);
static void gtk_vscrollbutton_set_sensitivity (GtkAdjustment *adjustment,
GtkVScrollbutton *scrollbutton);
GType gtk_vscrollbutton_get_type(void)
{
static GType vscrollbutton_type = 0;
if (!vscrollbutton_type) {
static const GTypeInfo vscrollbutton_info = {
sizeof (GtkVScrollbuttonClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gtk_vscrollbutton_class_init,
(GClassFinalizeFunc) NULL,
NULL, /* class_data */
sizeof (GtkVScrollbutton),
0, /* n_preallocs */
(GInstanceInitFunc) gtk_vscrollbutton_init,
};
vscrollbutton_type = g_type_register_static (GTK_TYPE_VBOX, "GtkVScrollbutton", &vscrollbutton_info, (GTypeFlags)0);
}
return vscrollbutton_type;
}
static void gtk_vscrollbutton_class_init(GtkVScrollbuttonClass *class)
{
}
static GdkCursor *hand_cursor = NULL;
static gboolean vscroll_visi_notify(GtkWidget *widget,
GdkEventVisibility *event,
gpointer data)
{
gdk_window_set_cursor(widget->window, hand_cursor);
return FALSE;
}
static gboolean vscroll_leave_notify(GtkWidget *widget,
GdkEventCrossing *event,
gpointer data)
{
gdk_window_set_cursor(widget->window, NULL);
return FALSE;
}
static gboolean vscroll_enter_notify(GtkWidget *widget,
GdkEventCrossing *event,
gpointer data)
{
gdk_window_set_cursor(widget->window, hand_cursor);
return FALSE;
}
static void gtk_vscrollbutton_init(GtkVScrollbutton *scrollbutton)
{
GtkWidget *arrow;
if (!hand_cursor)
hand_cursor = gdk_cursor_new(GDK_HAND2);
scrollbutton->upbutton = gtk_event_box_new();
scrollbutton->downbutton = gtk_event_box_new();
arrow = gtk_arrow_new(GTK_ARROW_UP, GTK_SHADOW_NONE);
gtk_widget_show(arrow);
gtk_container_add(GTK_CONTAINER(scrollbutton->upbutton), arrow);
gtk_widget_set_size_request(scrollbutton->upbutton, -1, 16);
arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
gtk_widget_show(arrow);
gtk_container_add(GTK_CONTAINER(scrollbutton->downbutton), arrow);
gtk_widget_set_size_request(scrollbutton->downbutton, -1, 16);
GTK_WIDGET_UNSET_FLAGS(scrollbutton->upbutton, GTK_CAN_FOCUS);
GTK_WIDGET_UNSET_FLAGS(scrollbutton->downbutton, GTK_CAN_FOCUS);
gtk_widget_show(scrollbutton->downbutton);
gtk_widget_show(scrollbutton->upbutton);
g_signal_connect(G_OBJECT(scrollbutton->upbutton), "visibility-notify-event",
G_CALLBACK(vscroll_visi_notify), NULL);
g_signal_connect(G_OBJECT(scrollbutton->upbutton), "motion-notify-event",
G_CALLBACK(vscroll_visi_notify), NULL);
g_signal_connect(G_OBJECT(scrollbutton->upbutton), "leave-notify-event",
G_CALLBACK(vscroll_leave_notify), NULL);
g_signal_connect(G_OBJECT(scrollbutton->upbutton), "enter-notify-event",
G_CALLBACK(vscroll_enter_notify), NULL);
g_signal_connect(G_OBJECT(scrollbutton->downbutton), "visibility-notify-event",
G_CALLBACK(vscroll_visi_notify), NULL);
g_signal_connect(G_OBJECT(scrollbutton->downbutton), "motion-notify-event",
G_CALLBACK(vscroll_visi_notify), NULL);
g_signal_connect(G_OBJECT(scrollbutton->downbutton), "leave-notify-event",
G_CALLBACK(vscroll_leave_notify), NULL);
g_signal_connect(G_OBJECT(scrollbutton->downbutton), "enter-notify-event",
G_CALLBACK(vscroll_enter_notify), NULL);
g_signal_connect(G_OBJECT(scrollbutton->upbutton),
"button_press_event",
G_CALLBACK(gtk_vscrollbutton_button_press),
scrollbutton);
g_signal_connect(G_OBJECT(scrollbutton->downbutton),
"button_press_event",
G_CALLBACK(gtk_vscrollbutton_button_press),
scrollbutton);
g_signal_connect(G_OBJECT(scrollbutton->upbutton),
"button_release_event",
G_CALLBACK
(gtk_vscrollbutton_button_release), scrollbutton);
g_signal_connect(G_OBJECT(scrollbutton->downbutton),
"button_release_event",
G_CALLBACK
(gtk_vscrollbutton_button_release), scrollbutton);
gtk_box_pack_start(GTK_BOX(&scrollbutton->vbox),
scrollbutton->upbutton, TRUE, TRUE, 0);
gtk_box_pack_end(GTK_BOX(&scrollbutton->vbox),
scrollbutton->downbutton, TRUE, TRUE, 0);
scrollbutton->timer = 0;
}
GtkWidget *gtk_vscrollbutton_new(GtkAdjustment *adjustment)
{
GtkWidget *vscrollbutton;
vscrollbutton = g_object_new (gtk_vscrollbutton_get_type(),
NULL);
gtk_vscrollbutton_set_adjustment(GTK_VSCROLLBUTTON(vscrollbutton),
adjustment);
g_signal_connect(G_OBJECT(GTK_VSCROLLBUTTON(vscrollbutton)->adjustment),
"value_changed",
G_CALLBACK
(gtk_vscrollbutton_set_sensitivity), vscrollbutton);
g_signal_connect(G_OBJECT(GTK_VSCROLLBUTTON(vscrollbutton)->adjustment),
"changed",
G_CALLBACK
(gtk_vscrollbutton_set_sensitivity), vscrollbutton);
return vscrollbutton;
}
void gtk_vscrollbutton_set_adjustment(GtkVScrollbutton *scrollbutton,
GtkAdjustment *adjustment)
{
g_return_if_fail(scrollbutton != NULL);
g_return_if_fail(GTK_IS_VSCROLLBUTTON(scrollbutton));
if (!adjustment)
adjustment =
GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
else
g_return_if_fail(GTK_IS_ADJUSTMENT(adjustment));
if (scrollbutton->adjustment != adjustment) {
if (scrollbutton->adjustment) {
g_signal_handlers_disconnect_matched(scrollbutton->adjustment,
G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL,
(gpointer) scrollbutton);
g_object_unref(G_OBJECT(scrollbutton->adjustment));
}
scrollbutton->adjustment = adjustment;
g_object_ref(G_OBJECT(adjustment));
#if GLIB_CHECK_VERSION(2,10,0)
g_object_ref_sink (G_OBJECT(adjustment));
#else
gtk_object_ref (G_OBJECT (adjustment));
gtk_object_sink (G_OBJECT (adjustment));
#endif
}
}
static gint gtk_vscrollbutton_button_press(GtkWidget *widget,
GdkEventButton *event,
GtkVScrollbutton *scrollbutton)
{
if (!GTK_WIDGET_HAS_FOCUS(widget))
gtk_widget_grab_focus(widget);
if (scrollbutton->button == 0) {
gtk_grab_add(widget);
scrollbutton->button = event->button;
if (widget == scrollbutton->downbutton)
scrollbutton->scroll_type = GTK_SCROLL_STEP_FORWARD;
else
scrollbutton->scroll_type = GTK_SCROLL_STEP_BACKWARD;
gtk_vscrollbutton_scroll(scrollbutton);
gtk_vscrollbutton_add_timer(scrollbutton);
}
return TRUE;
}
static gint gtk_vscrollbutton_button_release(GtkWidget *widget,
GdkEventButton *event,
GtkVScrollbutton *scrollbutton)
{
if (!GTK_WIDGET_HAS_FOCUS(widget))
gtk_widget_grab_focus(widget);
if (scrollbutton->button == event->button) {
gtk_grab_remove(widget);
scrollbutton->button = 0;
gtk_vscrollbutton_remove_timer(scrollbutton);
gtk_vscrollbutton_set_sensitivity(scrollbutton->adjustment, scrollbutton);
}
return TRUE;
}
gint gtk_vscrollbutton_scroll(GtkVScrollbutton *scrollbutton)
{
gfloat new_value;
gint return_val;
g_return_val_if_fail(scrollbutton != NULL, FALSE);
g_return_val_if_fail(GTK_IS_VSCROLLBUTTON(scrollbutton), FALSE);
new_value = scrollbutton->adjustment->value;
return_val = TRUE;
switch (scrollbutton->scroll_type) {
case GTK_SCROLL_STEP_BACKWARD:
new_value -= scrollbutton->adjustment->step_increment;
if (new_value <= scrollbutton->adjustment->lower) {
new_value = scrollbutton->adjustment->lower;
return_val = FALSE;
scrollbutton->timer = 0;
}
break;
case GTK_SCROLL_STEP_FORWARD:
new_value += scrollbutton->adjustment->step_increment;
if (new_value >=
(scrollbutton->adjustment->upper -
scrollbutton->adjustment->page_size)) {
new_value =
scrollbutton->adjustment->upper -
scrollbutton->adjustment->page_size;
return_val = FALSE;
scrollbutton->timer = 0;
}
break;
default:
break;
}
if (new_value != scrollbutton->adjustment->value) {
scrollbutton->adjustment->value = new_value;
g_signal_emit_by_name(G_OBJECT
(scrollbutton->adjustment),
"value_changed");
gtk_widget_queue_resize(GTK_WIDGET(scrollbutton)); /* ensure resize */
}
return return_val;
}
static gboolean
gtk_vscrollbutton_timer_1st_time(GtkVScrollbutton *scrollbutton)
{
/*
* If the real timeout function succeeds and the timeout is still set,
* replace it with a quicker one so successive scrolling goes faster.
*/
g_object_ref(G_OBJECT(scrollbutton));
if (scrollbutton->timer) {
/* We explicitely remove ourselves here in the paranoia
* that due to things happening above in the callback
* above, we might have been removed, and another added.
*/
g_source_remove(scrollbutton->timer);
scrollbutton->timer = g_timeout_add(SCROLL_LATER_DELAY,
(GtkFunction)
gtk_real_vscrollbutton_timer,
scrollbutton);
}
g_object_unref(G_OBJECT(scrollbutton));
return FALSE; /* don't keep calling this function */
}
static void gtk_vscrollbutton_add_timer(GtkVScrollbutton *scrollbutton)
{
g_return_if_fail(scrollbutton != NULL);
g_return_if_fail(GTK_IS_VSCROLLBUTTON(scrollbutton));
if (!scrollbutton->timer) {
scrollbutton->need_timer = TRUE;
scrollbutton->timer = g_timeout_add(SCROLL_INITIAL_DELAY,
(GtkFunction)
gtk_vscrollbutton_timer_1st_time,
scrollbutton);
}
}
static void gtk_vscrollbutton_remove_timer(GtkVScrollbutton *scrollbutton)
{
g_return_if_fail(scrollbutton != NULL);
g_return_if_fail(GTK_IS_VSCROLLBUTTON(scrollbutton));
if (scrollbutton->timer) {
g_source_remove(scrollbutton->timer);
scrollbutton->timer = 0;
}
scrollbutton->need_timer = FALSE;
}
static gint gtk_real_vscrollbutton_timer(GtkVScrollbutton *scrollbutton)
{
gint return_val;
GDK_THREADS_ENTER();
return_val = TRUE;
if (!scrollbutton->timer) {
return_val = FALSE;
if (scrollbutton->need_timer)
scrollbutton->timer =
g_timeout_add(SCROLL_TIMER_LENGTH,
(GtkFunction) gtk_real_vscrollbutton_timer,
(gpointer) scrollbutton);
else {
GDK_THREADS_LEAVE();
return FALSE;
}
scrollbutton->need_timer = FALSE;
}
GDK_THREADS_LEAVE();
return_val = gtk_vscrollbutton_scroll(scrollbutton);
return return_val;
}
static void gtk_vscrollbutton_set_sensitivity (GtkAdjustment *adjustment,
GtkVScrollbutton *scrollbutton)
{
if (!GTK_WIDGET_REALIZED(GTK_WIDGET(scrollbutton))) return;
if (scrollbutton->button != 0) return; /* not while something is pressed */
gtk_widget_set_sensitive(scrollbutton->upbutton,
(adjustment->value > adjustment->lower));
gtk_widget_set_sensitive(scrollbutton->downbutton,
(adjustment->value < (adjustment->upper - adjustment->page_size)));
}