Exemplo n.º 1
0
static gboolean
xfce_arrow_button_draw (GtkWidget      *widget,
                        cairo_t        *cr)
{
    gint x, y, w;
    GtkStyleContext *context;
    xfce_arrow_button_thickness thickness;
    GtkAllocation allocation;

    if (G_LIKELY (gtk_widget_is_drawable (widget)))
    {
        context = gtk_widget_get_style_context (widget);
        xfce_arrow_button_get_thickness (context, &thickness);
        gtk_widget_get_allocation (widget, &allocation);

        w = MIN (allocation.height - 2 * thickness.y,
                 allocation.width  - 2 * thickness.x);
        w = MIN (w, ARROW_WIDTH);

        x = (allocation.width - w) / 2;
        y = (allocation.height - w) / 2;

        GTK_WIDGET_CLASS (parent_class)->draw (widget, cr);

        gtk_style_context_save (context);
        gtk_style_context_set_state (context, gtk_widget_get_state_flags (widget));

        gtk_render_arrow (context, cr, G_PI, x, y, w);

        gtk_style_context_restore (context);
    }

    return TRUE;
}
Exemplo n.º 2
0
static gboolean
draw_cb_arrows (GtkWidget *widget, cairo_t *cr)
{
  GtkStyleContext *context;

  context = gtk_widget_get_style_context (widget);

  gtk_style_context_save (context);

  gtk_style_context_set_state (context, 0);
  gtk_render_arrow (context, cr, 0,        12, 12, 12);
  gtk_render_arrow (context, cr, G_PI/2,   36, 12, 12);
  gtk_render_arrow (context, cr, G_PI,     60, 12, 12);
  gtk_render_arrow (context, cr, G_PI*3/2, 84, 12, 12);

  gtk_style_context_restore (context);

  return TRUE;
}
Exemplo n.º 3
0
/********************************************************************\
 * Draw an arrow on a Widget so it can be altered with css          *
 *                                                                  *
 * Args:     widget - widget to add arrow to in the draw callback   *
 *               cr - cairo context for the draw callback           *
 *        direction - 0 for up, 1 for down                          *
 * Returns:  TRUE, stop other handlers being invoked for the event  *
\********************************************************************/
gboolean
gnc_draw_arrow_cb (GtkWidget *widget, cairo_t *cr, gpointer direction)
{
    GtkStyleContext *context = gtk_widget_get_style_context (widget);
    gint width = gtk_widget_get_allocated_width (widget);
    gint height = gtk_widget_get_allocated_height (widget);
    gint size;

    gtk_render_background (context, cr, 0, 0, width, height);
    gtk_style_context_add_class (context, GTK_STYLE_CLASS_ARROW);

    size = MIN(width / 2, height / 2);

    if (GPOINTER_TO_INT(direction) == 0)
        gtk_render_arrow (context, cr, 0,
                         (width - size)/2, (height - size)/2, size);
    else
        gtk_render_arrow (context, cr, G_PI,
                         (width - size)/2, (height - size)/2, size);

    return TRUE;
}
void ScrollbarThemeGtk::paintButton(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect, ScrollbarPart part)
{
    GtkStyleContext* styleContext = gtkScrollbarStyleContext();
    gtk_style_context_save(styleContext);

    ScrollbarOrientation orientation = scrollbar->orientation();
    applyScrollbarStyleContextClasses(styleContext, orientation);

    guint flags = 0;
    if ((BackButtonStartPart == part && scrollbar->currentPos())
        || (BackButtonEndPart == part && scrollbar->currentPos())
        || (ForwardButtonEndPart == part && scrollbar->currentPos() != scrollbar->maximum())
        || (ForwardButtonStartPart == part && scrollbar->currentPos() != scrollbar->maximum())) {
        if (part == scrollbar->pressedPart())
            flags |= GTK_STATE_FLAG_ACTIVE;
        if (part == scrollbar->hoveredPart())
            flags |= GTK_STATE_FLAG_PRELIGHT;
    } else
        flags |= GTK_STATE_FLAG_INSENSITIVE;
    gtk_style_context_set_state(styleContext, static_cast<GtkStateFlags>(flags));

    gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_BUTTON);
    gtk_render_background(styleContext, context->platformContext()->cr(), rect.x(), rect.y(), rect.width(), rect.height());
    gtk_render_frame(styleContext, context->platformContext()->cr(), rect.x(), rect.y(), rect.width(), rect.height());

    gfloat arrowScaling;
    gtk_style_context_get_style(styleContext, "arrow-scaling", &arrowScaling, nullptr);

    double arrowSize = std::min(rect.width(), rect.height()) * arrowScaling;
    FloatPoint arrowPoint(
        rect.x() + (rect.width() - arrowSize) / 2,
        rect.y() + (rect.height() - arrowSize) / 2);

    if (flags & GTK_STATE_FLAG_ACTIVE) {
        gint arrowDisplacementX, arrowDisplacementY;
        gtk_style_context_get_style(styleContext, "arrow-displacement-x", &arrowDisplacementX, "arrow-displacement-y", &arrowDisplacementY, nullptr);
        arrowPoint.move(arrowDisplacementX, arrowDisplacementY);
    }

    gdouble angle;
    if (orientation == VerticalScrollbar)
        angle = (part == ForwardButtonEndPart || part == ForwardButtonStartPart) ? G_PI : 0;
    else
        angle = (part == ForwardButtonEndPart || part == ForwardButtonStartPart) ? G_PI / 2 : 3 * (G_PI / 2);

    gtk_render_arrow(styleContext, context->platformContext()->cr(), angle, arrowPoint.x(), arrowPoint.y(), arrowSize);

    gtk_style_context_restore(styleContext);
}
static gboolean
draw_arrow_cb (GtkWidget *widget, cairo_t *cr, gpointer data)
{
    GncItemEdit *item_edit = GNC_ITEM_EDIT (data);
    GtkStyleContext *context = gtk_widget_get_style_context (widget);
    gint width = gtk_widget_get_allocated_width (widget);
    gint height = gtk_widget_get_allocated_height (widget);
    gint size;

    gtk_render_background (context, cr, 0, 0, width, height);

    gtk_style_context_add_class (context, GTK_STYLE_CLASS_ARROW);

    size = MIN(width / 2, height / 2);

    if (item_edit->popup_toggle.arrow_down == 0)
        gtk_render_arrow (context, cr, 0,
                         (width - size)/2, (height - size)/2, size);
    else
        gtk_render_arrow (context, cr, G_PI,
                         (width - size)/2, (height - size)/2, size);

    return FALSE;
}
Exemplo n.º 6
0
/* This code was originally rendering anti-aliased using X primitives, and
 * now has been switched to draw anti-aliased using cairo. In general, the
 * closest correspondence between X rendering and cairo rendering is given
 * by offsetting the geometry by 0.5 pixels in both directions before rendering
 * with cairo. This is because X samples at the upper left corner of the
 * pixel while cairo averages over the entire pixel. However, in the cases
 * where the X rendering was an exact rectangle with no "jaggies"
 * we need to be a bit careful about applying the offset. We want to produce
 * the exact same pixel-aligned rectangle, rather than a rectangle with
 * fuzz around the edges.
 */
