* 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
431 lines
13 KiB
C
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)));
|
|
}
|