gimpfontselectbutton.c 13.9 KB
Newer Older
1 2 3
/* LIBGIMP - The GIMP Library
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
 *
4
 * gimpfontselectbutton.c
5 6
 * Copyright (C) 2003  Sven Neumann  <sven@gimp.org>
 *
7
 * This library is free software: you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 3 of the License, or (at your option) any later version.
11 12 13 14 15 16 17
 *
 * 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
18
 * License along with this library.  If not, see
19
 * <https://www.gnu.org/licenses/>.
20 21 22 23
 */

#include "config.h"

24
#include <gegl.h>
25 26 27 28
#include <gtk/gtk.h>

#include "libgimpwidgets/gimpwidgets.h"

29
#include "gimp.h"
30 31 32

#include "gimpuitypes.h"
#include "gimpfontselectbutton.h"
33
#include "gimpuimarshal.h"
34

35 36
#include "libgimp-intl.h"

37

38 39 40 41 42 43 44 45 46
/**
 * SECTION: gimpfontselectbutton
 * @title: GimpFontSelectButton
 * @short_description: A button which pops up a font selection dialog.
 *
 * A button which pops up a font selection dialog.
 **/


47 48 49 50 51 52 53 54 55 56 57 58 59
enum
{
  FONT_SET,
  LAST_SIGNAL
};

enum
{
  PROP_0,
  PROP_TITLE,
  PROP_FONT_NAME
};

60

61 62 63 64 65 66 67 68 69 70 71 72 73
struct _GimpFontSelectButtonPrivate
{
  gchar       *title;

  gchar       *font_name;      /* local copy */

  GtkWidget   *inside;
  GtkWidget   *label;
};

#define GET_PRIVATE(obj) (((GimpFontSelectButton *) (obj))->priv)


74
/*  local function prototypes  */
75

76 77
static void   gimp_font_select_button_finalize     (GObject      *object);

78 79 80 81 82 83 84 85 86
static void   gimp_font_select_button_set_property (GObject      *object,
                                                    guint         property_id,
                                                    const GValue *value,
                                                    GParamSpec   *pspec);
static void   gimp_font_select_button_get_property (GObject      *object,
                                                    guint         property_id,
                                                    GValue       *value,
                                                    GParamSpec   *pspec);

87
static void   gimp_font_select_button_clicked  (GimpFontSelectButton *button);
88 89 90 91

static void   gimp_font_select_button_callback (const gchar *font_name,
                                                gboolean     dialog_closing,
                                                gpointer     user_data);
92

93
static void   gimp_font_select_drag_data_received (GimpFontSelectButton *button,
94 95 96 97 98 99
                                                   GdkDragContext       *context,
                                                   gint                  x,
                                                   gint                  y,
                                                   GtkSelectionData     *selection,
                                                   guint                 info,
                                                   guint                 time);
100

101
static GtkWidget * gimp_font_select_button_create_inside (GimpFontSelectButton *button);
102

103 104 105

static const GtkTargetEntry target = { "application/x-gimp-font-name", 0 };

106 107 108
static guint font_button_signals[LAST_SIGNAL] = { 0 };


109 110
G_DEFINE_TYPE_WITH_PRIVATE (GimpFontSelectButton, gimp_font_select_button,
                            GIMP_TYPE_SELECT_BUTTON)
111

112 113 114 115

static void
gimp_font_select_button_class_init (GimpFontSelectButtonClass *klass)
{
116 117
  GObjectClass          *object_class        = G_OBJECT_CLASS (klass);
  GimpSelectButtonClass *select_button_class = GIMP_SELECT_BUTTON_CLASS (klass);
118

119 120 121
  object_class->finalize     = gimp_font_select_button_finalize;
  object_class->set_property = gimp_font_select_button_set_property;
  object_class->get_property = gimp_font_select_button_get_property;
122

123
  select_button_class->select_destroy = gimp_font_select_destroy;
124 125 126 127 128 129

  klass->font_set = NULL;

  /**
   * GimpFontSelectButton:title:
   *
130
   * The title to be used for the font selection popup dialog.
131
   *
132
   * Since: 2.4
133
   */
134 135 136 137
  g_object_class_install_property (object_class, PROP_TITLE,
                                   g_param_spec_string ("title",
                                                        "Title",
                                                        "The title to be used for the font selection popup dialog",
138
                                                        _("Font Selection"),
139
                                                        GIMP_PARAM_READWRITE |
140 141 142 143 144 145 146
                                                        G_PARAM_CONSTRUCT_ONLY));

  /**
   * GimpFontSelectButton:font-name:
   *
   * The name of the currently selected font.
   *
147
   * Since: 2.4
148
   */
149 150 151 152
  g_object_class_install_property (object_class, PROP_FONT_NAME,
                                   g_param_spec_string ("font-name",
                                                        "Font name",
                                                        "The name of the currently selected font",
153
                                                        "Sans-serif",
154
                                                        GIMP_PARAM_READWRITE));
155 156 157 158 159 160 161 162 163

  /**
   * GimpFontSelectButton::font-set:
   * @widget: the object which received the signal.
   * @font_name: the name of the currently selected font.
   * @dialog_closing: whether the dialog was closed or not.
   *
   * The ::font-set signal is emitted when the user selects a font.
   *
164
   * Since: 2.4
165 166 167 168 169 170 171 172 173 174 175 176 177 178
   */
  font_button_signals[FONT_SET] =
    g_signal_new ("font-set",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpFontSelectButtonClass, font_set),
                  NULL, NULL,
                  _gimpui_marshal_VOID__STRING_BOOLEAN,
                  G_TYPE_NONE, 2,
                  G_TYPE_STRING,
                  G_TYPE_BOOLEAN);
}

