static int ol_scroll_window_compute_line_count (OlScrollWindow *scroll) { ol_assert_ret (OL_IS_SCROLL_WINDOW (scroll), 0); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); int font_height = ol_scroll_window_get_font_height (scroll) + priv->line_margin; gint width, height; gtk_window_get_size (GTK_WINDOW (scroll), &width, &height); int line_count = height - priv->padding_y * 2 / font_height; return line_count; }
void ol_scroll_window_set_text (OlScrollWindow *scroll, const char *text) { ol_assert (OL_IS_SCROLL_WINDOW (scroll)); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); if (priv->text != NULL) g_free (priv->text); priv->text = g_strdup (text); gtk_widget_queue_draw (GTK_WIDGET (scroll)); }
void ol_scroll_window_set_can_seek (OlScrollWindow *scroll, gboolean can_seek) { ol_assert (OL_IS_SCROLL_WINDOW (scroll)); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); if (can_seek != priv->can_seek) { priv->can_seek = can_seek; ol_scroll_window_update_tooltip (scroll); } }
static PangoLayout* _get_pango (OlScrollWindow *scroll, cairo_t *cr) { ol_assert_ret (OL_IS_SCROLL_WINDOW (scroll), NULL); ol_assert_ret (cr != NULL, NULL); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); PangoLayout *layout = pango_cairo_create_layout (cr); PangoFontDescription *desc = pango_font_description_from_string (priv->font_name); pango_layout_set_font_description (layout, desc); pango_font_description_free (desc); return layout; }
static cairo_t* _get_cairo (OlScrollWindow *scroll, GtkWidget *widget) { ol_assert_ret (OL_IS_SCROLL_WINDOW (scroll), NULL); ol_assert_ret (GTK_IS_WIDGET (widget), NULL); cairo_t *cr; cr = gdk_cairo_create (gtk_widget_get_window (widget)); cairo_save (cr); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_paint(cr); cairo_restore (cr); return cr; }
void ol_scroll_window_set_progress (OlScrollWindow *scroll, int lyric_id, double percentage) { ol_assert (OL_IS_SCROLL_WINDOW (scroll)); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); gint saved_lyric_id = scroll->current_lyric_id; scroll->current_lyric_id = lyric_id; scroll->percentage = percentage; if (saved_lyric_id != lyric_id || priv->saved_lrc_y != _calc_lrc_ypos (scroll, percentage)) gtk_widget_queue_draw (GTK_WIDGET (scroll)); }
static gboolean ol_scroll_window_expose (GtkWidget *widget, GdkEventExpose *event, gpointer userdata) { ol_assert_ret (OL_IS_SCROLL_WINDOW (userdata), FALSE); OlScrollWindow *scroll = OL_SCROLL_WINDOW (userdata); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); cairo_t *cr = _get_cairo (scroll, widget); _paint_bg (scroll, cr); if (scroll->whole_lyrics != NULL) _paint_lyrics (scroll, cr); else if (priv->text != NULL) _paint_text (scroll, cr); cairo_destroy (cr); return FALSE; }
static void _paint_bg (OlScrollWindow *scroll, cairo_t *cr) { ol_assert (OL_IS_SCROLL_WINDOW (scroll)); ol_assert (cr != NULL); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); gint width, height; gdk_drawable_get_size (gtk_widget_get_window (GTK_WIDGET (scroll)), &width, &height); cairo_save (cr); cairo_new_path (cr); /* Top-left */ cairo_arc (cr, priv->corner_radius, priv->corner_radius, priv->corner_radius, M_PI, M_PI * 1.5); cairo_line_to (cr, width - priv->corner_radius, 0); /* Top-right */ cairo_arc (cr, width - priv->corner_radius, priv->corner_radius, priv->corner_radius, M_PI * 1.5, M_PI * 2); cairo_line_to (cr, width, height - priv->corner_radius); /* Bottom-right */ cairo_arc (cr, width - priv->corner_radius, height - priv->corner_radius, priv->corner_radius, 0, M_PI * 0.5); cairo_line_to (cr, priv->corner_radius, height); /* Bottom-left */ cairo_arc (cr, priv->corner_radius, height - priv->corner_radius, priv->corner_radius, M_PI * 0.5, M_PI); cairo_close_path (cr); cairo_set_source_rgba (cr, priv->bg_color.r, priv->bg_color.g, priv->bg_color.b, priv->bg_opacity); cairo_fill (cr); /* cairo_stroke (cr); */ cairo_restore (cr); }
static gint _calc_lrc_ypos (OlScrollWindow *scroll, double percentage) { ol_assert_ret (OL_IS_SCROLL_WINDOW (scroll), -1); GtkWidget *widget = GTK_WIDGET (scroll); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); if (!GTK_WIDGET_REALIZED (widget)) return -1; gint line_height; line_height = ol_scroll_window_get_font_height (scroll) + priv->line_margin; if (priv->scroll_mode == OL_SCROLL_WINDOW_BY_LINES) { if (percentage < 0.15) percentage = percentage / 0.15; else percentage = 1; } return line_height * percentage; }
static gboolean ol_scroll_window_button_press (GtkWidget *widget, GdkEventButton *event) { ol_assert_ret (OL_IS_SCROLL_WINDOW (widget), FALSE); OlScrollWindow *scroll = OL_SCROLL_WINDOW (widget); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); if (event->button == 1) { if (event->state & GDK_CONTROL_MASK && scroll->whole_lyrics != NULL && priv->can_seek) { ol_scroll_window_begin_seek (OL_SCROLL_WINDOW (widget), event); } else { ol_scroll_window_begin_move_resize (widget, event); } } return FALSE; }
static gboolean ol_scroll_window_motion_notify (GtkWidget *widget, GdkEventMotion *event) { ol_assert_ret (OL_IS_SCROLL_WINDOW (widget), FALSE); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (widget); if (priv->seeking) { ol_scroll_window_seek (OL_SCROLL_WINDOW (widget), event); } else if (event->state & GDK_CONTROL_MASK) { gdk_window_set_cursor (widget->window, NULL); } else { ol_scroll_window_update_cursor (widget, event); } return FALSE; }
static gboolean ol_scroll_window_button_release (GtkWidget *widget, GdkEventButton *event) { ol_assert_ret (OL_IS_SCROLL_WINDOW (widget), FALSE); OlScrollWindow *scroll = OL_SCROLL_WINDOW (widget); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (widget); if (priv->seeking) { gint current_lyric_id, lrc_y; gint line_height = ol_scroll_window_get_font_height (scroll) + priv->line_margin; _calc_paint_pos (scroll, ¤t_lyric_id, &lrc_y); gdouble percentage = (gdouble) lrc_y / (gdouble) line_height; ol_scroll_window_end_seek (scroll); g_signal_emit (scroll, _signals[SEEK_SIGNAL], 0, /* detail */ (guint)current_lyric_id, percentage); } return FALSE; }
int ol_scroll_window_get_current_lyric_id (OlScrollWindow *scroll) { ol_assert_ret (OL_IS_SCROLL_WINDOW (scroll), -1); return scroll->current_lyric_id; }
static void _paint_lyrics (OlScrollWindow *scroll, cairo_t *cr) { ol_assert (OL_IS_SCROLL_WINDOW (scroll)); GtkWidget *widget = GTK_WIDGET (scroll); ol_assert (GTK_WIDGET_REALIZED (widget)); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); int line_height = ol_scroll_window_get_font_height (scroll) + priv->line_margin; int count = ol_scroll_window_compute_line_count (scroll); gint width, height; gdk_drawable_get_size (gtk_widget_get_window (GTK_WIDGET (scroll)), &width, &height); /* set the font */ PangoLayout *layout = _get_pango (scroll, cr); /* paint the lyrics*/ cairo_save (cr); cairo_new_path (cr); cairo_rectangle (cr, priv->padding_x, 0, width - priv->padding_x * 2, height - priv->padding_y * 2); cairo_close_path (cr); cairo_clip (cr); int i; gint current_lyric_id; gint lrc_y; _calc_paint_pos (scroll, ¤t_lyric_id, &lrc_y); int begin = current_lyric_id - count / 2; int end = current_lyric_id + count / 2 + 1; int ypos = height / 2 - lrc_y - (count / 2 + 1) * line_height; cairo_set_source_rgb(cr, priv->inactive_color.r, priv->inactive_color.g, priv->inactive_color.b); if (scroll->whole_lyrics != NULL) { for (i = begin; i < end; i++) { ypos += line_height; if (i < 0) continue; if (i >= scroll->whole_lyrics->len) break; pango_layout_set_text (layout, g_ptr_array_index (scroll->whole_lyrics, i), -1); cairo_save (cr); double ratio = _get_active_color_ratio (scroll, i); double alpha = 1.0; if (ypos < line_height / 2.0 + priv->padding_y) alpha = 1.0 - (line_height / 2.0 + priv->padding_y - ypos) * 1.0 / line_height * 2; else if (ypos > height - line_height * 1.5 - priv->padding_y) alpha = (height - line_height - priv->padding_y - ypos) * 1.0 / line_height * 2; if (alpha < 0.0) alpha = 0.0; cairo_set_source_rgba (cr, priv->active_color.r * ratio + priv->inactive_color.r * (1 - ratio), priv->active_color.g * ratio + priv->inactive_color.g * (1 - ratio), priv->active_color.b * ratio + priv->inactive_color.b * (1 - ratio), alpha); cairo_move_to (cr, priv->padding_x, ypos); pango_cairo_update_layout (cr, layout); pango_cairo_show_layout (cr, layout); cairo_restore (cr); } } g_object_unref (layout); cairo_reset_clip (cr); cairo_restore (cr); }