[sysprof/wip/visualizers] visualizer-ticks: start on minimal ticks implementation



commit aa21c2379f347d6bfd6dcec44209a630eeadabd6
Author: Christian Hergert <chergert redhat com>
Date:   Tue Sep 27 15:42:26 2016 -0700

    visualizer-ticks: start on minimal ticks implementation
    
    We need some sort of scale for content, so we will do this with
    an overlay for now. However, we will also want something to be
    able to do selections in the future.
    
    This still needs some iteration for correctness, but this sort
    of gets the ball rolling.

 lib/Makefile.am                |    2 +
 lib/sp-visualizer-ticks.c      |  201 ++++++++++++++++++++++++++++++++++++++++
 lib/sp-visualizer-ticks.h      |   40 ++++++++
 lib/sysprof-ui.h               |    1 +
 src/resources/theme/shared.css |    6 +-
 src/resources/ui/sp-window.ui  |   35 +++++--
 6 files changed, 273 insertions(+), 12 deletions(-)
---
diff --git a/lib/Makefile.am b/lib/Makefile.am
index e90d63c..acd604d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -151,6 +151,7 @@ uiheaders_DATA = \
        sp-recording-state-view.h \
        sp-visualizer-list.h \
        sp-visualizer-row.h \
+       sp-visualizer-ticks.h \
        sysprof-ui.h \
        $(NULL)
 
@@ -170,6 +171,7 @@ libsysprof_ui_@API_VERSION@_la_SOURCES = \
        sp-recording-state-view.c \
        sp-visualizer-list.c \
        sp-visualizer-row.c \
+       sp-visualizer-ticks.c \
        $(NULL)
 
 libsysprof_ui_@API_VERSION@_la_CFLAGS = \
