/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #+ #+ 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 #+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ // April 18, 2019 #include #include #include #include #include #include #include #include #include #include #include void on_destroy(); gboolean clock_timer_handler(); double second = 0; double minute = 0; double hour = 0; char time_string[128]; void on_destroy() { gtk_main_quit(); } //----------------------------- // main timer process //----------------------------- gboolean clock_timer_handler() { // check pulse every second struct tm *tod; time_t tx = time(NULL); // get time of day` tod = localtime(&tx); // get time structure pointer strcpy(time_string, asctime(tod)); // ASCII string of time time_string[strlen(time_string)-1] = 0; // char at end second = tod->tm_sec; // extract seconds minute = tod->tm_min; // extract minutes hour = tod->tm_hour % 12; // extract hour (12) gtk_widget_queue_draw (draw2); // trigger a draw event return TRUE; // timer keeps running (TRUE) } //-------------------------- // draw meter //-------------------------- void needles(cairo_t *cr, double hor, double ver, double needle_length, double needle_position, double meter_radius, int cFlg) { double x, x1, x2, y, y1, y2; ver = ver + 1.0; double X; //--------------------- // hash marks //--------------------- //------------------------------------------------------------------------------ // color is same as needle until past needle point and then color is gray //------------------------------------------------------------------------------ cairo_set_source_rgb(cr, 0.5, 0.5, 1.0); // blue cairo_set_line_width(cr, 2.5); //-------------------------------------------------------- // One quarter of a circle (2 * M_PI -> full circle) //-------------------------------------------------------- X = M_PI / 2.0; for (int i = 0; i < 60; i++ ) { // all long hash marks // -------------------------------------------------------- // Put marks only on 5 second intervals (0, 5, 10, ...) // -------------------------------------------------------- if (!(i % 5) ) { cairo_set_source_rgb(cr, 0.5, 0.5, 1.0); // blue-ish //------------------------------------------------------------------------ // Get coordinates of outer end of long hash mark //------------------------------------------------------------------------ cairo_arc (cr, hor, ver, meter_radius + 10, -M_PI, -M_PI + X); //long length hash cairo_get_current_point (cr, &x, &y); // sets x and y //----------------------------------------------------------------- // Get coordinates of inner end of hash mark //----------------------------------------------------------------- cairo_arc (cr, hor, ver, meter_radius, -M_PI, -M_PI + X); // short length hash cairo_get_current_point (cr, &x1, &y1); // sets x1 and y1 //---------------------------------------------------------------- // Draw hash mark from (x,y) to (x1,y1) //---------------------------------------------------------------- cairo_new_path (cr); cairo_move_to(cr, x, y); cairo_line_to (cr, x1, y1 ); cairo_stroke (cr); } else if (cFlg == 1) { // seconds if (i % 5) { cairo_set_source_rgb(cr, 1.0, 1.0, 0.3); // yellow cairo_arc (cr, hor, ver, needle_length + 2, -M_PI, -M_PI + X); //long length cairo_get_current_point (cr, &x, &y); cairo_arc (cr, hor, ver, needle_length - 1, -M_PI, -M_PI + X); // short length cairo_get_current_point (cr, &x1, &y1); if (X > needle_position) break; cairo_new_path (cr); cairo_move_to(cr, x, y); cairo_line_to (cr, x1, y1 ); cairo_stroke (cr); } } //---------------------------------------------------------------------------- // There are 30 hash marks per half circle (60 for full circle) // A half circle is M_PI. A full circle is 2 * M_PI so each // hash mark is M_PI / 30.0 apart. //---------------------------------------------------------------------------- X = X + M_PI / 30.0; } //------------------ // Pick a color //------------------ if (cFlg == 1) cairo_set_source_rgb(cr, 1.0, 1.0, 0.3); // yellow else if (cFlg == 2) cairo_set_source_rgb(cr, 1.0, 0., 0.); // red else if (cFlg == 3) cairo_set_source_rgb(cr, 0.5, 1.0, 0.5); // green //---------------- // needle //---------------- if (cFlg == 1) cairo_set_line_width(cr, 1.0); else if (cFlg == 2) cairo_set_line_width(cr, 2.0); else cairo_set_line_width(cr, 3.0); cairo_arc (cr, hor, ver, needle_length, -M_PI, -M_PI + needle_position); cairo_get_current_point (cr, &x, &y); cairo_new_path (cr); cairo_move_to(cr, x, y); cairo_line_to (cr, hor, ver ); cairo_stroke (cr); //---------------- // spindle //---------------- cairo_arc (cr, hor, ver, 4.0, -M_PI, M_PI ); // -M_PI -> 0.0 -> +M_PI : full circle cairo_line_to (cr, hor, ver+3 ); cairo_fill(cr); // fill in arc } gboolean on_draw2_draw (GtkDrawingArea *widget, cairo_t *cr) { double hor, ver, needle_length, meter_radius, needle_position; #define MHOR 106.0 #define MVER 76.0 hor = MHOR; ver = MVER; meter_radius = 50; //---------------------------------------------------------------------- // note: don't alter original (hour,minute,second) variables as // re-draws triggered by system will used modified values //---------------------------------------------------------------------- //----------------------------------------------------------------------------- // Zero for a clock it straight up. Adjust needle positions accordingly // Example: if hour == zero, needle should be straight up: add 3 hours. //----------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Sixty minutes to an hour: Adjust hour to include how close minute // hand is to the next hour. //--------------------------------------------------------------------------- needle_position = hour + 3.0 + minute / 60.0; //-------------------------------------------------------------------------- // 6 hours per half circle so hour marks are hour * (M_PI / 6.0) apart //-------------------------------------------------------------------------- needle_position = needle_position * (M_PI / 6.0); needle_length = 30.0; needles(cr, hor, ver, needle_length, needle_position, meter_radius, 3); //-------------------------------- // minute zero adjustment //-------------------------------- needle_position = minute + 15; //---------------------------------------------- // Minutes are 30 per half circle apart //---------------------------------------------- needle_position = needle_position * (M_PI / 30.0); needle_length = 45.0; needles(cr, hor, ver, needle_length, needle_position, meter_radius, 2); //---------------------------------------------------------- // Seconds handles similar to minutes (60 per circle) //---------------------------------------------------------- needle_position = second + 15; // adjust zero to top of dial needle_position = needle_position * (M_PI / 30.0); needle_length = 50.0; needles(cr, hor, ver, needle_length, needle_position, meter_radius, 1); //--------------------------------- // Show digital text of time //--------------------------------- cairo_move_to (cr, 40.0, 150.0 ); // location: horizontal, vertical cairo_show_text(cr, time_string); // you can change the font if you want cairo_stroke (cr); return FALSE; }