gtkvolumebutton.c 8.11 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 * Copyright (C) 2007 Red Hat, Inc.
 *
 * Authors:
 * - Bastien Nocera <bnocera@redhat.com>
 *
 * 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
 * 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.
 */

/*
 * Modified by the GTK+ Team and others 2007.  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
27
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 29
 */

30
#include "config.h"
31 32 33

#include "gtkvolumebutton.h"
#include "gtkstock.h"
34
#include "gtktooltip.h"
35
#include "gtkintl.h"
36

37

38 39 40 41 42 43 44 45 46 47
/**
 * SECTION:gtkvolumebutton
 * @Short_description: A button which pops up a volume control
 * @Title: GtkVolumeButton
 *
 * #GtkVolumeButton is a subclass of #GtkScaleButton that has
 * been tailored for use as a volume control widget with suitable
 * icons, tooltips and accessible labels.
 */

48
#define EPSILON (1e-10)
49

50
static const gchar * const icons[] =
51 52 53 54 55 56 57
{
  "audio-volume-muted",
  "audio-volume-high",
  "audio-volume-low",
  "audio-volume-medium",
  NULL
};
58 59

static const gchar * const icons_symbolic[] =
60 61 62 63 64 65 66 67 68 69 70 71 72
{
  "audio-volume-muted-symbolic",
  "audio-volume-high-symbolic",
  "audio-volume-low-symbolic",
  "audio-volume-medium-symbolic",
  NULL
};

enum
{
  PROP_0,
  PROP_SYMBOLIC
};
73

74 75 76 77 78 79 80 81 82
static gboolean	cb_query_tooltip (GtkWidget       *button,
                                  gint             x,
                                  gint             y,
                                  gboolean         keyboard_mode,
                                  GtkTooltip      *tooltip,
                                  gpointer         user_data);
static void	cb_value_changed (GtkVolumeButton *button,
                                  gdouble          value,
                                  gpointer         user_data);
83 84 85

