static void internal_text_get_size_layout(GtkCellRenderer *cell,
        GtkWidget       *widget,
        PangoLayout     *layout,
        const GdkRectangle    *cell_area,
        gint            *x_offset,
        gint            *y_offset,
        gint            *width,
        gint            *height)
{
    CustomCellRendererFlexi *cellflexi = CUSTOM_CELL_RENDERER_FLEXI (cell);
    PangoRectangle rect;
    gint calc_width;
    gint calc_height;
    gint xpad;
    gint ypad;
    gfloat yalign;

    if (layout==NULL)
        layout = internal_text_create_layout(widget,cellflexi);
    else
        g_object_ref(layout);

    g_assert(layout!=NULL);

    pango_layout_get_pixel_extents(layout,NULL,&rect);

    gtk_cell_renderer_get_padding(cell,&xpad,&ypad);

    calc_width  = xpad * 2 + rect.width;
    calc_height = ypad * 2 + rect.height;

    if (width)
    {
        *width = calc_width;
    }

    if (height)
    {
        *height = calc_height;
    }

    if (cell_area)
    {
        if (x_offset)
        {
            *x_offset = 0;
        }

        if (y_offset)
        {
            gtk_cell_renderer_get_alignment(cell,NULL,&yalign);
            *y_offset = yalign * (cell_area->height - calc_height);
            *y_offset = MAX (*y_offset, 0);
        }
    }
    g_object_unref(layout);
}
static void
gimp_cell_renderer_dashes_get_size (GtkCellRenderer    *cell,
                                    GtkWidget          *widget,
                                    const GdkRectangle *cell_area,
                                    gint               *x_offset,
                                    gint               *y_offset,
                                    gint               *width,
                                    gint               *height)
{
  gfloat xalign, yalign;
  gint   xpad, ypad;

  gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);

  if (cell_area)
    {
      if (x_offset)
        {
          gdouble align;

          align = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
                   1.0 - xalign : xalign);

          *x_offset = align * (cell_area->width - DASHES_WIDTH);
          *x_offset = MAX (*x_offset, 0) + xpad;
        }

      if (y_offset)
        {
          *y_offset = yalign * (cell_area->height - DASHES_HEIGHT);
          *y_offset = MAX (*y_offset, 0) + ypad;
        }
    }
  else
    {
      if (x_offset)
        *x_offset = 0;

      if (y_offset)
        *y_offset = 0;
    }

  *width  = DASHES_WIDTH  + 2 * xpad;
  *height = DASHES_HEIGHT + 2 * ypad;
}
static void
gossip_cell_renderer_expander_get_size (GtkCellRenderer     *cell,
                                        GtkWidget           *widget,
                                        const GdkRectangle  *cell_area,
                                        gint                *x_offset,
                                        gint                *y_offset,
                                        gint                *width,
                                        gint                *height)
{
    GossipCellRendererExpander     *expander;
    GossipCellRendererExpanderPriv *priv;
    gint                            xpad, ypad;
    gfloat                          xalign, yalign;

    expander = (GossipCellRendererExpander*) cell;
    priv = GET_PRIV (expander);
    gtk_cell_renderer_get_padding (cell, &xpad, &ypad);

    if (cell_area) {

        gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);

        if (x_offset) {
            *x_offset = xalign * (cell_area->width - (priv->expander_size + (2 * xpad)));
            *x_offset = MAX (*x_offset, 0);
        }

        if (y_offset) {
            *y_offset = yalign * (cell_area->height - (priv->expander_size + (2 * ypad)));
            *y_offset = MAX (*y_offset, 0);
        }
    } else {
        if (x_offset)
            *x_offset = 0;

        if (y_offset)
            *y_offset = 0;
    }

    if (width)
        *width = xpad * 2 + priv->expander_size;

    if (height)
        *height = ypad * 2 + priv->expander_size;
}
/*! \brief Calculates the window area the renderer will use */
static void
ghid_cell_renderer_visibility_get_size (GtkCellRenderer *cell,
                                        GtkWidget       *widget,
                                        GdkRectangle    *cell_area,
                                        gint            *x_offset,
                                        gint            *y_offset,
                                        gint            *width,
                                        gint            *height)
{
  GtkStyle *style = gtk_widget_get_style (widget);
  gint w, h;
  gint xpad, ypad;
  gfloat xalign, yalign;

  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
  gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);

  w = VISIBILITY_TOGGLE_SIZE + 2 * (xpad + style->xthickness);
  h = VISIBILITY_TOGGLE_SIZE + 2 * (ypad + style->ythickness);

  if (width)
    *width = w;
  if (height)
    *height = h;

  if (cell_area)
    {
      if (x_offset)
        {
          if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
            xalign = 1. - xalign;
          *x_offset = MAX (0, xalign * (cell_area->width - w));
        }
      if (y_offset)
        *y_offset = MAX(0, yalign * (cell_area->height - h));
    }
}
static gint
gtk_text_cell_accessible_get_offset_at_point (AtkText      *text,
                                              gint          x,
                                              gint          y,
                                              AtkCoordType  coords)
{
  AtkObject *parent;
  GtkRendererCellAccessible *gail_renderer;
  GtkCellRendererText *gtk_renderer;
  GtkRequisition min_size;
  GtkWidget *widget;
  GdkRectangle rendered_rect;
  PangoLayout *layout;
  gchar *renderer_text;
  gfloat xalign, yalign;
  gint x_offset, y_offset, index;
  gint xpad, ypad;
  gint x_window, y_window, x_toplevel, y_toplevel;
  gint x_temp, y_temp;
  gboolean ret;

  if (!GTK_TEXT_CELL_ACCESSIBLE (text)->cell_text)
    return -1;

  gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text);
  gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer);
  parent = atk_object_get_parent (ATK_OBJECT (text));

  g_object_get (gtk_renderer, "text", &renderer_text, NULL);
  if (text == NULL)
    {
      g_free (renderer_text);
      return -1;
    }

  if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
    parent = atk_object_get_parent (parent);

  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));

  g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent), -1);
  _gtk_cell_accessible_parent_get_cell_area (GTK_CELL_ACCESSIBLE_PARENT (parent),
                                             GTK_CELL_ACCESSIBLE (text),
                                             &rendered_rect);

  gtk_cell_renderer_get_preferred_size (GTK_CELL_RENDERER (gtk_renderer),
                                        widget,
                                        &min_size, NULL);
  gtk_cell_renderer_get_alignment (GTK_CELL_RENDERER (gtk_renderer), &xalign, &yalign);
  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
    xalign = 1.0 - xalign;
  x_offset = MAX (0, xalign * (rendered_rect.width - min_size.width));
  y_offset = MAX (0, yalign * (rendered_rect.height - min_size.height));

  layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text));

  gtk_cell_renderer_get_padding (gail_renderer->renderer, &xpad, &ypad);

  get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel);

  x_temp =  x - (x_offset + rendered_rect.x + xpad) - x_window;
  y_temp =  y - (y_offset + rendered_rect.y + ypad) - y_window;
  if (coords == ATK_XY_WINDOW)
    {
      x_temp += x_toplevel;
      y_temp += y_toplevel;
    }
  else if (coords != ATK_XY_SCREEN)
    index = -1;

  ret = pango_layout_xy_to_index (layout,
                                  x_temp * PANGO_SCALE,
                                  y_temp * PANGO_SCALE,
                                  &index, NULL);
  if (!ret)
    {
      if (x_temp < 0 || y_temp < 0)
        index = 0;
      else
        index = -1;
    }

  g_object_unref (layout);
  if (index == -1)
    {
      if (coords == ATK_XY_WINDOW || coords == ATK_XY_SCREEN)
        {
          glong length;

          length = g_utf8_strlen (renderer_text, -1);
          g_free (renderer_text);

          return length;
        }

      g_free (renderer_text);

      return index;
    }
  else
    {
      glong offset;

      offset = g_utf8_pointer_to_offset (renderer_text,
                                         renderer_text + index);
      g_free (renderer_text);

      return offset;
    }
}
static void
gtk_text_cell_accessible_get_character_extents (AtkText      *text,
                                                gint          offset,
                                                gint         *x,
                                                gint         *y,
                                                gint         *width,
                                                gint         *height,
                                                AtkCoordType  coords)
{
  GtkRendererCellAccessible *gail_renderer;
  GtkRequisition min_size;
  GtkCellRendererText *gtk_renderer;
  GdkRectangle rendered_rect;
  GtkWidget *widget;
  AtkObject *parent;
  PangoRectangle char_rect;
  PangoLayout *layout;
  gchar *renderer_text;
  gfloat xalign, yalign;
  gint x_offset, y_offset, index;
  gint xpad, ypad;
  gint x_window, y_window, x_toplevel, y_toplevel;

  if (!GTK_TEXT_CELL_ACCESSIBLE (text)->cell_text)
    {
      *x = *y = *height = *width = 0;
      return;
    }
  if (offset < 0 || offset >= GTK_TEXT_CELL_ACCESSIBLE (text)->cell_length)
    {
      *x = *y = *height = *width = 0;
      return;
    }
  gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text);
  gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer);

  g_object_get (gtk_renderer, "text", &renderer_text, NULL);
  if (text == NULL)
    {
      g_free (renderer_text);
      return;
    }

  parent = atk_object_get_parent (ATK_OBJECT (text));
  if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
    parent = atk_object_get_parent (parent);
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
  g_return_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent));
  _gtk_cell_accessible_parent_get_cell_area (GTK_CELL_ACCESSIBLE_PARENT (parent),
                                             GTK_CELL_ACCESSIBLE (text),
                                             &rendered_rect);

  gtk_cell_renderer_get_preferred_size (GTK_CELL_RENDERER (gtk_renderer),
                                        widget,
                                        &min_size, NULL);

  gtk_cell_renderer_get_alignment (GTK_CELL_RENDERER (gtk_renderer), &xalign, &yalign);
  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
    xalign = 1.0 - xalign;
  x_offset = MAX (0, xalign * (rendered_rect.width - min_size.width));
  y_offset = MAX (0, yalign * (rendered_rect.height - min_size.height));

  layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text));

  index = g_utf8_offset_to_pointer (renderer_text, offset) - renderer_text;
  pango_layout_index_to_pos (layout, index, &char_rect);

  gtk_cell_renderer_get_padding (gail_renderer->renderer, &xpad, &ypad);

  get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel);

  *x = (char_rect.x / PANGO_SCALE) + x_offset + rendered_rect.x + xpad + x_window;
  *y = (char_rect.y / PANGO_SCALE) + y_offset + rendered_rect.y + ypad + y_window;
  *height = char_rect.height / PANGO_SCALE;
  *width = char_rect.width / PANGO_SCALE;

  if (coords == ATK_XY_WINDOW)
    {
      *x -= x_toplevel;
      *y -= y_toplevel;
    }
  else if (coords != ATK_XY_SCREEN)
    {
      *x = 0;
      *y = 0;
      *height = 0;
      *width = 0;
    }

  g_free (renderer_text);
  g_object_unref (layout);
}
static void
gimp_cell_renderer_toggle_get_size (GtkCellRenderer *cell,
                                    GtkWidget       *widget,
                                    GdkRectangle    *cell_area,
                                    gint            *x_offset,
                                    gint            *y_offset,
                                    gint            *width,
                                    gint            *height)
{
  GimpCellRendererToggle *toggle = GIMP_CELL_RENDERER_TOGGLE (cell);
  GtkStyle               *style  = gtk_widget_get_style (widget);
  gint                    calc_width;
  gint                    calc_height;
  gint                    pixbuf_width;
  gint                    pixbuf_height;
  gfloat                  xalign;
  gfloat                  yalign;
  gint                    xpad;
  gint                    ypad;

  if (! toggle->stock_id)
    {
      GTK_CELL_RENDERER_CLASS (parent_class)->get_size (cell,
                                                        widget,
                                                        cell_area,
                                                        x_offset, y_offset,
                                                        width, height);
      return;
    }

  gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);

  if (! toggle->pixbuf)
    gimp_cell_renderer_toggle_create_pixbuf (toggle, widget);

  pixbuf_width  = gdk_pixbuf_get_width  (toggle->pixbuf);
  pixbuf_height = gdk_pixbuf_get_height (toggle->pixbuf);

  calc_width  = (pixbuf_width +
                 (gint) xpad * 2 + style->xthickness * 2);
  calc_height = (pixbuf_height +
                 (gint) ypad * 2 + style->ythickness * 2);

  if (width)
    *width  = calc_width;

  if (height)
    *height = calc_height;

  if (cell_area)
    {
      if (x_offset)
        {
          *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
                        (1.0 - xalign) : xalign) *
                       (cell_area->width - calc_width));
          *x_offset = MAX (*x_offset, 0);
        }

      if (y_offset)
        {
          *y_offset = yalign * (cell_area->height - calc_height);
          *y_offset = MAX (*y_offset, 0);
        }
    }
}
static void
gd_two_lines_renderer_get_size (GtkCellRenderer *cell,
                                GtkWidget *widget,
                                PangoLayout *layout_1,
                                PangoLayout *layout_2,
                                gint *width,
                                gint *height,
                                const GdkRectangle *cell_area,
                                gint *x_offset_1,
                                gint *x_offset_2,
                                gint *y_offset)
{
  GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
  gint xpad, ypad;
  PangoLayout *layout_one, *layout_two;
  GdkRectangle layout_one_rect, layout_two_rect, layout_union;

  if (layout_1 == NULL)
    {
      gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two);
    }
  else
    {
      layout_one = g_object_ref (layout_1);

      if (layout_2 != NULL)
        layout_two = g_object_ref (layout_2);
      else
        layout_two = NULL;
    }

  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
  pango_layout_get_pixel_extents (layout_one, NULL, (PangoRectangle *) &layout_one_rect);

  if (layout_two != NULL)
    {
      pango_layout_get_pixel_extents (layout_two, NULL, (PangoRectangle *) &layout_two_rect);

      layout_union.width = MAX (layout_one_rect.width, layout_two_rect.width);
      layout_union.height = layout_one_rect.height + layout_two_rect.height;
    }
  else
    {
      layout_union = layout_one_rect;
    }

  if (cell_area)
    {
      gfloat xalign, yalign;

      gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);

      layout_union.width  = MIN (layout_union.width, cell_area->width - 2 * xpad);
      layout_union.height = MIN (layout_union.height, cell_area->height - 2 * ypad);

      if (x_offset_1)
	{
	  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
	    *x_offset_1 = (1.0 - xalign) * (cell_area->width - (layout_one_rect.width + (2 * xpad)));
	  else 
	    *x_offset_1 = xalign * (cell_area->width - (layout_one_rect.width + (2 * xpad)));

          *x_offset_1 = MAX (*x_offset_1, 0);
	}
      if (x_offset_2)
        {
          if (layout_two != NULL)
            {
              if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
                *x_offset_2 = (1.0 - xalign) * (cell_area->width - (layout_two_rect.width + (2 * xpad)));
              else 
                *x_offset_2 = xalign * (cell_area->width - (layout_two_rect.width + (2 * xpad)));

              *x_offset_2 = MAX (*x_offset_2, 0);
            }
          else
            {
              *x_offset_2 = 0;
            }
        }

      if (y_offset)
	{
	  *y_offset = yalign * (cell_area->height - (layout_union.height + (2 * ypad)));
	  *y_offset = MAX (*y_offset, 0);
	}
    }
  else
    {
      if (x_offset_1) *x_offset_1 = 0;
      if (x_offset_2) *x_offset_2 = 0;
      if (y_offset) *y_offset = 0;
    }

  g_clear_object (&layout_one);
  g_clear_object (&layout_two);

  if (height)
    *height = ypad * 2 + layout_union.height;

  if (width)
    *width = xpad * 2 + layout_union.width;
}
Beispiel #9
0
static GtkCellEditable*
marlin_text_renderer_start_editing (GtkCellRenderer     *cell,
                                    GdkEvent            *event,
                                    GtkWidget           *widget,
                                    const gchar         *path,
                                    const GdkRectangle  *background_area,
                                    const GdkRectangle  *cell_area,
                                    GtkCellRendererState flags)
{
    MarlinTextRenderer *text_renderer = MARLIN_TEXT_RENDERER (cell);
    gint xpad, ypad;
    gfloat xalign, yalign;
    gboolean mode, visible;

    /* verify that we are visible & editable */
    g_object_get (cell, "visible", &visible, "mode", &mode, NULL);
    if (!(visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE))
        return NULL;
    //g_message ("%s %s\n", G_STRFUNC, path);

    gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);

    /* allocate a new text entry widget to be used for editing */
    /*text_renderer->entry = g_object_new (GTK_TYPE_ENTRY,
                                         "has-frame", FALSE,
                                         "text", text_renderer->text,
                                         "visible", TRUE,
                                         "xalign", xalign,
                                         NULL);*/
    text_renderer->entry = eel_editable_label_new ("Test text");
    eel_editable_label_set_line_wrap (EEL_EDITABLE_LABEL (text_renderer->entry), TRUE);
    eel_editable_label_set_line_wrap_mode (EEL_EDITABLE_LABEL (text_renderer->entry), text_renderer->wrap_mode);
    eel_editable_label_set_draw_outline (EEL_EDITABLE_LABEL (text_renderer->entry), TRUE);

    /* presume we're in POSITION UNDER */
    if (text_renderer->wrap_width > 0)
        eel_editable_label_set_justify (EEL_EDITABLE_LABEL (text_renderer->entry), GTK_JUSTIFY_CENTER);

    //gtk_misc_set_alignment (GTK_MISC (text_renderer->entry), xalign, yalign);
    g_object_set (text_renderer->entry, "yalign", yalign, NULL);
    gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
    gtk_misc_set_padding (GTK_MISC (text_renderer->entry), xpad, ypad);

    if (text_renderer->zoom_level < MARLIN_ZOOM_LEVEL_NORMAL)
        g_object_set (text_renderer->entry, "small-size", TRUE, NULL);

    gtk_widget_set_size_request (text_renderer->entry, text_renderer->wrap_width, -1);
    eel_editable_label_set_text (EEL_EDITABLE_LABEL (text_renderer->entry),
                                 text_renderer->text);
    gtk_widget_show (text_renderer->entry);

    /* remember the tree path that we're editing */
    g_object_set_data_full (G_OBJECT (text_renderer->entry), "marlin-text-renderer-path", g_strdup (path), g_free);

    /* connect required signals */
    g_signal_connect (G_OBJECT (text_renderer->entry), "editing-done", G_CALLBACK (marlin_text_renderer_editing_done), text_renderer);
    g_signal_connect (G_OBJECT (text_renderer->entry), "focus-out-event", G_CALLBACK (marlin_text_renderer_focus_out_event), text_renderer);
    g_signal_connect (G_OBJECT (text_renderer->entry), "populate-popup", G_CALLBACK (marlin_text_renderer_populate_popup), text_renderer);

    return GTK_CELL_EDITABLE (text_renderer->entry);
}
Beispiel #10
0
static void
marlin_text_renderer_render (GtkCellRenderer    *cell,
                             cairo_t            *cr,
                             GtkWidget          *widget,
                             const GdkRectangle *background_area,
                             const GdkRectangle *cell_area,
                             GtkCellRendererState flags)
{
    MarlinTextRenderer *text_renderer = MARLIN_TEXT_RENDERER (cell);
    GtkStyleContext *context;
    GtkStateFlags state;
    gint x0, x1, y0, y1;
    gint text_width;
    gint text_height;
    gint x_offset;
    gint y_offset;
    gint xpad, ypad;
    gfloat xalign, yalign;
    gboolean selected;

    /* setup the new widget */
    marlin_text_renderer_set_widget (text_renderer, widget);

    state = gtk_widget_get_state_flags (widget);
    if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
    {
        state |= GTK_STATE_FLAG_SELECTED;
    }
    else if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT
             && gtk_widget_get_state (widget) == GTK_STATE_PRELIGHT)
    {
        state = GTK_STATE_PRELIGHT;
    }
    else
    {
        state = gtk_widget_get_sensitive (widget) ? GTK_STATE_FLAG_NORMAL : GTK_STATE_INSENSITIVE;
    }

    /* render small/normal text depending on the zoom_level */
    if (text_renderer->zoom_level < MARLIN_ZOOM_LEVEL_NORMAL)
    {
        if (text_renderer->follow_prelit && (flags & GTK_CELL_RENDERER_PRELIT) != 0)
            pango_layout_set_attributes (text_renderer->layout, eel_pango_attr_list_small_underline_single ());
        else
            pango_layout_set_attributes (text_renderer->layout, eel_pango_attr_list_small ());
    } else {
        if (text_renderer->follow_prelit && (flags & GTK_CELL_RENDERER_PRELIT) != 0)
            pango_layout_set_attributes (text_renderer->layout, eel_pango_attr_list_underline_single ());
        else
            pango_layout_set_attributes (text_renderer->layout, NULL);
    }

    /* setup the wrapping */
    if (text_renderer->wrap_width < 0)
    {
        pango_layout_set_width (text_renderer->layout, -1);
        pango_layout_set_wrap (text_renderer->layout, PANGO_WRAP_CHAR);
    }
    else
    {
        pango_layout_set_width (text_renderer->layout, text_renderer->wrap_width * PANGO_SCALE);
        pango_layout_set_wrap (text_renderer->layout, text_renderer->wrap_mode);
    }

    /* ellipsize to max lines except for selected or prelit items */
    pango_layout_set_ellipsize (text_renderer->layout, PANGO_ELLIPSIZE_END);
    pango_layout_set_height (text_renderer->layout, -3);
    if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED ||
            (flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT) {
        pango_layout_set_ellipsize (text_renderer->layout, PANGO_ELLIPSIZE_NONE);
    }

    gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
    if (xalign == 0.5f)
        pango_layout_set_alignment (text_renderer->layout, PANGO_ALIGN_CENTER);

    pango_layout_set_text (text_renderer->layout, text_renderer->text, -1);

    /* calculate the real text dimension */
    pango_layout_get_pixel_size (text_renderer->layout, &text_width, &text_height);


    /* take into account the state indicator (required for calculation) */
    if (text_renderer->follow_state)
    {
        text_width += 2 * text_renderer->focus_width;
        text_height += 2 * text_renderer->focus_width;
    }

    gtk_cell_renderer_get_padding (cell, &xpad, &ypad);

    /* calculate the real x-offset */
    x_offset = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? (1.0 - xalign) : xalign)
               * (cell_area->width - text_width - (2 * xpad));
    x_offset = MAX (x_offset, 0);

    /* calculate the real y-offset */
    y_offset = yalign * (cell_area->height - text_height - (2 * ypad));
    y_offset = MAX (y_offset, 0);

    context = gtk_widget_get_style_context (gtk_widget_get_parent (widget));
    gtk_style_context_save (context);
    gtk_style_context_set_state (context, state);

    selected = ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED && text_renderer->follow_state);

    /* render the state indicator */
    if (selected || text_renderer->background != NULL)
    {
        /* calculate the text bounding box (including the focus padding/width) */
        x0 = cell_area->x + x_offset;
        y0 = cell_area->y + y_offset;
        x1 = x0 + text_width;
        y1 = y0 + text_height;

        cairo_move_to (cr, x0 + 5, y0);
        cairo_line_to (cr, x1 - 5, y0);
        cairo_curve_to (cr, x1 - 5, y0, x1, y0, x1, y0 + 5);
        cairo_line_to (cr, x1, y1 - 5);
        cairo_curve_to (cr, x1, y1 - 5, x1, y1, x1 - 5, y1);
        cairo_line_to (cr, x0 + 5, y1);
        cairo_curve_to (cr, x0 + 5, y1, x0, y1, x0, y1 - 5);
        cairo_line_to (cr, x0, y0 + 5);
        cairo_curve_to (cr, x0, y0 + 5, x0, y0, x0 + 5, y0);

        GdkRGBA color;

        if(text_renderer->background != NULL && !selected)
        {
            if(!gdk_rgba_parse(&color, text_renderer->background))
            {
                g_critical("Can't parse this color value: %s", text_renderer->background);
                gtk_style_context_get_background_color (context, state, &color);
            }

        }
        else
        {
            gtk_style_context_get_background_color (context, state, &color);
        }
        gdk_cairo_set_source_rgba (cr, &color);
        cairo_fill (cr);
    }

    /* draw the focus indicator */
    if (text_renderer->follow_state && (flags & GTK_CELL_RENDERER_FOCUSED) != 0)
    {
        gtk_render_focus (context, cr, cell_area->x + x_offset, cell_area->y + y_offset, text_width, text_height);
    }

    /* get proper sizing for the layout drawing */
    if (text_renderer->follow_state)
    {
        text_width -= 2 * text_renderer->focus_width;
        text_height -= 2 * text_renderer->focus_width;
        x_offset += text_renderer->focus_width;
        y_offset += text_renderer->focus_width;
    }

    /* draw the text */
    if (xalign == 0.5f)
        x_offset = (cell_area->width - text_renderer->wrap_width)/2;

    gtk_render_layout (context, cr,
                       cell_area->x + x_offset + xpad,
                       cell_area->y + y_offset + ypad,
                       text_renderer->layout);

    gtk_style_context_restore (context);
}
Beispiel #11
0
static void
marlin_text_renderer_get_size (GtkCellRenderer      *cell,
                               GtkWidget            *widget,
                               const GdkRectangle   *cell_area,
                               gint                 *x_offset,
                               gint                 *y_offset,
                               gint                 *width,
                               gint                 *height)
{
    MarlinTextRenderer *text_renderer = MARLIN_TEXT_RENDERER (cell);
    gint text_length;
    gint text_width;
    gint text_height;
    gint xpad, ypad;

    /* setup the new widget */
    marlin_text_renderer_set_widget (text_renderer, widget);

    gfloat xalign, yalign;
    gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);

    /* we can guess the dimensions if we don't wrap */
    if (text_renderer->wrap_width < 0)
    {
        /* determine the text_length in characters */
        text_length = g_utf8_strlen (text_renderer->text, -1);

        /* the approximation is usually 1-2 chars wrong, so wth */
        text_length += 2;

        /* calculate the appromixate text width/height */
        text_width = text_renderer->char_width * text_length;
        text_height = text_renderer->char_height;
    }
    else
    {
        /* calculate the real text dimension */
        pango_layout_set_ellipsize (text_renderer->layout, PANGO_ELLIPSIZE_END);
        pango_layout_set_height (text_renderer->layout, -3);
        pango_layout_set_width (text_renderer->layout, text_renderer->wrap_width * PANGO_SCALE);
        pango_layout_set_wrap (text_renderer->layout, text_renderer->wrap_mode);
        pango_layout_set_text (text_renderer->layout, text_renderer->text, -1);
        if (xalign == 0.5f)
            pango_layout_set_alignment (text_renderer->layout, PANGO_ALIGN_CENTER);

        pango_layout_get_pixel_size (text_renderer->layout, &text_width, &text_height);
    }

    /* if we have to follow the state manually, we'll need
     * to reserve some space to render the indicator to.
     */
    if (text_renderer->follow_state)
    {
        text_width += 2 * text_renderer->focus_width;
        text_height += 2 * text_renderer->focus_width;
    }

    gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
    /* update width/height */
    if (G_LIKELY (width != NULL))
        *width = text_width + 2 * xpad;
    if (G_LIKELY (height != NULL))
        *height = text_height + 2 * ypad;

    /* update the x/y offsets */
    if (G_LIKELY (cell_area != NULL))
    {
        /*gfloat xalign, yalign;
        gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);*/
        if (G_LIKELY (x_offset != NULL))
        {
            *x_offset = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
                         (1.0 - xalign) : xalign) *
                        (cell_area->width - text_width - (2 * xpad));
            *x_offset = MAX (*x_offset, 0);
        }

        if (G_LIKELY (y_offset != NULL))
        {
            *y_offset = yalign * (cell_area->height - text_height - (2 * ypad));
            *y_offset = MAX (*y_offset, 0);
        }
    }
}
Beispiel #12
0
static void fm_cell_renderer_text_render(GtkCellRenderer *cell,
                                         GdkDrawable *window,
                                         GtkWidget *widget,
                                         GdkRectangle *background_area,
                                         GdkRectangle *cell_area,
                                         GdkRectangle *expose_area,
                                         GtkCellRendererState flags)
