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 <[email protected]> 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. _______________________________________________ Xfce4-commits mailing list [email protected] https://mail.xfce.org/mailman/listinfo/xfce4-commits
