[Xfce4-commits] [panel-plugins/xfce4-hardware-monitor-plugin] 24/29: Move out CurveView text overlay and do_draw_loop implementation to CanvasView
noreply at xfce.org
noreply at xfce.org
Mon Dec 18 12:45:55 CET 2017
This is an automated email from the git hooks/post-receive script.
o m e g a p h i l p u s h e d a c o m m i t t o b r a n c h m a s t e r
in repository panel-plugins/xfce4-hardware-monitor-plugin.
commit 9a268f6f317196607af28e23a55b0597bd5c7617
Author: OmegaPhil <OmegaPhil at startmail.com>
Date: Sun Dec 17 18:19:44 2017 +0000
Move out CurveView text overlay and do_draw_loop implementation to CanvasView
This allows for more than just the CurveView to implement a text
overlay, similarly for allowing maxima to be grouped per monitor
types. Just CurveView uses the new template function, others will
be next
---
po/POTFILES.in | 1 +
src/bar-view.cpp | 29 ----
src/bar-view.hpp | 29 +++-
src/canvas-view.cpp | 347 +++++++++++++++++++++++++++++++++++++++++++-
src/canvas-view.hpp | 46 +++++-
src/column-view.cpp | 28 ----
src/column-view.hpp | 29 +++-
src/curve-view.cpp | 352 ++-------------------------------------------
src/curve-view.hpp | 55 ++++---
src/flame-view.cpp | 31 ----
src/flame-view.hpp | 32 ++++-
src/plugin.cpp | 18 +--
src/plugin.hpp | 6 +-
src/preferences-window.cpp | 12 +-
14 files changed, 529 insertions(+), 486 deletions(-)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 16d36df..e7b05d7 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -2,6 +2,7 @@
# Please keep this file sorted alphabetically.
xfce4-hardware-monitor-plugin.desktop.in
src/bar-view.cpp
+src/canvas-view.cpp
src/choose-monitor-window.cpp
src/column-view.cpp
src/curve-view.cpp
diff --git a/src/bar-view.cpp b/src/bar-view.cpp
index 78e78e8..3601fa0 100644
--- a/src/bar-view.cpp
+++ b/src/bar-view.cpp
@@ -21,40 +21,11 @@
#include <cmath> // for ceil/floor
#include <algorithm> // for max/min
-#include <libgnomecanvasmm/rect.h>
-
#include "bar-view.hpp"
#include "plugin.hpp"
#include "monitor.hpp"
-//
-// class Bar - represents a single bar graph
-//
-
-class Bar
-{
-public:
- Bar(Monitor *monitor, unsigned int fill_color, bool horizontal = false);
- ~Bar();
-
- void draw(Gnome::Canvas::Canvas &canvas,
- Plugin *plugin, int width, int height, int no, int total,
- double time_offset, double max);
- double get_max_value();
- void update();
-
- Monitor *monitor;
-
-private:
- typedef std::vector<Gnome::Canvas::Rect *> box_sequence;
- box_sequence boxes;
-
- double old_value, new_value;
- bool horizontal;
- unsigned int fill_color;
-};
-
Bar::Bar(Monitor *m, unsigned int c, bool horizontal)
: monitor(m), old_value(0), new_value(0), fill_color(c)
{
diff --git a/src/bar-view.hpp b/src/bar-view.hpp
index 2865df2..762935b 100644
--- a/src/bar-view.hpp
+++ b/src/bar-view.hpp
@@ -25,11 +25,38 @@
#include <memory>
#include <libgnomecanvasmm/canvas.h>
+#include <libgnomecanvasmm/rect.h>
+
#include <glibmm/ustring.h>
#include "canvas-view.hpp"
-class Bar;
+//
+// class Bar - represents a single bar graph
+//
+
+class Bar
+{
+public:
+ Bar(Monitor *monitor, unsigned int fill_color, bool horizontal = false);
+ ~Bar();
+
+ void draw(Gnome::Canvas::Canvas &canvas,
+ Plugin *plugin, int width, int height, int no, int total,
+ double time_offset, double max);
+ double get_max_value();
+ void update();
+
+ Monitor *monitor;
+
+private:
+ typedef std::vector<Gnome::Canvas::Rect *> box_sequence;
+ box_sequence boxes;
+
+ double old_value, new_value;
+ bool horizontal;
+ unsigned int fill_color;
+};
class BarView: public CanvasView
{
diff --git a/src/canvas-view.cpp b/src/canvas-view.cpp
index 9474732..28d4ea3 100644
--- a/src/canvas-view.cpp
+++ b/src/canvas-view.cpp
@@ -26,18 +26,29 @@
#include "canvas-view.hpp"
#include "plugin.hpp"
+#include "bar-view.hpp"
+#include "curve-view.hpp"
+#include "flame-view.hpp"
+
int const CanvasView::draw_interval = 100;
int const CanvasView::draw_iterations = 10;
+// Text overlay format string substitution codes
+const Glib::ustring CanvasView::monitor_full = "%M";
+const Glib::ustring CanvasView::monitor_compact = "%m";
+const Glib::ustring CanvasView::graph_max_full = "%A";
+const Glib::ustring CanvasView::graph_max_compact = "%a";
+
CanvasView::CanvasView(bool keeps_history)
- : View(keeps_history)
+ : View(keeps_history), text_overlay(NULL)
{
}
CanvasView::~CanvasView()
{
- draw_timer.disconnect(); // FIXME: is this enough to prevent crash?
+ draw_timer.disconnect();
+ delete text_overlay;
}
void CanvasView::do_display()
@@ -141,3 +152,335 @@ bool CanvasView::draw_loop()
return true;
}
+template <typename T>
+std::list<std::pair<T*, double>> CanvasView::process_mon_maxes_text_overlay(
+ typename std::list<T*> graph_elements)
+{
+ double max;
+ typename std::list<std::pair<T*, double>> elems_and_maxes;
+
+ /* NULL references are not allowed, so those passed in must already be
+ * initialised */
+
+ // Monitor maxes maintained as a pair of <normal max>, <fixed max>
+ std::map<Glib::ustring, std::pair<int, int>> monitor_maxes;
+
+ // Monitors collected by type to allow easy access to separated data sets
+ typename std::map<Glib::ustring, std::list<T*>> elems_by_mon_type;
+
+ Glib::ustring max_formatted, max_formatted_compact, monitor_data,
+ monitor_data_compact, overlay_text, per_type_overlay_text,
+ text_overlay_format_string, tag_string,
+ separator_string = plugin->get_viewer_text_overlay_separator();
+ bool graph_max_needed = false, graph_max_compact_needed = false,
+ monitor_data_needed = false, monitor_data_compact_needed = false,
+ text_overlay_enabled = plugin->get_viewer_text_overlay_enabled();
+
+ /* Obtain maximum value of all curves/flames/bars etc in the view on a per monitor type basis
+ * but only when the user wants visualisations to be split by type,
+ * separately tracking fixed maxes incase all monitors are fixed. Graphs with
+ * fixed monitors are not supposed to be scaled, but the text overlay still
+ * needs to refer to a max if there are no normal monitors present
+ * Priority-wise, non-fixed monitor sources are always reported in preference
+ * to fixed-max sources
+ * On top of this, collect the curves together by monitor type so that they
+ * can be looped over later - easy to do this here while I'm already looping
+ * over everything, rather than maintaining a separate list on
+ * attaching/detaching monitors
+ * Unified maxes are needed even if the text overlay is not enabled */
+ mon_type_iterator it;
+ typename std::map<Glib::ustring, std::list<T*>>::iterator it_mon_type;
+ Glib::ustring mon_type;
+ for (typename std::list<T*>::iterator i = graph_elements.begin(),
+ end = graph_elements.end(); i != end; ++i)
+ {
+ if (plugin->get_viewer_monitor_type_sync_enabled())
+ {
+ // To get the real type, Monitor* must be dereferenced too...
+ mon_type = typeid(*((*i)->monitor)).name();
+ }
+ else mon_type = "All the same";
+
+ // If the monitor type hasn't yet been recorded, zero the maxes
+ it = monitor_maxes.find(mon_type);
+ if (it == monitor_maxes.end())
+ monitor_maxes[mon_type] = std::make_pair(0, 0);
+
+ if (!(*i)->monitor->fixed_max()
+ && (*i)->get_max_value() > monitor_maxes[mon_type].first)
+ monitor_maxes[mon_type].first = (*i)->get_max_value();
+ else if ((*i)->monitor->fixed_max()
+ && (*i)->monitor->max() > monitor_maxes[mon_type].second)
+ monitor_maxes[mon_type].second = (*i)->monitor->max();
+
+ // Record curve in monitor type list
+ it_mon_type = elems_by_mon_type.find(mon_type);
+ if (it_mon_type == elems_by_mon_type.end())
+ elems_by_mon_type[mon_type] = std::list<T*>();
+ elems_by_mon_type[mon_type].push_back(*i);
+ }
+
+ /* If a visualisation monitor type only has fixed maxes, then make sure the
+ * max value used is the fixed max
+ * Remember that a map iterator returns a pair of key,value!! */
+ for (mon_type_iterator i = monitor_maxes.begin(), end = monitor_maxes.end();
+ i != end; ++i)
+ {
+ if (i->second.first == 0 && i->second.second > 0)
+ i->second.first = i->second.second;
+ }
+
+ /* I tried to split out the text overlay path from non-text overlay, but as
+ * the visualisation maxes need to be tied to monitor types and not simply
+ * the biggest value across all monitors, keeping everything together in a
+ * type-based loop is still the best way */
+ if (text_overlay_enabled)
+ {
+ text_overlay_format_string = plugin->get_viewer_text_overlay_format_string();
+
+ /* Glib::ustring::npos is the strange way C++ flags as a failure to find a
+ * string */
+ if (text_overlay_format_string.find(monitor_full) != Glib::ustring::npos)
+ monitor_data_needed = true;
+ if (text_overlay_format_string.find(monitor_compact) != Glib::ustring::npos)
+ monitor_data_compact_needed = true;
+ if (text_overlay_format_string.find(graph_max_full) != Glib::ustring::npos)
+ graph_max_needed = true;
+ if (text_overlay_format_string.find(graph_max_compact) != Glib::ustring::npos)
+ graph_max_compact_needed = true;
+ }
+
+ /* Looping for all monitor types being tracked - seems to be automagically
+ * sorted in alphabetical order??
+ * Curves are both plotted and monitor values collated for the text overlay */
+ for (typename std::map<Glib::ustring,
+ std::list<T*>>::iterator i = elems_by_mon_type.begin(),
+ end = elems_by_mon_type.end(); i != end; ++i)
+ {
+ /* Loading up relevant max, at this stage fixed_max is irrelevant -
+ * remember std::map iterator returns a pair itself! */
+ max = monitor_maxes[i->first].first;
+
+ // Debug code
+ /*plugin->debug_log(
+ String::ucompose("CurveView::do_draw_loop: In top curve monitor types"
+ " loop, monitor type '%1', max %2", i->first, max));*/
+
+ if (text_overlay_enabled)
+ {
+ // Resetting variables
+ monitor_data = monitor_data_compact = max_formatted
+ = max_formatted_compact = "";
+ }
+
+ for (typename std::list<T*>::iterator r = i->second.begin(), end = i->second.end();
+ r != end; ++r)
+ {
+ /* With separating out the monitor curves based on type, the max and
+ * units reported on can be correct */
+ if (text_overlay_enabled)
+ {
+ if (graph_max_needed && max_formatted.empty())
+ max_formatted += "Max:" + separator_string +
+ (*r)->monitor->format_value(max, false);
+ if (graph_max_compact_needed && max_formatted_compact.empty())
+ max_formatted_compact += "M:" + (*r)->monitor->format_value(max, true);
+
+ // Collecting a string of monitor data to overlay later
+ if (monitor_data_needed)
+ {
+ if (!(*r)->monitor->tag.empty())
+ tag_string = (*r)->monitor->tag + ":" + separator_string;
+ else
+ tag_string = "";
+
+ if (monitor_data.empty())
+ {
+ monitor_data = tag_string +
+ (*r)->monitor->format_value((*r)->monitor->value(), false);
+ }
+ else
+ {
+ monitor_data.append(separator_string + tag_string +
+ (*r)->monitor->format_value((*r)->monitor->value(), false));
+ }
+ }
+ if (monitor_data_compact_needed)
+ {
+ if (!(*r)->monitor->tag.empty())
+ tag_string = (*r)->monitor->tag + ":";
+ else
+ tag_string = "";
+
+ if (monitor_data_compact.empty())
+ {
+ monitor_data_compact = tag_string +
+ (*r)->monitor->format_value((*r)->monitor->value(), true);
+ }
+ else
+ {
+ monitor_data_compact.append(separator_string + tag_string +
+ (*r)->monitor->format_value((*r)->monitor->value(), true));
+ }
+ }
+ }
+
+ // Drawing the curves with the unified max value
+ //(*r)->draw(*canvas, width(), height(), max);
+ elems_and_maxes.push_back(std::make_pair(*r, max));
+ }
+
+ if (text_overlay_enabled)
+ {
+ /* Generation of text to overlay. This is now done on a per monitor type
+ * basis so that the maxes and units can be correctly reported on
+ * C++ does not have 'replace all' functionality??? Presumably using regex
+ * would be too slow for here? */
+ per_type_overlay_text = text_overlay_format_string;
+ if (monitor_data_needed)
+ find_and_replace(per_type_overlay_text, monitor_full, monitor_data);
+ if (monitor_data_compact_needed)
+ find_and_replace(per_type_overlay_text, monitor_compact,
+ monitor_data_compact);
+ if (graph_max_needed)
+ find_and_replace(per_type_overlay_text, graph_max_full, max_formatted);
+ if (graph_max_compact_needed)
+ find_and_replace(per_type_overlay_text, graph_max_compact,
+ max_formatted_compact);
+ if (overlay_text.empty())
+ overlay_text = per_type_overlay_text;
+ else
+ overlay_text += separator_string + per_type_overlay_text;
+ }
+ }
+
+ if (text_overlay_enabled)
+ {
+ // Checking if overlay is already initialised
+ if (!text_overlay)
+ {
+ /* Font and colour are required to output text, anchor is used to define
+ * what point on the item (canvas thing) to take as the 'centre' to then
+ * place on the canvas - e.g. ANCHOR_NW means the top-left corner is the
+ * 'centre' and the item will be placed exactly as you would expect it to.
+ * The default is GTK_ANCHOR_CENTER, hence text gets clipped in half top
+ * and side */
+ text_overlay = new Gnome::Canvas::Text(*canvas->root());
+ text_overlay->property_anchor() = Gtk::ANCHOR_NW;
+ text_overlay->property_text() = overlay_text;
+ }
+
+ // It is - updating if it has changed
+ else if (text_overlay->property_text() != overlay_text)
+ text_overlay->property_text() = overlay_text;
+
+ /* Setting/fixing changed font and colour - doing it here since the CurveView
+ * updates so frequently that its not worth also setting it directly from the
+ * UI etc */
+ Glib::ustring font_details = plugin->get_viewer_text_overlay_font();
+ if (font_details.empty())
+ font_details = "Sans 8";
+ if (text_overlay->property_font() != font_details)
+ text_overlay->property_font() = font_details;
+
+ unsigned int color = plugin->get_viewer_text_overlay_color();
+ if (text_overlay->property_fill_color_rgba() != color)
+ text_overlay->property_fill_color_rgba() = color;
+
+ // Positioning text
+ int x, y;
+ text_overlay_calc_position(x, y, plugin->get_viewer_text_overlay_position());
+ if (text_overlay->property_x() != x)
+ text_overlay->property_x() = x;
+ if (text_overlay->property_y() != y)
+ text_overlay->property_y() = y;
+ }
+ else
+ {
+ // Text overlay not enabled - ensure text is erased
+ if (text_overlay && text_overlay->property_text() != "")
+ text_overlay->property_text() = "";
+ }
+
+ return elems_and_maxes;
+}
+
+void CanvasView::text_overlay_calc_position(int& x, int& y,
+ TextOverlayPosition position)
+{
+ switch(position)
+ {
+ case top_left:
+ x = y = 0;
+ break;
+
+ case top_center:
+ x = (plugin->get_width() - text_overlay->property_text_width()) / 2;
+ y = 0;
+ break;
+
+ case top_right:
+ x = plugin->get_width() - text_overlay->property_text_width();
+ y = 0;
+ break;
+
+ case center:
+ x = (plugin->get_width() - text_overlay->property_text_width()) / 2;
+ y = (plugin->get_height() - text_overlay->property_text_height()) / 2;
+ break;
+
+ case bottom_left:
+ x = 0;
+ y = plugin->get_height() - text_overlay->property_text_height();
+ break;
+
+ case bottom_center:
+ x = (plugin->get_width() - text_overlay->property_text_width()) / 2;
+ y = plugin->get_height() - text_overlay->property_text_height();
+ break;
+
+ case bottom_right:
+ x = plugin->get_width() - text_overlay->property_text_width();
+ y = plugin->get_height() - text_overlay->property_text_height();
+ break;
+
+ default:
+ x = y = 0;
+ break;
+ }
+}
+
+const Glib::ustring CanvasView::text_overlay_position_to_string(
+ TextOverlayPosition position)
+{
+ switch(position)
+ {
+ case top_left:
+ return _("Top left");
+ case top_center:
+ return _("Top center");
+ case top_right:
+ return _("Top right");
+ case center:
+ return _("Center");
+ case bottom_left:
+ return _("Bottom left");
+ case bottom_center:
+ return _("Bottom center");
+ case bottom_right:
+ return _("Bottom right");
+ default:
+ return _("Top left");
+ }
+}
+
+/* Forced instantiation of template function to ensure the linker actually has
+ * something to link to from another compilation unit... without the include
+ * hell of moving the function implementation to the header */
+template class std::list<std::pair<Bar*, double>> CanvasView::process_mon_maxes_text_overlay(
+ typename std::list<Bar*> graph_elements);
+template class std::list<std::pair<Curve*, double>> CanvasView::process_mon_maxes_text_overlay(
+ typename std::list<Curve*> graph_elements);
+template class std::list<std::pair<Flame*, double>> CanvasView::process_mon_maxes_text_overlay(
+ typename std::list<Flame*> graph_elements);
+
diff --git a/src/canvas-view.hpp b/src/canvas-view.hpp
index c6e4021..0893c36 100644
--- a/src/canvas-view.hpp
+++ b/src/canvas-view.hpp
@@ -25,6 +25,7 @@
#include <memory>
#include <libgnomecanvasmm/canvas.h>
+#include <libgnomecanvasmm/text.h>
#include <glibmm/ustring.h>
#include <gtkmm/frame.h>
@@ -36,30 +37,53 @@ class Canvas;
class CanvasView: public View, public sigc::trackable
{
public:
+
+ enum TextOverlayPosition {
+ top_left,
+ top_center,
+ top_right,
+ center,
+ bottom_left,
+ bottom_center,
+ bottom_right,
+ NUM_TEXT_OVERLAY_POSITIONS
+ };
+
CanvasView(bool keeps_history);
~CanvasView();
+ /* Used to locate monitor type of interest in monitor_maxes during
+ * visualisation draw loop */
+ typedef std::map<Glib::ustring, std::pair<int, int>>::iterator
+ mon_type_iterator;
+
+ static const Glib::ustring text_overlay_position_to_string(
+ TextOverlayPosition position);
+
static int const draw_interval;
// for animation, number of drawings to break an update into
static int const draw_iterations;
-
+
protected:
virtual void do_display();
virtual void do_update();
virtual void do_set_background(unsigned int color);
virtual void do_unset_background();
+ /* Included in the header as other compilation units need access to the
+ * definition in order to instantiate the relevant template function
+ * TODO: When I officially move to C++11, implement 'alias templates' as a
+ * form of typedefs that work with template declarations */
+ template <typename T>
+ std::list<std::pair<T*, double>> process_mon_maxes_text_overlay(
+ typename std::list<T*> graph_elements);
+
int width() const;
int height() const;
void resize_canvas(); // resize canvas according to width and height
int size; // in pixels, width when vertical, else height
- /* Used to locate monitor type of interest in monitor_maxes during
- * visualisation draw loop */
- typedef std::map<Glib::ustring, std::pair<int, int>>::iterator
- mon_type_iterator;
-
std::auto_ptr<Gnome::Canvas::Canvas> canvas;
sigc::connection draw_timer;
@@ -67,6 +91,16 @@ protected:
private:
bool draw_loop();
virtual void do_draw_loop() = 0;
+
+ void text_overlay_calc_position(int &x, int &y, TextOverlayPosition position);
+
+ Gnome::Canvas::Text *text_overlay;
+
+ // Text overlay format string substitution codes
+ static const Glib::ustring monitor_full;
+ static const Glib::ustring monitor_compact;
+ static const Glib::ustring graph_max_full;
+ static const Glib::ustring graph_max_compact;
};
#endif
diff --git a/src/column-view.cpp b/src/column-view.cpp
index 86999fe..0e7d260 100644
--- a/src/column-view.cpp
+++ b/src/column-view.cpp
@@ -19,41 +19,13 @@
#include <cmath>
-#include <libgnomecanvasmm/pixbuf.h>
-
#include "column-view.hpp"
#include "plugin.hpp"
#include "monitor.hpp"
-#include "value-history.hpp"
#include "pixbuf-drawing.hpp"
-//
-// class ColumnGraph - represents the columns in a column diagram
-//
-
-class ColumnGraph
-{
-public:
- ColumnGraph(Monitor *monitor, unsigned int color);
-
- void update(unsigned int max_samples); // Gather info from monitor
- void draw(Gnome::Canvas::Canvas &canvas, // Redraw columns on canvas
- Plugin *plugin, int width, int height, double max);
- double get_max_value(); // Used to get overall max across columns
-
- Monitor *monitor;
-
-private:
- // A pixbuf is used for the columns
- std::auto_ptr<Gnome::Canvas::Pixbuf> columns;
-
- ValueHistory value_history;
- int remaining_draws;
- unsigned int color;
-};
-
ColumnGraph::ColumnGraph(Monitor *m, unsigned int c)
: monitor(m), value_history(m), remaining_draws(0), color(c)
{
diff --git a/src/column-view.hpp b/src/column-view.hpp
index 110c085..945e433 100644
--- a/src/column-view.hpp
+++ b/src/column-view.hpp
@@ -25,12 +25,39 @@
#include <memory>
#include <libgnomecanvasmm/canvas.h>
+#include <libgnomecanvasmm/pixbuf.h>
+
#include <glibmm/ustring.h>
#include "canvas-view.hpp"
+#include "value-history.hpp"
+
+
+//
+// class ColumnGraph - represents the columns in a column diagram
+//
+
+class ColumnGraph
+{
+public:
+ ColumnGraph(Monitor *monitor, unsigned int color);
+ void update(unsigned int max_samples); // Gather info from monitor
+ void draw(Gnome::Canvas::Canvas &canvas, // Redraw columns on canvas
+ Plugin *plugin, int width, int height, double max);
+ double get_max_value(); // Used to get overall max across columns
+
+ Monitor *monitor;
+
+private:
+ // A pixbuf is used for the columns
+ std::auto_ptr<Gnome::Canvas::Pixbuf> columns;
+
+ ValueHistory value_history;
+ int remaining_draws;
+ unsigned int color;
+};
-class ColumnGraph;
class ColumnView: public CanvasView
{
diff --git a/src/curve-view.cpp b/src/curve-view.cpp
index 8214ea9..c06910d 100644
--- a/src/curve-view.cpp
+++ b/src/curve-view.cpp
@@ -22,7 +22,6 @@
#include <typeinfo> // For keeping track of monitor types in the visualisation
#include <utility> // For keeping track of monitor types in the visualisation
-#include <libgnomecanvasmm/line.h>
#include <libgnomecanvasmm/point.h>
#include "curve-view.hpp"
@@ -33,30 +32,6 @@
#include "value-history.hpp"
-//
-// class Curve - represents a line curve
-//
-
-class Curve
-{
-public:
- Curve(Monitor *monitor, unsigned int color);
-
- void update(unsigned int max_samples); // Gather info from monitor
- void draw(Gnome::Canvas::Canvas &canvas, // Redraw curve on canvas
- int width, int height, double max);
- double get_max_value(); // Used to get overall max across curves
-
- Monitor *monitor;
-
-private:
- std::auto_ptr<Gnome::Canvas::Line> line;
-
- ValueHistory value_history;
- int remaining_draws;
- unsigned int color;
-};
-
Curve::Curve(Monitor *m, unsigned int c)
: monitor(m), value_history(m), remaining_draws(0), color(c)
{}
@@ -161,15 +136,8 @@ double Curve::get_max_value()
int const CurveView::pixels_per_sample = 2;
-// Text overlay format string substitution codes
-const Glib::ustring CurveView::monitor_full = "%M";
-const Glib::ustring CurveView::monitor_compact = "%m";
-const Glib::ustring CurveView::graph_max_full = "%A";
-const Glib::ustring CurveView::graph_max_compact = "%a";
-
-
CurveView::CurveView()
- : CanvasView(true), text_overlay(NULL)
+ : CanvasView(true)
{
}
@@ -177,7 +145,6 @@ CurveView::~CurveView()
{
for (curve_iterator i = curves.begin(), end = curves.end(); i != end; ++i)
delete *i;
- delete text_overlay;
}
void CurveView::do_update()
@@ -270,311 +237,16 @@ void CurveView::do_detach(Monitor *monitor)
void CurveView::do_draw_loop()
{
- double max;
-
- // Monitor maxes maintained as a pair of <normal max>, <fixed max>
- std::map<Glib::ustring, std::pair<int, int>> monitor_maxes;
-
- // Monitors collected by type to allow easy access to separated data sets
- std::map<Glib::ustring, std::list<Curve*>> curves_by_mon_type;
-
- Glib::ustring max_formatted, max_formatted_compact, monitor_data,
- monitor_data_compact, overlay_text, per_type_overlay_text,
- text_overlay_format_string, tag_string,
- separator_string = plugin->get_viewer_text_overlay_separator();
- bool graph_max_needed = false, graph_max_compact_needed = false,
- monitor_data_needed = false, monitor_data_compact_needed = false,
- text_overlay_enabled = plugin->get_viewer_text_overlay_enabled();
-
- /* Obtain maximum value of all curves in the view on a per monitor type basis
- * but only when the user wants visualisations to be split by type,
- * separately tracking fixed maxes incase all monitors are fixed. Graphs with
- * fixed monitors are not supposed to be scaled, but the text overlay still
- * needs to refer to a max if there are no normal monitors present
- * Priority-wise, non-fixed monitor sources are always reported in preference
- * to fixed-max sources
- * On top of this, collect the curves together by monitor type so that they
- * can be looped over later - easy to do this here while I'm already looping
- * over everything, rather than maintaining a separate list on
- * attaching/detaching monitors
- * Unified maxes are needed even if the text overlay is not enabled */
- mon_type_iterator it;
- curves_mon_type_iterator it_mon_type;
- Glib::ustring mon_type;
- for (curve_iterator i = curves.begin(), end = curves.end(); i != end; ++i)
- {
- if (plugin->get_viewer_monitor_type_sync_enabled())
- {
- // To get the real type, Monitor* must be dereferenced too...
- mon_type = typeid(*((*i)->monitor)).name();
- }
- else mon_type = "All the same";
-
- // If the monitor type hasn't yet been recorded, zero the maxes
- it = monitor_maxes.find(mon_type);
- if (it == monitor_maxes.end())
- monitor_maxes[mon_type] = std::make_pair(0, 0);
-
- if (!(*i)->monitor->fixed_max()
- && (*i)->get_max_value() > monitor_maxes[mon_type].first)
- monitor_maxes[mon_type].first = (*i)->get_max_value();
- else if ((*i)->monitor->fixed_max()
- && (*i)->monitor->max() > monitor_maxes[mon_type].second)
- monitor_maxes[mon_type].second = (*i)->monitor->max();
-
- // Record curve in monitor type list
- it_mon_type = curves_by_mon_type.find(mon_type);
- if (it_mon_type == curves_by_mon_type.end())
- curves_by_mon_type[mon_type] = std::list<Curve*>();
- curves_by_mon_type[mon_type].push_back(*i);
- }
-
- /* If a visualisation monitor type only has fixed maxes, then make sure the
- * max value used is the fixed max
- * Remember that a map iterator returns a pair of key,value!! */
- for (mon_type_iterator i = monitor_maxes.begin(), end = monitor_maxes.end();
- i != end; ++i)
- {
- if (i->second.first == 0 && i->second.second > 0)
- i->second.first = i->second.second;
- }
-
- /* I tried to split out the text overlay path from non-text overlay, but as
- * the visualisation maxes need to be tied to monitor types and not simply
- * the biggest value across all monitors, keeping everything together in a
- * type-based loop is still the best way */
- if (text_overlay_enabled)
- {
- text_overlay_format_string = plugin->get_viewer_text_overlay_format_string();
-
- /* Glib::ustring::npos is the strange way C++ flags as a failure to find a
- * string */
- if (text_overlay_format_string.find(monitor_full) != Glib::ustring::npos)
- monitor_data_needed = true;
- if (text_overlay_format_string.find(monitor_compact) != Glib::ustring::npos)
- monitor_data_compact_needed = true;
- if (text_overlay_format_string.find(graph_max_full) != Glib::ustring::npos)
- graph_max_needed = true;
- if (text_overlay_format_string.find(graph_max_compact) != Glib::ustring::npos)
- graph_max_compact_needed = true;
- }
-
- /* Looping for all monitor types being tracked - seems to be automagically
- * sorted in alphabetical order??
- * Curves are both plotted and monitor values collated for the text overlay */
- for (curves_mon_type_iterator i = curves_by_mon_type.begin(),
- end = curves_by_mon_type.end(); i != end; ++i)
- {
- /* Loading up relevant max, at this stage fixed_max is irrelevant -
- * remember std::map iterator returns a pair itself! */
- max = monitor_maxes[i->first].first;
-
- // Debug code
- /*plugin->debug_log(
- String::ucompose("CurveView::do_draw_loop: In top curve monitor types"
- " loop, monitor type '%1', max %2", i->first, max));*/
-
- if (text_overlay_enabled)
- {
- // Resetting variables
- monitor_data = monitor_data_compact = max_formatted
- = max_formatted_compact = "";
- }
-
- for (curve_iterator r = i->second.begin(), end = i->second.end();
- r != end; ++r)
- {
- /* With separating out the monitor curves based on type, the max and
- * units reported on can be correct */
- if (text_overlay_enabled)
- {
- if (graph_max_needed && max_formatted.empty())
- max_formatted += "Max:" + separator_string +
- (*r)->monitor->format_value(max, false);
- if (graph_max_compact_needed && max_formatted_compact.empty())
- max_formatted_compact += "M:" + (*r)->monitor->format_value(max, true);
-
- // Collecting a string of monitor data to overlay later
- if (monitor_data_needed)
- {
- if (!(*r)->monitor->tag.empty())
- tag_string = (*r)->monitor->tag + ":" + separator_string;
- else
- tag_string = "";
-
- if (monitor_data.empty())
- {
- monitor_data = tag_string +
- (*r)->monitor->format_value((*r)->monitor->value(), false);
- }
- else
- {
- monitor_data.append(separator_string + tag_string +
- (*r)->monitor->format_value((*r)->monitor->value(), false));
- }
- }
- if (monitor_data_compact_needed)
- {
- if (!(*r)->monitor->tag.empty())
- tag_string = (*r)->monitor->tag + ":";
- else
- tag_string = "";
-
- if (monitor_data_compact.empty())
- {
- monitor_data_compact = tag_string +
- (*r)->monitor->format_value((*r)->monitor->value(), true);
- }
- else
- {
- monitor_data_compact.append(separator_string + tag_string +
- (*r)->monitor->format_value((*r)->monitor->value(), true));
- }
- }
- }
-
- // Drawing the curves with the unified max value
- (*r)->draw(*canvas, width(), height(), max);
- }
-
- if (text_overlay_enabled)
- {
- /* Generation of text to overlay. This is now done on a per monitor type
- * basis so that the maxes and units can be correctly reported on
- * C++ does not have 'replace all' functionality??? Presumably using regex
- * would be too slow for here? */
- per_type_overlay_text = text_overlay_format_string;
- if (monitor_data_needed)
- find_and_replace(per_type_overlay_text, monitor_full, monitor_data);
- if (monitor_data_compact_needed)
- find_and_replace(per_type_overlay_text, monitor_compact,
- monitor_data_compact);
- if (graph_max_needed)
- find_and_replace(per_type_overlay_text, graph_max_full, max_formatted);
- if (graph_max_compact_needed)
- find_and_replace(per_type_overlay_text, graph_max_compact,
- max_formatted_compact);
- if (overlay_text.empty())
- overlay_text = per_type_overlay_text;
- else
- overlay_text += separator_string + per_type_overlay_text;
- }
- }
-
- if (text_overlay_enabled)
- {
- // Checking if overlay is already initialised
- if (!text_overlay)
- {
- /* Font and colour are required to output text, anchor is used to define
- * what point on the item (canvas thing) to take as the 'centre' to then
- * place on the canvas - e.g. ANCHOR_NW means the top-left corner is the
- * 'centre' and the item will be placed exactly as you would expect it to.
- * The default is GTK_ANCHOR_CENTER, hence text gets clipped in half top
- * and side */
- text_overlay = new Gnome::Canvas::Text(*canvas->root());
- text_overlay->property_anchor() = Gtk::ANCHOR_NW;
- text_overlay->property_text() = overlay_text;
- }
-
- // It is - updating if it has changed
- else if (text_overlay->property_text() != overlay_text)
- text_overlay->property_text() = overlay_text;
-
- /* Setting/fixing changed font and colour - doing it here since the CurveView
- * updates so frequently that its not worth also setting it directly from the
- * UI etc */
- Glib::ustring font_details = plugin->get_viewer_text_overlay_font();
- if (font_details.empty())
- font_details = "Sans 8";
- if (text_overlay->property_font() != font_details)
- text_overlay->property_font() = font_details;
-
- unsigned int color = plugin->get_viewer_text_overlay_color();
- if (text_overlay->property_fill_color_rgba() != color)
- text_overlay->property_fill_color_rgba() = color;
-
- // Positioning text
- int x, y;
- text_overlay_calc_position(x, y, plugin->get_viewer_text_overlay_position());
- if (text_overlay->property_x() != x)
- text_overlay->property_x() = x;
- if (text_overlay->property_y() != y)
- text_overlay->property_y() = y;
- }
- else
- {
- // Text overlay not enabled - ensure text is erased
- if (text_overlay && text_overlay->property_text() != "")
- text_overlay->property_text() = "";
- }
-}
-
-const Glib::ustring CurveView::text_overlay_position_to_string(
- TextOverlayPosition position)
-{
- switch(position)
- {
- case top_left:
- return _("Top left");
- case top_center:
- return _("Top center");
- case top_right:
- return _("Top right");
- case center:
- return _("Center");
- case bottom_left:
- return _("Bottom left");
- case bottom_center:
- return _("Bottom center");
- case bottom_right:
- return _("Bottom right");
- default:
- return _("Top left");
- }
-}
-
-void CurveView::text_overlay_calc_position(int& x, int& y,
- TextOverlayPosition position)
-{
- switch(position)
- {
- case top_left:
- x = y = 0;
- break;
- case top_center:
- x = (plugin->get_width() - text_overlay->property_text_width()) / 2;
- y = 0;
- break;
-
- case top_right:
- x = plugin->get_width() - text_overlay->property_text_width();
- y = 0;
- break;
-
- case center:
- x = (plugin->get_width() - text_overlay->property_text_width()) / 2;
- y = (plugin->get_height() - text_overlay->property_text_height()) / 2;
- break;
-
- case bottom_left:
- x = 0;
- y = plugin->get_height() - text_overlay->property_text_height();
- break;
-
- case bottom_center:
- x = (plugin->get_width() - text_overlay->property_text_width()) / 2;
- y = plugin->get_height() - text_overlay->property_text_height();
- break;
-
- case bottom_right:
- x = plugin->get_width() - text_overlay->property_text_width();
- y = plugin->get_height() - text_overlay->property_text_height();
- break;
-
- default:
- x = y = 0;
- break;
- }
+ /* Generating list of curves with correct maxima (unified and potentially
+ * grouped by monitor type) to then draw, and triggering processing of text
+ * overlay on the CanvasView if the user desires */
+ std::list<std::pair<Curve*, double>> curves_and_maxes =
+ process_mon_maxes_text_overlay(curves);
+
+ /* Looping for all curves to draw - in the std::pair, first is the Curve,
+ * second is the max */
+ for (std::list<std::pair<Curve*, double>>::iterator i = curves_and_maxes.begin(),
+ end = curves_and_maxes.end(); i != end; ++i)
+ i->first->draw(*canvas, width(), height(), i->second);
}
diff --git a/src/curve-view.hpp b/src/curve-view.hpp
index 31f1b21..e18725f 100644
--- a/src/curve-view.hpp
+++ b/src/curve-view.hpp
@@ -23,13 +23,38 @@
#include <memory>
#include <libgnomecanvasmm/canvas.h>
+#include <libgnomecanvasmm/line.h>
#include <libgnomecanvasmm/text.h>
#include <glibmm/ustring.h>
#include "canvas-view.hpp"
+#include "value-history.hpp"
-class Curve;
+//
+// class Curve - represents a line curve
+//
+
+class Curve
+{
+public:
+ Curve(Monitor *monitor, unsigned int color);
+
+ void update(unsigned int max_samples); // Gather info from monitor
+ void draw(Gnome::Canvas::Canvas &canvas, // Redraw curve on canvas
+ int width, int height, double max);
+ double get_max_value(); // Used to get overall max across curves
+
+ Monitor *monitor;
+
+private:
+ std::auto_ptr<Gnome::Canvas::Line> line;
+
+ ValueHistory value_history;
+ int remaining_draws;
+ unsigned int color;
+};
+
class CurveView: public CanvasView
{
@@ -39,44 +64,16 @@ public:
static int const pixels_per_sample;
- enum TextOverlayPosition {
- top_left,
- top_center,
- top_right,
- center,
- bottom_left,
- bottom_center,
- bottom_right,
- NUM_TEXT_OVERLAY_POSITIONS
- };
-
- static const Glib::ustring text_overlay_position_to_string(
- TextOverlayPosition position);
-
private:
virtual void do_update();
virtual void do_attach(Monitor *monitor);
virtual void do_detach(Monitor *monitor);
virtual void do_draw_loop();
- void text_overlay_calc_position(int &x, int &y, TextOverlayPosition position);
-
// Must be destroyed before the canvas
typedef std::list<Curve *> curve_sequence;
typedef curve_sequence::iterator curve_iterator;
curve_sequence curves;
-
- // Used to move through curves maintained per monitor type
- typedef std::map<Glib::ustring, std::list<Curve*>>::iterator
- curves_mon_type_iterator;
-
- Gnome::Canvas::Text *text_overlay;
-
- // Text overlay format string substitution codes
- static const Glib::ustring monitor_full;
- static const Glib::ustring monitor_compact;
- static const Glib::ustring graph_max_full;
- static const Glib::ustring graph_max_compact;
};
#endif
diff --git a/src/flame-view.cpp b/src/flame-view.cpp
index 67d9cab..b868d1a 100644
--- a/src/flame-view.cpp
+++ b/src/flame-view.cpp
@@ -21,8 +21,6 @@
#include <cmath>
#include <vector>
-#include <libgnomecanvasmm/pixbuf.h>
-
#include "pixbuf-drawing.hpp"
#include "flame-view.hpp"
@@ -30,35 +28,6 @@
#include "monitor.hpp"
-//
-// class Flame - represents a flame layer
-//
-
-class Flame
-{
-public:
- Flame(Monitor *monitor, unsigned int color);
-
- void burn(double overall_max);
- double get_max_value();
- void update(Gnome::Canvas::Canvas &canvas,
- Plugin *plugin, int width, int height, int no, int total);
-
- Monitor *monitor;
-
-private:
- std::auto_ptr<Gnome::Canvas::Pixbuf> flame;
-
- double value, max;
-
- std::vector<unsigned char> fuel;
- int next_refuel;
- int cooling; // cooling factor
-
- void recompute_fuel(double overall_max);
- unsigned int color;
-};
-
Flame::Flame(Monitor *m, unsigned int c)
: monitor(m), value(0), next_refuel(0), color(c)
{}
diff --git a/src/flame-view.hpp b/src/flame-view.hpp
index e2db676..ea9d76a 100644
--- a/src/flame-view.hpp
+++ b/src/flame-view.hpp
@@ -26,12 +26,42 @@
#include <memory>
#include <libgnomecanvasmm/canvas.h>
+#include <libgnomecanvasmm/pixbuf.h>
+
#include <glibmm/ustring.h>
#include "canvas-view.hpp"
-class Flame;
+//
+// class Flame - represents a flame layer
+//
+
+class Flame
+{
+public:
+ Flame(Monitor *monitor, unsigned int color);
+
+ void burn(double overall_max);
+ double get_max_value();
+ void update(Gnome::Canvas::Canvas &canvas,
+ Plugin *plugin, int width, int height, int no, int total);
+
+ Monitor *monitor;
+
+private:
+ std::auto_ptr<Gnome::Canvas::Pixbuf> flame;
+
+ double value, max;
+
+ std::vector<unsigned char> fuel;
+ int next_refuel;
+ int cooling; // cooling factor
+
+ void recompute_fuel(double overall_max);
+ unsigned int color;
+};
+
class FlameView: public CanvasView
{
diff --git a/src/plugin.cpp b/src/plugin.cpp
index 4b4e0ea..982d66a 100644
--- a/src/plugin.cpp
+++ b/src/plugin.cpp
@@ -167,7 +167,7 @@ Plugin::Plugin(XfcePanelPlugin *xfce_plugin)
viewer_text_overlay_separator(" "),
viewer_text_overlay_font(""),
viewer_text_overlay_color(0x000000FF),
- viewer_text_overlay_position(CurveView::top_left),
+ viewer_text_overlay_position(CanvasView::top_left),
viewer_monitor_type_sync_enabled(true)
{
// Search for settings file
@@ -211,10 +211,10 @@ Plugin::Plugin(XfcePanelPlugin *xfce_plugin)
"viewer_monitor_type_sync_enabled", viewer_monitor_type_sync_enabled);
// Enum is validated in set_viewer_text_overlay_position
- CurveView::TextOverlayPosition text_overlay_position =
- static_cast<CurveView::TextOverlayPosition>(
+ CanvasView::TextOverlayPosition text_overlay_position =
+ static_cast<CanvasView::TextOverlayPosition>(
xfce_rc_read_int_entry(settings_ro, "viewer_text_overlay_position",
- CurveView::top_left));
+ CanvasView::top_left));
set_viewer_text_overlay_position(text_overlay_position);
}
@@ -631,21 +631,21 @@ void Plugin::set_viewer_text_overlay_color(const unsigned int color)
viewer_text_overlay_color = color;
}
-const CurveView::TextOverlayPosition Plugin::get_viewer_text_overlay_position()
+const CanvasView::TextOverlayPosition Plugin::get_viewer_text_overlay_position()
{
return viewer_text_overlay_position;
}
-void Plugin::set_viewer_text_overlay_position(CurveView::TextOverlayPosition
+void Plugin::set_viewer_text_overlay_position(CanvasView::TextOverlayPosition
position)
{
// Validating input - an enum does not enforce a range!!
- if (position < CurveView::top_left ||
- position >= CurveView::NUM_TEXT_OVERLAY_POSITIONS)
+ if (position < CanvasView::top_left ||
+ position >= CanvasView::NUM_TEXT_OVERLAY_POSITIONS)
{
std::cerr << "Plugin::set_viewer_text_overlay_position was called with an "
"invalid position: " << position << "!\n";
- position = CurveView::top_left;
+ position = CanvasView::top_left;
}
viewer_text_overlay_position = position;
diff --git a/src/plugin.hpp b/src/plugin.hpp
index f4aaa3f..a8169e0 100644
--- a/src/plugin.hpp
+++ b/src/plugin.hpp
@@ -85,8 +85,8 @@ public:
void set_viewer_text_overlay_font(const Glib::ustring font_details);
const unsigned int get_viewer_text_overlay_color() const;
void set_viewer_text_overlay_color(const unsigned int color);
- const CurveView::TextOverlayPosition get_viewer_text_overlay_position();
- void set_viewer_text_overlay_position(CurveView::TextOverlayPosition
+ const CanvasView::TextOverlayPosition get_viewer_text_overlay_position();
+ void set_viewer_text_overlay_position(CanvasView::TextOverlayPosition
position);
/* Force update allows for this to be called to essentially reload the view
@@ -144,7 +144,7 @@ private:
Glib::ustring viewer_text_overlay_format_string, viewer_text_overlay_separator,
viewer_text_overlay_font;
unsigned int viewer_text_overlay_color;
- CurveView::TextOverlayPosition viewer_text_overlay_position;
+ CanvasView::TextOverlayPosition viewer_text_overlay_position;
unsigned int background_color;
int viewer_size, next_color;
diff --git a/src/preferences-window.cpp b/src/preferences-window.cpp
index 4d3149e..c2d277d 100644
--- a/src/preferences-window.cpp
+++ b/src/preferences-window.cpp
@@ -31,7 +31,7 @@
#include "gui-helpers.hpp"
#include "plugin.hpp"
#include "monitor.hpp"
-#include "curve-view.hpp"
+#include "canvas-view.hpp"
#include "i18n.hpp"
@@ -253,15 +253,15 @@ PreferencesWindow::PreferencesWindow(Plugin &plugin_, monitor_seq monitors)
monitor_treeview->get_selection()->unselect_all();
// Populating text overlay position combobox and selecting the correct position
- CurveView::TextOverlayPosition current_pos, position =
+ CanvasView::TextOverlayPosition current_pos, position =
plugin.get_viewer_text_overlay_position();
store_iter i;
- for (int r = 0; r < CurveView::NUM_TEXT_OVERLAY_POSITIONS; ++r)
+ for (int r = 0; r < CanvasView::NUM_TEXT_OVERLAY_POSITIONS; ++r)
{
- current_pos = static_cast<CurveView::TextOverlayPosition>(r);
+ current_pos = static_cast<CanvasView::TextOverlayPosition>(r);
i = text_overlay_position_store->append();
- (*i)[topc.position] = CurveView::text_overlay_position_to_string(current_pos);
+ (*i)[topc.position] = CanvasView::text_overlay_position_to_string(current_pos);
if (position == current_pos)
text_overlay_position_combobox->set_active(r);
@@ -919,7 +919,7 @@ void PreferencesWindow::on_text_overlay_position_combobox_changed()
int position = text_overlay_position_combobox->get_active_row_number();
plugin.set_viewer_text_overlay_position(
- static_cast<CurveView::TextOverlayPosition>(position));
+ static_cast<CanvasView::TextOverlayPosition>(position));
// Search for a writeable settings file, create one if it doesnt exist */
gchar* file = xfce_panel_plugin_save_location(plugin.xfce_plugin, true);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the Xfce4-commits
mailing list