static void
179
gimp_font_select_button_init (GimpFontSelectButton *button)
180
{
181
  GimpFontSelectButtonPrivate *priv;
182

183
  button->priv = gimp_font_select_button_get_instance_private (button);
184 185

  priv = GET_PRIVATE (button);
186

187
  priv->font_name = NULL;
188

189 190
  priv->inside = gimp_font_select_button_create_inside (button);
  gtk_container_add (GTK_CONTAINER (button), priv->inside);
191
}
192 193

/**
194
 * gimp_font_select_button_new:
195
 * @title:     Title of the dialog to use or %NULL to use the default title.
196
 * @font_name: Initial font name.
197
 *
198 199
 * Creates a new #GtkWidget that completely controls the selection of
 * a font.  This widget is suitable for placement in a table in a
200 201
 * plug-in dialog.
 *
202
 * Returns: A #GtkWidget that you can use in your UI.
203
 *
204
 * Since: 2.4
205
 */
206
GtkWidget *
207 208
gimp_font_select_button_new (const gchar *title,
                             const gchar *font_name)
209
{
210
  GtkWidget *button;
211

212
  if (title)
213 214 215 216
    button = g_object_new (GIMP_TYPE_FONT_SELECT_BUTTON,
                           "title",     title,
                           "font-name", font_name,
                           NULL);
217
  else
218 219 220
    button = g_object_new (GIMP_TYPE_FONT_SELECT_BUTTON,
                           "font-name", font_name,
                           NULL);
221

222
  return button;
223 224 225
}

/**
226 227
 * gimp_font_select_button_get_font:
 * @button: A #GimpFontSelectButton
228 229 230 231
 *
 * Retrieves the name of currently selected font.
 *
 * Returns: an internal copy of the font name which must not be freed.
232
 *
233
 * Since: 2.4
234
 */
235
const gchar *
236
gimp_font_select_button_get_font (GimpFontSelectButton *button)
237
{
238
  g_return_val_if_fail (GIMP_IS_FONT_SELECT_BUTTON (button), NULL);
239

240
  return GET_PRIVATE (button)->font_name;
241
}
242

243
/**
244 245
 * gimp_font_select_button_set_font:
 * @button: A #GimpFontSelectButton
246 247 248 249
 * @font_name: Font name to set; %NULL means no change.
 *
 * Sets the current font for the font select button.
 *
250
 * Since: 2.4
251 252
 */
void
253 254
gimp_font_select_button_set_font (GimpFontSelectButton *button,
                                  const gchar          *font_name)
255
{
256
  GimpSelectButton *select_button;
257

258
  g_return_if_fail (GIMP_IS_FONT_SELECT_BUTTON (button));
259

260
  select_button = GIMP_SELECT_BUTTON (button);
261

262 263
  if (select_button->temp_callback)
    gimp_fonts_set_popup (select_button->temp_callback, font_name);
264
  else
265
    gimp_font_select_button_callback (font_name, FALSE, button);
266 267 268 269 270
}


/*  private functions  */

271 272 273
static void
gimp_font_select_button_finalize (GObject *object)
{
274
  GimpFontSelectButtonPrivate *priv = GET_PRIVATE (object);
275 276 277 278 279 280 281 282 283 284

  g_free (priv->font_name);
  priv->font_name = NULL;

  g_free (priv->title);
  priv->title = NULL;

  G_OBJECT_CLASS (gimp_font_select_button_parent_class)->finalize (object);
}