static void
draw_op_draw_with_env (const MetaDrawOp    *op,
                       GtkStyleContext     *context,
                       cairo_t             *cr,
                       const MetaDrawInfo  *info,
                       MetaPositionExprEnv *env)
{
  GdkRGBA color;

  cairo_save (cr);

  cairo_set_line_width (cr, 1.0);

  switch (op->type)
    {
    case META_DRAW_LINE:
      {
        gdouble x1, x2, y1, y2;

        meta_color_spec_render (op->data.line.color_spec, context, &color);
        gdk_cairo_set_source_rgba (cr, &color);

        if (op->data.line.width > 0)
          cairo_set_line_width (cr, op->data.line.width);

        if (op->data.line.dash_on_length > 0 &&
            op->data.line.dash_off_length > 0)
          {
            double dash_list[2];
            dash_list[0] = op->data.line.dash_on_length;
            dash_list[1] = op->data.line.dash_off_length;
            cairo_set_dash (cr, dash_list, 2, 0);
          }

        x1 = meta_draw_spec_parse_x_position (op->data.line.x1, env);
        y1 = meta_draw_spec_parse_y_position (op->data.line.y1, env);

        if (!op->data.line.x2 && !op->data.line.y2 &&
            op->data.line.width == 0)
          {
            cairo_rectangle (cr, x1, y1, 1, 1);
            cairo_fill (cr);
          }
        else
          {
            if (op->data.line.x2)
              x2 = meta_draw_spec_parse_x_position (op->data.line.x2, env);
            else
              x2 = x1;

            if (op->data.line.y2)
              y2 = meta_draw_spec_parse_y_position (op->data.line.y2, env);
            else
              y2 = y1;

            /* This is one of the cases where we are matching the exact
             * pixel aligned rectangle produced by X; for zero-width lines
             * the generic algorithm produces the right result so we don't
             * need to handle them here.
             */
            if ((y1 == y2 || x1 == x2) && op->data.line.width != 0)
              {
                double offset = op->data.line.width % 2 ? .5 : 0;

                if (y1 == y2)
                  {
                    cairo_move_to (cr, x1, y1 + offset);
                    cairo_line_to (cr, x2, y2 + offset);
                  }
                else
                  {
                    cairo_move_to (cr, x1 + offset, y1);
                    cairo_line_to (cr, x2 + offset, y2);
                  }
              }
            else
              {
                /* zero-width lines include both end-points in X, unlike wide lines */
                if (op->data.line.width == 0)
                  cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);

                cairo_move_to (cr, x1 + .5, y1 + .5);
                cairo_line_to (cr, x2 + .5, y2 + .5);
              }
            cairo_stroke (cr);
          }
      }
      break;

    case META_DRAW_RECTANGLE:
      {
        gdouble rx, ry, rwidth, rheight;

        meta_color_spec_render (op->data.rectangle.color_spec, context, &color);
        gdk_cairo_set_source_rgba (cr, &color);

        rx = meta_draw_spec_parse_x_position (op->data.rectangle.x, env);
        ry = meta_draw_spec_parse_y_position (op->data.rectangle.y, env);
        rwidth = meta_draw_spec_parse_size (op->data.rectangle.width, env);
        rheight = meta_draw_spec_parse_size (op->data.rectangle.height, env);

        /* Filled and stroked rectangles are the other cases
         * we pixel-align to X rasterization
         */
        if (op->data.rectangle.filled)
          {
            cairo_rectangle (cr, rx, ry, rwidth, rheight);
            cairo_fill (cr);
          }
        else
          {
            cairo_rectangle (cr, rx + .5, ry + .5, rwidth, rheight);
            cairo_stroke (cr);
          }
      }
      break;

    case META_DRAW_ARC:
      {
        gdouble rx, ry, rwidth, rheight;
        double start_angle, end_angle;
        double center_x, center_y;

        meta_color_spec_render (op->data.arc.color_spec, context, &color);
        gdk_cairo_set_source_rgba (cr, &color);

        rx = meta_draw_spec_parse_x_position (op->data.arc.x, env);
        ry = meta_draw_spec_parse_y_position (op->data.arc.y, env);
        rwidth = meta_draw_spec_parse_size (op->data.arc.width, env);
        rheight = meta_draw_spec_parse_size (op->data.arc.height, env);

        start_angle = op->data.arc.start_angle * (M_PI / 180.)
                      - (.5 * M_PI); /* start at 12 instead of 3 oclock */
        end_angle = start_angle + op->data.arc.extent_angle * (M_PI / 180.);
        center_x = rx + (double)rwidth / 2. + .5;
        center_y = ry + (double)rheight / 2. + .5;

        cairo_save (cr);

        cairo_translate (cr, center_x, center_y);
        cairo_scale (cr, (double)rwidth / 2., (double)rheight / 2.);

        if (op->data.arc.extent_angle >= 0)
          cairo_arc (cr, 0, 0, 1, start_angle, end_angle);
        else
          cairo_arc_negative (cr, 0, 0, 1, start_angle, end_angle);

        cairo_restore (cr);

        if (op->data.arc.filled)
          {
            cairo_line_to (cr, center_x, center_y);
            cairo_fill (cr);
          }
        else
          cairo_stroke (cr);
      }
      break;

    case META_DRAW_CLIP:
      break;

    case META_DRAW_TINT:
      {
        gdouble rx, ry, rwidth, rheight;

        rx = meta_draw_spec_parse_x_position (op->data.tint.x, env);
        ry = meta_draw_spec_parse_y_position (op->data.tint.y, env);
        rwidth = meta_draw_spec_parse_size (op->data.tint.width, env);
        rheight = meta_draw_spec_parse_size (op->data.tint.height, env);

        meta_color_spec_render (op->data.tint.color_spec, context, &color);
        meta_alpha_gradient_spec_render (op->data.tint.alpha_spec, color, cr,
                                         rx, ry, rwidth, rheight);
      }
      break;

    case META_DRAW_GRADIENT:
      {
        gdouble rx, ry, rwidth, rheight;

        rx = meta_draw_spec_parse_x_position (op->data.gradient.x, env);
        ry = meta_draw_spec_parse_y_position (op->data.gradient.y, env);
        rwidth = meta_draw_spec_parse_size (op->data.gradient.width, env);
        rheight = meta_draw_spec_parse_size (op->data.gradient.height, env);

        meta_gradient_spec_render (op->data.gradient.gradient_spec,
                                   op->data.gradient.alpha_spec,
                                   cr, context, rx, ry, rwidth, rheight);
      }
      break;

    case META_DRAW_IMAGE:
      {
        gdouble scale;
        gdouble rx, ry, rwidth, rheight;
        cairo_surface_t *surface;

        scale = info->scale;
        cairo_scale (cr, 1.0 / scale, 1.0 / scale);

        if (op->data.image.pixbuf)
          {
            env->object_width = gdk_pixbuf_get_width (op->data.image.pixbuf);
            env->object_height = gdk_pixbuf_get_height (op->data.image.pixbuf);
          }

        rwidth = meta_draw_spec_parse_size (op->data.image.width, env) * scale;
        rheight = meta_draw_spec_parse_size (op->data.image.height, env) * scale;

        surface = draw_op_as_surface (op, context, info, rwidth, rheight);

        if (surface)
          {
            rx = meta_draw_spec_parse_x_position (op->data.image.x, env) * scale;
            ry = meta_draw_spec_parse_y_position (op->data.image.y, env) * scale;

            cairo_set_source_surface (cr, surface, rx, ry);

            if (op->data.image.alpha_spec)
              {
                cairo_pattern_t *pattern;

                cairo_translate (cr, rx, ry);
                cairo_scale (cr, rwidth, rheight);

                pattern = meta_alpha_gradient_spec_get_mask (op->data.image.alpha_spec);
                cairo_mask (cr, pattern);

                cairo_pattern_destroy (pattern);
              }
            else
              {
                cairo_paint (cr);
              }

            cairo_surface_destroy (surface);
          }
      }
      break;

    case META_DRAW_GTK_ARROW:
      {
        gdouble rx, ry, rwidth, rheight;
        double angle = 0, size;

        rx = meta_draw_spec_parse_x_position (op->data.gtk_arrow.x, env);
        ry = meta_draw_spec_parse_y_position (op->data.gtk_arrow.y, env);
        rwidth = meta_draw_spec_parse_size (op->data.gtk_arrow.width, env);
        rheight = meta_draw_spec_parse_size (op->data.gtk_arrow.height, env);

        size = MAX(rwidth, rheight);

        switch (op->data.gtk_arrow.arrow)
          {
          case GTK_ARROW_UP:
            angle = 0;
            break;
          case GTK_ARROW_RIGHT:
            angle = M_PI / 2;
            break;
          case GTK_ARROW_DOWN:
            angle = M_PI;
            break;
          case GTK_ARROW_LEFT:
            angle = 3 * M_PI / 2;
            break;
          case GTK_ARROW_NONE:
            return;
          default:
            break;
          }

        gtk_style_context_set_state (context, op->data.gtk_arrow.state);
        gtk_render_arrow (context, cr, angle, rx, ry, size);
      }
      break;

    case META_DRAW_GTK_BOX:
      {
        gdouble rx, ry, rwidth, rheight;

        rx = meta_draw_spec_parse_x_position (op->data.gtk_box.x, env);
        ry = meta_draw_spec_parse_y_position (op->data.gtk_box.y, env);
        rwidth = meta_draw_spec_parse_size (op->data.gtk_box.width, env);
        rheight = meta_draw_spec_parse_size (op->data.gtk_box.height, env);

        gtk_style_context_set_state (context, op->data.gtk_box.state);
        gtk_render_background (context, cr, rx, ry, rwidth, rheight);
        gtk_render_frame (context, cr, rx, ry, rwidth, rheight);
      }
      break;

    case META_DRAW_GTK_VLINE:
      {
        gdouble rx, ry1, ry2;

        rx = meta_draw_spec_parse_x_position (op->data.gtk_vline.x, env);
        ry1 = meta_draw_spec_parse_y_position (op->data.gtk_vline.y1, env);
        ry2 = meta_draw_spec_parse_y_position (op->data.gtk_vline.y2, env);

        gtk_style_context_set_state (context, op->data.gtk_vline.state);
        gtk_render_line (context, cr, rx, ry1, rx, ry2);
      }
      break;

    case META_DRAW_ICON:
      {
        gdouble rx, ry, rwidth, rheight;
        cairo_surface_t *surface;

        rwidth = meta_draw_spec_parse_size (op->data.icon.width, env);
        rheight = meta_draw_spec_parse_size (op->data.icon.height, env);

        surface = draw_op_as_surface (op, context, info, rwidth, rheight);

        if (surface)
          {
            rx = meta_draw_spec_parse_x_position (op->data.icon.x, env);
            ry = meta_draw_spec_parse_y_position (op->data.icon.y, env);

            cairo_set_source_surface (cr, surface, rx, ry);

            if (op->data.icon.alpha_spec)
              {
                cairo_pattern_t *pattern;

                cairo_translate (cr, rx, ry);
                cairo_scale (cr, rwidth, rheight);

                pattern = meta_alpha_gradient_spec_get_mask (op->data.icon.alpha_spec);
                cairo_mask (cr, pattern);

                cairo_pattern_destroy (pattern);
              }
            else
              {
                cairo_paint (cr);
              }

            cairo_surface_destroy (surface);
          }
      }
      break;

    case META_DRAW_TITLE:
      if (info->title_layout)
        {
          gdouble rx, ry;
          PangoRectangle ink_rect, logical_rect;

          meta_color_spec_render (op->data.title.color_spec, context, &color);
          gdk_cairo_set_source_rgba (cr, &color);

          rx = meta_draw_spec_parse_x_position (op->data.title.x, env);
          ry = meta_draw_spec_parse_y_position (op->data.title.y, env);

          if (op->data.title.ellipsize_width)
            {
              gdouble ellipsize_width;
              int right_bearing;

              ellipsize_width = meta_draw_spec_parse_x_position (op->data.title.ellipsize_width, env);
              /* HACK: meta_draw_spec_parse_x_position adds in env->rect.x, subtract out again */
              ellipsize_width -= env->rect.x;

              pango_layout_set_width (info->title_layout, -1);
              pango_layout_get_pixel_extents (info->title_layout,
                                              &ink_rect, &logical_rect);

              /* Pango's idea of ellipsization is with respect to the logical rect.
               * correct for this, by reducing the ellipsization width by the overflow
               * of the un-ellipsized text on the right... it's always the visual
               * right we want regardless of bidi, since since the X we pass in to
               * cairo_move_to() is always the left edge of the line.
               */
              right_bearing = (ink_rect.x + ink_rect.width) - (logical_rect.x + logical_rect.width);
              right_bearing = MAX (right_bearing, 0);

              ellipsize_width -= right_bearing;
              ellipsize_width = MAX (ellipsize_width, 0);

              /* Only ellipsizing when necessary is a performance optimization -
               * pango_layout_set_width() will force a relayout if it isn't the
               * same as the current width of -1.
               */
              if (ellipsize_width < logical_rect.width)
                pango_layout_set_width (info->title_layout, PANGO_SCALE * ellipsize_width);
            }
          else if (rx - env->rect.x + env->title_width >= env->rect.width)
          {
            const double alpha_margin = 30.0;
            int text_space = env->rect.x + env->rect.width -
                             (rx - env->rect.x) - env->right_width;

            double startalpha = 1.0 - (alpha_margin/((double)text_space));

            cairo_pattern_t *linpat;
            linpat = cairo_pattern_create_linear (rx, ry, text_space,
                                                  env->title_height);
            cairo_pattern_add_color_stop_rgba (linpat, 0, color.red,
                                                          color.green,
                                                          color.blue,
                                                          color.alpha);
            cairo_pattern_add_color_stop_rgba (linpat, startalpha,
                                                       color.red,
                                                       color.green,
                                                       color.blue,
                                                       color.alpha);
            cairo_pattern_add_color_stop_rgba (linpat, 1, color.red,
                                                          color.green,
                                                          color.blue, 0);
            cairo_set_source(cr, linpat);
            cairo_pattern_destroy(linpat);
          }

          cairo_move_to (cr, rx, ry);
          pango_cairo_show_layout (cr, info->title_layout);

          /* Remove any ellipsization we might have set; will short-circuit
           * if the width is already -1 */
          pango_layout_set_width (info->title_layout, -1);
        }
      break;

    case META_DRAW_OP_LIST:
      {
        MetaRectangleDouble d_rect;

        d_rect.x = meta_draw_spec_parse_x_position (op->data.op_list.x, env);
        d_rect.y = meta_draw_spec_parse_y_position (op->data.op_list.y, env);
        d_rect.width = meta_draw_spec_parse_size (op->data.op_list.width, env);
        d_rect.height = meta_draw_spec_parse_size (op->data.op_list.height, env);

        meta_draw_op_list_draw_with_style (op->data.op_list.op_list,
                                           context, cr, info, d_rect);
      }
      break;

    case META_DRAW_TILE:
      {
        gdouble rx, ry, rwidth, rheight;
        gdouble tile_xoffset, tile_yoffset;
        MetaRectangleDouble tile;

        rx = meta_draw_spec_parse_x_position (op->data.tile.x, env);
        ry = meta_draw_spec_parse_y_position (op->data.tile.y, env);
        rwidth = meta_draw_spec_parse_size (op->data.tile.width, env);
        rheight = meta_draw_spec_parse_size (op->data.tile.height, env);

        cairo_save (cr);

        cairo_rectangle (cr, rx, ry, rwidth, rheight);
        cairo_clip (cr);

        tile_xoffset = meta_draw_spec_parse_x_position (op->data.tile.tile_xoffset, env);
        tile_yoffset = meta_draw_spec_parse_y_position (op->data.tile.tile_yoffset, env);
        /* tile offset should not include x/y */
        tile_xoffset -= env->rect.x;
        tile_yoffset -= env->rect.y;

        tile.width = meta_draw_spec_parse_size (op->data.tile.tile_width, env);
        tile.height = meta_draw_spec_parse_size (op->data.tile.tile_height, env);

        tile.x = rx - tile_xoffset;

        while (tile.x < (rx + rwidth))
          {
            tile.y = ry - tile_yoffset;
            while (tile.y < (ry + rheight))
              {
                meta_draw_op_list_draw_with_style (op->data.tile.op_list,
                                                   context, cr, info, tile);

                tile.y += tile.height;
              }

            tile.x += tile.width;
          }
        cairo_restore (cr);
      }
      break;

    default:
      break;
    }

   cairo_restore (cr);
}
Exemplo n.º 7
0
static void
draw_combobox (GtkWidget *widget,
               cairo_t   *cr,
               gint       x,
               gint       y,
               gint       width,
               gboolean   has_entry,
               gint      *height)
{
  GtkStyleContext *combo_context;
  GtkStyleContext *box_context;
  GtkStyleContext *button_context;
  GtkStyleContext *button_box_context;
  GtkStyleContext *entry_context;
  GtkStyleContext *arrow_context;
  gint contents_x, contents_y, contents_width, contents_height;
  gint button_width;
  gint arrow_width, arrow_height, arrow_size;

  /* This information is taken from the GtkComboBox docs, see "CSS nodes" */
  combo_context = get_style (NULL, "combobox:focus");
  box_context = get_style (combo_context, "box.horizontal.linked");
  if (has_entry)
    {
      const char *siblings[3] = { "entry.combo:focus", "button.combo" , NULL };

      entry_context = get_style_with_siblings (box_context, "entry.combo:focus", siblings, 0);
      button_context = get_style_with_siblings (box_context, "button.combo", siblings, 1);
    }
  else
    {
      const char *siblings[2] = { "button.combo" , NULL };

      button_context = get_style_with_siblings (box_context, "button.combo", siblings, 0);
    }
  button_box_context = get_style (button_context, "box.horizontal");
  arrow_context = get_style (button_box_context, "arrow");

  *height = 0;
  query_size (combo_context, NULL, height);
  query_size (box_context, NULL, height);
  if (has_entry)
    query_size (entry_context, NULL, height);
  query_size (button_context, NULL, height);
  query_size (button_box_context, NULL, height);
  query_size (arrow_context, NULL, height);

  gtk_style_context_get (arrow_context,
                         "min-width", &arrow_width, "min-height", &arrow_height, NULL);
  arrow_size = MIN (arrow_width, arrow_height);

  draw_style_common (combo_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
  draw_style_common (box_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
  if (has_entry)
    {
      button_width = *height;
      draw_style_common (entry_context, cr, x, y, width - button_width, *height, NULL, NULL, NULL, NULL);
      draw_style_common (button_context, cr, x + width - button_width, y, button_width, *height,
                         &contents_x, &contents_y, &contents_width, &contents_height);
    }
  else
    {
      button_width = width;
      draw_style_common (button_context, cr, x, y, width, *height,
                         &contents_x, &contents_y, &contents_width, &contents_height);
    }

  draw_style_common (button_box_context, cr, contents_x, contents_y, contents_width, contents_height,
                     NULL, NULL, NULL, NULL);
  draw_style_common (arrow_context, cr, contents_x, contents_y, contents_width, contents_height,
                     NULL, NULL, NULL, NULL);
  gtk_render_arrow (arrow_context, cr, G_PI / 2,
                    contents_x + contents_width - arrow_size,
                    contents_y + (contents_height - arrow_size) / 2, arrow_size);

  g_object_unref (arrow_context);
  if (has_entry)
    g_object_unref (entry_context);
  g_object_unref (button_context);
  g_object_unref (combo_context);
}
Exemplo n.º 8
0
static void
draw_menu (GtkWidget *widget,
           cairo_t   *cr,
           gint       x,
           gint       y,
           gint       width,
           gint      *height)
{
  GtkStyleContext *menu_context;
  GtkStyleContext *menuitem_context;
  GtkStyleContext *hovermenuitem_context;
  GtkStyleContext *hoveredarrowmenuitem_context;
  GtkStyleContext *arrowmenuitem_context;
  GtkStyleContext *checkmenuitem_context;
  GtkStyleContext *disabledarrowmenuitem_context;
  GtkStyleContext *disabledcheckmenuitem_context;
  GtkStyleContext *radiomenuitem_context;
  GtkStyleContext *disablemenuitem_context;
  GtkStyleContext *disabledradiomenuitem_context;
  GtkStyleContext *separatormenuitem_context;
  gint menuitem1_height, menuitem2_height, menuitem3_height, menuitem4_height, menuitem5_height;
  gint contents_x, contents_y, contents_width, contents_height;
  gint menu_x, menu_y, menu_width, menu_height;
  gint arrow_width, arrow_height, arrow_size;
  gint toggle_x, toggle_y, toggle_width, toggle_height;

  /* This information is taken from the GtkMenu docs, see "CSS nodes" */
  menu_context = get_style (gtk_widget_get_style_context(widget), "menu");
  hovermenuitem_context = get_style (menu_context, "menuitem:hover");
  hoveredarrowmenuitem_context = get_style (hovermenuitem_context, "arrow.right:dir(ltr)");
  menuitem_context = get_style (menu_context, "menuitem");
  arrowmenuitem_context = get_style (menuitem_context, "arrow:dir(rtl)");
  disablemenuitem_context = get_style (menu_context, "menuitem:disabled");
  disabledarrowmenuitem_context = get_style (disablemenuitem_context, "arrow:dir(rtl)");
  checkmenuitem_context = get_style (menuitem_context, "check:checked");
  disabledcheckmenuitem_context = get_style (disablemenuitem_context, "check");
  separatormenuitem_context = get_style (menu_context, "separator:disabled");
  radiomenuitem_context = get_style (menuitem_context, "radio:checked");
  disabledradiomenuitem_context = get_style (disablemenuitem_context, "radio");

  *height = 0;
  query_size (menu_context, NULL, height);
  menuitem1_height = 0;
  query_size (hovermenuitem_context, NULL, &menuitem1_height);
  query_size (hoveredarrowmenuitem_context, NULL, &menuitem1_height);
  *height += menuitem1_height;
  menuitem2_height = 0;
  query_size (menu_context, NULL, &menuitem5_height);
  query_size (menuitem_context, NULL, &menuitem2_height);
  query_size (arrowmenuitem_context, NULL, &menuitem2_height);
  query_size (disabledarrowmenuitem_context, NULL, &menuitem2_height);
  *height += menuitem2_height;
  menuitem3_height = 0;
  query_size (menu_context, NULL, &menuitem5_height);
  query_size (menuitem_context, NULL, &menuitem3_height);
  query_size (checkmenuitem_context, NULL, &menuitem3_height);
  query_size (disabledcheckmenuitem_context, NULL, &menuitem3_height);
  *height += menuitem3_height;
  menuitem4_height = 0;
  query_size (menu_context, NULL, &menuitem5_height);
  query_size (separatormenuitem_context, NULL, &menuitem4_height);
  *height += menuitem4_height;
  menuitem5_height = 0;
  query_size (menu_context, NULL, &menuitem5_height);
  query_size (menuitem_context, NULL, &menuitem5_height);
  query_size (radiomenuitem_context, NULL, &menuitem5_height);
  query_size (disabledradiomenuitem_context, NULL, &menuitem5_height);
  *height += menuitem5_height;

  draw_style_common (menu_context, cr, x, y, width, *height,
                     &menu_x, &menu_y, &menu_width, &menu_height);

  /* Hovered with right arrow */
  gtk_style_context_get (hoveredarrowmenuitem_context,
                         "min-width", &arrow_width, "min-height", &arrow_height, NULL);
  arrow_size = MIN (arrow_width, arrow_height);
  draw_style_common (hovermenuitem_context, cr, menu_x, menu_y, menu_width, menuitem1_height,
                     &contents_x, &contents_y, &contents_width, &contents_height);
  gtk_render_arrow (hoveredarrowmenuitem_context, cr, G_PI / 2,
                    contents_x + contents_width - arrow_size,
                    contents_y + (contents_height - arrow_size) / 2, arrow_size);

  /* Left arrow sensitive, and right arrow insensitive */
  draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height, menu_width, menuitem2_height,
                     &contents_x, &contents_y, &contents_width, &contents_height);
  gtk_style_context_get (arrowmenuitem_context,
                         "min-width", &arrow_width, "min-height", &arrow_height, NULL);
  arrow_size = MIN (arrow_width, arrow_height);
  gtk_render_arrow (arrowmenuitem_context, cr, G_PI / 2,
                    contents_x,
                    contents_y + (contents_height - arrow_size) / 2, arrow_size);
  gtk_style_context_get (disabledarrowmenuitem_context,
                         "min-width", &arrow_width, "min-height", &arrow_height, NULL);
  arrow_size = MIN (arrow_width, arrow_height);
  gtk_render_arrow (disabledarrowmenuitem_context, cr, G_PI / 2,
                    contents_x + contents_width - arrow_size,
                    contents_y + (contents_height - arrow_size) / 2, arrow_size);


  /* Left check enabled, sensitive, and right check unchecked, insensitive */
  draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height, menu_width, menuitem3_height,
                     &contents_x, &contents_y, &contents_width, &contents_height);
  gtk_style_context_get (checkmenuitem_context,
                         "min-width", &toggle_width, "min-height", &toggle_height, NULL);
  draw_style_common (checkmenuitem_context, cr,
                     contents_x,
                     contents_y,
                     toggle_width, toggle_height,
                     &toggle_x, &toggle_y, &toggle_width, &toggle_height);
  gtk_render_check (checkmenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
  gtk_style_context_get (disabledcheckmenuitem_context,
                         "min-width", &toggle_width, "min-height", &toggle_height, NULL);
  draw_style_common (disabledcheckmenuitem_context, cr,
                     contents_x + contents_width - toggle_width,
                     contents_y,
                     toggle_width, toggle_height,
                     &toggle_x, &toggle_y, &toggle_width, &toggle_height);
  gtk_render_check (disabledcheckmenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);

  /* Separator */
  draw_style_common (separatormenuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height + menuitem3_height,
                     menu_width, menuitem4_height,
                     NULL, NULL, NULL, NULL);

  /* Left check enabled, sensitive, and right check unchecked, insensitive */
  draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height + menuitem3_height + menuitem4_height,
                     menu_width, menuitem5_height,
                     &contents_x, &contents_y, &contents_width, &contents_height);
  gtk_style_context_get (radiomenuitem_context,
                         "min-width", &toggle_width, "min-height", &toggle_height, NULL);
  draw_style_common (radiomenuitem_context, cr,
                     contents_x,
                     contents_y,
                     toggle_width, toggle_height,
                     &toggle_x, &toggle_y, &toggle_width, &toggle_height);
  gtk_render_check (radiomenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
  gtk_style_context_get (disabledradiomenuitem_context,
                         "min-width", &toggle_width, "min-height", &toggle_height, NULL);
  draw_style_common (disabledradiomenuitem_context, cr,
                     contents_x + contents_width - toggle_width,
                     contents_y,
                     toggle_width, toggle_height,
                     &toggle_x, &toggle_y, &toggle_width, &toggle_height);
  gtk_render_check (disabledradiomenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);

  g_object_unref (menu_context);
  g_object_unref (menuitem_context);
  g_object_unref (hovermenuitem_context);
  g_object_unref (hoveredarrowmenuitem_context);
  g_object_unref (arrowmenuitem_context);
  g_object_unref (checkmenuitem_context);
  g_object_unref (disabledarrowmenuitem_context);
  g_object_unref (disabledcheckmenuitem_context);
  g_object_unref (radiomenuitem_context);
  g_object_unref (disablemenuitem_context);
  g_object_unref (disabledradiomenuitem_context);
  g_object_unref (separatormenuitem_context);
}
Exemplo n.º 9
0
static gboolean
gtk_tearoff_menu_item_draw (GtkWidget *widget,
                            cairo_t   *cr)
{
    GtkMenuItem *menu_item;
    GtkStateFlags state;
    GtkStyleContext *context;
    GtkBorder padding;
    gint x, y, width, height;
    gint right_max;
    guint border_width;
    GtkTextDirection direction;
    GtkWidget *parent;
    gdouble angle;

    menu_item = GTK_MENU_ITEM (widget);
    context = gtk_widget_get_style_context (widget);
    direction = gtk_widget_get_direction (widget);
    state = gtk_widget_get_state_flags (widget);

    border_width = gtk_container_get_border_width (GTK_CONTAINER (menu_item));
    x = border_width;
    y = border_width;
    width = gtk_widget_get_allocated_width (widget) - border_width * 2;
    height = gtk_widget_get_allocated_height (widget) - border_width * 2;
    right_max = x + width;

    gtk_style_context_save (context);
    gtk_style_context_set_state (context, state);
    gtk_style_context_get_padding (context, state, &padding);

    if (state & GTK_STATE_FLAG_PRELIGHT)
    {
        gtk_render_background (context, cr, x, y, width, height);
        gtk_render_frame (context, cr, x, y, width, height);
    }

    parent = gtk_widget_get_parent (widget);
    if (GTK_IS_MENU (parent) && gtk_menu_get_tearoff_state (GTK_MENU (parent)))
    {
        gint arrow_x;

        if (menu_item->priv->toggle_size > ARROW_SIZE)
        {
            if (direction == GTK_TEXT_DIR_LTR)
            {
                arrow_x = x + (menu_item->priv->toggle_size - ARROW_SIZE)/2;
                angle = (3 * G_PI) / 2;
            }
            else
            {
                arrow_x = x + width - menu_item->priv->toggle_size + (menu_item->priv->toggle_size - ARROW_SIZE)/2;
                angle = G_PI / 2;
            }
            x += menu_item->priv->toggle_size + BORDER_SPACING;
        }
        else
        {
            if (direction == GTK_TEXT_DIR_LTR)
            {
                arrow_x = ARROW_SIZE / 2;
                angle = (3 * G_PI) / 2;
            }
            else
            {
                arrow_x = x + width - 2 * ARROW_SIZE + ARROW_SIZE / 2;
                angle = G_PI / 2;
            }
            x += 2 * ARROW_SIZE;
        }

        gtk_render_arrow (context, cr, angle,
                          arrow_x, height / 2 - 5,
                          ARROW_SIZE);
    }

    while (x < right_max)
    {
        gint x1, x2;

        if (direction == GTK_TEXT_DIR_LTR)
        {
            x1 = x;
            x2 = MIN (x + TEAR_LENGTH, right_max);
        }
        else
        {
            x1 = right_max - x;
            x2 = MAX (right_max - x - TEAR_LENGTH, 0);
        }

        gtk_render_line (context, cr,
                         x1, y + (height - padding.bottom) / 2,
                         x2, y + (height - padding.bottom) / 2);
        x += 2 * TEAR_LENGTH;
    }

    gtk_style_context_restore (context);

    return FALSE;
}