mirror of https://github.com/GNOME/gimp.git
922 lines
33 KiB
C
922 lines
33 KiB
C
/* LIBGIMP - The GIMP Library
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
*
|
|
* gimpscalecontrol.c
|
|
* Copyright (C) 2000 Michael Natterer <mitch@gimp.org>
|
|
* 2008 Bill Skaggs <weskaggs@primate.ucdavis.edu>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 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 Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libgimpcolor/gimpcolor.h"
|
|
#include "libgimpmath/gimpmath.h"
|
|
#include "libgimpbase/gimpbase.h"
|
|
|
|
#include "gimpwidgetstypes.h"
|
|
|
|
#include "gimphelpui.h"
|
|
#include "gimpcolorscale.h"
|
|
#include "gimpscalecontrol.h"
|
|
|
|
static void gimp_scale_control_class_init (GimpScaleControlClass *klass);
|
|
|
|
static void gimp_scale_control_init (GimpScaleControl *control);
|
|
|
|
static void gimp_scale_control_finalize (GObject *object);
|
|
|
|
static void unconstrained_adjustment_callback (GtkAdjustment *adjustment,
|
|
GtkAdjustment *other_adj);
|
|
|
|
static void exp_adjustment_callback (GtkAdjustment *adjustment,
|
|
GtkAdjustment *other_adj);
|
|
|
|
static void log_adjustment_callback (GtkAdjustment *adjustment,
|
|
GtkAdjustment *other_adj);
|
|
|
|
static GimpScaleControl * gimp_scale_control_create (gboolean color_scale,
|
|
gint scale_width,
|
|
gint spinbutton_width,
|
|
gdouble value,
|
|
gdouble lower,
|
|
gdouble upper,
|
|
gdouble step_increment,
|
|
gdouble page_increment,
|
|
guint digits,
|
|
gboolean constrain,
|
|
gdouble unconstrained_lower,
|
|
gdouble unconstrained_upper,
|
|
const gchar *tooltip,
|
|
const gchar *help_id);
|
|
|
|
static void gimp_scale_control_create_widgets (GimpScaleControl *scale_control);
|
|
|
|
static GtkWidget * gimp_scale_control_create_label (GimpScaleControl *scale_control,
|
|
const gchar *text);
|
|
|
|
static GtkWidget * gimp_scale_control_popup (GimpScaleControl *scale_control);
|
|
|
|
static void gimp_scale_control_show_popup (GtkWidget *widget,
|
|
GimpScaleControl *scale_control);
|
|
|
|
static void gimp_scale_control_remove_popup (GtkWidget *widget,
|
|
GdkEventCrossing *event,
|
|
GimpScaleControl *scale_control);
|
|
|
|
static void gimp_scale_control_value_changed (GimpScaleControl *scale_control);
|
|
|
|
static void gimp_scale_control_set_value (GimpScaleControl *scale_control,
|
|
gdouble value);
|
|
|
|
|
|
G_DEFINE_TYPE (GimpScaleControl, gimp_scale_control, GTK_TYPE_ADJUSTMENT)
|
|
|
|
#define parent_class gimp_scale_control_parent_class
|
|
|
|
static void
|
|
gimp_scale_control_class_init (GimpScaleControlClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->finalize = gimp_scale_control_finalize;
|
|
}
|
|
|
|
static void
|
|
gimp_scale_control_init (GimpScaleControl *scale_control)
|
|
{
|
|
scale_control->color_scale = FALSE;
|
|
scale_control->scale_width = 0;
|
|
scale_control->spinbutton_width = 0;
|
|
scale_control->digits = 0;
|
|
scale_control->constrain = FALSE;
|
|
scale_control->unconstrained_lower = 0;
|
|
scale_control->unconstrained_upper = 0;
|
|
scale_control->tooltip = NULL;
|
|
scale_control->help_id = NULL;
|
|
scale_control->logarithmic = FALSE;
|
|
scale_control->policy = GTK_UPDATE_DISCONTINUOUS;
|
|
scale_control->text = NULL;
|
|
|
|
scale_control->scale_adj = NULL;
|
|
scale_control->spinbutton_adj = NULL;
|
|
|
|
scale_control->button = NULL;
|
|
scale_control->button_label = NULL;
|
|
scale_control->label = NULL;
|
|
scale_control->scale = NULL;
|
|
scale_control->spinbutton = NULL;
|
|
scale_control->entry = NULL;
|
|
scale_control->popup_button = NULL;
|
|
scale_control->popup_window = NULL;
|
|
}
|
|
|
|
static void
|
|
gimp_scale_control_finalize (GObject *object)
|
|
{
|
|
}
|
|
|
|
static void
|
|
unconstrained_adjustment_callback (GtkAdjustment *adjustment,
|
|
GtkAdjustment *other_adj)
|
|
{
|
|
g_signal_handlers_block_by_func (other_adj,
|
|
unconstrained_adjustment_callback,
|
|
adjustment);
|
|
|
|
gtk_adjustment_set_value (other_adj, adjustment->value);
|
|
|
|
g_signal_handlers_unblock_by_func (adjustment,
|
|
unconstrained_adjustment_callback,
|
|
other_adj);
|
|
}
|
|
|
|
static void
|
|
log_adjustment_callback (GtkAdjustment *adjustment,
|
|
GtkAdjustment *other_adj)
|
|
{
|
|
gdouble value;
|
|
|
|
g_signal_handlers_block_by_func (other_adj,
|
|
exp_adjustment_callback,
|
|
adjustment);
|
|
if (adjustment->lower <= 0.0)
|
|
value = log (adjustment->value - adjustment->lower + 0.1);
|
|
else
|
|
value = log (adjustment->value);
|
|
|
|
gtk_adjustment_set_value (other_adj, value);
|
|
|
|
g_signal_handlers_unblock_by_func (other_adj,
|
|
exp_adjustment_callback,
|
|
adjustment);
|
|
}
|
|
|
|
static void
|
|
exp_adjustment_callback (GtkAdjustment *adjustment,
|
|
GtkAdjustment *other_adj)
|
|
{
|
|
gdouble value;
|
|
|
|
g_signal_handlers_block_by_func (other_adj,
|
|
log_adjustment_callback,
|
|
adjustment);
|
|
|
|
value = exp (adjustment->value);
|
|
if (other_adj->lower <= 0.0)
|
|
value += other_adj->lower - 0.1;
|
|
|
|
gtk_adjustment_set_value (other_adj, value);
|
|
|
|
g_signal_handlers_unblock_by_func (other_adj,
|
|
log_adjustment_callback,
|
|
adjustment);
|
|
}
|
|
|
|
static GimpScaleControl *
|
|
gimp_scale_control_create (gboolean color_scale,
|
|
gint scale_width,
|
|
gint spinbutton_width,
|
|
gdouble value,
|
|
gdouble lower,
|
|
gdouble upper,
|
|
gdouble step_increment,
|
|
gdouble page_increment,
|
|
guint digits,
|
|
gboolean constrain,
|
|
gdouble unconstrained_lower,
|
|
gdouble unconstrained_upper,
|
|
const gchar *tooltip,
|
|
const gchar *help_id)
|
|
{
|
|
GimpScaleControl *scale_control;
|
|
GtkAdjustment *adjustment;
|
|
|
|
scale_control = g_object_new (GIMP_TYPE_SCALE_CONTROL, NULL);
|
|
|
|
adjustment = GTK_ADJUSTMENT (scale_control);
|
|
|
|
adjustment->value = value;
|
|
adjustment->step_increment = step_increment;
|
|
adjustment->page_increment = page_increment;
|
|
adjustment->page_size = 0;
|
|
|
|
scale_control->color_scale = color_scale;
|
|
scale_control->scale_width = scale_width;
|
|
scale_control->spinbutton_width = spinbutton_width;
|
|
scale_control->digits = digits;
|
|
scale_control->constrain = constrain;
|
|
scale_control->unconstrained_lower = unconstrained_lower;
|
|
scale_control->unconstrained_upper = unconstrained_upper;
|
|
scale_control->tooltip = tooltip;
|
|
scale_control->help_id = help_id;
|
|
|
|
if (! constrain &&
|
|
unconstrained_lower <= lower &&
|
|
unconstrained_upper >= upper)
|
|
{
|
|
adjustment->lower = unconstrained_lower;
|
|
adjustment->upper = unconstrained_upper;
|
|
|
|
scale_control->scale_adj = GTK_OBJECT (adjustment);
|
|
|
|
scale_control->spinbutton_adj = gtk_adjustment_new (value, lower, upper,
|
|
step_increment,
|
|
page_increment,
|
|
0.0);
|
|
|
|
g_signal_connect
|
|
(G_OBJECT (scale_control->scale_adj), "value-changed",
|
|
G_CALLBACK (unconstrained_adjustment_callback),
|
|
scale_control->spinbutton_adj);
|
|
|
|
g_signal_connect
|
|
(G_OBJECT (scale_control->spinbutton_adj), "value-changed",
|
|
G_CALLBACK (unconstrained_adjustment_callback),
|
|
scale_control->scale_adj);
|
|
}
|
|
else
|
|
{
|
|
adjustment->lower = lower;
|
|
adjustment->upper = upper;
|
|
|
|
scale_control->scale_adj = GTK_OBJECT (scale_control);
|
|
scale_control->spinbutton_adj = GTK_OBJECT (scale_control);
|
|
}
|
|
|
|
return scale_control;
|
|
}
|
|
|
|
/*
|
|
* Create the scale and spinbutton for a scale control.
|
|
*/
|
|
static void
|
|
gimp_scale_control_create_widgets (GimpScaleControl *scale_control)
|
|
{
|
|
gint spinbutton_width = scale_control->spinbutton_width;
|
|
GtkWidget *scale;
|
|
GtkWidget *spinbutton;
|
|
GtkAdjustment *adjustment;
|
|
|
|
adjustment = GTK_ADJUSTMENT (scale_control->spinbutton_adj);
|
|
|
|
spinbutton = gtk_spin_button_new (adjustment,
|
|
1.0, scale_control->digits);
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
|
|
|
|
|
|
if (spinbutton_width > 0)
|
|
{
|
|
if (spinbutton_width < 17)
|
|
gtk_entry_set_width_chars (GTK_ENTRY (spinbutton),
|
|
spinbutton_width);
|
|
else
|
|
gtk_widget_set_size_request (spinbutton,
|
|
spinbutton_width, -1);
|
|
}
|
|
|
|
adjustment = GTK_ADJUSTMENT (scale_control->scale_adj);
|
|
|
|
if (scale_control->color_scale)
|
|
{
|
|
scale = gimp_color_scale_new (GTK_ORIENTATION_HORIZONTAL,
|
|
GIMP_COLOR_SELECTOR_VALUE);
|
|
|
|
gtk_range_set_adjustment (GTK_RANGE (scale), adjustment);
|
|
}
|
|
else
|
|
{
|
|
scale = gtk_hscale_new (adjustment);
|
|
}
|
|
|
|
if (scale_control->scale_width > 0)
|
|
gtk_widget_set_size_request (scale, scale_control->scale_width, -1);
|
|
gtk_scale_set_digits (GTK_SCALE (scale), scale_control->digits);
|
|
gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
|
|
|
|
scale_control->spinbutton = spinbutton;
|
|
scale_control->scale = scale;
|
|
}
|
|
|
|
/*
|
|
* returns either a label or an event box containing a label,
|
|
* depending on whether there is a tooltip
|
|
*/
|
|
static GtkWidget *
|
|
gimp_scale_control_create_label (GimpScaleControl *scale_control,
|
|
const gchar *text)
|
|
{
|
|
gchar *markup;
|
|
GtkWidget *label;
|
|
|
|
markup = g_markup_printf_escaped ("%s", text);
|
|
label = gtk_label_new (NULL);
|
|
|
|
gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), markup);
|
|
g_free (markup);
|
|
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
|
|
|
if (scale_control->tooltip)
|
|
{
|
|
GtkWidget *ebox = g_object_new (GTK_TYPE_EVENT_BOX,
|
|
"visible-window", FALSE,
|
|
NULL);
|
|
gtk_container_add (GTK_CONTAINER (ebox), label);
|
|
gtk_widget_show (label);
|
|
|
|
gimp_help_set_help_data (ebox, scale_control->tooltip,
|
|
scale_control->help_id);
|
|
return ebox;
|
|
}
|
|
else
|
|
return label;
|
|
}
|
|
|
|
/**
|
|
* gimp_scale_control_new:
|
|
* @table: The #GtkTable the widgets will be attached to.
|
|
* @column: The column to start with.
|
|
* @row: The row to attach the widgets.
|
|
* @text: The text for the #GtkLabel which will appear
|
|
* left of the #GtkHScale.
|
|
* @scale_width: The minimum horizontal size of the #GtkHScale.
|
|
* @spinbutton_width: The minimum horizontal size of the #GtkSpinButton.
|
|
* @value: The initial value.
|
|
* @lower: The lower boundary.
|
|
* @upper: The upper boundary.
|
|
* @step_increment: The step increment.
|
|
* @page_increment: The page increment.
|
|
* @digits: The number of decimal digits.
|
|
* @constrain: %TRUE if the range of possible values of the
|
|
* #GtkSpinButton should be the same as of the #GtkHScale.
|
|
* @unconstrained_lower: The spinbutton's lower boundary
|
|
* if @constrain == %FALSE.
|
|
* @unconstrained_upper: The spinbutton's upper boundary
|
|
* if @constrain == %FALSE.
|
|
* @tooltip: A tooltip message for the scale and the spinbutton.
|
|
* @help_id: The widgets' help_id (see gimp_help_set_help_data()).
|
|
*
|
|
* This function creates a #GtkLabel, a #GtkHScale and a #GtkSpinButton and
|
|
* attaches them to a 3-column #GtkTable.
|
|
*
|
|
* Returns: The #GtkSpinButton's #GtkAdjustment.
|
|
**/
|
|
GtkObject *
|
|
gimp_scale_control_new (GtkTable *table,
|
|
gint column,
|
|
gint row,
|
|
const gchar *text,
|
|
gint scale_width,
|
|
gint spinbutton_width,
|
|
gdouble value,
|
|
gdouble lower,
|
|
gdouble upper,
|
|
gdouble step_increment,
|
|
gdouble page_increment,
|
|
guint digits,
|
|
gboolean constrain,
|
|
gdouble unconstrained_lower,
|
|
gdouble unconstrained_upper,
|
|
const gchar *tooltip,
|
|
const gchar *help_id)
|
|
{
|
|
GimpScaleControl *scale_control;
|
|
GtkWidget *entry;
|
|
GtkWidget *popup_button;
|
|
GtkWidget *arrow;
|
|
GtkWidget *hbox;
|
|
|
|
/* we override the scale width */
|
|
scale_control = gimp_scale_control_create (FALSE, 180, spinbutton_width,
|
|
value, lower, upper, step_increment,
|
|
page_increment, digits, constrain,
|
|
unconstrained_upper, unconstrained_lower,
|
|
tooltip, help_id);
|
|
|
|
scale_control->text = text;
|
|
scale_control->label = gimp_scale_control_create_label (scale_control, text);
|
|
|
|
g_signal_connect (scale_control, "value-changed",
|
|
G_CALLBACK (gimp_scale_control_value_changed),
|
|
NULL);
|
|
|
|
/* scale_control->button = gtk_button_new (); */
|
|
/* gtk_button_set_relief (GTK_BUTTON (scale_control->button), */
|
|
/* GTK_RELIEF_NONE); */
|
|
/* gtk_button_set_alignment (GTK_BUTTON (scale_control->button), */
|
|
/* 0, 0.5); */
|
|
|
|
/* scale_control->button_label = gtk_label_new (NULL); */
|
|
/* gtk_container_add (GTK_CONTAINER (scale_control->button), */
|
|
/* scale_control->button_label); */
|
|
/* gtk_misc_set_alignment (GTK_MISC (scale_control->button_label), 0, 0.5); */
|
|
/* gtk_widget_show (scale_control->button_label); */
|
|
|
|
/* g_signal_connect (scale_control->button, "clicked", */
|
|
/* G_CALLBACK (gimp_scale_control_show_popup), */
|
|
/* (gpointer) scale_control); */
|
|
|
|
scale_control->entry = entry = gtk_entry_new ();
|
|
|
|
if (digits == 0)
|
|
gtk_entry_set_width_chars (GTK_ENTRY (entry), 4);
|
|
else
|
|
gtk_entry_set_width_chars (GTK_ENTRY (entry), 8);
|
|
|
|
gtk_entry_set_has_frame (GTK_ENTRY (entry), FALSE);
|
|
gimp_scale_control_set_value (scale_control, value);
|
|
|
|
scale_control->popup_button = popup_button = gtk_button_new ();
|
|
/* gtk_button_set_relief (GTK_BUTTON (popup_button), GTK_RELIEF_NONE); */
|
|
|
|
g_signal_connect (popup_button, "clicked",
|
|
G_CALLBACK (gimp_scale_control_show_popup),
|
|
(gpointer) scale_control);
|
|
|
|
arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_ETCHED_OUT);
|
|
gtk_container_add (GTK_CONTAINER (popup_button), arrow);
|
|
gtk_widget_show (arrow);
|
|
|
|
hbox = gtk_hbox_new (FALSE, 0);
|
|
gtk_box_pack_start (GTK_BOX (hbox), scale_control->entry, FALSE, FALSE, 0);
|
|
gtk_box_pack_start (GTK_BOX (hbox), popup_button, FALSE, FALSE, 0);
|
|
gtk_widget_show (hbox);
|
|
|
|
gtk_table_attach (GTK_TABLE (table), scale_control->label,
|
|
column, column + 1, row, row + 1,
|
|
GTK_FILL, GTK_FILL, 0, 0);
|
|
gtk_widget_show (scale_control->label);
|
|
/* gtk_table_attach (GTK_TABLE (table), scale_control->entry, */
|
|
/* column + 1, column + 2, row, row + 1, */
|
|
/* GTK_FILL, GTK_FILL, 0, 0); */
|
|
|
|
|
|
/* gtk_widget_show (scale_control->button); */
|
|
gtk_widget_show (scale_control->entry);
|
|
|
|
gtk_table_attach (GTK_TABLE (table), hbox,
|
|
column + 1, column + 2, row, row + 1,
|
|
GTK_FILL, GTK_FILL, 0, 0);
|
|
gtk_widget_show (popup_button);
|
|
|
|
scale_control->popup_window = gimp_scale_control_popup (scale_control);
|
|
|
|
return GTK_OBJECT (scale_control);
|
|
}
|
|
|
|
/**
|
|
* gimp_color_scale_control_new:
|
|
* @table: The #GtkTable the widgets will be attached to.
|
|
* @column: The column to start with.
|
|
* @row: The row to attach the widgets.
|
|
* @text: The text for the #GtkLabel which will appear
|
|
* left of the #GtkHScale.
|
|
* @scale_width: The minimum horizontal size of the #GtkHScale.
|
|
* @spinbutton_width: The minimum horizontal size of the #GtkSpinButton.
|
|
* @value: The initial value.
|
|
* @lower: The lower boundary.
|
|
* @upper: The upper boundary.
|
|
* @step_increment: The step increment.
|
|
* @page_increment: The page increment.
|
|
* @digits: The number of decimal digits.
|
|
* @tooltip: A tooltip message for the scale and the spinbutton.
|
|
* @help_id: The widgets' help_id (see gimp_help_set_help_data()).
|
|
*
|
|
* This function creates a #GtkLabel, a #GimpColorScale and a
|
|
* #GtkSpinButton and attaches them to a 3-column #GtkTable.
|
|
*
|
|
* Returns: The #GtkSpinButton's #GtkAdjustment.
|
|
**/
|
|
GtkObject *
|
|
gimp_color_scale_control_new (GtkTable *table,
|
|
gint column,
|
|
gint row,
|
|
const gchar *text,
|
|
gint scale_width,
|
|
gint spinbutton_width,
|
|
gdouble value,
|
|
gdouble lower,
|
|
gdouble upper,
|
|
gdouble step_increment,
|
|
gdouble page_increment,
|
|
guint digits,
|
|
const gchar *tooltip,
|
|
const gchar *help_id)
|
|
{
|
|
GimpScaleControl *scale_control;
|
|
|
|
scale_control = gimp_scale_control_create (TRUE, scale_width, spinbutton_width,
|
|
value, lower, upper, step_increment,
|
|
page_increment, digits, TRUE,
|
|
0, 0, tooltip, help_id);
|
|
|
|
gimp_scale_control_create_widgets (scale_control);
|
|
|
|
scale_control->text = text;
|
|
scale_control->label = gimp_scale_control_create_label (scale_control, text);
|
|
|
|
gtk_table_attach (GTK_TABLE (table), scale_control->label,
|
|
column, column + 1, row, row + 1,
|
|
GTK_FILL, GTK_FILL, 0, 0);
|
|
gtk_widget_show (scale_control->label);
|
|
gtk_table_attach (GTK_TABLE (table), scale_control->scale,
|
|
column + 1, column + 2, row, row + 1,
|
|
GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
|
|
gtk_widget_show (scale_control->scale);
|
|
gtk_table_attach (GTK_TABLE (table), scale_control->spinbutton,
|
|
column + 2, column + 3, row, row + 1,
|
|
GTK_SHRINK, GTK_SHRINK, 0, 0);
|
|
gtk_widget_show (scale_control->spinbutton);
|
|
|
|
return GTK_OBJECT (scale_control);
|
|
}
|
|
|
|
/**
|
|
* gimp_scale_control_set_logarithmic:
|
|
* @adjustment: a #GtkAdjustment as returned by gimp_scale_control_new()
|
|
* @logarithmic: a boolean value to set or reset logarithmic behaviour
|
|
* of the scale widget
|
|
*
|
|
* Sets whether the scale_control's scale widget will behave in a linear
|
|
* or logharithmic fashion. Useful when an control has to attend large
|
|
* ranges, but smaller selections on that range require a finer
|
|
* adjustment.
|
|
*
|
|
* Since: GIMP 2.2
|
|
**/
|
|
void
|
|
gimp_scale_control_set_logarithmic (GtkObject *adjustment,
|
|
gboolean logarithmic)
|
|
{
|
|
GtkAdjustment *adj;
|
|
GtkAdjustment *scale_adj;
|
|
gdouble correction;
|
|
gdouble log_value, log_lower, log_upper;
|
|
gdouble log_step_increment, log_page_increment;
|
|
GimpScaleControl *scale_control;
|
|
|
|
g_return_if_fail (GIMP_IS_SCALE_CONTROL (adjustment));
|
|
|
|
adj = GTK_ADJUSTMENT (adjustment);
|
|
scale_control = GIMP_SCALE_CONTROL (adjustment);
|
|
|
|
scale_adj = GTK_ADJUSTMENT (scale_control->scale_adj);
|
|
|
|
if (logarithmic)
|
|
{
|
|
if (gimp_scale_control_get_logarithmic (adjustment))
|
|
return;
|
|
|
|
correction = scale_adj->lower > 0 ? 0 : 0.1 + - scale_adj->lower;
|
|
|
|
log_value = log (scale_adj->value + correction);
|
|
log_lower = log (scale_adj->lower + correction);
|
|
log_upper = log (scale_adj->upper + correction);
|
|
log_step_increment = (log_upper - log_lower) / ((scale_adj->upper -
|
|
scale_adj->lower) /
|
|
scale_adj->step_increment);
|
|
log_page_increment = (log_upper - log_lower) / ((scale_adj->upper -
|
|
scale_adj->lower) /
|
|
scale_adj->page_increment);
|
|
|
|
if (scale_adj == adj)
|
|
{
|
|
GtkObject *new_adj;
|
|
gdouble lower;
|
|
gdouble upper;
|
|
|
|
lower = scale_adj->lower;
|
|
upper = scale_adj->upper;
|
|
new_adj = gtk_adjustment_new (scale_adj->value,
|
|
scale_adj->lower,
|
|
scale_adj->upper,
|
|
scale_adj->step_increment,
|
|
scale_adj->page_increment,
|
|
0.0);
|
|
|
|
if (scale_control->scale)
|
|
gtk_range_set_adjustment (GTK_RANGE (scale_control->scale),
|
|
GTK_ADJUSTMENT (new_adj));
|
|
|
|
scale_adj = (GtkAdjustment *) new_adj;
|
|
scale_control->scale_adj = GTK_OBJECT (scale_adj);
|
|
}
|
|
else
|
|
{
|
|
g_signal_handlers_disconnect_by_func
|
|
(adj,
|
|
G_CALLBACK (unconstrained_adjustment_callback),
|
|
scale_adj);
|
|
g_signal_handlers_disconnect_by_func
|
|
(scale_adj,
|
|
G_CALLBACK (unconstrained_adjustment_callback),
|
|
adj);
|
|
}
|
|
|
|
scale_adj->value = log_value;
|
|
scale_adj->lower = log_lower;
|
|
scale_adj->upper = log_upper;
|
|
scale_adj->step_increment = log_step_increment;
|
|
scale_adj->page_increment = log_page_increment;
|
|
|
|
g_signal_connect (scale_adj, "value-changed",
|
|
G_CALLBACK (exp_adjustment_callback),
|
|
adj);
|
|
|
|
g_signal_connect (adj, "value-changed",
|
|
G_CALLBACK (log_adjustment_callback),
|
|
scale_adj);
|
|
|
|
scale_control->logarithmic = TRUE;
|
|
}
|
|
else
|
|
{
|
|
gdouble lower, upper;
|
|
|
|
if (! gimp_scale_control_get_logarithmic (adjustment))
|
|
return;
|
|
|
|
g_signal_handlers_disconnect_by_func (adj,
|
|
G_CALLBACK (log_adjustment_callback),
|
|
scale_adj);
|
|
g_signal_handlers_disconnect_by_func (scale_adj,
|
|
G_CALLBACK (exp_adjustment_callback),
|
|
adj);
|
|
|
|
lower = exp (scale_adj->lower);
|
|
upper = exp (scale_adj->upper);
|
|
|
|
if (adj->lower <= 0.0)
|
|
{
|
|
lower += - 0.1 + adj->lower;
|
|
upper += - 0.1 + adj->lower;
|
|
}
|
|
|
|
scale_adj->value = adj->value;
|
|
scale_adj->lower = lower;
|
|
scale_adj->upper = upper;
|
|
scale_adj->step_increment = adj->step_increment;
|
|
scale_adj->page_increment = adj->page_increment;
|
|
|
|
g_signal_connect (scale_adj, "value-changed",
|
|
G_CALLBACK (unconstrained_adjustment_callback),
|
|
adj);
|
|
|
|
g_signal_connect (adj, "value-changed",
|
|
G_CALLBACK (unconstrained_adjustment_callback),
|
|
scale_adj);
|
|
|
|
scale_control->logarithmic = FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gimp_scale_control_get_logarithmic:
|
|
* @adjustment: a #GtkAdjustment as returned by gimp_scale_control_new()
|
|
*
|
|
* Return value: %TRUE if the the control's scale widget will behave in
|
|
* logharithmic fashion, %FALSE for linear behaviour.
|
|
*
|
|
* Since: GIMP 2.2
|
|
**/
|
|
gboolean
|
|
gimp_scale_control_get_logarithmic (GtkObject *adjustment)
|
|
{
|
|
g_return_val_if_fail (GIMP_IS_SCALE_CONTROL (adjustment), FALSE);
|
|
|
|
return GIMP_SCALE_CONTROL (adjustment)->logarithmic;
|
|
}
|
|
|
|
/**
|
|
* gimp_scale_control_set_sensitive:
|
|
* @adjustment: a #GtkAdjustment returned by gimp_scale_control_new()
|
|
* @sensitive: a boolean value with the same semantics as the @sensitive
|
|
* parameter of gtk_widget_set_sensitive()
|
|
*
|
|
* Sets the sensitivity of the scale_control's #GtkLabel, #GtkHScale and
|
|
* #GtkSpinbutton.
|
|
**/
|
|
void
|
|
gimp_scale_control_set_sensitive (GtkObject *adjustment,
|
|
gboolean sensitive)
|
|
{
|
|
GimpScaleControl *scale_control;
|
|
|
|
g_return_if_fail (GIMP_IS_SCALE_CONTROL (adjustment));
|
|
|
|
scale_control = GIMP_SCALE_CONTROL (adjustment);
|
|
|
|
if (scale_control->label)
|
|
gtk_widget_set_sensitive (scale_control->label, sensitive);
|
|
|
|
if (scale_control->spinbutton)
|
|
gtk_widget_set_sensitive (scale_control->spinbutton, sensitive);
|
|
|
|
if (scale_control->scale)
|
|
gtk_widget_set_sensitive (scale_control->scale, sensitive);
|
|
|
|
if (scale_control->entry)
|
|
gtk_widget_set_sensitive (scale_control->entry, sensitive);
|
|
|
|
if (scale_control->popup_button)
|
|
gtk_widget_set_sensitive (scale_control->popup_button, sensitive);
|
|
}
|
|
|
|
/**
|
|
* gimp_scale_control_set_update_policy:
|
|
* @adjustment: a #GimpScaleControl
|
|
* @policy: a policy for updating the adjustment.
|
|
*
|
|
* Determines how rapidly the widget responds to changes
|
|
* in value.
|
|
*
|
|
* Since: GIMP 2.6
|
|
**/
|
|
void
|
|
gimp_scale_control_set_update_policy (GtkObject *adjustment,
|
|
GtkUpdateType policy)
|
|
{
|
|
g_return_if_fail (GIMP_IS_SCALE_CONTROL (adjustment));
|
|
|
|
GIMP_SCALE_CONTROL (adjustment)->policy = policy;
|
|
}
|
|
|
|
/*
|
|
* creates the popup. It can later be shown by calling
|
|
* gimp_scale_control_show_popup.
|
|
*/
|
|
static GtkWidget *
|
|
gimp_scale_control_popup (GimpScaleControl *scale_control)
|
|
{
|
|
GtkWidget *popup_window;
|
|
GtkWidget *table;
|
|
GtkWidget *frame;
|
|
GtkWidget *label;
|
|
gchar *value_str;
|
|
GdkColor bg = {0, 50000, 40000, 50000};
|
|
GtkAdjustment *adjustment = GTK_ADJUSTMENT (scale_control->scale_adj);
|
|
|
|
gimp_scale_control_create_widgets (scale_control);
|
|
|
|
popup_window = gtk_window_new (GTK_WINDOW_POPUP);
|
|
gtk_widget_set_name (popup_window, "gimp-scale-control-popup-window");
|
|
gtk_window_set_type_hint (GTK_WINDOW (popup_window),
|
|
GDK_WINDOW_TYPE_HINT_COMBO);
|
|
gtk_widget_set_size_request (popup_window, 220, 80);
|
|
gtk_window_set_resizable (GTK_WINDOW (popup_window), FALSE);
|
|
gtk_window_set_gravity (GTK_WINDOW (popup_window), GDK_GRAVITY_WEST);
|
|
gtk_widget_add_events (popup_window, GDK_LEAVE_NOTIFY_MASK);
|
|
gtk_widget_modify_bg (popup_window, GTK_STATE_NORMAL, &bg);
|
|
g_signal_connect (popup_window, "leave-notify-event",
|
|
G_CALLBACK (gimp_scale_control_remove_popup),
|
|
scale_control);
|
|
|
|
frame = gtk_frame_new (scale_control->text);
|
|
gtk_container_add (GTK_CONTAINER (popup_window), frame);
|
|
gtk_widget_show (frame);
|
|
|
|
table = gtk_table_new (4, 9, TRUE);
|
|
gtk_container_add (GTK_CONTAINER (frame), table);
|
|
gtk_widget_show (table);
|
|
|
|
gtk_table_attach (GTK_TABLE (table), scale_control->scale,
|
|
1, 7, 0, 1,
|
|
GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
|
|
gtk_widget_show (scale_control->scale);
|
|
|
|
gtk_table_attach (GTK_TABLE (table), scale_control->spinbutton,
|
|
3, 5, 1, 3,
|
|
GTK_SHRINK, GTK_SHRINK, 0, 0);
|
|
gtk_widget_show (scale_control->spinbutton);
|
|
|
|
value_str = g_strdup_printf ("%lg", adjustment->lower);
|
|
label = gtk_label_new (value_str);
|
|
g_free (value_str);
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0);
|
|
gtk_table_attach (GTK_TABLE (table), label,
|
|
0, 2, 1, 2,
|
|
GTK_SHRINK, GTK_SHRINK, 0, 0);
|
|
gtk_widget_show (label);
|
|
|
|
value_str = g_strdup_printf ("%lg", adjustment->upper);
|
|
label = gtk_label_new (value_str);
|
|
g_free (value_str);
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0);
|
|
gtk_table_attach (GTK_TABLE (table), label,
|
|
6, 8, 1, 2,
|
|
GTK_SHRINK, GTK_SHRINK, 0, 0);
|
|
gtk_widget_show (label);
|
|
|
|
return popup_window;
|
|
}
|
|
|
|
/*
|
|
* position the popup window next to the calling widget,
|
|
* and show it
|
|
*/
|
|
static void
|
|
gimp_scale_control_show_popup (GtkWidget *widget,
|
|
GimpScaleControl *scale_control)
|
|
{
|
|
GtkWidget *popup_window = scale_control->popup_window;
|
|
GtkWidget *toplevel;
|
|
gint x0;
|
|
gint y0;
|
|
gint x1;
|
|
gint y1;
|
|
|
|
|
|
toplevel = gtk_widget_get_toplevel (widget);
|
|
|
|
if (! GTK_IS_WINDOW (toplevel))
|
|
return;
|
|
|
|
gtk_window_get_position (GTK_WINDOW (toplevel), &x0, &y0);
|
|
gtk_widget_translate_coordinates (widget, toplevel, 0, 0, &x1, &y1);
|
|
|
|
gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
|
|
GTK_WINDOW (popup_window));
|
|
gtk_window_set_transient_for (GTK_WINDOW (popup_window),
|
|
GTK_WINDOW (toplevel));
|
|
|
|
gtk_window_set_screen (GTK_WINDOW (popup_window),
|
|
gtk_widget_get_screen (widget));
|
|
|
|
gtk_window_move (GTK_WINDOW (popup_window), x1 + x0 - 100, y1 + y0);
|
|
|
|
gtk_widget_show (popup_window);
|
|
}
|
|
|
|
static void
|
|
gimp_scale_control_remove_popup (GtkWidget *widget,
|
|
GdkEventCrossing *event,
|
|
GimpScaleControl *scale_control)
|
|
{
|
|
if (event->detail != GDK_NOTIFY_INFERIOR)
|
|
gtk_widget_hide (scale_control->popup_window);
|
|
}
|
|
|
|
static void
|
|
gimp_scale_control_value_changed (GimpScaleControl *scale_control)
|
|
{
|
|
gdouble value;
|
|
|
|
value = GTK_ADJUSTMENT (scale_control)->value;
|
|
|
|
gimp_scale_control_set_value (scale_control, value);
|
|
}
|
|
|
|
/*
|
|
* sets the value in the entry
|
|
*/
|
|
static void
|
|
gimp_scale_control_set_value (GimpScaleControl *scale_control,
|
|
gdouble value)
|
|
{
|
|
/* gchar *markup; */
|
|
gchar *text;
|
|
|
|
/* markup = g_strdup_printf ("<u>%.*lf</u>", scale_control->digits, value); */
|
|
|
|
if (scale_control->digits == 0)
|
|
text = g_strdup_printf ("%d", (gint) value);
|
|
else
|
|
text = g_strdup_printf ("%.*lf", scale_control->digits, value);
|
|
|
|
|
|
if (scale_control->entry)
|
|
gtk_entry_set_text (GTK_ENTRY (scale_control->entry), text);
|
|
/* gtk_label_set_markup (GTK_LABEL (scale_control->button_label), markup); */
|
|
|
|
g_free (text);
|
|
/* g_free (markup); */
|
|
}
|
|
|
|
/*
|
|
* return the visible widget in the interface
|
|
*/
|
|
GtkWidget *
|
|
gimp_scale_control_get_widget (GtkObject *adjustment)
|
|
{
|
|
g_return_val_if_fail (GIMP_IS_SCALE_CONTROL (adjustment), NULL);
|
|
|
|
/* the hbox */
|
|
return GIMP_SCALE_CONTROL (adjustment)->entry->parent;
|
|
}
|