285
static void
286 287 288 289 290
gimp_font_select_button_set_property (GObject      *object,
                                      guint         property_id,
                                      const GValue *value,
                                      GParamSpec   *pspec)
{
291
  GimpFontSelectButton        *button = GIMP_FONT_SELECT_BUTTON (object);
292
  GimpFontSelectButtonPrivate *priv   = GET_PRIVATE (button);
293 294 295 296

  switch (property_id)
    {
    case PROP_TITLE:
297
      priv->title = g_value_dup_string (value);
298 299
      break;
    case PROP_FONT_NAME:
300 301
      gimp_font_select_button_set_font (button,
                                        g_value_get_string (value));
302
      break;
303

304 305 306 307 308 309 310 311 312 313 314 315
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
gimp_font_select_button_get_property (GObject    *object,
                                      guint       property_id,
                                      GValue     *value,
                                      GParamSpec *pspec)
{
316
  GimpFontSelectButton        *button = GIMP_FONT_SELECT_BUTTON (object);
317
  GimpFontSelectButtonPrivate *priv   = GET_PRIVATE (button);
318 319 320 321

  switch (property_id)
    {
    case PROP_TITLE:
322
      g_value_set_string (value, priv->title);
323 324
      break;
    case PROP_FONT_NAME:
325
      g_value_set_string (value, priv->font_name);
326
      break;
327

328 329 330 331 332 333 334
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
335 336 337
gimp_font_select_button_callback (const gchar *font_name,
                                  gboolean     dialog_closing,
                                  gpointer     user_data)
338
{
339 340 341
  GimpFontSelectButton        *button        = GIMP_FONT_SELECT_BUTTON (user_data);
  GimpFontSelectButtonPrivate *priv          = GET_PRIVATE (button);
  GimpSelectButton            *select_button = GIMP_SELECT_BUTTON (button);
342

343
  g_free (priv->font_name);
344
  priv->font_name = g_strdup (font_name);
345

346
  gtk_label_set_text (GTK_LABEL (priv->label), font_name);
347

348 349
  if (dialog_closing)
    select_button->temp_callback = NULL;
350

351
  g_signal_emit (button, font_button_signals[FONT_SET], 0,
352
                 font_name, dialog_closing);
353
  g_object_notify (G_OBJECT (button), "font-name");
354 355 356
}

static void
357
gimp_font_select_button_clicked (GimpFontSelectButton *button)
358
{
359 360
  GimpFontSelectButtonPrivate *priv          = GET_PRIVATE (button);
  GimpSelectButton            *select_button = GIMP_SELECT_BUTTON (button);
361

362
  if (select_button->temp_callback)
363
    {
364
      /*  calling gimp_fonts_set_popup() raises the dialog  */
365 366
      gimp_fonts_set_popup (select_button->temp_callback,
                            priv->font_name);
367 368 369
    }
  else
    {
370
      select_button->temp_callback =
371
        gimp_font_select_new (priv->title, priv->font_name,
372
                              gimp_font_select_button_callback,
373
                              button);
374 375
    }
}
376 377

static void
378
gimp_font_select_drag_data_received (GimpFontSelectButton *button,
379 380 381 382 383 384
                                     GdkDragContext       *context,
                                     gint                  x,
                                     gint                  y,
                                     GtkSelectionData     *selection,
                                     guint                 info,
                                     guint                 time)
385
{
386
  gint   length = gtk_selection_data_get_length (selection);
387
  gchar *str;
388

389
  if (gtk_selection_data_get_format (selection) != 8 || length < 1)
390
    {
391
      g_warning ("%s: received invalid font data", G_STRFUNC);
392 393 394
      return;
    }

395 396
  str = g_strndup ((const gchar *) gtk_selection_data_get_data (selection),
                   length);
397

398 399 400 401 402 403 404 405 406 407 408
  if (g_utf8_validate (str, -1, NULL))
    {
      gint     pid;
      gpointer unused;
      gint     name_offset = 0;

      if (sscanf (str, "%i:%p:%n", &pid, &unused, &name_offset) >= 2 &&
          pid == gimp_getpid () && name_offset > 0)
        {
          gchar *name = str + name_offset;

409
          gimp_font_select_button_set_font (button, name);
410 411
        }
    }
412

413
  g_free (str);
414
}
415 416

static GtkWidget *
417
gimp_font_select_button_create_inside (GimpFontSelectButton *font_button)
418
{
419
  GimpFontSelectButtonPrivate *priv = GET_PRIVATE (font_button);
420 421 422
  GtkWidget                   *button;
  GtkWidget                   *hbox;
  GtkWidget                   *image;
423

424 425
  button = gtk_button_new ();

426
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
427
  gtk_container_add (GTK_CONTAINER (button), hbox);
428

429 430
  image = gtk_image_new_from_icon_name (GIMP_ICON_FONT,
                                        GTK_ICON_SIZE_BUTTON);
431 432
  gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);

433 434
  priv->label = gtk_label_new (priv->font_name);
  gtk_box_pack_start (GTK_BOX (hbox), priv->label, TRUE, TRUE, 4);
435

436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
  gtk_widget_show_all (button);

  g_signal_connect_swapped (button, "clicked",
                            G_CALLBACK (gimp_font_select_button_clicked),
                            font_button);

  gtk_drag_dest_set (GTK_WIDGET (button),
                     GTK_DEST_DEFAULT_HIGHLIGHT |
                     GTK_DEST_DEFAULT_MOTION |
                     GTK_DEST_DEFAULT_DROP,
                     &target, 1,
                     GDK_ACTION_COPY);

  g_signal_connect_swapped (button, "drag-data-received",
                            G_CALLBACK (gimp_font_select_drag_data_received),
                            font_button);
452

453
  return button;
454
}