diff --git a/lib/sp-visualizer-ticks.c b/lib/sp-visualizer-ticks.c
new file mode 100644
index 0000000..a03795e
--- /dev/null
+++ b/lib/sp-visualizer-ticks.c
@@ -0,0 +1,201 @@
+/* sp-visualizer-ticks.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+
+#include "sp-visualizer-ticks.h"
+
+#define NSEC_PER_SEC G_GINT64_CONSTANT(1000000000)
+#define MIN_TICK_DISTANCE 20
+
+struct _SpVisualizerTicks
+{
+  GtkDrawingArea parent_instance;
+
+  gint64 begin_time;
+  gint64 end_time;
+};
+
+enum {
+  TICK_MINUTES,
+  TICK_HALF_MINUTES,
+  TICK_SECONDS,
+  TICK_HALF_SECONDS,
+  TICK_QUARTER_SECONDS,
+  TICK_TENTHS,
+  TICK_HUNDREDTHS,
+  TICK_THOUSANDTHS,
+  N_TICKS
+};
+
+struct {
+  gint width;
+  gint height;
+  gint64 span;
+} tick_sizing[N_TICKS] = {
+  { 3, 12, NSEC_PER_SEC * 60 },
+  { 2, 11, NSEC_PER_SEC * 30 },
+  { 1, 10, NSEC_PER_SEC },
+  { 1, 9, NSEC_PER_SEC / 2 },
+  { 1, 7, NSEC_PER_SEC / 4 },
+  { 1, 6, NSEC_PER_SEC / 10 },
+  { 1, 5, NSEC_PER_SEC / 100 },
+  { 1, 4, NSEC_PER_SEC / 1000 },
+};
+
+G_DEFINE_TYPE (SpVisualizerTicks, sp_visualizer_ticks, GTK_TYPE_DRAWING_AREA)
+
+static void
+draw_ticks (SpVisualizerTicks *self,
+            cairo_t           *cr,
+            GtkAllocation     *area,
+            gint               ticks)
+{
+  gdouble half;
+  gint64 timespan;
+  gint64 n_ticks;
+  gint space;
+
+  g_assert (SP_IS_VISUALIZER_TICKS (self));
+  g_assert (cr != NULL);
+  g_assert (area != NULL);
+  g_assert (ticks >= 0);
+  g_assert (ticks < N_TICKS);
+
+  timespan = self->end_time - self->begin_time;
+  n_ticks = timespan / tick_sizing[ticks].span;
+  space = area->width / n_ticks;
+  half = tick_sizing[ticks].width / 2.0;
+
+  for (gint x = 0; x < area->width; x += space)
+    {
+      cairo_move_to (cr, x - half, 0);
+      cairo_line_to (cr, x - half, tick_sizing[ticks].height);
+    }
+
+  cairo_set_line_width (cr, tick_sizing[ticks].width);
+  cairo_stroke (cr);
+}
+
+static gboolean
+sp_visualizer_ticks_draw (GtkWidget *widget,
+                          cairo_t   *cr)
+{
+  SpVisualizerTicks *self = (SpVisualizerTicks *)widget;
+  GtkAllocation alloc;
+  gint64 timespan;
+
+  g_assert (SP_IS_VISUALIZER_TICKS (self));
+  g_assert (cr != NULL);
+
+  if (0 == (timespan = self->end_time - self->begin_time))
+    return GDK_EVENT_PROPAGATE;
+
+  gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+
+  cairo_set_source_rgba (cr, 0, 0, 0, .2);
+
+  /*
+   * We need to discover up to what level we will draw tick marks.
+   * This is based on the width of the widget and the number of ticks
+   * to draw (which is determined from our timespan). We will skip a
+   * mark if they will end up less than MIN_TICK_DISTANCE px apart.
+   */
+
+  for (guint i = G_N_ELEMENTS (tick_sizing); i > 0; i--)
+    {
+      gint64 n_ticks = timespan / tick_sizing[i - 1].span;
+
+      if ((alloc.width / n_ticks) < MIN_TICK_DISTANCE)
+        continue;
+
+      for (guint j = 0; j < i; j++)
+        draw_ticks (self, cr, &alloc, j);
+
+      break;
+    }
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+static void
+sp_visualizer_ticks_get_preferred_height (GtkWidget *widget,
+                                          gint      *min_height,
+                                          gint      *nat_height)
+{
+  g_assert (SP_IS_VISUALIZER_TICKS (widget));
+
+  *min_height = *nat_height = tick_sizing[0].height;
+}
+
+static void
+sp_visualizer_ticks_class_init (SpVisualizerTicksClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  widget_class->draw = sp_visualizer_ticks_draw;
+  widget_class->get_preferred_height = sp_visualizer_ticks_get_preferred_height;
+}
+
+static void
+sp_visualizer_ticks_init (SpVisualizerTicks *self)
+{
+  /* XXX: set range from callers */
+  self->end_time = 1000000000UL * 60UL;
+}
+
+GtkWidget *
+sp_visualizer_ticks_new (void)
+{
+  return g_object_new (SP_TYPE_VISUALIZER_TICKS, NULL);
+}
+
+void
+sp_visualizer_ticks_get_time_range (SpVisualizerTicks *self,
+                                    gint64            *begin_time,
+                                    gint64            *end_time)
+{
+  g_return_if_fail (SP_IS_VISUALIZER_TICKS (self));
+  g_return_if_fail (begin_time != NULL || end_time != NULL);
+
+  if (begin_time != NULL)
+    *begin_time = self->begin_time;
+
+  if (end_time != NULL)
+    *end_time = self->end_time;
+}
+
+void
+sp_visualizer_ticks_set_time_range (SpVisualizerTicks *self,
+                                    gint64             begin_time,
+                                    gint64             end_time)
+{
+  g_return_if_fail (SP_IS_VISUALIZER_TICKS (self));
+
+  if (begin_time < end_time)
+    {
+      gint64 tmp = begin_time;
+      begin_time = end_time;
+      end_time = tmp;
+    }
+
+  self->begin_time = begin_time;
+  self->end_time = end_time;
+
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+}
diff --git a/lib/sp-visualizer-ticks.h b/lib/sp-visualizer-ticks.h
new file mode 100644
index 0000000..c75ce5e
--- /dev/null
+++ b/lib/sp-visualizer-ticks.h
@@ -0,0 +1,40 @@
+/* sp-visualizer-ticks.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SP_VISUALIZER_TICKS_H
+#define SP_VISUALIZER_TICKS_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_VISUALIZER_TICKS (sp_visualizer_ticks_get_type())
+
+G_DECLARE_FINAL_TYPE (SpVisualizerTicks, sp_visualizer_ticks, SP, VISUALIZER_TICKS, GtkDrawingArea)
+
+GtkWidget *sp_visualizer_ticks_new            (void);
+void       sp_visualizer_ticks_get_time_range (SpVisualizerTicks *self,
+                                               gint64            *begin_time,
+                                               gint64            *end_time);
+void       sp_visualizer_ticks_set_time_range (SpVisualizerTicks *self,
+                                               gint64             begin_time,
+                                               gint64             end_time);
+
+G_END_DECLS
+
+#endif /* SP_VISUALIZER_TICKS_H */
diff --git a/lib/sysprof-ui.h b/lib/sysprof-ui.h
index f46ddf8..6e31a66 100644
--- a/lib/sysprof-ui.h
+++ b/lib/sysprof-ui.h
@@ -36,6 +36,7 @@ G_BEGIN_DECLS
 # include "sp-profiler-menu-button.h"
 # include "sp-visualizer-list.h"
 # include "sp-visualizer-row.h"
