Миграция небольшого образца gtk3 с gtk 3.18 на gtk 3.22 - PullRequest
0 голосов
/ 04 января 2019

Я работаю над некоторым приложением, где мы рисуем виджеты, такие как «RadioButton», «CheckButton» и т. Д., Вызывая «gtk_render_option», «gtk_render_check» и так далее. Наше приложение отлично работает на GTK 3.18, но на GTK 3.22 виджеты отображаются не правильно. Я прошел через изменения, внесенные в темы в 3.20, и попытался внести некоторые изменения в свое приложение, но я не могу понять, что мне нужно делать точно.

Я создал небольшой пример, где я рисую «RadioButton» с помощью API gtk_render_option. Это прекрасно работает для меня в gtk-3.18, но причины проблемы в gtk 3.22. Я прилагаю изображения и код для справки. Было бы замечательно, если бы кто-то здесь мог направить меня на "Как я могу заставить эту маленькую демонстрацию работать на GTK 3.22". Я должен быть в состоянии позаботиться об остальном сам. Я могу предоставить любую дополнительную информацию.

Примечание: я попробовал и "radio", и "radiobutton" в API gtk_style_context_add_class. Оба не работают для меня.

Вывод с gtk 3.18

Вывод с gtk 3.22

gtk 3.22

Код

#include <string.h>
#include <gtk/gtk.h>

static gboolean
draw_cb_options (GtkWidget *widget, cairo_t *cr)
{
  GtkStyleContext *context;

  context = gtk_widget_get_style_context (widget);

  gtk_style_context_save (context);

  gtk_style_context_add_class (context, "radio");
  gtk_style_context_set_state (context, 0);
  gtk_render_option (context, cr, 10, 50, 40, 40);
  gtk_style_context_set_state (context, GTK_STATE_FLAG_CHECKED);
  gtk_render_option (context, cr, 70, 50, 40, 40);
  gtk_style_context_set_state (context, GTK_STATE_FLAG_INCONSISTENT);
  gtk_render_option (context, cr, 120, 50, 40, 40);
  gtk_style_context_set_state (context, GTK_STATE_FLAG_INSENSITIVE);
  gtk_render_option (context, cr, 170, 50, 40, 40);

  gtk_style_context_restore (context);

  return TRUE;
}


int main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkStyleContext *context;
  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  g_signal_connect (window, "draw", G_CALLBACK (draw_cb_options), NULL);
  gtk_widget_show_all (window);

  gtk_main ();

  return 0;
}

1 Ответ

0 голосов
/ 08 января 2019

Согласно GTK + 3.20 журнал изменений :

GtkDrawingArea используется для неявной визуализации фона темы перед вызовом обработчика :: draw.Это больше не так.Если вы полагаетесь на фон, предоставленный темой, вызовите gtk_render_background() из вашего обработчика :: draw.

Даже вызов gtk_render_background в функции рисования не имел значения.Приведенный ниже пример основан на иностранной ничьей в gtk3-демо , я старался изо всех сил упростить, но все же для достижения того, что вам нужно, нужно многое сделать.

sample screenshot

#include <gtk/gtk.h>
#include <string.h>

static GtkStyleContext *
get_style (GtkStyleContext *parent,
           const char      *selector)
{
  GtkWidgetPath *path;
  GtkStyleContext *context;

  if (parent)
    path = gtk_widget_path_copy (gtk_style_context_get_path (parent));
  else
    path = gtk_widget_path_new ();

  gtk_widget_path_append_type (path, G_TYPE_NONE);
  gtk_widget_path_iter_set_object_name (path, -1, selector);

  context = gtk_style_context_new ();
  gtk_style_context_set_path (context, path);
  gtk_style_context_set_parent (context, parent);
  /* Unfortunately, we have to explicitly set the state again here for it to take effect */
  gtk_style_context_set_state (context, gtk_widget_path_iter_get_state (path, -1));
  gtk_widget_path_unref (path);

  return context;
}

