Beispiel #1
0
static int box_get_desired_width  ( widget *wid )
{
    box *b      = (box *) wid;
    int spacing = distance_get_pixel ( b->spacing, b->type );
    int width   = 0;
    if ( b->type == ROFI_ORIENTATION_HORIZONTAL ) {
        int active_widgets = 0;
        for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
            widget * child = (widget *) iter->data;
            if ( !child->enabled ) {
                continue;
            }
            active_widgets++;
            if ( child->expand == TRUE ) {
                width += widget_get_desired_width ( child );
                continue;
            }
            width += widget_get_desired_width ( child );
        }
        if ( active_widgets > 0 ) {
            width += ( active_widgets - 1 ) * spacing;
        }
    }
    else {
        for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
            widget * child = (widget *) iter->data;
            if ( !child->enabled ) {
                continue;
            }
            width = MAX ( widget_get_desired_width ( child ), width );
        }
    }
    width += widget_padding_get_padding_width ( wid );
    return width;
}
Beispiel #2
0
int textbox_get_width ( widget *wid )
{
    textbox *tb = (textbox *) wid;
    if ( tb->flags & TB_AUTOWIDTH ) {
        unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
        return textbox_get_font_width ( tb ) + widget_padding_get_padding_width ( wid ) + offset;
    }
    return tb->widget.w;
}
Beispiel #3
0
// within the parent handled auto width/height modes
void textbox_moveresize ( textbox *tb, int x, int y, int w, int h )
{
    unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
    if ( tb->flags & TB_AUTOWIDTH ) {
        pango_layout_set_width ( tb->layout, -1 );
        unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
        w = textbox_get_font_width ( tb ) + widget_padding_get_padding_width ( WIDGET ( tb ) ) + offset;
    }
    else {
        // set ellipsize
        if ( ( tb->flags & TB_EDITABLE ) == TB_EDITABLE ) {
            pango_layout_set_ellipsize ( tb->layout, PANGO_ELLIPSIZE_MIDDLE );
        }
        else if ( ( tb->flags & TB_WRAP ) != TB_WRAP ) {
            pango_layout_set_ellipsize ( tb->layout, PANGO_ELLIPSIZE_END );
        }
    }

    if ( tb->flags & TB_AUTOHEIGHT ) {
        // Width determines height!
        int tw = MAX ( 1, w );
        pango_layout_set_width ( tb->layout, PANGO_SCALE * ( tw - widget_padding_get_padding_width ( WIDGET ( tb ) ) - offset ) );
        int hd = textbox_get_height ( tb );
        h = MAX ( hd, h );
    }

    if ( x != tb->widget.x || y != tb->widget.y || w != tb->widget.w || h != tb->widget.h ) {
        tb->widget.x = x;
        tb->widget.y = y;
        tb->widget.h = MAX ( 1, h );
        tb->widget.w = MAX ( 1, w );
    }

    // We always want to update this
    pango_layout_set_width ( tb->layout, PANGO_SCALE * ( tb->widget.w - widget_padding_get_padding_width ( WIDGET ( tb ) ) - offset ) );
    tb->update = TRUE;
    widget_queue_redraw ( WIDGET ( tb ) );
}
Beispiel #4
0
void box_add ( box *box, widget *child, gboolean expand )
{
    if ( box == NULL ) {
        return;
    }
    // Make sure box is width/heigh enough.
    if ( box->type == ROFI_ORIENTATION_VERTICAL ) {
        int width = box->widget.w;
        width         = MAX ( width, child->w + widget_padding_get_padding_width ( WIDGET ( box ) ) );
        box->widget.w = width;
    }
    else {
        int height = box->widget.h;
        height        = MAX ( height, child->h + widget_padding_get_padding_height ( WIDGET ( box ) ) );
        box->widget.h = height;
    }
    child->expand = rofi_theme_get_boolean ( child, "expand", expand );
    g_assert ( child->parent == WIDGET ( box ) );
    box->children = g_list_append ( box->children, (void *) child );
    widget_update ( WIDGET ( box ) );
}
Beispiel #5
0
scrollbar *scrollbar_create ( widget *parent, const char *name )
{
    scrollbar *sb = g_malloc0 ( sizeof ( scrollbar ) );
    widget_init ( WIDGET ( sb ), parent, WIDGET_TYPE_SCROLLBAR, name );
    sb->widget.x = 0;
    sb->widget.y = 0;
    sb->width    = rofi_theme_get_distance ( WIDGET ( sb ), "handle-width", DEFAULT_SCROLLBAR_WIDTH );
    int width = distance_get_pixel ( sb->width, ROFI_ORIENTATION_HORIZONTAL );
    sb->widget.w = widget_padding_get_padding_width ( WIDGET ( sb ) ) + width;
    sb->widget.h = widget_padding_get_padding_height ( WIDGET ( sb ) );

    sb->widget.draw               = scrollbar_draw;
    sb->widget.free               = scrollbar_free;
    sb->widget.trigger_action     = scrollbar_trigger_action;
    sb->widget.motion_notify      = scrollbar_motion_notify;
    sb->widget.get_desired_height = scrollbar_get_desired_height;

    sb->length     = 10;
    sb->pos        = 0;
    sb->pos_length = 4;

    return sb;
}
Beispiel #6
0
static void listview_draw ( widget *wid, cairo_t *draw )
{
    unsigned int offset = 0;
    listview     *lv    = (listview *) wid;
    if ( lv->scroll_type == LISTVIEW_SCROLL_CONTINIOUS ) {
        offset = scroll_continious ( lv );
    }
    else {
        offset = scroll_per_page ( lv );
    }
    // Set these all together to make sure they update consistently.
    scrollbar_set_max_value ( lv->scrollbar, lv->req_elements );
    scrollbar_set_handle_length ( lv->scrollbar, lv->cur_columns * lv->max_rows );
    if ( lv->reverse ) {
        scrollbar_set_handle ( lv->scrollbar, lv->req_elements - lv->selected - 1 );
    }
    else {
        scrollbar_set_handle ( lv->scrollbar, lv->selected  );
    }
    lv->last_offset = offset;
    int spacing_vert = distance_get_pixel ( lv->spacing, ORIENTATION_VERTICAL );
    int spacing_hori = distance_get_pixel ( lv->spacing, ORIENTATION_HORIZONTAL );

    int left_offset = widget_padding_get_left ( wid );
    int top_offset  = widget_padding_get_top ( wid );
    if ( lv->scrollbar->widget.index == 0 ) {
        left_offset += spacing_hori + lv->scrollbar->widget.w;
    }
    if ( lv->cur_elements > 0 && lv->max_rows > 0 ) {
        // Set new x/y possition.
        unsigned int max = MIN ( lv->cur_elements, lv->req_elements - offset );
        if ( lv->rchanged ) {
            unsigned int width = lv->widget.w - spacing_hori * ( lv->cur_columns - 1 );
            width -= widget_padding_get_padding_width ( wid );
            if ( widget_enabled ( WIDGET ( lv->scrollbar ) ) ) {
                width -= spacing_hori;
                width -= widget_get_width ( WIDGET ( lv->scrollbar ) );
            }
            unsigned int element_width = ( width ) / lv->cur_columns;
            for ( unsigned int i = 0; i < max; i++ ) {
                unsigned int ex = left_offset + ( ( i ) / lv->max_rows ) * ( element_width + spacing_hori );
                if ( lv->reverse ) {
                    unsigned int ey = wid->h - ( widget_padding_get_bottom ( wid ) + ( ( i ) % lv->max_rows ) * ( lv->element_height + spacing_vert ) ) - lv->element_height;
                    textbox_moveresize ( lv->boxes[i], ex, ey, element_width, lv->element_height );
                }
                else {
                    unsigned int ey = top_offset + ( ( i ) % lv->max_rows ) * ( lv->element_height + spacing_vert );
                    textbox_moveresize ( lv->boxes[i], ex, ey, element_width, lv->element_height );
                }

                update_element ( lv, i, i + offset, TRUE );
                widget_draw ( WIDGET ( lv->boxes[i] ), draw );
            }
            lv->rchanged = FALSE;
        }
        else {
            for ( unsigned int i = 0; i < max; i++ ) {
                update_element ( lv, i, i + offset, FALSE );
                widget_draw ( WIDGET ( lv->boxes[i] ), draw );
            }
        }
    }
    widget_draw ( WIDGET ( lv->scrollbar ), draw );
}
Beispiel #7
0
static void hori_calculate_size ( box *b )
{
    int spacing           = distance_get_pixel ( b->spacing, ROFI_ORIENTATION_HORIZONTAL );
    int expanding_widgets = 0;
    int active_widgets    = 0;
    int rem_width         = widget_padding_get_remaining_width ( WIDGET ( b ) );
    int rem_height        = widget_padding_get_remaining_height ( WIDGET ( b ) );
    for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
        widget * child = (widget *) iter->data;
        if ( child->enabled && child->expand == FALSE ) {
            widget_resize ( child,
                            widget_get_desired_width ( child ), //child->w,
                            rem_height );
        }
    }
    b->max_size = 0;
    for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
        widget * child = (widget *) iter->data;
        if ( !child->enabled ) {
            continue;
        }
        active_widgets++;
        if ( child->expand == TRUE ) {
            expanding_widgets++;
            continue;
        }
        // Size used by fixed width widgets.
        if ( child->h > 0 ) {
            b->max_size += child->w;
        }
    }
    b->max_size += MAX ( 0, ( ( active_widgets - 1 ) * spacing ) );
    if ( b->max_size > ( rem_width ) ) {
        b->max_size = rem_width;
        g_debug ( "Widgets to large (width) for box: %d %d", b->max_size, b->widget.w );
        return;
    }
    if ( active_widgets > 0 ) {
        int    left  = widget_padding_get_left ( WIDGET ( b ) );
        double rem   = rem_width - b->max_size;
        int    index = 0;
        for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
            widget * child = (widget *) iter->data;
            if ( child->enabled == FALSE  ) {
                continue;
            }
            if ( child->expand == TRUE ) {
                // Re-calculate to avoid round issues leaving one pixel left.
                int expanding_widgets_size = ( rem ) / ( expanding_widgets - index );
                widget_move ( child, left, widget_padding_get_top ( WIDGET ( b ) ) );
                left += expanding_widgets_size;
                widget_resize ( child, expanding_widgets_size, rem_height );
                left += spacing;
                rem  -= expanding_widgets_size;
                index++;
            }
            else {
                widget_move ( child, left, widget_padding_get_top ( WIDGET ( b ) ) );
                left += widget_get_width (  child );
                left += spacing;
            }
        }
    }
    b->max_size += widget_padding_get_padding_width ( WIDGET ( b ) );
}
Beispiel #8
0
static void texbox_update ( textbox *tb )
{
    if ( tb->update ) {
        unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
        if ( tb->main_surface ) {
            cairo_destroy ( tb->main_draw );
            cairo_surface_destroy ( tb->main_surface );
            tb->main_draw    = NULL;
            tb->main_surface = NULL;
        }
        tb->main_surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, tb->widget.w, tb->widget.h );
        tb->main_draw    = cairo_create ( tb->main_surface );
        cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_OVER );

        pango_cairo_update_layout ( tb->main_draw, tb->layout );
        int font_height = textbox_get_font_height ( tb );

        int cursor_x      = 0;
        int cursor_y      = 0;
        int cursor_width  = 2; //MAX ( 2, font_height / 10 );
        int cursor_height = font_height;

        if ( tb->changed ) {
            __textbox_update_pango_text ( tb );
        }

        if ( tb->flags & TB_EDITABLE ) {
            // We want to place the cursor based on the text shown.
            const char     *text = pango_layout_get_text ( tb->layout );
            // Clamp the position, should not be needed, but we are paranoid.
            int            cursor_offset = MIN ( tb->cursor, g_utf8_strlen ( text, -1 ) );
            PangoRectangle pos;
            // convert to byte location.
            char           *offset = g_utf8_offset_to_pointer ( text, cursor_offset );
            pango_layout_get_cursor_pos ( tb->layout, offset - text, &pos, NULL );
            cursor_x      = pos.x / PANGO_SCALE;
            cursor_y      = pos.y / PANGO_SCALE;
            cursor_height = pos.height / PANGO_SCALE;
        }

        // Skip the side MARGIN on the X axis.
        int x = widget_padding_get_left ( WIDGET ( tb ) ) + offset;
        int y = 0;

        if ( tb->flags & TB_RIGHT ) {
            int line_width = 0;
            // Get actual width.
            pango_layout_get_pixel_size ( tb->layout, &line_width, NULL );
            x = ( tb->widget.w - line_width - widget_padding_get_right ( WIDGET ( tb ) ) - offset );
        }
        else if ( tb->flags & TB_CENTER ) {
            int tw = textbox_get_font_width ( tb );
            x = (  ( tb->widget.w - tw - widget_padding_get_padding_width ( WIDGET ( tb ) ) - offset ) ) / 2;
        }
        y = widget_padding_get_top ( WIDGET ( tb ) ) + ( pango_font_metrics_get_ascent ( p_metrics ) - pango_layout_get_baseline ( tb->layout ) ) / PANGO_SCALE;

        rofi_theme_get_color ( WIDGET ( tb ), "foreground", tb->main_draw );
        // Text
        rofi_theme_get_color ( WIDGET ( tb ), "text", tb->main_draw );
        // draw the cursor
        if ( tb->flags & TB_EDITABLE && tb->blink ) {
            cairo_rectangle ( tb->main_draw, x + cursor_x, y + cursor_y, cursor_width, cursor_height );
            cairo_fill ( tb->main_draw );
        }

        // Set ARGB
        // We need to set over, otherwise subpixel hinting wont work.
        //cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_OVER );
        cairo_move_to ( tb->main_draw, x, y );
        pango_cairo_show_layout ( tb->main_draw, tb->layout );

        if ( ( tb->flags & TB_INDICATOR ) == TB_INDICATOR && ( tb->tbft & ( SELECTED ) ) ) {
            cairo_arc ( tb->main_draw, DOT_OFFSET / 2.0, tb->widget.h / 2.0, 2.0, 0, 2.0 * M_PI );
            cairo_fill ( tb->main_draw );
        }

        tb->update = FALSE;
    }
}