~siretart/gxine/bug.542506

« back to all changes in this revision

Viewing changes to src/xml_widgets.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-03-21 11:24:59 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20080321112459-igb0jy01nytpdrzt
Tags: 0.5.901-1ubuntu1
* merge debian changes for hardy PPA. Remaining changes:
  - debian/control: added Xb-Npp-xxx tags accordingly to "firefox distro
    add-on suport" spec,
    (https://blueprints.launchpad.net/ubuntu/+spec/firefox-distro-addon-support)
* Feature Freeze exception granted in LP: #204563
* New upstream release fixes playing DVDs. LP: #128864
* mime.default: add "x-content/video-dvd;x-content/video-vcd;x-content/video-svcd;"
  to get it listed as a player for dvd and video cds in nautilus. Thanks to
  Sebastien Bacher for the hint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2005 the xine-project
 
2
 * Copyright (C) 2005-2006 the xine-project
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or
5
5
 * modify it under the terms of the GNU General Public License as
16
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
17
17
 * USA
18
18
 *
19
 
 * $Id: xml_widgets.c,v 1.25 2006/04/04 21:56:18 dsalt Exp $
20
 
 *
21
19
 * windows, generated from XML and using JS and gxine's .gtkrc
22
20
 */
23
21
 
81
79
    return;
82
80
 
83
81
  printf ("TN_(\"");
84
 
  while ((lf = strchr (text, '"')) != NULL)
 
82
  --text;
 
83
  while (*++text)
85
84
  {
86
 
    *lf = 0;
87
 
    printf ("%s\\\"", text);
88
 
    text = lf + 1;
 
85
    switch (*text)
 
86
    {
 
87
    case '"':
 
88
      printf ("\\\"");
 
89
      break;
 
90
    case '\n':
 
91
      printf ("\\n\"\n\"");
 
92
      break;
 
93
    default:
 
94
      putchar (*text);
 
95
    }
89
96
  }
90
 
  printf ("%s\");\n", text);
 
97
  puts ("\");");
91
98
}
92
99
 
93
100
#define xml_error(msg, ...) g_printerr ((msg), ## __VA_ARGS__)
363
370
 * Interactive widgets
364
371
 */
365
372
 
366
 
static GtkWidget *
367
 
create_button (xml_node_t *node)
 
373
#ifndef MAKE_TRANSLATION_SOURCE
 
374
static GtkWidget *
 
375
gxine_toggle_button_new_from_stock (const char *stock)
 
376
{
 
377
  GtkWidget *btn = gtk_toggle_button_new_with_label (stock);
 
378
  gtk_button_set_use_stock (GTK_BUTTON (btn), TRUE);
 
379
  return btn;
 
380
}
 
381
#endif
 
382
 
 
383
static GtkWidget *
 