#endif
{
    FmCellRendererText *self = FM_CELL_RENDERER_TEXT(cell);
#if GTK_CHECK_VERSION(3, 0, 0)
    GtkStyleContext* style;
    GtkStateFlags state;
#else
    GtkStyle* style;
    GtkStateType state;
#endif
    gchar* text;
    gint text_width;
    gint text_height;
    gint x_offset;
    gint y_offset;
    gint x_align_offset;
    GdkRectangle rect;
    PangoWrapMode wrap_mode;
    gint wrap_width;
    PangoAlignment alignment;
    gfloat xalign, yalign;
    gint xpad, ypad;

    /* FIXME: this is time-consuming since it invokes pango_layout.
     *        if we want to fix this, we must implement the whole cell
     *        renderer ourselves instead of derived from GtkCellRendererText. */
    PangoContext* context = gtk_widget_get_pango_context(widget);

    PangoLayout* layout = pango_layout_new(context);

    g_object_get(G_OBJECT(cell),
                 "wrap-mode" , &wrap_mode,
                 "wrap-width", &wrap_width,
                 "alignment" , &alignment,
                 "text", &text,
                 NULL);

    pango_layout_set_alignment(layout, alignment);

    /* Setup the wrapping. */
    if (wrap_width < 0)
    {
        pango_layout_set_width(layout, -1);
        pango_layout_set_wrap(layout, PANGO_WRAP_CHAR);
    }
    else
    {
        pango_layout_set_width(layout, wrap_width * PANGO_SCALE);
        pango_layout_set_wrap(layout, wrap_mode);
        if(self->height > 0)
        {
            /* FIXME: add custom ellipsize from object? */
            pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
            pango_layout_set_height(layout, self->height * PANGO_SCALE);
        }
        else
            pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
    }

    pango_layout_set_text(layout, text, -1);

    pango_layout_set_auto_dir(layout, TRUE);

    pango_layout_get_pixel_size(layout, &text_width, &text_height);

    gtk_cell_renderer_get_alignment(cell, &xalign, &yalign);
    gtk_cell_renderer_get_padding(cell, &xpad, &ypad);
    /* Calculate the real x and y offsets. */
    x_offset = ((gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL) ? (1.0 - xalign) : xalign)
             * (cell_area->width - text_width - (2 * xpad));
    x_offset = MAX(x_offset, 0);

    y_offset = yalign * (cell_area->height - text_height - (2 * ypad));
    y_offset = MAX (y_offset, 0);

    if(flags & (GTK_CELL_RENDERER_SELECTED|GTK_CELL_RENDERER_FOCUSED))
    {
        rect.x = cell_area->x + x_offset;
        rect.y = cell_area->y + y_offset;
        rect.width = text_width + (2 * xpad);
        rect.height = text_height + (2 * ypad);
    }

#if GTK_CHECK_VERSION(3, 0, 0)
    style = gtk_widget_get_style_context(widget);
#else
    style = gtk_widget_get_style(widget);
#endif
    if(flags & GTK_CELL_RENDERER_SELECTED) /* item is selected */
    {
#if GTK_CHECK_VERSION(3, 0, 0)
        GdkRGBA clr;

        if(flags & GTK_CELL_RENDERER_INSENSITIVE) /* insensitive */
            state = GTK_STATE_FLAG_INSENSITIVE;
        else
            state = GTK_STATE_FLAG_SELECTED;

        gtk_style_context_get_background_color(style, state, &clr);
        gdk_cairo_rectangle(cr, &rect);
        gdk_cairo_set_source_rgba(cr, &clr);
#else
        cairo_t *cr = gdk_cairo_create (window);
        GdkColor clr;

        if(flags & GTK_CELL_RENDERER_INSENSITIVE) /* insensitive */
            state = GTK_STATE_INSENSITIVE;
        else
            state = GTK_STATE_SELECTED;

        clr = style->bg[state];

        /* paint the background */
        if(expose_area)
        {
            gdk_cairo_rectangle(cr, expose_area);
            cairo_clip(cr);
        }
        gdk_cairo_rectangle(cr, &rect);

        cairo_set_source_rgb(cr, clr.red / 65535., clr.green / 65535., clr.blue / 65535.);
#endif
        cairo_fill (cr);

#if !GTK_CHECK_VERSION(3, 0, 0)
        cairo_destroy (cr);
#endif
    }
#if !GTK_CHECK_VERSION(3, 0, 0)
    else
        state = GTK_STATE_NORMAL;
#endif

    x_align_offset = (alignment == PANGO_ALIGN_CENTER) ? (wrap_width - text_width) / 2 : 0;

#if GTK_CHECK_VERSION(3, 0, 0)
    gtk_render_layout(style, cr,
                      cell_area->x + x_offset + xpad - x_align_offset,
                      cell_area->y + y_offset + ypad, layout);
#else
    gtk_paint_layout(style, window, state, TRUE,
                     expose_area, widget, "cellrenderertext",
                     cell_area->x + x_offset + xpad - x_align_offset,
                     cell_area->y + y_offset + ypad, layout);
#endif

    g_object_unref(layout);

    if(G_UNLIKELY( flags & GTK_CELL_RENDERER_FOCUSED) ) /* focused */
    {
#if GTK_CHECK_VERSION(3, 0, 0)
        gtk_render_focus(style, cr, rect.x, rect.y, rect.width, rect.height);
#else
        gtk_paint_focus(style, window, state, background_area,
                        widget, "cellrenderertext", rect.x, rect.y,
                        rect.width, rect.height);
#endif
    }

    if(flags & GTK_CELL_RENDERER_PRELIT) /* hovered */
        g_object_set(G_OBJECT(widget), "tooltip-text", text, NULL);
    else
        g_object_set(G_OBJECT(widget), "tooltip-text", NULL, NULL);
    g_free(text);
}