Beispiel #1
0
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;
}
Beispiel #2
0
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, &current_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,
                   &current_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);
}