/** * The range is the height - handle length. * r = h - handle; * handle is the element length of the handle* length of one element. * handle = r / ( num ) * hl * * r = h - r / ( num) *hl * r*num = num*h - r*hl * r*num+r*hl = num*h; * r ( num+hl ) = num*h * r = (num*h)/(num+hl) */ static void scrollbar_draw ( widget *wid, cairo_t *draw ) { scrollbar *sb = (scrollbar *) wid; unsigned int wh = widget_padding_get_remaining_height ( wid ); // Calculate position and size. unsigned int r = ( sb->length * wh ) / ( (double) ( sb->length + sb->pos_length ) ); unsigned int handle = wid->h - r; double sec = ( ( r ) / (double) ( sb->length - 1 ) ); unsigned int height = handle; unsigned int y = sb->pos * sec; // Set max pos. y = MIN ( y, wh - handle ); // Never go out of bar. height = MAX ( 2, height ); // Cap length; rofi_theme_get_color ( WIDGET ( sb ), "handle-color", draw ); cairo_rectangle ( draw, widget_padding_get_left ( wid ), widget_padding_get_top ( wid ) + y, widget_padding_get_remaining_width ( wid ), height ); cairo_fill ( draw ); }
void widget_draw ( widget *widget, cairo_t *d ) { // Check if enabled and if draw is implemented. if ( widget && widget->enabled && widget->draw ) { // Don't draw if there is no space. if ( widget->h < 1 || widget->w < 1 ) { widget->need_redraw = FALSE; return; } // Store current state. cairo_save ( d ); int margin_left = distance_get_pixel ( widget->margin.left, ORIENTATION_HORIZONTAL ); int margin_top = distance_get_pixel ( widget->margin.top, ORIENTATION_VERTICAL ); int margin_right = distance_get_pixel ( widget->margin.right, ORIENTATION_HORIZONTAL ); int margin_bottom = distance_get_pixel ( widget->margin.bottom, ORIENTATION_VERTICAL ); // Define a clipmask so we won't draw outside out widget. cairo_rectangle ( d, widget->x + margin_left, widget->y + margin_top, widget->w - margin_right - margin_left, widget->h - margin_top - margin_bottom ); cairo_clip ( d ); cairo_set_source_rgba ( d, 1.0, 1.0, 1.0, 1.0 ); rofi_theme_get_color ( widget, "background", d ); cairo_paint ( d ); // Set new x/y possition. cairo_translate ( d, widget->x, widget->y ); cairo_set_source_rgba ( d, 0.0, 0.0, 0.0, 1.0 ); int left = distance_get_pixel ( widget->border.left, ORIENTATION_HORIZONTAL ); int right = distance_get_pixel ( widget->border.right, ORIENTATION_HORIZONTAL ); int top = distance_get_pixel ( widget->border.top, ORIENTATION_VERTICAL ); int bottom = distance_get_pixel ( widget->border.bottom, ORIENTATION_VERTICAL ); if ( left || top || right || bottom ) { cairo_save ( d ); rofi_theme_get_color ( widget, "foreground", d ); if ( left > 0 ) { cairo_set_line_width ( d, left ); distance_get_linestyle ( widget->border.left, d ); cairo_move_to ( d, margin_left + left / 2.0, margin_top ); cairo_line_to ( d, margin_left + left / 2.0, widget->h - margin_bottom ); cairo_stroke ( d ); } if ( right > 0 ) { cairo_set_line_width ( d, right ); distance_get_linestyle ( widget->border.right, d ); cairo_move_to ( d, widget->w - margin_right - right / 2.0, 0 ); cairo_line_to ( d, widget->w - margin_right - right / 2.0, widget->h - margin_bottom ); cairo_stroke ( d ); } if ( top > 0 ) { cairo_set_line_width ( d, top ); distance_get_linestyle ( widget->border.top, d ); cairo_move_to ( d, margin_left, margin_top + top / 2.0 ); cairo_line_to ( d, widget->w - margin_right, margin_top + top / 2.0 ); cairo_stroke ( d ); } if ( bottom > 0 ) { cairo_set_line_width ( d, bottom ); distance_get_linestyle ( widget->border.bottom, d ); cairo_move_to ( d, margin_left, widget->h - bottom / 2.0 - margin_bottom ); cairo_line_to ( d, widget->w - margin_right, widget->h - bottom / 2.0 - margin_bottom ); cairo_stroke ( d ); } cairo_restore ( d ); } widget->draw ( widget, d ); widget->need_redraw = FALSE; cairo_restore ( d ); } }
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; } }