static void
gtk_revealer_real_get_preferred_width_for_height (GtkWidget *widget,
                                                  gint       height,
                                                  gint      *minimum_width_out,
                                                  gint      *natural_width_out)
{
  GtkRevealer *revealer = GTK_REVEALER (widget);
  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
  gint minimum_width;
  gint natural_width;
  GtkRevealerTransitionType transition;

  GTK_WIDGET_CLASS (gtk_revealer_parent_class)->get_preferred_width_for_height (widget, height, &minimum_width, &natural_width);

  transition = effective_transition (revealer);
  if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT ||
      transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
    natural_width = round (natural_width * priv->current_pos);

  minimum_width = MIN (minimum_width, natural_width);

  if (minimum_width_out)
    *minimum_width_out = minimum_width;
  if (natural_width_out)
    *natural_width_out = natural_width;
}
static void
gtk_revealer_start_animation (GtkRevealer *revealer,
                              gdouble      target)
{
  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
  GtkWidget *widget = GTK_WIDGET (revealer);
  GtkRevealerTransitionType transition;

  if (priv->target_pos == target)
    return;

  priv->target_pos = target;
  g_object_notify (G_OBJECT (revealer), "reveal-child");

  transition = effective_transition (revealer);
  if (gtk_widget_get_mapped (widget) &&
      priv->transition_duration != 0 &&
      transition != GTK_REVEALER_TRANSITION_TYPE_NONE)
    {
      priv->source_pos = priv->current_pos;
      priv->start_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
      priv->end_time = priv->start_time + (priv->transition_duration * 1000);
      if (priv->tick_id == 0)
        priv->tick_id =
          gtk_widget_add_tick_callback (widget, (GtkTickCallback)gtk_revealer_animate_cb, revealer, NULL);
      gtk_revealer_animate_step (revealer, priv->start_time);
    }
  else
    {
      gtk_revealer_set_position (revealer, target);
    }
}
static void
gtk_revealer_real_get_preferred_height_for_width (GtkWidget *widget,
                                                  gint       width,
                                                  gint      *minimum_height_out,
                                                  gint      *natural_height_out)
{
  GtkRevealer *revealer = GTK_REVEALER (widget);
  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
  gint minimum_height;
  gint natural_height;
  GtkRevealerTransitionType transition;

  GTK_WIDGET_CLASS (gtk_revealer_parent_class)->get_preferred_height_for_width (widget, width, &minimum_height, &natural_height);

  transition = effective_transition (revealer);
  if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP ||
      transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN)
    natural_height = round (natural_height * priv->current_pos);

  minimum_height = MIN (minimum_height, natural_height);

  if (minimum_height_out)
    *minimum_height_out = minimum_height;
  if (natural_height_out)
    *natural_height_out = natural_height;
}
static void
gtk_revealer_get_child_allocation (GtkRevealer   *revealer,
                                   GtkAllocation *allocation,
                                   GtkAllocation *child_allocation)
{
  GtkWidget *child;
  GtkRevealerTransitionType transition;

  g_return_if_fail (revealer != NULL);
  g_return_if_fail (allocation != NULL);

  child_allocation->x = 0;
  child_allocation->y = 0;
  child_allocation->width = allocation->width;
  child_allocation->height = allocation->height;

  child = gtk_bin_get_child (GTK_BIN (revealer));
  if (child != NULL && gtk_widget_get_visible (child))
    {
      transition = effective_transition (revealer);
      if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT ||
          transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
        gtk_widget_get_preferred_width_for_height (child, child_allocation->height, NULL,
                                                   &child_allocation->width);
      else
        gtk_widget_get_preferred_height_for_width (child, child_allocation->width, NULL,
                                                   &child_allocation->height);
    }
}
static void
gtk_revealer_real_realize (GtkWidget *widget)
{
  GtkRevealer *revealer = GTK_REVEALER (widget);
  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
  GtkAllocation allocation;
  GdkWindowAttr attributes = { 0 };
  GdkWindowAttributesType attributes_mask;
  GtkAllocation child_allocation;
  GtkWidget *child;
  GtkStyleContext *context;
  GtkRevealerTransitionType transition;

  gtk_widget_set_realized (widget, TRUE);

  gtk_widget_get_allocation (widget, &allocation);

  attributes.x = allocation.x;
  attributes.y = allocation.y;
  attributes.width = allocation.width;
  attributes.height = allocation.height;
  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.visual = gtk_widget_get_visual (widget);
  attributes.event_mask =
    gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
  attributes_mask = (GDK_WA_X | GDK_WA_Y) | GDK_WA_VISUAL;

  priv->view_window =
    gdk_window_new (gtk_widget_get_parent_window ((GtkWidget*) revealer),
                    &attributes, attributes_mask);
  gtk_widget_set_window (widget, priv->view_window);
  gtk_widget_register_window (widget, priv->view_window);

  gtk_revealer_get_child_allocation (revealer, &allocation, &child_allocation);

  attributes.x = 0;
  attributes.y = 0;
  attributes.width = child_allocation.width;
  attributes.height = child_allocation.height;

  transition = effective_transition (revealer);
  if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN)
    attributes.y = allocation.height - child_allocation.height;
  else if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
    attributes.x = allocation.width - child_allocation.width;

  priv->bin_window =
    gdk_window_new (priv->view_window, &attributes, attributes_mask);
  gtk_widget_register_window (widget, priv->bin_window);

  child = gtk_bin_get_child (GTK_BIN (revealer));
  if (child != NULL)
    gtk_widget_set_parent_window (child, priv->bin_window);

  context = gtk_widget_get_style_context (widget);
  gtk_style_context_set_background (context, priv->view_window);
  gtk_style_context_set_background (context, priv->bin_window);
  gdk_window_show (priv->bin_window);
}
示例#6
0
static void
set_width_with_paddings (GtkRevealer *revealer,
                         gint         preferred_minimum_width,
                         gint         preferred_natural_width,
                         gint        *minimum_width_out,
                         gint        *natural_width_out)
{
  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
  gint minimum_width;
  gint natural_width;
  GtkRevealerTransitionType transition;
  GtkBorder padding;
  gint horizontal_padding;

  gtk_revealer_get_padding (revealer, &padding);
  horizontal_padding = padding.left + padding.right;
  minimum_width = preferred_minimum_width + horizontal_padding;
  natural_width = preferred_natural_width + horizontal_padding;

  transition = effective_transition (revealer);
  if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT ||
      transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
    {
      /* Paddings are included in the animation */
      minimum_width = round (minimum_width * priv->current_pos);
      natural_width = round (natural_width * priv->current_pos);
    }

  *minimum_width_out = MIN (minimum_width, natural_width);
  *natural_width_out = natural_width;
}
示例#7
0
static void
set_height_with_paddings (GtkRevealer *revealer,
                          gint         preferred_minimum_height,
                          gint         preferred_natural_height,
                          gint        *minimum_height_out,
                          gint        *natural_height_out)
{
  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
  gint minimum_height;
  gint natural_height;
  GtkRevealerTransitionType transition;
  GtkBorder padding;
  gint vertical_padding;

  gtk_revealer_get_padding (revealer, &padding);
  vertical_padding = padding.top + padding.bottom;
  minimum_height = preferred_minimum_height + vertical_padding;
  natural_height = preferred_natural_height + vertical_padding;

  transition = effective_transition (revealer);
  if (transition == GTK_REVEALER_TRANSITION_TYPE_NONE ||
      transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP ||
      transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN)
    {
      /* Padding are included in the animation */
      minimum_height = round (minimum_height * priv->current_pos);
      natural_height = round (natural_height * priv->current_pos);
    }

  *minimum_height_out = MIN (minimum_height, natural_height);
  *natural_height_out = natural_height;
}
static void
gtk_revealer_real_size_allocate (GtkWidget     *widget,
                                 GtkAllocation *allocation)
{
  GtkRevealer *revealer = GTK_REVEALER (widget);
  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
  GtkAllocation child_allocation;
  GtkWidget *child;
  gboolean window_visible;
  int bin_x, bin_y;
  GtkRevealerTransitionType transition;

  g_return_if_fail (allocation != NULL);

  gtk_widget_set_allocation (widget, allocation);
  gtk_revealer_get_child_allocation (revealer, allocation, &child_allocation);

  child = gtk_bin_get_child (GTK_BIN (revealer));
  if (child != NULL && gtk_widget_get_visible (child))
    gtk_widget_size_allocate (child, &child_allocation);

  if (gtk_widget_get_realized (widget))
    {
      if (gtk_widget_get_mapped (widget))
        {
          window_visible = allocation->width > 0 && allocation->height > 0;

          if (!window_visible && gdk_window_is_visible (priv->view_window))
            gdk_window_hide (priv->view_window);

          if (window_visible && !gdk_window_is_visible (priv->view_window))
            gdk_window_show (priv->view_window);
        }

      gdk_window_move_resize (priv->view_window,
                              allocation->x, allocation->y,
                              allocation->width, allocation->height);

      bin_x = 0;
      bin_y = 0;
      transition = effective_transition (revealer);
      if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN)
        bin_y = allocation->height - child_allocation.height;
      else if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
        bin_x = allocation->width - child_allocation.width;

      gdk_window_move_resize (priv->bin_window,
                              bin_x, bin_y,
                              child_allocation.width, child_allocation.height);
    }
}
示例#9
0
static void
gtk_revealer_get_child_allocation (GtkRevealer   *revealer,
                                   GtkAllocation *allocation,
                                   GtkAllocation *child_allocation)
{
  GtkWidget *child;
  GtkRevealerTransitionType transition;
  GtkBorder padding;
  gint vertical_padding, horizontal_padding;

  g_return_if_fail (revealer != NULL);
  g_return_if_fail (allocation != NULL);

  /* See explanation on gtk_revealer_real_size_allocate */
  gtk_revealer_get_padding (revealer, &padding);
  vertical_padding = padding.top + padding.bottom;
  horizontal_padding = padding.left + padding.right;

  child_allocation->x = 0;
  child_allocation->y = 0;
  child_allocation->width = 0;
  child_allocation->height = 0;

  child = gtk_bin_get_child (GTK_BIN (revealer));
  if (child != NULL && gtk_widget_get_visible (child))
    {
      transition = effective_transition (revealer);
      if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT ||
          transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
        gtk_widget_get_preferred_width_for_height (child, MAX (0, allocation->height - vertical_padding), NULL,
                                                   &child_allocation->width);
      else
        gtk_widget_get_preferred_height_for_width (child, MAX (0, allocation->width - horizontal_padding), NULL,
                                                   &child_allocation->height);
    }

  child_allocation->width = MAX (child_allocation->width, allocation->width - horizontal_padding);
  child_allocation->height = MAX (child_allocation->height, allocation->height - vertical_padding);
}
示例#10
0
static void
gtk_revealer_set_position (GtkRevealer *revealer,
                           gdouble      pos)
{
  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
  gboolean new_visible;
  GtkWidget *child;
  GtkRevealerTransitionType transition;

  priv->current_pos = pos;

  /* We check target_pos here too, because we want to ensure we set
   * child_visible immediately when starting a reveal operation
   * otherwise the child widgets will not be properly realized
   * after the reveal returns.
   */
  new_visible = priv->current_pos != 0.0 || priv->target_pos != 0.0;

  child = gtk_bin_get_child (GTK_BIN (revealer));
  if (child != NULL &&
      new_visible != gtk_widget_get_child_visible (child))
    gtk_widget_set_child_visible (child, new_visible);

  transition = effective_transition (revealer);
  if (transition == GTK_REVEALER_TRANSITION_TYPE_CROSSFADE)
    {
      gtk_widget_set_opacity (GTK_WIDGET (revealer), priv->current_pos);
      gtk_widget_queue_draw (GTK_WIDGET (revealer));
    }
  else
    {
      gtk_widget_queue_resize (GTK_WIDGET (revealer));
    }

  if (priv->current_pos == priv->target_pos)
    g_object_notify (G_OBJECT (revealer), "child-revealed");
}
示例#11
0
static void
gtk_revealer_real_size_allocate (GtkWidget     *widget,
                                 GtkAllocation *allocation)
{
  GtkRevealer *revealer = GTK_REVEALER (widget);
  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
  GtkAllocation child_allocation;
  GtkWidget *child;
  gboolean window_visible;
  int bin_x, bin_y;
  GtkRevealerTransitionType transition;
  GtkBorder padding;

  g_return_if_fail (allocation != NULL);

  gtk_widget_set_allocation (widget, allocation);
  gtk_revealer_get_child_allocation (revealer, allocation, &child_allocation);

  child = gtk_bin_get_child (GTK_BIN (revealer));
  if (child != NULL && gtk_widget_get_visible (child))
    gtk_widget_size_allocate (child, &child_allocation);

  if (gtk_widget_get_realized (widget))
    {
      if (gtk_widget_get_mapped (widget))
        {
          window_visible = allocation->width > 0 && allocation->height > 0;

          if (!window_visible && gdk_window_is_visible (priv->view_window))
            gdk_window_hide (priv->view_window);

          if (window_visible && !gdk_window_is_visible (priv->view_window))
            gdk_window_show (priv->view_window);
        }

      /* The view window will follow the revealer allocation, which is modified
       * along the animation */
      gdk_window_move_resize (priv->view_window,
                              allocation->x, allocation->y,
                              allocation->width, allocation->height);

      gtk_revealer_get_padding (revealer, &padding);
      bin_x = 0;
      bin_y = 0;

      transition = effective_transition (revealer);
      /* The child allocation is fixed (it is not modified by the animation),
       * and it's origin is relative to the bin_window.
       * The bin_window has the same allocation as the child, and then the bin_window
       * deals with the relative positioning with respect to the revealer taking
       * into account the paddings of the revealer.
       *
       * For most of transitions, the bin_window moves along with the revealer,
       * as its allocation changes.
       * However for GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN
       * we need to first move the bin_window upwards and then slide it down in
       * the revealer.
       * Otherwise the child would appear as static and the revealer will allocate
       * following the animation, clipping the child.
       * To calculate the correct y position for this case:
       * allocation->height - child_allocation.height is the relative position
       * towards the revealer taking into account the animation progress with
       * both vertical paddings added, therefore we need to substract the part
       * that we don't want to take into account for the y position, which
       * in this case is the bottom padding.
       *
       * The same special treatment is needed for GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT.
       */
      if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN)
        {
          bin_y = allocation->height - child_allocation.height - padding.bottom;
          bin_x = padding.left;
        }
      else if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
        {
          bin_y = padding.top;
          bin_x = allocation->width - child_allocation.width - padding.right;
        }
     else
       {
         bin_x = padding.left;
         bin_y = padding.top;
       }

      gdk_window_move_resize (priv->bin_window,
                              bin_x, bin_y,
                              child_allocation.width, child_allocation.height);
    }
}
示例#12
0
static void
gtk_revealer_real_realize (GtkWidget *widget)
{
  GtkRevealer *revealer = GTK_REVEALER (widget);
  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
  GtkAllocation allocation;
  GdkWindowAttr attributes = { 0 };
  GdkWindowAttributesType attributes_mask;
  GtkAllocation child_allocation;
  GtkWidget *child;
  GtkRevealerTransitionType transition;
  GtkBorder padding;

  gtk_widget_set_realized (widget, TRUE);

  gtk_widget_get_allocation (widget, &allocation);

  attributes.x = allocation.x;
  attributes.y = allocation.y;
  attributes.width = allocation.width;
  attributes.height = allocation.height;
  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.visual = gtk_widget_get_visual (widget);
  attributes.event_mask =
    gtk_widget_get_events (widget);
  attributes_mask = (GDK_WA_X | GDK_WA_Y) | GDK_WA_VISUAL;

  priv->view_window =
    gdk_window_new (gtk_widget_get_parent_window ((GtkWidget*) revealer),
                    &attributes, attributes_mask);
  gtk_widget_set_window (widget, priv->view_window);
  gtk_widget_register_window (widget, priv->view_window);

  gtk_revealer_get_child_allocation (revealer, &allocation, &child_allocation);

  gtk_revealer_get_padding (revealer, &padding);
  attributes.x = 0;
  attributes.y = 0;
  attributes.width = child_allocation.width;
  attributes.height = child_allocation.height;

  /* See explanation on gtk_revealer_real_size_allocate */
  transition = effective_transition (revealer);
  if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN)
    {
      attributes.y = allocation.height - child_allocation.height - padding.bottom;
      attributes.x = padding.left;
    }
  else if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
    {
      attributes.y = padding.top;
      attributes.x = allocation.width - child_allocation.width - padding.right;
    }
 else
   {
     attributes.y = padding.top;
     attributes.x = padding.left;
   }

  priv->bin_window =
    gdk_window_new (priv->view_window, &attributes, attributes_mask);
  gtk_widget_register_window (widget, priv->bin_window);

  child = gtk_bin_get_child (GTK_BIN (revealer));
  if (child != NULL)
    gtk_widget_set_parent_window (child, priv->bin_window);

  gdk_window_show (priv->bin_window);
}