* Lesser 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.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
#include <stdio.h>
#include <math.h>
-#include "gtkmainprivate.h"
+#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkorientableprivate.h"
#include "gtkrange.h"
#include "gtkscale.h"
+#include "gtkcolorscaleprivate.h"
#include "gtkscrollbar.h"
#include "gtkwindow.h"
#include "gtkprivate.h"
#include "gtkintl.h"
+#include "gtkmain.h"
#include "gtktypebuiltins.h"
#include "a11y/gtkrangeaccessible.h"
guint lower_sensitive : 1;
guint upper_sensitive : 1;
+ /* The range has an origin, should be drawn differently. Used by GtkScale */
+ guint has_origin : 1;
+
/* Fill level */
guint show_fill_level : 1;
guint restrict_to_fill_level : 1;
* @range: the #GtkRange that received the signal
* @scroll: the type of scroll action that was performed
* @value: the new value resulting from the scroll action
- * @returns: %TRUE to prevent other handlers from being invoked for the
- * signal, %FALSE to propagate the signal further
*
* The #GtkRange::change-value signal is emitted when a scroll action is
* performed on a range. It allows an application to determine the
* It is not possible to use delayed update policies in an overridden
* #GtkRange::change-value handler.
*
+ * Returns: %TRUE to prevent other handlers from being invoked for
+ * the signal, %FALSE to propagate the signal further
+ *
* Since: 2.6
*/
signals[CHANGE_VALUE] =
priv->upper_sensitivity = GTK_SENSITIVITY_AUTO;
priv->lower_sensitive = TRUE;
priv->upper_sensitive = TRUE;
+ priv->has_origin = FALSE;
priv->show_fill_level = FALSE;
priv->restrict_to_fill_level = TRUE;
priv->fill_level = G_MAXDOUBLE;
translated_rect = *allocation;
else
{
- gtk_widget_translate_coordinates (gtk_widget_get_parent (widget),
+ gtk_widget_translate_coordinates (parent,
window,
allocation->x, allocation->y,
&x, &y);
}
/* If the stepper button intersects the window resize grip.. */
- if (gdk_rectangle_intersect (&grip_rect, &translated_rect, NULL))
+ if (gdk_rectangle_intersect (&grip_rect, &translated_rect, &grip_rect))
{
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
cairo_t *cr,
GtkArrowType arrow_type,
gboolean clicked,
- gboolean prelighted)
+ gboolean prelighted,
+ GtkStateFlags state)
{
GtkRangePrivate *priv = range->priv;
GtkAllocation allocation;
- GtkStateFlags state = 0;
GtkStyleContext *context;
GtkWidget *widget = GTK_WIDGET (range);
gfloat arrow_scaling;
arrow_sensitive = priv->lower_sensitive;
}
- if (!gtk_widget_is_sensitive (GTK_WIDGET (range)) || !arrow_sensitive)
- state = GTK_STATE_FLAG_INSENSITIVE;
+ state &= ~(GTK_STATE_FLAG_ACTIVE | GTK_STATE_FLAG_PRELIGHT);
+
+ if ((state & GTK_STATE_FLAG_INSENSITIVE) || !arrow_sensitive)
+ {
+ state |= GTK_STATE_FLAG_INSENSITIVE;
+ }
else
{
if (clicked)
gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON);
gtk_style_context_set_state (context, state);
+ switch (arrow_type)
+ {
+ case GTK_ARROW_RIGHT:
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
+ break;
+ case GTK_ARROW_DOWN:
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_BOTTOM);
+ break;
+ case GTK_ARROW_LEFT:
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
+ break;
+ case GTK_ARROW_UP:
+ default:
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP);
+ break;
+ }
+
gtk_render_background (context, cr,
rect->x, rect->y,
rect->width, rect->height);
{
GtkRange *range = GTK_RANGE (widget);
GtkRangePrivate *priv = range->priv;
- gboolean sensitive;
- GtkStateFlags state = 0;
+ GtkStateFlags widget_state;
gint focus_line_width = 0;
gint focus_padding = 0;
gboolean touchscreen;
gboolean draw_trough = TRUE;
+ gboolean draw_slider = TRUE;
GtkStyleContext *context;
context = gtk_widget_get_style_context (widget);
if (GTK_IS_SCALE (widget) &&
gtk_adjustment_get_upper (priv->adjustment) == gtk_adjustment_get_lower (priv->adjustment))
- draw_trough = FALSE;
+ {
+ draw_trough = TRUE;
+ draw_slider = FALSE;
+ }
+ if (GTK_IS_COLOR_SCALE (widget))
+ {
+ draw_trough = FALSE;
+ draw_slider = TRUE;
+ }
if (gtk_widget_get_can_focus (GTK_WIDGET (range)))
gtk_widget_style_get (GTK_WIDGET (range),
gtk_range_calc_marks (range);
gtk_range_calc_layout (range, gtk_adjustment_get_value (priv->adjustment));
- sensitive = gtk_widget_is_sensitive (widget);
+ widget_state = gtk_widget_get_state_flags (widget);
/* Just to be confusing, we draw the trough for the whole
* range rectangle, not the trough rectangle (the trough
"stepper-spacing", &stepper_spacing,
NULL);
- gtk_style_context_save (context);
-
- if (!sensitive)
- gtk_style_context_set_state (context, GTK_STATE_FLAG_INSENSITIVE);
-
if (!trough_under_steppers)
{
gint offset = 0;
if (draw_trough)
{
- gint trough_change_pos_x = width;
- gint trough_change_pos_y = height;
-
- if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
- trough_change_pos_x = (priv->slider.x +
- priv->slider.width / 2 -
- x);
- else
- trough_change_pos_y = (priv->slider.y +
- priv->slider.height / 2 -
- y);
-
- /* FIXME: was trough-upper and trough-lower really used,
- * in that case, it should still be exposed somehow.
- */
- gtk_render_background (context, cr, x, y,
- trough_change_pos_x,
- trough_change_pos_y);
+ if (!priv->has_origin)
+ {
+ gtk_render_background (context, cr,
+ x, y, width, height);
- if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
- trough_change_pos_y = 0;
+ gtk_render_frame (context, cr,
+ x, y, width, height);
+ }
else
- trough_change_pos_x = 0;
-
- gtk_render_background (context, cr,
- x + trough_change_pos_x, y + trough_change_pos_y,
- width - trough_change_pos_x,
- height - trough_change_pos_y);
-
- gtk_render_frame (context, cr,
- x, y, width, height);
- }
- else
- {
- gtk_render_background (context, cr,
- x, y, width, height);
- gtk_render_frame (context, cr,
- x, y, width, height);
+ {
+ gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
+
+ gint trough_change_pos_x = width;
+ gint trough_change_pos_y = height;
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ trough_change_pos_x = (priv->slider.x +
+ priv->slider.width / 2 -
+ x);
+ else
+ trough_change_pos_y = (priv->slider.y +
+ priv->slider.height / 2 -
+ y);
+
+ gtk_style_context_save (context);
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
+
+ if (!is_rtl)
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_HIGHLIGHT);
+ }
+ else
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP);
+
+ gtk_render_background (context, cr, x, y,
+ trough_change_pos_x,
+ trough_change_pos_y);
+
+ gtk_render_frame (context, cr, x, y,
+ trough_change_pos_x,
+ trough_change_pos_y);
+
+ gtk_style_context_restore (context);
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ trough_change_pos_y = 0;
+ else
+ trough_change_pos_x = 0;
+
+ gtk_style_context_save (context);
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
+
+ if (is_rtl)
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_HIGHLIGHT);
+ }
+ else
+ {
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_BOTTOM);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_HIGHLIGHT);
+ }
+
+ gtk_render_background (context, cr,
+ x + trough_change_pos_x, y + trough_change_pos_y,
+ width - trough_change_pos_x,
+ height - trough_change_pos_y);
+
+ gtk_render_frame (context, cr,
+ x + trough_change_pos_x, y + trough_change_pos_y,
+ width - trough_change_pos_x,
+ height - trough_change_pos_y);
+
+ gtk_style_context_restore (context);
+ }
}
gtk_style_context_restore (context);
gtk_style_context_restore (context);
}
- gtk_style_context_restore (context);
-
- if (sensitive && gtk_widget_has_focus (widget))
+ if (!(widget_state & GTK_STATE_FLAG_INSENSITIVE) && gtk_widget_has_visible_focus (widget))
{
- gtk_style_context_save (context);
- gtk_style_context_set_state (context,
- gtk_widget_get_state_flags (widget));
-
gtk_render_focus (context, cr,
priv->range_rect.x,
priv->range_rect.y,
priv->range_rect.width,
priv->range_rect.height);
-
- gtk_style_context_restore (context);
}
}
cairo_restore (cr);
- if (!sensitive)
- state = GTK_STATE_FLAG_INSENSITIVE;
- else if (!touchscreen && priv->mouse_location == MOUSE_SLIDER)
- state = GTK_STATE_FLAG_PRELIGHT;
+ if (draw_slider)
+ {
+ GtkStateFlags state = widget_state;
- if (priv->grab_location == MOUSE_SLIDER)
- state |= GTK_STATE_FLAG_ACTIVE;
+ state &= ~(GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_ACTIVE);
- cairo_save (cr);
- gdk_cairo_rectangle (cr, &priv->slider);
- cairo_clip (cr);
+ if (!touchscreen && priv->mouse_location == MOUSE_SLIDER && !(state & GTK_STATE_FLAG_INSENSITIVE))
+ state |= GTK_STATE_FLAG_PRELIGHT;
+
+ if (priv->grab_location == MOUSE_SLIDER)
+ state |= GTK_STATE_FLAG_ACTIVE;
+
+ cairo_save (cr);
+ gdk_cairo_rectangle (cr, &priv->slider);
+ cairo_clip (cr);
- if (draw_trough)
- {
gtk_style_context_save (context);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER);
gtk_style_context_set_state (context, state);
priv->orientation);
gtk_style_context_restore (context);
- }
- cairo_restore (cr);
+ cairo_restore (cr);
+ }
if (priv->has_stepper_a)
draw_stepper (range, STEPPER_A, cr,
priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_ARROW_UP : GTK_ARROW_LEFT,
priv->grab_location == MOUSE_STEPPER_A,
- !touchscreen && priv->mouse_location == MOUSE_STEPPER_A);
+ !touchscreen && priv->mouse_location == MOUSE_STEPPER_A,
+ widget_state);
if (priv->has_stepper_b)
draw_stepper (range, STEPPER_B, cr,
priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_ARROW_DOWN : GTK_ARROW_RIGHT,
priv->grab_location == MOUSE_STEPPER_B,
- !touchscreen && priv->mouse_location == MOUSE_STEPPER_B);
+ !touchscreen && priv->mouse_location == MOUSE_STEPPER_B,
+ widget_state);
if (priv->has_stepper_c)
draw_stepper (range, STEPPER_C, cr,
priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_ARROW_UP : GTK_ARROW_LEFT,
priv->grab_location == MOUSE_STEPPER_C,
- !touchscreen && priv->mouse_location == MOUSE_STEPPER_C);
+ !touchscreen && priv->mouse_location == MOUSE_STEPPER_C,
+ widget_state);
if (priv->has_stepper_d)
draw_stepper (range, STEPPER_D, cr,
priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_ARROW_DOWN : GTK_ARROW_RIGHT,
priv->grab_location == MOUSE_STEPPER_D,
- !touchscreen && priv->mouse_location == MOUSE_STEPPER_D);
+ !touchscreen && priv->mouse_location == MOUSE_STEPPER_D,
+ widget_state);
return FALSE;
}
if (device == priv->grab_device)
return;
- if (priv->grab_device != NULL)
- {
- g_warning ("GtkRange already had a grab device, releasing device grab");
- gtk_device_grab_remove (GTK_WIDGET (range), priv->grab_device);
- }
-
- /* we don't actually gdk_grab, since a button is down */
- gtk_device_grab_add (GTK_WIDGET (range), device, TRUE);
-
+ /* Don't perform any GDK/GTK+ grab here. Since a button
+ * is down, there's an ongoing implicit grab on
+ * priv->event_window, which pretty much guarantees this
+ * is the only widget receiving the pointer events.
+ */
priv->grab_location = location;
priv->grab_button = button;
priv->grab_device = device;
case MOUSE_STEPPER_C:
switch (priv->grab_button)
{
- case 1:
+ case GDK_BUTTON_PRIMARY:
return invert ? GTK_SCROLL_STEP_FORWARD : GTK_SCROLL_STEP_BACKWARD;
break;
- case 2:
+ case GDK_BUTTON_MIDDLE:
return invert ? GTK_SCROLL_PAGE_FORWARD : GTK_SCROLL_PAGE_BACKWARD;
break;
- case 3:
+ case GDK_BUTTON_SECONDARY:
return invert ? GTK_SCROLL_END : GTK_SCROLL_START;
break;
}
case MOUSE_STEPPER_D:
switch (priv->grab_button)
{
- case 1:
+ case GDK_BUTTON_PRIMARY:
return invert ? GTK_SCROLL_STEP_BACKWARD : GTK_SCROLL_STEP_FORWARD;
break;
- case 2:
+ case GDK_BUTTON_MIDDLE:
return invert ? GTK_SCROLL_PAGE_BACKWARD : GTK_SCROLL_PAGE_FORWARD;
break;
- case 3:
+ case GDK_BUTTON_SECONDARY:
return invert ? GTK_SCROLL_START : GTK_SCROLL_END;
break;
}
if (gtk_range_update_mouse_location (range))
gtk_widget_queue_draw (widget);
+ if (priv->mouse_location == MOUSE_SLIDER &&
+ gdk_event_triggers_context_menu ((GdkEvent *)event))
+ {
+ gboolean handled;
+
+ g_signal_emit_by_name (widget, "popup-menu", &handled);
+
+ return TRUE;
+ }
+
if (priv->mouse_location == MOUSE_TROUGH &&
- event->button == 1)
+ event->button == GDK_BUTTON_PRIMARY)
{
/* button 1 steps by page increment, as with button 2 on a stepper
*/
priv->mouse_location == MOUSE_STEPPER_B ||
priv->mouse_location == MOUSE_STEPPER_C ||
priv->mouse_location == MOUSE_STEPPER_D) &&
- (event->button == 1 || event->button == 2 || event->button == 3))
+ (event->button == GDK_BUTTON_PRIMARY ||
+ event->button == GDK_BUTTON_MIDDLE ||
+ event->button == GDK_BUTTON_SECONDARY))
{
GtkAllocation allocation;
GdkRectangle *stepper_area;
return TRUE;
}
else if ((priv->mouse_location == MOUSE_TROUGH &&
- event->button == 2) ||
+ event->button == GDK_BUTTON_MIDDLE) ||
priv->mouse_location == MOUSE_SLIDER)
{
gboolean need_value_update = FALSE;
* On button 2 press, we warp the slider to mouse position,
* then begin the slider drag.
*/
- if (event->button == 2)
+ if (event->button == GDK_BUTTON_MIDDLE)
{
gdouble slider_low_value, slider_high_value, new_value;
}
}
+void
+_gtk_range_set_has_origin (GtkRange *range,
+ gboolean has_origin)
+{
+ range->priv->has_origin = has_origin;
+}
+
+gboolean
+_gtk_range_get_has_origin (GtkRange *range)
+{
+ return range->priv->has_origin;
+}
+
void
_gtk_range_set_stop_values (GtkRange *range,
gdouble *values,