Guest User

Untitled

a guest
Jun 19th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 18.67 KB | None | 0 0
  1. /**
  2.  * SECTION:ttk-box
  3.  * @Short_Description: An actor to display a rounded edge box
  4.  *
  5.  * Use this actor to display a rounded edged box of a given
  6.  * outline color and fill color.
  7.  *
  8.  * Note that the fill/outline colors are both optional
  9.  */
  10.  
  11. #ifdef HAVE_CONFIG_H
  12. #  include <config.h>
  13. #endif
  14.  
  15. #include <glib-object.h>
  16. #include <math.h>
  17.  
  18. #include <ttktransport/ttktransport.h>
  19.  
  20. #include "ttk-box.h"
  21. #include "ttk-client.h"
  22.  
  23. /* GObjectClass */
  24. static void            ttk_box_class_init            (TTKBoxClass           *klass);
  25. static void            ttk_box_init                  (TTKBox                *box);
  26. static void            ttk_box_constructed           (GObject               *object);
  27. static void            ttk_box_finalize              (GObject               *object);
  28. static void            ttk_box_get_property          (GObject               *object,
  29.                                                       guint                  prop_id,
  30.                                                       GValue                *value,
  31.                                                       GParamSpec            *pspec);
  32. static void            ttk_box_set_property          (GObject               *object,
  33.                                                       guint                  prop_id,
  34.                                                       const GValue          *value,
  35.                                                       GParamSpec            *pspec);
  36.  
  37. /* ClutterCairoTextureClass */
  38. static gboolean        ttk_box_draw                  (ClutterCairoTexture   *texture,
  39.                                                       cairo_t               *cr);
  40.  
  41. /* ClutterScriptableIface */
  42. static void            ttk_box_scriptable_iface_init (ClutterScriptableIface *iface);
  43. static gboolean        ttk_box_parse_custom_node     (ClutterScriptable *scriptable,
  44.                                                       ClutterScript     *script,
  45.                                                       GValue            *value,
  46.                                                       const gchar       *name,
  47.                                                       JsonNode          *node);
  48. static void            ttk_box_set_custom_property   (ClutterScriptable *scriptable,
  49.                                                       ClutterScript     *script,
  50.                                                       const gchar       *name,
  51.                                                       const GValue      *value);
  52.  
  53. static void            ttk_box_invalidate            (TTKBox           *box);
  54.  
  55. struct _TTKBoxPrivate {
  56.   ClutterColor     *fill_color;
  57.   ClutterColor     *outline_color;
  58.  
  59.   gdouble           outline_width;
  60.  
  61.   guint             repaint_id;
  62.  
  63.   gboolean          constructed;
  64. };
  65.  
  66. enum {
  67.   PROP_0,
  68.   PROP_FILL_COLOR,
  69.   PROP_OUTLINE_COLOR,
  70.   PROP_OUTLINE_WIDTH,
  71.   PROP_INIT_WIDTH,
  72.   PROP_INIT_HEIGHT,
  73. };
  74.  
  75. static ClutterScriptableIface *parent_scriptable_iface;
  76.  
  77. G_DEFINE_TYPE_WITH_CODE (TTKBox, ttk_box, CLUTTER_TYPE_CAIRO_TEXTURE,
  78.                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE,
  79.                                                 ttk_box_scriptable_iface_init));
  80.  
  81. /************************************************************************
  82.  *                          GObjectClass                                *
  83.  ************************************************************************/
  84. static void
  85. ttk_box_class_init (TTKBoxClass *klass)
  86. {
  87.   GObjectClass             *object_class;
  88.   ClutterCairoTextureClass *cairo_texture_class;
  89.  
  90.   object_class        = G_OBJECT_CLASS (klass);
  91.   cairo_texture_class = CLUTTER_CAIRO_TEXTURE_CLASS (klass);
  92.  
  93.   object_class->constructed  = ttk_box_constructed;
  94.   object_class->finalize     = ttk_box_finalize;
  95.   object_class->get_property = ttk_box_get_property;
  96.   object_class->set_property = ttk_box_set_property;
  97.  
  98.   cairo_texture_class->draw  = ttk_box_draw;
  99.  
  100.   /**
  101.    * TTKBox:fill-color:
  102.    *
  103.    * The color to fill the box with, if no fill color is
  104.    * specified, or after the fill color is explicitly set to %NULL,
  105.    * then the box will not be filled at all.
  106.    */
  107.   g_object_class_install_property (object_class, PROP_FILL_COLOR,
  108.                                    g_param_spec_boxed ("fill-color", "Fill Color",
  109.                                                        "The color to fill the box with",
  110.                                                        CLUTTER_TYPE_COLOR,
  111.                                                        G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
  112.  
  113.   /**
  114.    * TTKBox:outline-color:
  115.    *
  116.    * The color to outline the box with, if no outline color is
  117.    * specified, or after the outline color is explicitly set to %NULL,
  118.    * then no outline will be draw.
  119.    */
  120.   g_object_class_install_property (object_class, PROP_OUTLINE_COLOR,
  121.                                    g_param_spec_boxed ("outline-color", "Outline Color",
  122.                                                        "The color to outline the box with",
  123.                                                        CLUTTER_TYPE_COLOR,
  124.                                                        G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
  125.  
  126.   /**
  127.    * TTKBox:outline-width:
  128.    *
  129.    * The width of the outline to draw
  130.    */
  131.   g_object_class_install_property (object_class, PROP_OUTLINE_WIDTH,
  132.                                    g_param_spec_double ("outline-width", "Outline Width",
  133.                                                         "The width of the outline to draw",
  134.                                                         0.0F, G_MAXDOUBLE, 2.0F,
  135.                                                         G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
  136.  
  137.   /**
  138.    * TTKBox:init-width:
  139.    *
  140.    * The texture width to initialize with
  141.    */
  142.   g_object_class_install_property (object_class, PROP_INIT_WIDTH,
  143.                                    g_param_spec_uint ("init-width", "Initial width",
  144.                                                         "The texture width to initialize with",
  145.                                                         0, G_MAXUINT, 0,
  146.                                                         G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
  147.  
  148.   /**
  149.    * TTKBox:init-height:
  150.    *
  151.    * The texture height to initialize with
  152.    */
  153.   g_object_class_install_property (object_class, PROP_INIT_HEIGHT,
  154.                                    g_param_spec_uint ("init-height", "Initial height",
  155.                                                         "The texture height to initialize with",
  156.                                                         0, G_MAXUINT, 0,
  157.                                                         G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
  158.  
  159.   g_type_class_add_private (object_class, sizeof (TTKBoxPrivate));
  160.  
  161. }
  162.  
  163. static void
  164. ttk_box_init (TTKBox *box)
  165. {
  166.   box->priv = G_TYPE_INSTANCE_GET_PRIVATE (box, TTK_TYPE_BOX, TTKBoxPrivate);
  167.  
  168.   box->priv->outline_width = 2.0F;
  169.  
  170.   //clutter_cairo_texture_set_auto_resize (CLUTTER_CAIRO_TEXTURE (box), TRUE);
  171. }
  172.  
  173. static void
  174. ttk_box_constructed (GObject *object)
  175. {
  176.   TTKBox        *box = TTK_BOX (object);
  177.   TTKBoxPrivate *priv = box->priv;
  178.  
  179.   G_OBJECT_CLASS (ttk_box_parent_class)->constructed (object);
  180.  
  181.   TTK_NOTE (BOX, g_print ("TTKBox: Constructed, invalidating\n"));
  182.  
  183.   if (priv->repaint_id > 0)
  184.     clutter_threads_remove_repaint_func (priv->repaint_id);
  185.  
  186.   priv->constructed = TRUE;
  187.  
  188.   ttk_box_invalidate (box);
  189. }
  190.  
  191. static void
  192. ttk_box_finalize (GObject *object)
  193. {
  194.   TTKBox        *box = TTK_BOX (object);
  195.   TTKBoxPrivate *priv = box->priv;
  196.  
  197.   ttk_box_set_fill_color (box, NULL);
  198.   ttk_box_set_outline_color (box, NULL);
  199.  
  200.   if (priv->repaint_id > 0)
  201.     clutter_threads_remove_repaint_func (priv->repaint_id);
  202.  
  203.   G_OBJECT_CLASS (ttk_box_parent_class)->finalize (object);
  204. }
  205.  
  206. static void
  207. ttk_box_get_property (GObject               *object,
  208.                        guint                  prop_id,
  209.                        GValue                *value,
  210.                        GParamSpec            *pspec)
  211. {
  212.   TTKBox *box = TTK_BOX (object);
  213.  
  214.   switch (prop_id)
  215.     {
  216.     case PROP_FILL_COLOR:
  217.       g_value_set_boxed (value, ttk_box_get_fill_color (box));
  218.       break;
  219.     case PROP_OUTLINE_COLOR:
  220.       g_value_set_boxed (value, ttk_box_get_outline_color (box));
  221.       break;
  222.     case PROP_OUTLINE_WIDTH:
  223.       g_value_set_double (value, ttk_box_get_outline_width (box));
  224.       break;
  225.     default:
  226.       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  227.       break;
  228.     }
  229. }
  230.  
  231. static void
  232. ttk_box_set_property (GObject               *object,
  233.                        guint                  prop_id,
  234.                        const GValue          *value,
  235.                        GParamSpec            *pspec)
  236. {
  237.   TTKBox *box = TTK_BOX (object);
  238.  
  239.   switch (prop_id)
  240.     {
  241.     case PROP_FILL_COLOR:
  242.       ttk_box_set_fill_color (box, g_value_get_boxed (value));
  243.       break;
  244.     case PROP_OUTLINE_COLOR:
  245.       ttk_box_set_outline_color (box, g_value_get_boxed (value));
  246.       break;
  247.     case PROP_OUTLINE_WIDTH:
  248.       ttk_box_set_outline_width (box, g_value_get_double (value));
  249.       break;
  250.     case PROP_INIT_WIDTH:
  251.       {
  252.         guint width = 0, height = 0;
  253.  
  254.         clutter_cairo_texture_get_surface_size (CLUTTER_CAIRO_TEXTURE (box), &width, &height);
  255.         width = g_value_get_uint (value);
  256.         clutter_cairo_texture_set_surface_size (CLUTTER_CAIRO_TEXTURE (box), width, height);
  257.       }
  258.       break;
  259.     case PROP_INIT_HEIGHT:
  260.       {
  261.         guint width = 0, height = 0;
  262.  
  263.         clutter_cairo_texture_get_surface_size (CLUTTER_CAIRO_TEXTURE (box), &width, &height);
  264.         height = g_value_get_uint (value);
  265.         clutter_cairo_texture_set_surface_size (CLUTTER_CAIRO_TEXTURE (box), width, height);
  266.       }
  267.       break;
  268.    default:
  269.       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  270.       break;
  271.     }
  272. }
  273.  
  274. /************************************************************************
  275.  *                      ClutterCairoTextureClass                        *
  276.  ************************************************************************/
  277.  
  278. static gboolean
  279. ttk_box_draw (ClutterCairoTexture   *texture,
  280.                cairo_t               *cr)
  281. {
  282.   TTKBox        *box = TTK_BOX (texture);
  283.   TTKBoxPrivate *priv = box->priv;
  284.   gdouble        x, y, width, height, radius, degrees;
  285.   guint          texture_width = 0, texture_height = 0;
  286.  
  287.   clutter_cairo_texture_get_surface_size (texture, &texture_width, &texture_height);
  288.  
  289.   TTK_NOTE (BOX, g_print ("TTKBox: Drawing with width %d and height %d\n", texture_width, texture_height));
  290.  
  291.   clutter_cairo_texture_clear (texture);
  292.  
  293.   x       = priv->outline_width / 2;
  294.   y       = priv->outline_width / 2;
  295.   width   = texture_width - priv->outline_width;
  296.   height  = texture_height - priv->outline_width;
  297.   radius  = height / 10.0F;
  298.   degrees = M_PI / 180.0F;
  299.  
  300.   cairo_new_sub_path (cr);
  301.   cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees);
  302.   cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees);
  303.   cairo_arc (cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees);
  304.   cairo_arc (cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees);
  305.   cairo_close_path (cr);
  306.  
  307.   /* First draw the fill color */
  308.   if (priv->fill_color)
  309.     {
  310.       clutter_cairo_set_source_color (cr, priv->fill_color);
  311.       cairo_fill_preserve (cr);
  312.     }
  313.  
  314.   /* Now the outline (if any is set) */
  315.   if (priv->outline_color)
  316.     {
  317.       clutter_cairo_set_source_color (cr, priv->outline_color);
  318.  
  319.       cairo_set_line_width (cr, priv->outline_width);
  320.       cairo_stroke (cr);
  321.     }
  322.  
  323.   return FALSE;
  324. }
  325.  
  326. static gboolean
  327. ttk_box_do_invalidate (gpointer data)
  328. {
  329.   TTKBox              *box = (TTKBox *)data;
  330.   TTKBoxPrivate       *priv = box->priv;
  331.   ClutterCairoTexture *texture = CLUTTER_CAIRO_TEXTURE (box);
  332.  
  333.   clutter_cairo_texture_invalidate (texture);
  334.  
  335.   priv->repaint_id = 0;
  336.   return FALSE;
  337. }
  338.  
  339. /* We use a repaint function to invalidate redraw the rectangle
  340.  * at the last minute before actually drawing.
  341.  *
  342.  * In this way we avoid redrawing the box with cairo multiple
  343.  * times in a row for multiple property settings
  344.  */
  345. static void
  346. ttk_box_invalidate (TTKBox   *box)
  347. {
  348.   TTKBoxPrivate *priv = box->priv;
  349.  
  350.   /* if (priv->repaint_id == 0) */
  351.   /*   priv->repaint_id = */
  352.   /*     clutter_threads_add_repaint_func (ttk_box_do_invalidate, box, NULL); */
  353.  
  354.   if (!priv->constructed)
  355.     return;
  356.  
  357.   ttk_box_do_invalidate (box);
  358.   clutter_actor_queue_redraw (CLUTTER_ACTOR (box));
  359. }
  360.  
  361. /************************************************************************
  362.  *                       ClutterScriptableIface                         *
  363.  ************************************************************************/
  364. static gboolean
  365. ttk_box_parse_custom_node (ClutterScriptable *scriptable,
  366.                             ClutterScript     *script,
  367.                             GValue            *value,
  368.                             const gchar       *name,
  369.                             JsonNode          *node)
  370. {
  371.   gboolean success = FALSE;
  372.  
  373.   if (ttk_actor_parse_custom_node (scriptable, script, value, name, node, &success))
  374.     return success;
  375.  
  376.   return parent_scriptable_iface->parse_custom_node (scriptable, script, value, name, node);
  377. }
  378.  
  379. static void
  380. ttk_box_set_custom_property (ClutterScriptable *scriptable,
  381.                               ClutterScript     *script,
  382.                               const gchar       *name,
  383.                               const GValue      *value)
  384. {
  385.   if (!ttk_actor_set_custom_property (scriptable, script, name, value))
  386.     parent_scriptable_iface->set_custom_property (scriptable, script, name, value);
  387. }
  388.  
  389. static void
  390. ttk_box_scriptable_iface_init (ClutterScriptableIface *iface)
  391. {
  392.   parent_scriptable_iface = g_type_interface_peek_parent (iface);
  393.  
  394.   iface->parse_custom_node   = ttk_box_parse_custom_node;
  395.   iface->set_custom_property = ttk_box_set_custom_property;
  396. }
  397.  
  398. /************************************************************************
  399.  *                                API                                   *
  400.  ************************************************************************/
  401.  
  402. /**
  403.  * ttk_box_new:
  404.  *
  405.  * Creates a TTKBox actor.
  406.  *
  407.  * Returns: (transfer full): A newly created #TTKBox
  408.  */
  409. ClutterActor *
  410. ttk_box_new (void)
  411. {
  412.   return g_object_new (TTK_TYPE_BOX, NULL);
  413. }
  414.  
  415. /**
  416.  * ttk_box_new_full:
  417.  * @surface_width: The width for the texture
  418.  * @surface_height: The height for the texture
  419.  * @fill_color: (allow-none): The color to use to draw the box
  420.  * @outline_color: (allow-none): The outline color for the box
  421.  *
  422.  * Creates a fully parameterized TTKBox actor.
  423.  */
  424. ClutterActor *
  425. ttk_box_new_full (guint               surface_width,
  426.                   guint               surface_height,
  427.                   const ClutterColor *fill_color,
  428.                   const ClutterColor *outline_color)
  429. {
  430.   return g_object_new (TTK_TYPE_BOX,
  431.                        "init-width",  surface_width,
  432.                        "init-height", surface_height,
  433.                        "fill-color",     fill_color,
  434.                        "outline-color",  outline_color,
  435.                        NULL);
  436. }
  437.  
  438. /**
  439.  * ttk_box_set_fill_color:
  440.  * @box: A #TTKBox actor
  441.  * @fill_color: (allow-none): The color to fill the box with
  442.  *
  443.  * Sets @fill_color as the color to fill the box with
  444.  */
  445. void
  446. ttk_box_set_fill_color (TTKBox             *box,
  447.                         const ClutterColor *fill_color)
  448. {
  449.   TTKBoxPrivate       *priv;
  450.  
  451.   g_return_if_fail (TTK_IS_BOX (box));
  452.  
  453.   priv = box->priv;
  454.  
  455.   if (priv->fill_color)
  456.     {
  457.       clutter_color_free (priv->fill_color);
  458.       priv->fill_color = NULL;
  459.     }
  460.  
  461.   if (fill_color)
  462.     priv->fill_color = clutter_color_copy (fill_color);
  463.  
  464.  
  465.   TTK_NOTE (BOX, g_print ("TTKBox: invalidating for color setting\n"));
  466.  
  467.   ttk_box_invalidate (box);
  468.   g_object_notify (G_OBJECT (box), "fill-color");
  469. }
  470.  
  471. /**
  472.  * ttk_box_get_fill_color:
  473.  * @box: A #TTKBox actor
  474.  *
  475.  * Fetches the color used to fill the box with
  476.  *
  477.  * Returns: (transfer none): The color used to fill the box with
  478.  */
  479. const ClutterColor *
  480. ttk_box_get_fill_color (TTKBox *box)
  481. {
  482.   TTKBoxPrivate       *priv;
  483.  
  484.   g_return_val_if_fail (TTK_IS_BOX (box), NULL);
  485.  
  486.   priv = box->priv;
  487.  
  488.   return priv->fill_color;
  489. }
  490.  
  491. /**
  492.  * ttk_box_set_outline_color:
  493.  * @box: A #TTKBox actor
  494.  * @outline_color: (allow-none): The color to outline the box with
  495.  *
  496.  * Sets @outline_color as the color to outline the box with
  497.  */
  498. void
  499. ttk_box_set_outline_color (TTKBox             *box,
  500.                            const ClutterColor *outline_color)
  501. {
  502.   TTKBoxPrivate       *priv;
  503.  
  504.   g_return_if_fail (TTK_IS_BOX (box));
  505.  
  506.   priv = box->priv;
  507.  
  508.   if (priv->outline_color)
  509.     {
  510.       clutter_color_free (priv->outline_color);
  511.       priv->outline_color = NULL;
  512.     }
  513.  
  514.   if (outline_color)
  515.     priv->outline_color = clutter_color_copy (outline_color);
  516.   TTK_NOTE (BOX, g_print ("TTKBox: invalidating for outline color setting\n"));
  517.  
  518.   ttk_box_invalidate (box);
  519.   g_object_notify (G_OBJECT (box), "outline-color");
  520. }
  521.  
  522. /**
  523.  * ttk_box_get_outline_color:
  524.  * @box: A #TTKBox actor
  525.  *
  526.  * Fetches the color used to outline the box with
  527.  *
  528.  * Returns: (transfer none): The color used to outline the box with
  529.  */
  530. const ClutterColor *
  531. ttk_box_get_outline_color (TTKBox *box)
  532. {
  533.   TTKBoxPrivate       *priv;
  534.  
  535.   g_return_val_if_fail (TTK_IS_BOX (box), NULL);
  536.  
  537.   priv = box->priv;
  538.  
  539.   return priv->outline_color;
  540. }
  541.  
  542. /**
  543.  * ttk_box_set_outline_width:
  544.  * @box: A #TTKBox actor
  545.  * @width: The width of the outline
  546.  *
  547.  * Sets the outline width, the outline width will
  548.  * be used to call cairo_set_line_width() before
  549.  * drawing the box outline.
  550.  */
  551. void
  552. ttk_box_set_outline_width (TTKBox   *box,
  553.                            gdouble   width)
  554. {
  555.   TTKBoxPrivate       *priv;
  556.  
  557.   g_return_if_fail (TTK_IS_BOX (box));
  558.  
  559.   priv = box->priv;
  560.  
  561.   if (priv->outline_width != width)
  562.     {
  563.       priv->outline_width = width;
  564.  
  565.       TTK_NOTE (BOX, g_print ("TTKBox: invalidating for outline width setting\n"));
  566.  
  567.       ttk_box_invalidate (box);
  568.       g_object_notify (G_OBJECT (box), "outline-width");
  569.     }
  570. }
  571.  
  572. /**
  573.  * ttk_box_get_outline_width:
  574.  * @box: A #TTKBox actor
  575.  *
  576.  * Fetches the width that will be used to
  577.  * draw the box outline with cairo.
  578.  */
  579. gdouble
  580. ttk_box_get_outline_width (TTKBox *box)
  581. {
  582.   TTKBoxPrivate       *priv;
  583.  
  584.   g_return_val_if_fail (TTK_IS_BOX (box), 0.0F);
  585.  
  586.   priv = box->priv;
  587.  
  588.   return priv->outline_width;
  589. }
Add Comment
Please, Sign In to add comment