+# include "sp-visualizer-ticks.h"
 #undef SYSPROF_INSIDE
 
 G_END_DECLS
diff --git a/src/resources/theme/shared.css b/src/resources/theme/shared.css
index b7c73f1..2567c3f 100644
--- a/src/resources/theme/shared.css
+++ b/src/resources/theme/shared.css
@@ -1,10 +1,8 @@
-paned list row,
 popover list row {
   padding: 6px 10px 6px 10px;
   border-bottom: 1px solid alpha(@borders, 0.2);
 }
 
-paned list row:last-child,
 popover list row:last-child {
   border-bottom: none;
 }
@@ -12,3 +10,7 @@ popover list row:last-child {
 popover scrolledwindow {
   border-top: 1px solid alpha(@borders, 0.75);
 }
+
+list.visualizers row {
+  border-bottom: 1px solid alpha(@borders, 0.2);
+}
diff --git a/src/resources/ui/sp-window.ui b/src/resources/ui/sp-window.ui
index 5e2a2ed..656eee2 100644
--- a/src/resources/ui/sp-window.ui
+++ b/src/resources/ui/sp-window.ui
@@ -164,21 +164,36 @@
                 <property name="orientation">vertical</property>
                 <property name="visible">true</property>
                 <child>
-                  <object class="GtkScrolledWindow">
-                    <property name="min-content-height">75</property>
-                    <property name="max-content-height">225</property>
+                  <object class="GtkOverlay" id="visualizer_overlay">
                     <property name="visible">true</property>
+                    <child type="overlay">
+                      <object class="SpVisualizerTicks">
+                        <property name="valign">start</property>
+                        <property name="hexpand">true</property>
+                        <property name="visible">true</property>
+                      </object>
+                    </child>
                     <child>
-                      <object class="SpVisualizerList" id="visualizer_rows">
+                      <object class="GtkScrolledWindow">
+                        <property name="min-content-height">75</property>
+                        <property name="max-content-height">225</property>
                         <property name="visible">true</property>
                         <child>
-                          <object class="SpCpuVisualizerRow" id="cpu_row">
-                            <property name="title" translatable="yes">CPU</property>
-                            <property name="height-request">75</property>
-                            <property name="selectable">false</property>
+                          <object class="SpVisualizerList" id="visualizer_rows">
                             <property name="visible">true</property>
-                            <property name="y-lower">0.0</property>
-                            <property name="y-upper">100.0</property>
+                            <style>
+                              <class name="visualizers"/>
+                            </style>
+                            <child>
+                              <object class="SpCpuVisualizerRow" id="cpu_row">
+                                <property name="title" translatable="yes">CPU</property>
+                                <property name="height-request">75</property>
+                                <property name="selectable">false</property>
+                                <property name="visible">true</property>
+                                <property name="y-lower">0.0</property>
+                                <property name="y-upper">100.0</property>
+                              </object>
+                            </child>
                           </object>
                         </child>
                       </object>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]