On 01/25/2009 06:04 PM, Talguy wrote:
#ifndef DEFAULT_H #define DEFAULT_H #include <cairomm/context.h> #include <gtkmm/drawingarea.h> class Default : public Gtk::DrawingArea { private: void processSpeed(double); void processRPM(double); void processFuel(double); void drawGauge(double); void drawNeedle(double, double); void drawFuelGauge(double); virtual bool on_expose_event(GdkEventExpose* event); // Variables const std::string gauges[]; double currentSpeedValue, currentRpmValue, currentFuelValue; double totalDrawableWidth, totalDrawableHeight; double width, height; bool initialize; Cairo::RefPtr<Cairo::Context> cr; Glib::RefPtr<Glib::IOChannel> file_read; public: Default(void); virtual ~Default(void); bool Update(Glib::IOCondition); }; #endif --------------------------------------- #include "Default.h" #include <cairomm/context.h> #include <math.h> #include <string> #include <iostream> using namespace std; //Variables const string gauges[3] = {"speed", "rpm", "fuel"}; const double gaugeRadius = 0.225; const double gaugeWidth = 0.45; const double gaugePadding = 0.05; const double gaugeLowerPadding = 0.10; //percentages/100 const double signalArea = 0.15; //15% of the main drawing area will be devoted tCairo::RefPtr<Cairo::Context> cro drawign the signals const double drawableArea = 0.8; //80% of the drawable area will be devoted to drawing the gauges const double maxSpeed = 120; const double maxRPM = 8000; //Methods Default::Default(void) { currentSpeedValue = 0; currentRpmValue = 0; currentFuelValue = 0; initialize = true; file_read = Glib::IOChannel::create_from_file("test.txt", "r"); Glib::signal_io().connect(sigc::mem_fun(*this, &Default::Update), file_read, Glib::IO_IN | Glib::IO_HUP); #ifndef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED //Connect the signal handler if it isn't already a virtual method override: signal_expose_event().connect(sigc::mem_fun(*this, &Clock::on_expose_event), false); #endif //GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED } Default::~Default(void) { } bool Default::Update(Glib::IOCondition io_condition) { // force the program to redraw the screen Glib::RefPtr<Gdk::Window> win = get_window(); if (win) { cout << "forcing\n"; Gdk::Rectangle r(0, 0, get_allocation().get_width(), get_allocation().get_height()); win->invalidate_rect(r, false); cout << "invalidated\n"; } cout << "bye\n\n"; return true; } // use this to draw the intial screen bool Default::on_expose_event(GdkEventExpose* event) { cout << "exposing\n"; Glib::RefPtr<Gdk::Window> window = get_window(); if(window) { Gtk::Allocation allocation = get_allocation(); totalDrawableWidth = allocation.get_width(); totalDrawableHeight = allocation.get_height(); cr = window->create_cairo_context(); cr->rectangle(event->area.x, event->area.y, event->area.width, event->area.height); cr->clip(); if(!initialize) { cout << "Updating....\n"; Glib::ustring buf; cout << "created the buffer\n"; #ifdef GLIBMM_EXCEPTIONS_ENABLED file_read->read_line(buf); cout << "read in a line\n"; #else auto_ptr<Glib::Error> ex; file_read->read_line(buf, ex); if(ex.get()) { cout << "ouch\n"; cerr << "Error: " << ex->what() << endl; } #endif //GLIBMM_EXCEPTIONS_ENABLED string temp = buf.raw(); string tempVal = temp.substr(2, temp.length()-1); temp.erase(1, temp.length()-1); int SensID = atoi(temp.c_str()); double value = atof(tempVal.c_str()); cout << "data received\n"; switch(SensID) { case 0: cout << "speed baby\n"; processSpeed(value); break; case 1: processRPM(value); break; case 2: processFuel(value); break; default: cerr << "no luck bud\n"; break; } } else { // Draw initial gauges drawGauge(gaugePadding*totalDrawableWidth); // Speed Gauge drawGauge((gaugeWidth + gaugePadding)*totalDrawableWidth); // RPM Gauge drawNeedle(180, gaugePadding*totalDrawableWidth); // Speed Needle drawNeedle(180, (gaugeWidth + gaugePadding)*totalDrawableWidth); // RPM Needle drawFuelGauge(0); initialize = false; cout << "DONE INTIALIZATION\n"; } } return true; } void Default::drawGauge(double Offset) { cr->set_source_rgb(0,0,0); cr->set_line_width(5); cr->set_line_join(Cairo::LINE_JOIN_ROUND); //draw gauge outlines cr->save(); cr->arc(gaugeRadius * totalDrawableWidth + Offset + 1, totalDrawableHeight - (gaugePadding * totalDrawableHeight), gaugeRadius * totalDrawableWidth, M_PI, 0); cr->stroke(); cr->restore(); // Draw tick marks double lineLength = 0; bool evens = true; int temp = 0; int spacer = 0; for(int x = 0; x<13; x++) { cr->save(); cr->set_line_join(Cairo::LINE_JOIN_ROUND); cr->set_line_width(3); spacer = 0; if(x%2 == 0) { lineLength = gaugePadding * totalDrawableWidth; evens = true; } else { lineLength = gaugePadding * totalDrawableWidth/2; evens = false; } cr->move_to(Offset + gaugeRadius * totalDrawableWidth + 1 + (gaugeRadius * totalDrawableWidth - lineLength) * cos(x*M_PI/12), totalDrawableHeight - (gaugePadding * totalDrawableHeight) - (gaugeRadius * totalDrawableWidth - lineLength) * sin(x*M_PI/12)); cr->line_to(Offset + gaugeRadius * totalDrawableWidth + 1 + (gaugeRadius * totalDrawableWidth) * cos(x*M_PI/12), totalDrawableHeight - (gaugePadding * totalDrawableHeight) - (gaugeRadius * totalDrawableWidth) * sin(x*M_PI/12)); // write values of even tick marks to the screen if(evens) { string s; stringstream out; temp = 120 - 20*x/2; out << temp; s = out.str(); if(temp >=100) { spacer = 35; } if(temp >=60 && temp <=80) { spacer = 10; } cr->move_to(Offset + gaugeRadius * totalDrawableWidth + 1 + (gaugeRadius * totalDrawableWidth - lineLength - 7 - spacer) * cos(x*M_PI/12), totalDrawableHeight - (gaugePadding * totalDrawableHeight) - (gaugeRadius * totalDrawableWidth - lineLength - spacer - 7) * sin(x*M_PI/12)); cr->set_font_size(15); cr->text_path(s); } cr->stroke(); cr->restore(); } //cout << "here\n"; //cr->stroke(); //cout <<"done here\n"; } void Default::drawFuelGauge(double Nangle) { // Process angle Nangle = Nangle * M_PI / 180; cr->set_source_rgb(0,0,0); cr->set_line_width(5); cr->save(); cr->arc((2*gaugeRadius + gaugePadding) * totalDrawableWidth + 1, totalDrawableHeight - ((gaugePadding + 2*gaugeRadius)* totalDrawableHeight), gaugeRadius/2 * totalDrawableWidth, M_PI, 0); cr->stroke(); cr->restore(); // Draw tick marks double lineLength = 0; bool evens = true; int count = 0; int temp = 0; int spacer = 0; string labels[] = {"F","3/4","1/2","1/4","E"}; for(int x = 0; x<5; x++) { cr->save(); cr->set_line_width(3); spacer = 0; if(x%2 == 0) { lineLength = gaugePadding * totalDrawableWidth; evens = true; } else { lineLength = gaugePadding * totalDrawableWidth/2; evens = false; } cr->move_to((2*gaugeRadius + gaugePadding) * totalDrawableWidth + 1 + (gaugeRadius/2 * totalDrawableWidth - lineLength) * cos(x*M_PI/4), totalDrawableHeight - ((gaugePadding + 2*gaugeRadius)* totalDrawableHeight) - (gaugeRadius/2 * totalDrawableWidth - lineLength) * sin(x*M_PI/4)); cr->line_to((2*gaugeRadius + gaugePadding) * totalDrawableWidth + 1 + (gaugeRadius/2 * totalDrawableWidth) * cos(x*M_PI/4), totalDrawableHeight - ((gaugePadding + 2*gaugeRadius)* totalDrawableHeight) - (gaugeRadius/2 * totalDrawableWidth) * sin(x*M_PI/4)); cr->stroke(); cr->restore(); } //Draw Needle //Draw center dot cr->save(); cr->set_source_rgba(1,0.2,0.2,1); cr->arc((2*gaugeRadius + gaugePadding) * totalDrawableWidth + 1, totalDrawableHeight - ((gaugePadding + 2*gaugeRadius)* totalDrawableHeight), gaugePadding/6*totalDrawableWidth, 0, 2*M_PI); cr->fill(); cr->stroke(); cr->restore(); // Draw needle line cr->save(); cr->set_source_rgba(1,0.2,0.2,0.6); cr->set_line_width(6); cr->set_line_cap(Cairo::LINE_CAP_ROUND); cr->move_to((2*gaugeRadius + gaugePadding) * totalDrawableWidth + 1, totalDrawableHeight - ((gaugePadding + 2*gaugeRadius)* totalDrawableHeight)); cr->line_to((2*gaugeRadius + gaugePadding) * totalDrawableWidth + 1 + (gaugeRadius/2 * totalDrawableWidth -gaugePadding/2*totalDrawableWidth) * cos(Nangle), totalDrawableHeight - ((gaugePadding + 2*gaugeRadius)* totalDrawableHeight) - (gaugeRadius/2 * totalDrawableWidth - gaugePadding/2*totalDrawableWidth) * sin(Nangle)); cr->stroke(); cr->restore(); } void Default::drawNeedle(double Nangle, double Offset) { // Draw center dot cr->save(); cr->set_source_rgba(1,0.2,0.2,1); cr->arc(gaugeRadius * totalDrawableWidth + Offset + 1, totalDrawableHeight - (gaugePadding * totalDrawableHeight), gaugePadding/6*totalDrawableWidth, 0, 2*M_PI); cr->fill(); cr->stroke(); cr->restore(); // Process angle Nangle = Nangle * M_PI / 180; // Draw needle line cr->save(); cr->set_source_rgba(1,0.2,0.2,0.6); cr->set_line_width(6); cr->set_line_cap(Cairo::LINE_CAP_ROUND); cr->move_to(gaugeRadius * totalDrawableWidth + Offset + 1, totalDrawableHeight - (gaugePadding * totalDrawableHeight)); cr->line_to(Offset + gaugeRadius * totalDrawableWidth + 1 + (gaugeRadius * totalDrawableWidth -gaugePadding/2*totalDrawableWidth) * cos(Nangle), totalDrawableHeight - (gaugePadding * totalDrawableHeight) - (gaugeRadius * totalDrawableWidth - gaugePadding/2*totalDrawableWidth) * sin(Nangle)); cr->stroke(); cr->restore(); } void Default::processSpeed(double value) { cout << "updating speed\n"; //cr->rectangle(gaugePadding * totalDrawableWidth, gaugeLowerPadding * totalDrawableHeight, gaugeWidth * totalDrawableWidth, gaugeRadius * totalDrawableHeight); //cr->clip(); currentSpeedValue = value; double Nangle = 0; if(value <= 120) { cout << "I am here - 120\n"; Nangle = (1-(value/120)) * M_PI; // Already in radians } else { cout << "I am here - 0\n"; Nangle = 0; } cout << "the angle is: " << Nangle << endl; cout << "Drawing Gauge\n"; drawGauge(gaugePadding * totalDrawableWidth); cout << "Drawing Needle\n"; drawNeedle(Nangle, 0); cout << "DONE!!!!!!!!!\n"; } void Default::processRPM(double value) { //cr->rectangle((gaugePadding + gaugeWidth) * totalDrawableWidth, gaugeLowerPadding * totalDrawableHeight, gaugeWidth * totalDrawableWidth, gaugeRadius * totalDrawableHeight); //cr->clip(); currentRpmValue = value; double Nangle = 0; if(value <= 8000) Nangle = (1 - (value/8000)) * M_PI; // Already in radians else Nangle = 0; drawGauge((gaugePadding + gaugeWidth) * totalDrawableWidth); drawNeedle(Nangle, (gaugePadding + gaugeWidth) * totalDrawableWidth); } void Default::processFuel(double value) { currentFuelValue = value; double Nangle = 0; if(value <= 100) Nangle = (1 - (value/100)) * M_PI; // Already in radians else Nangle = 0; drawFuelGauge(Nangle); } --------------------------------------- #include "Default.h" #include <gtkmm/main.h> #include <gtkmm/window.h> #include <string> int main(int argc, char** argv) { Gtk::Main app(argc, argv); Gtk::Window win; win.set_title("Dynamic Vehicle Dashboard"); //win.fullscreen(); win.maximize(); Default deFault; win.add(deFault); deFault.show(); app.run(win); return 0; } --------------------------------------- CC = g++ SOURCES = Default.cpp CFLAGS = -Wall OBJECTS = $(SOURCES:.cpp=.o) EXECUTABLE = DynamicVehicleDashboard GTKMM = `pkg-config --cflags --libs gtkmm-2.4` all: mainTestDefault.cpp $(OBJECTS) $(CC) $(GTKMM) $(OBJECTS) mainTestDefault.cpp -o $(EXECUTABLE) Default.o: Default.cpp Default.h $(CC) `pkg-config --cflags gtkmm-2.4` -c Default.cpp .PHONY: clean clean: rm -f DVD $(OBJECTS)
First of all, this makefile is not building anything with debugging information (-g) so I'm guessing that you haven't run this under a debugger to inspect the behavior at all. I'd encourage you to do that rather than relying too heavily on debugging-by-print-statements.
So I think there are a few issues mixed together here. When you register an io handler, it will use the default priority (G_PRIORITY_DEFAULT) unless otherwise specified. This priority is apparently higher than the priority for re-drawing events (see [1]), so if there is io ready to be handled, it seems that it will always take priority over the redraw (in your current code). Combine this with the fact that you're actually calling the read_line() function in your expose handler rather than in your io handler, and what you have is Update() being called in a sort of an infinite loop with no data ever being read. (as a side note, you're never checking the return value of your read_line() call, so even if your read_line() function was getting called as desired, you would continue attempting to process data long after the end of file actually occurred).
I have hacked up a few changes to your code that gets things to a semi-working state, but it'll probably require a bit more work to get it working properly. hopefully it's enough to give you some ideas though.
[1] http://library.gnome.org/devel/glib/unstable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
Attachment:
dynamic-vehicle-dashboard.tar.gz
Description: GNU Zip compressed data