summaryrefslogtreecommitdiffstats
path: root/libgimpwidgets/gimpscaleentry.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgimpwidgets/gimpscaleentry.c')
-rw-r--r--libgimpwidgets/gimpscaleentry.c479
1 files changed, 479 insertions, 0 deletions
diff --git a/libgimpwidgets/gimpscaleentry.c b/libgimpwidgets/gimpscaleentry.c
new file mode 100644
index 0000000..8112434
--- /dev/null
+++ b/libgimpwidgets/gimpscaleentry.c
@@ -0,0 +1,479 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpscaleentry.c
+ * Copyright (C) 2000 Michael Natterer <mitch@gimp.org>
+ *
+ * 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 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 Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpmath/gimpmath.h"
+#include "libgimpbase/gimpbase.h"
+
+#include "gimpspinbutton.h"
+#include "gimpwidgets.h"
+
+
+static gboolean gimp_scale_entry_linear_to_log (GBinding *binding,
+ const GValue *from_value,
+ GValue *to_value,
+ gpointer user_data);
+static gboolean gimp_scale_entry_log_to_linear (GBinding *binding,
+ const GValue *from_value,
+ GValue *to_value,
+ gpointer user_data);
+
+static GtkAdjustment * gimp_scale_entry_new_internal (gboolean color_scale,
+ 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);
+
+
+static gboolean
+gimp_scale_entry_linear_to_log (GBinding *binding,
+ const GValue *from_value,
+ GValue *to_value,
+ gpointer user_data)
+{
+ GtkAdjustment *spin_adjustment;
+ gdouble value = g_value_get_double (from_value);
+
+ spin_adjustment = GTK_ADJUSTMENT (g_binding_get_source (binding));
+
+ if (gtk_adjustment_get_lower (spin_adjustment) <= 0.0)
+ value = log (value - gtk_adjustment_get_lower (spin_adjustment) + 0.1);
+ else
+ value = log (value);
+
+ g_value_set_double (to_value, value);
+
+ return TRUE;
+}
+
+static gboolean
+gimp_scale_entry_log_to_linear (GBinding *binding,
+ const GValue *from_value,
+ GValue *to_value,
+ gpointer user_data)
+{
+ GtkAdjustment *spin_adjustment;
+ gdouble value = g_value_get_double (from_value);
+
+ spin_adjustment = GTK_ADJUSTMENT (g_binding_get_source (binding));
+
+ value = exp (value);
+
+ if (gtk_adjustment_get_lower (spin_adjustment) <= 0.0)
+ value += gtk_adjustment_get_lower (spin_adjustment) - 0.1;
+
+ g_value_set_double (to_value, value);
+
+ return TRUE;
+}
+
+static GtkAdjustment *
+gimp_scale_entry_new_internal (gboolean color_scale,
+ 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)
+{
+ GtkWidget *label;
+ GtkWidget *scale;
+ GtkWidget *spinbutton;
+ GtkAdjustment *scale_adjustment;
+ GtkAdjustment *spin_adjustment;
+ GBinding *binding;
+
+ label = gtk_label_new_with_mnemonic (text);
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gtk_widget_show (label);
+
+ scale_adjustment = (GtkAdjustment *)
+ gtk_adjustment_new (value, lower, upper,
+ step_increment, page_increment, 0.0);
+
+ if (! constrain &&
+ unconstrained_lower <= lower &&
+ unconstrained_upper >= upper)
+ {
+ spin_adjustment = (GtkAdjustment *)
+ gtk_adjustment_new (value,
+ unconstrained_lower,
+ unconstrained_upper,
+ step_increment, page_increment, 0.0);
+ }
+ else
+ {
+ spin_adjustment = (GtkAdjustment *)
+ gtk_adjustment_new (value, lower, upper,
+ step_increment, page_increment, 0.0);
+ }
+
+ binding = g_object_bind_property (G_OBJECT (spin_adjustment), "value",
+ G_OBJECT (scale_adjustment), "value",
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE);
+
+ spinbutton = gimp_spin_button_new (spin_adjustment, step_increment, digits);
+ gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
+ gtk_widget_show (spinbutton);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
+
+ 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);
+ }
+
+ if (color_scale)
+ {
+ scale = gimp_color_scale_new (GTK_ORIENTATION_HORIZONTAL,
+ GIMP_COLOR_SELECTOR_VALUE);
+
+ gtk_range_set_adjustment (GTK_RANGE (scale), scale_adjustment);
+ }
+ else
+ {
+ scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, scale_adjustment);
+ }
+
+ if (scale_width > 0)
+ gtk_widget_set_size_request (scale, scale_width, -1);
+ gtk_scale_set_digits (GTK_SCALE (scale), digits);
+ gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
+ gtk_widget_show (scale);
+
+ gtk_table_attach (GTK_TABLE (table), label,
+ column, column + 1, row, row + 1,
+ GTK_FILL, GTK_FILL, 0, 0);
+
+ gtk_table_attach (GTK_TABLE (table), scale,
+ column + 1, column + 2, row, row + 1,
+ GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
+
+ gtk_table_attach (GTK_TABLE (table), spinbutton,
+ column + 2, column + 3, row, row + 1,
+ GTK_FILL | GTK_SHRINK, GTK_SHRINK, 0, 0);
+
+ if (tooltip || help_id)
+ {
+ gimp_help_set_help_data (label, tooltip, help_id);
+ gimp_help_set_help_data (scale, tooltip, help_id);
+ gimp_help_set_help_data (spinbutton, tooltip, help_id);
+ }
+
+ g_object_set_data (G_OBJECT (spin_adjustment), "label", label);
+ g_object_set_data (G_OBJECT (spin_adjustment), "scale", scale);
+ g_object_set_data (G_OBJECT (spin_adjustment), "spinbutton", spinbutton);
+ g_object_set_data (G_OBJECT (spin_adjustment), "binding", binding);
+
+ return spin_adjustment;
+}
+
+/**
+ * gimp_scale_entry_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_entry_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)
+{
+ return (GtkObject *)
+ gimp_scale_entry_new_internal (FALSE,
+ table, column, row,
+ text, scale_width, spinbutton_width,
+ value, lower, upper,
+ step_increment, page_increment,
+ digits,
+ constrain,
+ unconstrained_lower,
+ unconstrained_upper,
+ tooltip, help_id);
+}
+
+/**
+ * gimp_color_scale_entry_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_entry_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)
+{
+ return (GtkObject *)
+ gimp_scale_entry_new_internal (TRUE,
+ table, column, row,
+ text, scale_width, spinbutton_width,
+ value, lower, upper,
+ step_increment, page_increment,
+ digits,
+ TRUE, 0.0, 0.0,
+ tooltip, help_id);
+}
+
+/**
+ * gimp_scale_entry_set_logarithmic:
+ * @adjustment: a #GtkAdjustment as returned by gimp_scale_entry_new()
+ * @logarithmic: a boolean value to set or reset logarithmic behaviour
+ * of the scale widget
+ *
+ * Sets whether the scale_entry's scale widget will behave in a linear
+ * or logharithmic fashion. Useful when an entry has to attend large
+ * ranges, but smaller selections on that range require a finer
+ * adjustment.
+ *
+ * Since: 2.2
+ **/
+void
+gimp_scale_entry_set_logarithmic (GtkObject *adjustment,
+ gboolean logarithmic)
+{
+ GtkAdjustment *spin_adj;
+ GtkAdjustment *scale_adj;
+ GBinding *binding;
+
+ g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+
+ spin_adj = GTK_ADJUSTMENT (adjustment);
+ scale_adj = GIMP_SCALE_ENTRY_SCALE_ADJ (adjustment);
+ binding = g_object_get_data (G_OBJECT (adjustment), "binding");
+
+ g_return_if_fail (GTK_IS_ADJUSTMENT (scale_adj));
+ g_return_if_fail (G_IS_BINDING (binding));
+
+ logarithmic = logarithmic ? TRUE : FALSE;
+
+ if (logarithmic == gimp_scale_entry_get_logarithmic (adjustment))
+ return;
+
+ g_object_unref (binding);
+
+ if (logarithmic)
+ {
+ gdouble correction;
+ gdouble log_value, log_lower, log_upper;
+ gdouble log_step_increment, log_page_increment;
+
+ correction = (gtk_adjustment_get_lower (scale_adj) > 0 ?
+ 0 : 0.1 + - gtk_adjustment_get_lower (scale_adj));
+
+ log_value = log (gtk_adjustment_get_value (scale_adj) + correction);
+ log_lower = log (gtk_adjustment_get_lower (scale_adj) + correction);
+ log_upper = log (gtk_adjustment_get_upper (scale_adj) + correction);
+ log_step_increment =
+ (log_upper - log_lower) / ((gtk_adjustment_get_upper (scale_adj) -
+ gtk_adjustment_get_lower (scale_adj)) /
+ gtk_adjustment_get_step_increment (scale_adj));
+ log_page_increment =
+ (log_upper - log_lower) / ((gtk_adjustment_get_upper (scale_adj) -
+ gtk_adjustment_get_lower (scale_adj)) /
+ gtk_adjustment_get_page_increment (scale_adj));
+
+ gtk_adjustment_configure (scale_adj,
+ log_value, log_lower, log_upper,
+ log_step_increment, log_page_increment, 0.0);
+
+ binding = g_object_bind_property_full (G_OBJECT (spin_adj), "value",
+ G_OBJECT (scale_adj), "value",
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE,
+ gimp_scale_entry_linear_to_log,
+ gimp_scale_entry_log_to_linear,
+ NULL, NULL);
+ }
+ else
+ {
+ gdouble lower, upper;
+
+ lower = exp (gtk_adjustment_get_lower (scale_adj));
+ upper = exp (gtk_adjustment_get_upper (scale_adj));
+
+ if (gtk_adjustment_get_lower (spin_adj) <= 0.0)
+ {
+ lower += - 0.1 + gtk_adjustment_get_lower (spin_adj);
+ upper += - 0.1 + gtk_adjustment_get_lower (spin_adj);
+ }
+
+ gtk_adjustment_configure (scale_adj,
+ gtk_adjustment_get_value (spin_adj),
+ lower, upper,
+ gtk_adjustment_get_step_increment (spin_adj),
+ gtk_adjustment_get_page_increment (spin_adj),
+ 0.0);
+
+ binding = g_object_bind_property (G_OBJECT (spin_adj), "value",
+ G_OBJECT (scale_adj), "value",
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE);
+ }
+
+ g_object_set_data (G_OBJECT (spin_adj), "binding", binding);
+
+ g_object_set_data (G_OBJECT (adjustment), "logarithmic",
+ GINT_TO_POINTER (logarithmic));
+}
+
+/**
+ * gimp_scale_entry_get_logarithmic:
+ * @adjustment: a #GtkAdjustment as returned by gimp_scale_entry_new()
+ *
+ * Return value: %TRUE if the the entry's scale widget will behave in
+ * logharithmic fashion, %FALSE for linear behaviour.
+ *
+ * Since: 2.2
+ **/
+gboolean
+gimp_scale_entry_get_logarithmic (GtkObject *adjustment)
+{
+ return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (adjustment),
+ "logarithmic"));
+}
+
+/**
+ * gimp_scale_entry_set_sensitive:
+ * @adjustment: a #GtkAdjustment returned by gimp_scale_entry_new()
+ * @sensitive: a boolean value with the same semantics as the @sensitive
+ * parameter of gtk_widget_set_sensitive()
+ *
+ * Sets the sensitivity of the scale_entry's #GtkLabel, #GtkHScale and
+ * #GtkSpinButton.
+ **/
+void
+gimp_scale_entry_set_sensitive (GtkObject *adjustment,
+ gboolean sensitive)
+{
+ GtkWidget *widget;
+
+ g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+
+ widget = GIMP_SCALE_ENTRY_LABEL (adjustment);
+ if (widget)
+ gtk_widget_set_sensitive (widget, sensitive);
+
+ widget = GIMP_SCALE_ENTRY_SCALE (adjustment);
+ if (widget)
+ gtk_widget_set_sensitive (widget, sensitive);
+
+ widget = GIMP_SCALE_ENTRY_SPINBUTTON (adjustment);
+ if (widget)
+ gtk_widget_set_sensitive (widget, sensitive);
+}