384
create_button (xml_node_t *node, gboolean click)
368
385
/* Properties:
369
386
 *      stock           string  none            stock item
370
387
 *      label           string  none            text if stock is not set [translatable]
382
399
#ifndef MAKE_TRANSLATION_SOURCE
383
400
  GtkWidget *button;
384
401
  static const char *relief[] = { "none", "half", NULL };
 
402
 
 
403
  typedef GtkWidget *(*button_new_t) (const char *);
 
404
  typedef GtkWidget *(*plain_new_t) (void);
 
405
  static const struct {
 
406
    button_new_t stock[2], mnemonic[2], label[2];
 
407
    plain_new_t plain[2];
 
408
  } newbtn = {
 
409
    { gxine_toggle_button_new_from_stock, gtk_button_new_from_stock },
 
410
    { gtk_toggle_button_new_with_mnemonic, gtk_button_new_with_mnemonic },
 
411
    { gtk_toggle_button_new_with_label, gtk_button_new_with_label },
 
412
    { gtk_toggle_button_new, gtk_button_new },
 
413
  };
385
414
#endif
386
415
 
387
416
  alt = xml_parser_get_property (node, "alt");
397
426
    return NULL;
398
427
#else
399
428
    if (check_stock (image))
400
 
      button = gtk_button_new_from_stock (image);
 
429
      button = newbtn.stock[click] (image);
401
430
    else if (alt)
402
431
      button = xml_parser_get_bool (node, "mnemonic")
403
 
               ? gtk_button_new_with_mnemonic (TRANSLATE (alt))
404
 
               : gtk_button_new_with_label (TRANSLATE (alt));
 
432
               ? newbtn.mnemonic[click] (TRANSLATE (alt))
 
433
               : newbtn.label[click] (TRANSLATE (alt));
405
434
    else
406
435
    {
407
 
      button = gtk_button_new ();
 
436
      button = newbtn.plain[click] ();
408
437
      if (image)
409
438
        g_object_set (G_OBJECT (button), "image",
410
439
                      check_stock (image)
443
472
  if (label && !image)
444
473
  {
445
474
    button = xml_parser_get_bool (node, "mnemonic")
446
 
             ? gtk_button_new_with_mnemonic (TRANSLATE (label))
447
 
             : gtk_button_new_with_label (TRANSLATE (label));
 
475
             ? newbtn.mnemonic[click] (TRANSLATE (label))
 
476
             : newbtn.label[click] (TRANSLATE (label));
448
477
    goto created;
449
478
  }
450
479
 
451
 
  button = gtk_button_new ();
 
480
  button = newbtn.plain[click] ();
452
481
  if (label || image)
453
482
  {
454
483
    g_object_set (G_OBJECT (button),
489
518
  created:
490
519
  gtk_button_set_relief (GTK_BUTTON (button),
491
520
                         2 - lookup_type (node, "relief", relief));
492
 
  /* set the command which is executed when the button is clicked */
493
 
  label = xml_parser_get_property (node, "onclick");
494
 
  if (label)
495
 
    command_attach (button, "clicked", "js-onclick", label,
496
 
                    _("XML button click"));
 
521
  if (click)
 
522
  {
 
523
    /* set the command which is executed when the button is clicked */
 
524
    label = xml_parser_get_property (node, "onclick");
 
525
    if (label)
 
526
      command_attach (button, "clicked", "js-onclick", label,
 
527
                      _("XML button click"));
 
528
  }
497
529
  return button;
498
530
#endif /* ! MAKE_TRANSLATION_SOURCE */
499
531
}
559
591
                          TRANSLATE (*stock->tip ? stock->tip : stock->name),
560
592
                          NULL);
561
593
}
 
594
 
 
595
static gboolean
 
596
slider_button_cb (GtkWidget *widget, GdkEventButton *ev, gpointer data)
 
597
{
 
598
  gtk_grab_remove (widget);
 
599
  gdk_keyboard_ungrab (ev->time);
 
600
  gdk_pointer_ungrab (ev->time);
 
601
  gtk_widget_hide (widget);
 
602
  gtk_toggle_button_set_active (data, FALSE);
 
603
  return FALSE;
 
604
}
 
605
 
 
606
static gboolean
 
607
slider_widget_button_cb (GtkWidget *widget, GdkEventButton *ev, gpointer data)
 
608
{
 
609
  return slider_button_cb (gtk_widget_get_toplevel (widget), ev, data);
 
610
}
 
611
 
 
612
#include <gdk/gdkkeysyms.h>
 
613
static gboolean
 
614
slider_key_cb (GtkWidget *window, GdkEventKey *ev, gpointer data)
 
615
{
 
616
  switch (ev->keyval)
 
617
  {
 
618
  case GDK_Escape:
 
619
  case GDK_KP_Enter:
 
620
  case GDK_Return:
 
621
  case GDK_space:
 
622
    return slider_button_cb (window, (GdkEventButton *) ev, data);
 
623
  default:
 
624
    return FALSE;
 
625
  }
 
626
}
 
627
 
 
628
static gboolean
 
629
slider_window_cb (GtkWidget *button, gpointer window)
 