static void
draw_style_common (GtkStyleContext *context,
                   cairo_t         *cr,
                   gint             x,
                   gint             y,
                   gint             width,
                   gint             height,
                   gint            *contents_x,
                   gint            *contents_y,
                   gint            *contents_width,
                   gint            *contents_height)
{
  GtkBorder margin, border, padding;
  int min_width, min_height;

  gtk_style_context_get_margin (context, gtk_style_context_get_state (context), &margin);
  gtk_style_context_get_border (context, gtk_style_context_get_state (context), &border);
  gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &padding);

  gtk_style_context_get (context, gtk_style_context_get_state (context),
                         "min-width", &min_width,
                         "min-height", &min_height,
                         NULL);
  x += margin.left;
  y += margin.top;
  width -= margin.left + margin.right;
  height -= margin.top + margin.bottom;

  width = MAX (width, min_width);
  height = MAX (height, min_height);

  gtk_render_background (context, cr, x, y, width, height);
  gtk_render_frame (context, cr, x, y, width, height);

  if (contents_x)
    *contents_x = x + border.left + padding.left;
  if (contents_y)
    *contents_y = y + border.top + padding.top;
  if (contents_width)
    *contents_width = width - border.left - border.right - padding.left - padding.right;
  if (contents_height)
    *contents_height = height - border.top - border.bottom - padding.top - padding.bottom;
}

static void
query_size (GtkStyleContext *context,
            gint            *width,
            gint            *height)
{
  GtkBorder margin, border, padding;
  int min_width, min_height;

  gtk_style_context_get_margin (context, gtk_style_context_get_state (context), &margin);
  gtk_style_context_get_border (context, gtk_style_context_get_state (context), &border);
  gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &padding);

  gtk_style_context_get (context, gtk_style_context_get_state (context),
                         "min-width", &min_width,
                         "min-height", &min_height,
                         NULL);

  min_width += margin.left + margin.right + border.left + border.right + padding.left + padding.right;
  min_height += margin.top + margin.bottom + border.top + border.bottom + padding.top + padding.bottom;

  *width = MAX (*width, min_width);
  *height = MAX (*height, min_height);
}

static void
draw_radio (GtkWidget     *widget,
            cairo_t       *cr,
            gint           x,
            gint           y,
            GtkStateFlags  state)
{
  GtkStyleContext *button_context, *check_context;
  gint contents_x, contents_y, contents_width, contents_height;
  gint width = 0, height = 0;

  /* This information is taken from the GtkRadioButton docs, see "CSS nodes" */
  button_context = get_style (NULL, "radiobutton");
  check_context = get_style (button_context, "radio");

  gtk_style_context_set_state (check_context, state);

  query_size (button_context, &width, &height);
  query_size (check_context, &width, &height);

  draw_style_common (button_context, cr, x, y, width, height, NULL, NULL, NULL, NULL);
  draw_style_common (check_context, cr, x, y, width, height,
                     &contents_x, &contents_y, &contents_width, &contents_height);
  gtk_render_option (check_context, cr, contents_x, contents_y, contents_width, contents_height);

  g_object_unref (check_context);
  g_object_unref (button_context);

}

static gboolean
draw_cb (GtkWidget *widget,
         cairo_t   *cr)
{
  draw_radio (widget, cr, 10, 10, GTK_STATE_FLAG_NORMAL);
  draw_radio (widget, cr, 50, 50, GTK_STATE_FLAG_CHECKED);
  draw_radio (widget, cr, 100, 100, GTK_STATE_FLAG_INCONSISTENT);
  draw_radio (widget, cr, 150, 150, GTK_STATE_FLAG_INSENSITIVE);

  return FALSE;
}

int main (int argc, char *argv[])
{
  GtkWidget *box, *window, *da;

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
  gtk_container_add (GTK_CONTAINER (window), box);

  g_signal_connect (box, "draw", G_CALLBACK (draw_cb), NULL);

  gtk_widget_show_all (window);
  gtk_main ();

  return 0;
}
...