/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #+ #+ Glade / Gtk Programming #+ #+ Copyright (C) 2019 by Kevin C. O'Kane #+ #+ Kevin C. O'Kane #+ kc.okane@gmail.com #+ https://www.cs.uni.edu/~okane #+ http://threadsafebooks.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 2 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, write to the Free Software #+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ // May 14, 2019 #include #include #include #include #include #include #include #include #include #include #include #include int showArc = 0; // show filled-in arc along with needle? double Load; guint width=100, height=50; // initial dimensions of meter void on_destroy() { gtk_main_quit(); } //------------------------------------------------------------- // main timer process // called every 1000 milliseconds to update the meter //------------------------------------------------------------- gboolean timer_handler() { //-------------------------------- // read the system load data //-------------------------------- FILE *f1 = fopen("/proc/loadavg", "r"); fscanf(f1, "%lf", &Load); fclose(f1); gtk_widget_queue_draw (draw2); return TRUE; // please return } //-------------------------- // draw meters //-------------------------- void needles(cairo_t *cr, double hor, double ver, double len, double t1) { double x, x1, x2, y, y1, y2; double X; if (t1 > M_PI) t1 = M_PI; // limit is M_PI (PI) //------------------------------------------------------------------------------ // color is same as needle until past needle point and then color is gray //------------------------------------------------------------------------------ X = 0.0; // this will increment by 1/20 of the arc cairo_set_source_rgb(cr, 1.0, 0.0, 0.3); // yellow cairo_set_line_width(cr, 2.5); //-------------------------------------------- // Draw all short and long hash marks // 21 marks - includes 1st and last // Center of arcs is (hor,ver). //-------------------------------------------- for (int i = 0; i< 21; i++ ) { if (X > t1) cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); // gray from now on if (! (i % 2) ) { // long hash marks cairo_arc (cr, hor, ver, len + 10.0, -M_PI, -M_PI + X); // outer point of hash mark cairo_get_current_point (cr, &x, &y); cairo_arc (cr, hor, ver, len, -M_PI, -M_PI + X); // nearer point of hash mark cairo_get_current_point (cr, &x1, &y1); cairo_new_path (cr); cairo_move_to(cr, x, y); cairo_line_to (cr, x1, y1 ); cairo_stroke (cr); } else { // short hash marks cairo_arc (cr, hor, ver, len + 2.0, -M_PI, -M_PI + X); // further point cairo_get_current_point (cr, &x, &y); cairo_arc (cr, hor, ver, len - 1.0, -M_PI, -M_PI + X); // nearer point length cairo_get_current_point (cr, &x1, &y1); cairo_new_path (cr); // draw the mark cairo_move_to(cr, x, y); cairo_line_to (cr, x1, y1 ); cairo_stroke (cr); } X = X + M_PI / 20.0; // advance point on arc } //---------------- // draw needle //---------------- cairo_set_source_rgb(cr, 1.0, 1.0, 0.3); // yellow //------------------------------------- // arc from left horizon to t1 //------------------------------------- cairo_arc (cr, hor, ver, len, -M_PI, -M_PI + t1); //---------------------------------------- // get coordinates of point on arc //---------------------------------------- cairo_get_current_point (cr, &x, &y); //----------------------------------------------- // draw a line from the origin to the point //----------------------------------------------- cairo_new_path (cr); cairo_move_to(cr, x, y); cairo_line_to (cr, hor, ver ); // (hor,ver) becomes current point (see below) cairo_stroke (cr); //-------------- // arcs //-------------- if (showArc) { //-------------------------------------------- // draw arc from left horizon to t1 //-------------------------------------------- //-------------------------------------------------------------------------- // "If there is a current point, an initial line segment will // be added to the path to connect the current point to the // beginning of the arc." Current point from above is (hor,ver) //-------------------------------------------------------------------------- cairo_arc (cr, hor, ver, len - 2.0, -M_PI, -M_PI + t1); cairo_line_to (cr, hor, ver ); cairo_fill(cr); cairo_stroke (cr); } //---------------------------- // central circular dot //---------------------------- //-------------------------------------------------------------------- // following adds line from current point to arc as well. // current point is the last cairo_line_to above (the origin) //-------------------------------------------------------------------- cairo_set_source_rgb(cr, 1.0, 1.0, 0.3); // yellow cairo_arc (cr, hor, ver, 4.0, -M_PI, M_PI ); // full circle cairo_line_to (cr, hor, ver ); cairo_fill(cr); // fill in arc } //----------------------------- // // draw meters // //----------------------------- gboolean on_draw2_draw (GtkDrawingArea *widget, cairo_t *cr) { double hor, ver, len; // Load is from 0.0 to 1.0; Full meter semi-circle range is M_PI double t1 = (Load ) * M_PI; if (t1 > M_PI) t1 = M_PI; // limit //-------------------------------------------------------------------- // width and height set in on_window_configure_event() below // initial values are from initial signal and derived from // defaults size set in Glade (100,70). Negative ver adjustments // mean up. //-------------------------------------------------------------------- // center point halfway with a small margin for the left edge hor = (width - 10) / 2 + 4; ver = height; len = height - 35; // leave 20 pixels beneath the meter for a label needles(cr, hor, ver - 20, len, t1 ); // draw meter cairo_move_to (cr, hor - 25.0, ver - 4.0 ); // add caption cairo_show_text(cr, "CPU Load"); cairo_stroke (cr); return FALSE; } //---------------------------------------------- // capture GDK size drag configure event //---------------------------------------------- void on_window_configure_event(GtkWidget *win, GdkEvent *e) { static int w = 0, h = 0; // prior values width = e->configure.width; height = e->configure.height; //----------------------------------------------- // accelerate shrinkage to speed things up //----------------------------------------------- if (width < w || height < h) { // getting smaller? width = width - 5; height = height - 5; } w = width; h = height; // remember old values gtk_widget_set_size_request (GTK_WIDGET(draw2), width - 4 , height - 4 ); }