630
{
 
631
  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
 
632
    return FALSE;
 
633
 
 
634
  gtk_window_set_transient_for (window,
 
635
                                GTK_WINDOW (gtk_widget_get_toplevel (button)));
 
636
 
 
637
  GdkWindow *parent = gtk_widget_get_parent_window (button);
 
638
  GtkAllocation ppos;
 
639
  gdk_window_get_position (parent, &ppos.x, &ppos.y);
 
640
  gdk_drawable_get_size (GDK_DRAWABLE (parent), &ppos.width, &ppos.height);
 
641
 
 
642
  GdkScreen *screen = gtk_widget_get_screen (button);
 
643
  gint monitor = gdk_screen_get_monitor_at_window (screen, parent);
 
644
  GdkRectangle geom;
 
645
  gdk_screen_get_monitor_geometry (screen, monitor, &geom);
 
646
 
 
647
  gint wx, wy;
 
648
  GtkRequisition req;
 
649
  gtk_widget_size_request (window, &req);
 
650
  gtk_window_get_default_size (window, &wx, &wy);
 
651
  if (wx > req.width)
 
652
    req.width = wx;
 
653
  if (wy > req.height)
 
654
    req.height = wy;
 
655
 
 
656
  wx = button->allocation.x + ppos.x; /* button left */
 
657
  wy = button->allocation.y + ppos.y; /* button top */
 
658
 
 
659
  if (GTK_IS_VSCALE (((GtkBin *) window)->child))
 
660
  {
 
661
    /* arrange vertically, preferably below */
 
662
    wx += (button->allocation.width - req.width) / 2; /* centre-aligned */
 
663
    wy += (wy + req.height + button->allocation.height > geom.y + geom.height)
 
664
        ? -req.height                   /* below (if enough space) */
 
665
        : button->allocation.height;    /* above */
 
666
  }
 
667
  else if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
 
668
  {
 
669
    /* arrange vertically, preferably to the left (RTL) */
 
670
    wx -= (wx - req.width < geom.x)
 
671
        ? -button->allocation.width     /* left (if enough space) */
 
672
        : req.width;                    /* right */
 
673
    wy += (button->allocation.height - req.height) / 2; /* centre-aligned */
 
674
  }
 
675
  else
 
676
  {
 
677
    /* arrange vertically, preferably to the right (LTR) */
 
678
    wx += (wx + req.width + button->allocation.width > geom.x + geom.width)
 
679
        ? -req.width                    /* right (if enough space) */
 
680
        : button->allocation.width;     /* left */
 
681
    wy += (button->allocation.height - req.height) / 2; /* centre-aligned */
 
682
  }
 
683
 
 
684
  gtk_window_move (GTK_WINDOW (window), wx, wy);
 
685
  gtk_widget_show_all (window);
 
686
 
 
687
  gdk_keyboard_grab (((GtkWidget *)window)->window, TRUE, GDK_CURRENT_TIME);
 
688
  gdk_pointer_grab (((GtkWidget *)window)->window, TRUE,
 
689
                    GDK_BUTTON_RELEASE_MASK, NULL, NULL, GDK_CURRENT_TIME);
 
690
  gtk_grab_add (window);
 
691
 
 
692
  return TRUE;
 
693
}
562
694
#endif
563
695
 
564
696
static GtkWidget *
566
698
/* Properties:
567
699
 *      type            string  none    widget identifer (see stock[].name)
568
700
 *      vertical        bool    FALSE   slider orientation
 
701
 *      inverted        bool    FALSE   slider direction reversal
569
702
 *      show-value      bool    FALSE   show slider value numerically
 
703
 *      popup           bool    FALSE   slider is a popup
 
704
 *                                      (use button properties except onclick)
 
705
 *      window-width    int     -1      popup window width
 
706
 *      window-height   int     -1      popup window height
570
707
 */