G_DEFINE_TYPE (GtkVolumeButton, gtk_volume_button, GTK_TYPE_SCALE_BUTTON)

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
static void
gtk_volume_button_set_property (GObject       *object,
				guint          prop_id,
				const GValue  *value,
				GParamSpec    *pspec)
{
  GtkScaleButton *button = GTK_SCALE_BUTTON (object);

  switch (prop_id)
    {
    case PROP_SYMBOLIC:
      if (g_value_get_boolean (value))
        gtk_scale_button_set_icons (button, (const char **) icons_symbolic);
      else
	gtk_scale_button_set_icons (button, (const char **) icons);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gtk_volume_button_get_property (GObject     *object,
			        guint        prop_id,
			        GValue      *value,
			        GParamSpec  *pspec)
{
  switch (prop_id)
    {
    case PROP_SYMBOLIC: {
      char **icon_list;

      g_object_get (object, "icons", &icon_list, NULL);
      if (icon_list != NULL &&
	  icon_list[0] != NULL &&
      	  g_str_equal (icon_list[0], icons_symbolic[0]))
        g_value_set_boolean (value, TRUE);
      else
        g_value_set_boolean (value, FALSE);
      g_strfreev (icon_list);
      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

135 136 137
static void
gtk_volume_button_class_init (GtkVolumeButtonClass *klass)
{
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->set_property = gtk_volume_button_set_property;
  gobject_class->get_property = gtk_volume_button_get_property;

  /**
   * GtkVolumeButton:use-symbolic:
   *
   * Whether to use symbolic icons as the icons. Note that
   * if the symbolic icons are not available in your installed
   * theme, then the normal (potentially colorful) icons will
   * be used.
   *
   * Since: 3.0
   */
  g_object_class_install_property (gobject_class,
                                   PROP_SYMBOLIC,
                                   g_param_spec_boolean ("use-symbolic",
                                                         P_("Use symbolic icons"),
                                                         P_("Whether to use symbolic icons"),
                                                         FALSE,
                                                         G_PARAM_READWRITE));
160 161 162 163 164 165
}

static void
gtk_volume_button_init (GtkVolumeButton *button)
{
  GtkScaleButton *sbutton = GTK_SCALE_BUTTON (button);
166
  GtkAdjustment *adj;
167
  GtkWidget *minus_button, *plus_button;
168 169 170

  atk_object_set_name (gtk_widget_get_accessible (GTK_WIDGET (button)),
		       _("Volume"));
171 172 173 174 175 176
  atk_object_set_description (gtk_widget_get_accessible (GTK_WIDGET (button)),
		       _("Turns volume down or up"));
  atk_action_set_description (ATK_ACTION (gtk_widget_get_accessible (GTK_WIDGET (button))),
			      1,
			      _("Adjusts the volume"));

177 178 179 180
  minus_button = gtk_scale_button_get_minus_button (sbutton);
  plus_button = gtk_scale_button_get_plus_button (sbutton);

  atk_object_set_name (gtk_widget_get_accessible (minus_button),
181
		       _("Volume Down"));
182
  atk_object_set_description (gtk_widget_get_accessible (minus_button),
183
		       _("Decreases the volume"));
184
  gtk_widget_set_tooltip_text (minus_button, _("Volume Down"));
185

186
  atk_object_set_name (gtk_widget_get_accessible (plus_button),
187
		       _("Volume Up"));
188
  atk_object_set_description (gtk_widget_get_accessible (plus_button),
189
		       _("Increases the volume"));
190
  gtk_widget_set_tooltip_text (plus_button, _("Volume Up"));
191

192
  gtk_scale_button_set_icons (sbutton, (const char **) icons);
193

194
  adj = gtk_adjustment_new (0., 0., 1., 0.02, 0.2, 0.);
195 196 197
  g_object_set (G_OBJECT (button),
		"adjustment", adj,
		"size", GTK_ICON_SIZE_SMALL_TOOLBAR,
198
		"has-tooltip", TRUE,
199
		NULL);
200

201 202
  g_signal_connect (G_OBJECT (button), "query-tooltip",
		    G_CALLBACK (cb_query_tooltip), NULL);
203 204 205 206 207 208 209
  g_signal_connect (G_OBJECT (button), "value-changed",
		    G_CALLBACK (cb_value_changed), NULL);
}

/**
 * gtk_volume_button_new
 *
Matthias Clasen's avatar
Matthias Clasen committed
210 211
 * Creates a #GtkVolumeButton, with a range between 0.0 and 1.0, with
 * a stepping of 0.02. Volume values can be obtained and modified using
212 213 214 215 216 217 218 219 220 221 222 223 224 225
 * the functions from #GtkScaleButton.
 *
 * Return value: a new #GtkVolumeButton
 *
 * Since: 2.12
 */
GtkWidget *
gtk_volume_button_new (void)
{
  GObject *button;
  button = g_object_new (GTK_TYPE_VOLUME_BUTTON, NULL);
  return GTK_WIDGET (button);
}

226 227 228 229 230 231 232
static gboolean
cb_query_tooltip (GtkWidget  *button,
		  gint        x,
		  gint        y,
		  gboolean    keyboard_mode,
		  GtkTooltip *tooltip,
		  gpointer    user_data)
233
{
234
  GtkScaleButton *scale_button = GTK_SCALE_BUTTON (button);
235
  GtkAdjustment *adjustment;
236 237
  gdouble val;
  char *str;
238 239 240
  AtkImage *image;

  image = ATK_IMAGE (gtk_widget_get_accessible (button));
241

242
  adjustment = gtk_scale_button_get_adjustment (scale_button);
243
  val = gtk_scale_button_get_value (scale_button);
244

245
  if (val < (gtk_adjustment_get_lower (adjustment) + EPSILON))
246 247 248
    {
      str = g_strdup (_("Muted"));
    }
249
  else if (val >= (gtk_adjustment_get_upper (adjustment) - EPSILON))
250 251 252 253 254 255 256
    {
      str = g_strdup (_("Full Volume"));
    }
  else
    {
      int percent;

257
      percent = (int) (100. * val / (gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_lower (adjustment)) + .5);
258 259 260 261 262 263

      /* Translators: this is the percentage of the current volume,
       * as used in the tooltip, eg. "49 %".
       * Translate the "%d" to "%Id" if you want to use localised digits,
       * or otherwise translate the "%d" to "%d".
       */
264
      str = g_strdup_printf (C_("volume percentage", "%d %%"), percent);
265 266
    }

267
  gtk_tooltip_set_text (tooltip, str);
268
  atk_image_set_image_description (image, str);
269
  g_free (str);
270 271

  return TRUE;
272 273 274 275 276
}

static void
cb_value_changed (GtkVolumeButton *button, gdouble value, gpointer user_data)
{
277
  gtk_widget_trigger_tooltip_query (GTK_WIDGET (button));
278
}