* nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
* and Linux systems.
*
* Copyright (C) 2004 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program 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 General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>.
*/
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "ctkscale.h"
#include "ctkutils.h"
#include <stdio.h>
#ifdef CTK_GTK3
#include <gdk/gdkkeysyms-compat.h>
#endif
static void ctk_scale_finalize(GObject *object);
static void ctk_scale_init(CtkScaleClass *ctk_object_class, gpointer);
enum {
PROP_0,
PROP_GTK_ADJUSTMENT,
PROP_LABEL
};
GType ctk_scale_get_type(
void
)
{
static GType ctk_scale_type = 0;
if (!ctk_scale_type) {
static const GTypeInfo ctk_scale_info = {
sizeof (CtkScaleClass),
NULL,
NULL,
(GClassInitFunc) ctk_scale_init,
NULL,
NULL,
sizeof (CtkScale),
0,
NULL,
NULL
};
ctk_scale_type = g_type_register_static (GTK_TYPE_VBOX,
"CtkScale", &ctk_scale_info, 0);
}
return ctk_scale_type;
}
static void ctk_scale_init(CtkScaleClass *ctk_object_class,
gpointer class_data)
{
GObjectClass *gobject_class = (GObjectClass *)ctk_object_class;
gobject_class->finalize = ctk_scale_finalize;
}
static void ctk_scale_finalize(GObject *object)
{
CtkScale *ctk_scale = CTK_SCALE(object);
g_signal_handlers_disconnect_matched(G_OBJECT(ctk_scale->ctk_config),
G_SIGNAL_MATCH_DATA,
0,
0,
NULL,
NULL,
(gpointer) G_OBJECT(ctk_scale));
}
* ctk_scale_key_event() - GTK's default handling of the up/down keys
* for hscale widgets is odd, so override it: the up key and the page
* up key increase the adjustment value; similarly, the down key and
* the page down key decrease the adjustment value.
*/
static gboolean ctk_scale_key_event(GtkWidget *widget, GdkEvent *event,
gpointer user_data)
{
CtkScale *ctk_scale = CTK_SCALE(user_data);
GdkEventKey *key_event = (GdkEventKey *) event;
GtkAdjustment *adjustment = GTK_ADJUSTMENT(ctk_scale->gtk_adjustment);
gdouble newval;
gdouble value = gtk_adjustment_get_value(adjustment);
gdouble step_increment = ctk_adjustment_get_step_increment(adjustment);
gdouble page_increment = ctk_adjustment_get_page_increment(adjustment);
switch (key_event->keyval) {
case GDK_Left:
case GDK_KP_Left:
case GDK_Down:
case GDK_KP_Down:
newval = value - step_increment;
break;
case GDK_Right:
case GDK_KP_Right:
case GDK_Up:
case GDK_KP_Up:
newval = value + step_increment;
break;
case GDK_Page_Down:
case GDK_KP_Page_Down:
newval = value - page_increment;
break;
case GDK_Page_Up:
case GDK_KP_Page_Up:
newval = value + page_increment;
break;
default:
return FALSE;
}
gtk_adjustment_set_value(adjustment, newval);
return TRUE;
}
static void adjustment_value_changed(
GtkAdjustment *adjustment,
gpointer user_data
)
{
CtkScale *ctk_scale = CTK_SCALE(user_data);
gchar text[7];
switch (ctk_scale->value_type) {
case G_TYPE_INT:
g_snprintf(text, 6, "%d", (gint) gtk_adjustment_get_value(adjustment));
break;
case G_TYPE_DOUBLE:
default:
g_snprintf(text, 6, "%2.3f", gtk_adjustment_get_value(adjustment));
break;
}
gtk_entry_set_text(GTK_ENTRY(ctk_scale->text_entry), text);
}
static void text_entry_activate(
GtkEntry *entry,
gpointer user_data
)
{
CtkScale *ctk_scale = CTK_SCALE(user_data);
gdouble newval = g_strtod(gtk_entry_get_text(entry), NULL);
gtk_adjustment_set_value(ctk_scale->gtk_adjustment, newval);
}
* text_entry_toggled() -
*/
static void text_entry_toggled(CtkConfig *ctk_config, gpointer user_data)
{
CtkScale *ctk_scale = CTK_SCALE(user_data);
if (ctk_config_slider_text_entry_shown(ctk_config)) {
if (!ctk_scale->text_entry_packed) {
gtk_container_add(GTK_CONTAINER(ctk_scale->text_entry_container),
ctk_scale->text_entry);
}
gtk_widget_show(ctk_scale->text_entry);
ctk_scale->text_entry_packed = TRUE;
} else {
if (ctk_scale->text_entry_packed) {
gtk_container_remove
(GTK_CONTAINER(ctk_scale->text_entry_container),
ctk_scale->text_entry);
}
gtk_widget_hide(ctk_scale->text_entry);
ctk_scale->text_entry_packed = FALSE;
}
}
* ctk_scale_new() - constructor for the Scale widget
*/
GtkWidget* ctk_scale_new(GtkAdjustment *gtk_adjustment,
const gchar *label_text,
CtkConfig *ctk_config,
gint value_type)
{
GObject *object;
CtkScale *ctk_scale;
GtkWidget *label;
GtkWidget *frame;
GtkWidget *hbox;
g_return_val_if_fail(GTK_IS_ADJUSTMENT(gtk_adjustment), NULL);
g_return_val_if_fail(label_text != NULL, NULL);
object = g_object_new(CTK_TYPE_SCALE, NULL);
ctk_scale = CTK_SCALE(object);
ctk_scale->gtk_adjustment = gtk_adjustment;
ctk_scale->label = label_text;
ctk_scale->ctk_config = ctk_config;
ctk_scale->value_type = value_type;
gtk_box_set_spacing (GTK_BOX (object), 2);
label = gtk_label_new(ctk_scale->label);
gtk_box_pack_start(GTK_BOX (object), label, FALSE, FALSE, 0);
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(object), frame, TRUE, TRUE, 0);
ctk_scale->tooltip_widget = frame;
hbox = gtk_hbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(ctk_scale->tooltip_widget), hbox);
ctk_scale->text_entry = gtk_entry_new();
gtk_entry_set_max_length(GTK_ENTRY(ctk_scale->text_entry), 6);
gtk_entry_set_width_chars(GTK_ENTRY(ctk_scale->text_entry), 6);
ctk_scale->text_entry_container = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(ctk_scale->text_entry_container),
GTK_SHADOW_NONE);
gtk_container_set_border_width
(GTK_CONTAINER(ctk_scale->text_entry_container), 0);
gtk_container_add(GTK_CONTAINER(ctk_scale->text_entry_container),
ctk_scale->text_entry);
ctk_scale->text_entry_packed = TRUE;
g_object_ref(G_OBJECT(ctk_scale->text_entry));
gtk_box_pack_start(GTK_BOX(hbox),
ctk_scale->text_entry_container, FALSE, FALSE, 0);
text_entry_toggled(ctk_scale->ctk_config, (gpointer) ctk_scale);
adjustment_value_changed(ctk_scale->gtk_adjustment, G_OBJECT(ctk_scale));
g_signal_connect(G_OBJECT(ctk_scale->gtk_adjustment), "value_changed",
G_CALLBACK(adjustment_value_changed),
(gpointer) ctk_scale);
g_signal_connect(G_OBJECT(ctk_scale->text_entry), "activate",
G_CALLBACK(text_entry_activate),
(gpointer) ctk_scale);
g_signal_connect(G_OBJECT(ctk_config), "slider_text_entry_toggled",
G_CALLBACK(text_entry_toggled),
(gpointer) ctk_scale);
ctk_scale->gtk_scale =
gtk_hscale_new(GTK_ADJUSTMENT(ctk_scale->gtk_adjustment));
gtk_scale_set_draw_value(GTK_SCALE(ctk_scale->gtk_scale), FALSE);
gtk_scale_set_digits(GTK_SCALE(ctk_scale->gtk_scale), 6);
gtk_box_pack_start(GTK_BOX(hbox), ctk_scale->gtk_scale, TRUE, TRUE, 3);
g_signal_connect(ctk_scale->gtk_scale, "key_press_event",
G_CALLBACK(ctk_scale_key_event), G_OBJECT(ctk_scale));
return GTK_WIDGET (object);
}