571
708
{
572
709
#ifndef MAKE_TRANSLATION_SOURCE
573
 
  stock_t stock[] = {
 
710
  static const stock_t stock[] = {
574
711
    { BUTTON,   Control_PLAY,           "play",         TN_("Start or resume a stream\n(at normal speed)"),
575
712
      GTK_STOCK_MEDIA_PLAY, NULL,                       "play ();" },
576
713
    { BUTTON,   Control_FASTFWD,        "forward",      TN_("Fast forward"),
588
725
    { SLIDER,   Control_COMPRESSOR,     TN_("Compressor"), "" },
589
726
    { SLIDER,   Control_AMPLIFIER,      TN_("Amplifier"), "" },
590
727
    { SLIDER,   Control_AV_SYNC,        TN_("A/V sync"), "" },
 
728
    { SLIDER,   Control_SPU_SYNC,       TN_("SPU sync"), "" },
591
729
    { SLIDER,   Control_HUE,            TN_("Hue"), "" },
592
730
    { SLIDER,   Control_SATURATION,     TN_("Saturation"), "" },
593
731
    { SLIDER,   Control_CONTRAST,       TN_("Contrast"), "" },
685
823
        goto do_spin_slider_again;
686
824
      }
687
825
 
 
826
      ui_register_adjustment_widget (stock[i].control, w);
 
827
 
688
828
      if (GTK_IS_SCALE (w))
689
829
      {
 
830
        gtk_scale_set_digits (GTK_SCALE (w), 0);
690
831
        gtk_scale_set_draw_value
691
832
          (GTK_SCALE (w), xml_parser_get_bool (node, "show-value"));
692
833
        gtk_range_set_inverted
693
834
          (GTK_RANGE (w), xml_parser_get_bool (node, "inverted"));
 
835
        if (xml_parser_get_bool (node, "popup"))
 
836
        {
 
837
          GtkWindow *window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_POPUP));
 
838
          gtk_window_set_default_size (window,
 
839
                xml_parser_get_property_int (node, "window-width", -1),
 
840
                xml_parser_get_property_int (node, "window-height", -1));
 
841
          gtk_window_set_decorated (window, FALSE);
 
842
          gtk_window_set_skip_pager_hint (window, TRUE);
 
843
          gtk_window_set_skip_taskbar_hint (window, TRUE);
 
844
          gtk_container_add (GTK_CONTAINER (window), w);
 
845
          gtk_widget_add_events ((GtkWidget *)window, GDK_BUTTON_RELEASE_MASK);
 
846
          gtk_widget_show (w);
 
847
          GtkWidget *btn = create_button (node, FALSE);
 
848
          g_object_connect (G_OBJECT (window),
 
849
            "signal::destroy-event", gtk_widget_hide_on_delete, btn,
 
850
            "signal::button-release-event", G_CALLBACK (slider_button_cb), btn,
 
851
            "signal::key-press-event", G_CALLBACK (slider_key_cb), btn,
 
852
            NULL);
 
853
          g_signal_connect (G_OBJECT (w), "button-release-event",
 
854
                            G_CALLBACK (slider_widget_button_cb), btn);
 
855
          g_signal_connect (G_OBJECT (btn), "toggled",
 
856
                            G_CALLBACK (slider_window_cb), window);
 
857
          w = btn; /* for popups, we return the button, not the slider */
 
858
        }
694
859
      }
695
860
      else
696
861
        gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (w), TRUE);
992
1157
 
993
1158
  case 'b':
994
1159
    if (!strcasecmp (node->name + 1, "utton"))
995
 
      widget = create_button (node);
 
1160
      widget = create_button (node, TRUE);
996
1161
    break;
997
1162
 
998
1163
  case 'c':
1032
1197
#ifndef MAKE_TRANSLATION_SOURCE
1033
1198
    else if (!strcasecmp (node->name + 1, "ime"))
1034
1199
    {
1035
 
      widget = create_time_widget (xml_parser_get_bool (node, "small"));
 
1200
      widget = create_time_widget (xml_parser_get_bool (node, "small"),
 
1201
                                   &timewidgets);
1036
1202
      timewidgets = g_slist_append (timewidgets, widget);
1037
1203
    }
1038
1204
    else if (!strcasecmp (node->name + 1, "itle"))