lasergui_hildon.cpp

00001 
00002 /***************************************************************************
00003  *  lasergui_hildon.cpp - minimalistic laser visualization on Hildon
00004  *
00005  *  Created: Sun Oct 12 17:06:06 2008
00006  *  Copyright  2008  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  Read the full text in the LICENSE.GPL file in the doc directory.
00021  */
00022 
00023 #include "laser_drawing_area.h"
00024 
00025 #include <gui_utils/robot/allemaniacs_athome.h>
00026 #include <gtkmm.h>
00027 #include <hildonmm.h>
00028 #include <libosso.h>
00029 
00030 #include <netcomm/fawkes/client.h>
00031 #include <blackboard/remote.h>
00032 #include <interfaces/Laser360Interface.h>
00033 #include <gui_utils/interface_dispatcher.h>
00034 #include <gui_utils/connection_dispatcher.h>
00035 #include <gui_utils/service_chooser_dialog.h>
00036 
00037 #if MAEMO_VERSION_MAJOR >= 5
00038 #  define ICON_FORMAT "white_48x48"
00039 #else
00040 #  define ICON_FORMAT "32x32"
00041 #endif
00042 
00043 using namespace fawkes;
00044 
00045 /** @class LaserGuiHildonWindow "lasergui_hildon.cpp"
00046  * Laser GUI window for Hildon.
00047  * @author Tim Niemueller
00048  */
00049 
00050 class LaserGuiHildonWindow : public Hildon::Window
00051 {
00052  public:
00053   /** Constructor. */
00054   LaserGuiHildonWindow()
00055     : __athome_drawer(true),
00056       __img_lines(RESDIR"/lasergui/lines_"ICON_FORMAT".png"),
00057       __img_points(RESDIR"/lasergui/points_"ICON_FORMAT".png"),
00058       __img_hull(RESDIR"/lasergui/hull_"ICON_FORMAT".png"),
00059       __img_lowres(RESDIR"/lasergui/lines_lowres_"ICON_FORMAT".png"),
00060       __img_rotation(RESDIR"/lasergui/rotate-90.png"),
00061       __tb_connection(Gtk::Stock::CONNECT),
00062       __tb_lines(__img_lines),
00063       __tb_points(__img_points),
00064       __tb_hull(__img_hull),
00065       __tb_lowres(__img_lowres),
00066       __tb_rotation(__img_rotation),
00067       __tb_zoom_in(Gtk::Stock::ZOOM_IN),
00068       __tb_zoom_out(Gtk::Stock::ZOOM_OUT)
00069   {
00070     __fullscreen = false;
00071     __bb = NULL;
00072     __laser_if = NULL;
00073     __ifd = NULL;
00074 
00075     std::auto_ptr<Glib::Error> error;
00076     set_icon_from_file(RESDIR"/lasergui/lines_"ICON_FORMAT".png", error);
00077 
00078     add(__area);
00079     __area.show();
00080     __area.set_robot_drawer(&__athome_drawer);
00081 
00082     Gtk::RadioButton::Group group = __tb_lines.get_group();
00083     __tb_points.set_group(group);
00084     group = __tb_lines.get_group();
00085     __tb_hull.set_group(group);
00086     __tb_lines.set_active(true);
00087 
00088     __tb_lines.set_sensitive(false);
00089     __tb_points.set_sensitive(false);
00090     __tb_hull.set_sensitive(false);
00091     __tb_lowres.set_sensitive(false);
00092     __tb_rotation.set_sensitive(false);
00093     __tb_zoom_in.set_sensitive(false);
00094     __tb_zoom_out.set_sensitive(false);
00095 
00096     __tbar.append(__tb_connection);
00097     __tbar.append(__sep_0);
00098     __tbar.append(__tb_lines);
00099     __tbar.append(__tb_points);
00100     __tbar.append(__tb_hull);
00101     __tbar.append(__sep_1);
00102     __tbar.append(__tb_lowres);
00103     __tbar.append(__tb_rotation);
00104     __tbar.append(__sep_2);
00105     __tbar.append(__tb_zoom_in);
00106     __tbar.append(__tb_zoom_out);
00107 
00108     add_toolbar(__tbar);
00109     __tbar.show_all();
00110 
00111     __tb_lines.signal_toggled().connect(sigc::bind(sigc::mem_fun(__area, &LaserDrawingArea::set_draw_mode), LaserDrawingArea::MODE_LINES));
00112     __tb_points.signal_toggled().connect(sigc::bind(sigc::mem_fun(__area, &LaserDrawingArea::set_draw_mode), LaserDrawingArea::MODE_POINTS));
00113     __tb_hull.signal_toggled().connect(sigc::bind(sigc::mem_fun(__area, &LaserDrawingArea::set_draw_mode), LaserDrawingArea::MODE_HULL));
00114     __tb_zoom_in.signal_clicked().connect(sigc::mem_fun(__area, &LaserDrawingArea::zoom_in));
00115     __tb_zoom_out.signal_clicked().connect(sigc::mem_fun(__area, &LaserDrawingArea::zoom_out));
00116 
00117     __tb_connection.signal_clicked().connect(sigc::mem_fun(*this, &LaserGuiHildonWindow::on_connection_clicked));
00118     __tb_rotation.signal_clicked().connect(sigc::mem_fun(*this, &LaserGuiHildonWindow::on_rotation_toggled));
00119     __tb_lowres.signal_clicked().connect(sigc::mem_fun(*this, &LaserGuiHildonWindow::on_resolution_toggled));
00120 
00121     __connection_dispatcher.signal_connected().connect(sigc::mem_fun(*this, &LaserGuiHildonWindow::on_connect));
00122     __connection_dispatcher.signal_disconnected().connect(sigc::mem_fun(*this, &LaserGuiHildonWindow::on_disconnect));
00123 
00124 #ifndef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED
00125     signal_key_press_event().connect(sigc::mem_fun(*this, &LaserGuiHildonWindow::on_key_pressed));
00126     signal_window_state_event().connect(sigc::mem_fun(*this, &LaserGuiHildonWindow::on_window_state_event));
00127 #endif
00128   }
00129 
00130   /** Destructor. */
00131   ~LaserGuiHildonWindow()
00132   {
00133     __area.set_laser360_if(NULL);
00134     if (__bb) {
00135       __bb->close(__laser_if);
00136       delete __bb;
00137       delete __ifd;
00138     }
00139   }
00140 
00141  protected:
00142   /** Event handler for key pressed events.
00143    * @param event event parameters
00144    * @return always false
00145    */
00146   virtual bool on_key_pressed(GdkEventKey* event)
00147   {
00148     if(!event)  return false;
00149 
00150     switch (event->keyval) {
00151     case GDK_F6:
00152       if ( __fullscreen ) {
00153         unfullscreen();
00154       } else {
00155         fullscreen();
00156       }
00157       break;
00158     case GDK_F7:
00159       __area.zoom_in();
00160       break;
00161     case GDK_F8:
00162       __area.zoom_out();
00163       break;
00164     }
00165 
00166     // Returning true would stop the event now
00167     return false;
00168   }
00169 
00170   /** Event handler for window state change events.
00171    * @param event event parameters
00172    * @return always false
00173    */
00174   virtual bool on_window_state_event(GdkEventWindowState *event)
00175   {
00176     if (event->new_window_state == GDK_WINDOW_STATE_FULLSCREEN) {
00177       __fullscreen = true;
00178     } else {
00179       __fullscreen = false;
00180     }
00181     return false;
00182   }
00183 
00184   /** Event handler for connection button. */
00185   void on_connection_clicked()
00186   {
00187     if ( ! __connection_dispatcher.get_client()->connected() ) {
00188       ServiceChooserDialog ssd(*this, __connection_dispatcher.get_client());
00189       ssd.run_and_connect();
00190     } else {
00191       __connection_dispatcher.get_client()->disconnect();
00192     }
00193   }
00194 
00195   /** Event handler for connected event. */
00196   virtual void on_connect()
00197   {
00198     try {
00199       __bb = new RemoteBlackBoard(__connection_dispatcher.get_client());
00200       __laser_if = __bb->open_for_reading<Laser360Interface>("Laser");
00201 
00202       __area.set_laser360_if(__laser_if);
00203       __ifd = new InterfaceDispatcher("LaserInterfaceDispatcher", __laser_if);
00204       __ifd->signal_data_changed().connect(sigc::hide(sigc::mem_fun(__area, &LaserDrawingArea::queue_draw)));
00205       __ifd->signal_writer_removed().connect(sigc::hide(sigc::mem_fun(__area, &LaserDrawingArea::queue_draw)));
00206       __bb->register_listener(__ifd, BlackBoard::BBIL_FLAG_DATA | BlackBoard::BBIL_FLAG_WRITER);
00207 
00208       __area.queue_draw();
00209 
00210       __tb_connection.set_stock_id(Gtk::Stock::DISCONNECT);
00211       __tb_lines.set_sensitive(true);
00212       __tb_points.set_sensitive(true);
00213       __tb_hull.set_sensitive(true);
00214       __tb_lowres.set_sensitive(true);
00215       __tb_rotation.set_sensitive(true);
00216       __tb_zoom_in.set_sensitive(true);
00217       __tb_zoom_out.set_sensitive(true);
00218     } catch (Exception &e) {
00219       e.print_trace();
00220       if ( __bb ) {
00221         __bb->close(__laser_if);
00222         delete __ifd;
00223         delete __bb;
00224         __laser_if = NULL;
00225         __bb = NULL;
00226         __ifd = NULL;
00227       }
00228     }
00229   }
00230 
00231   /** Event handler for disconnected event. */
00232   virtual void on_disconnect()
00233   {
00234     __area.set_laser360_if(NULL);
00235     __area.queue_draw();
00236     __bb->close(__laser_if);
00237     delete __bb;
00238     delete __ifd;
00239     __bb = NULL;
00240     __ifd = NULL;
00241     __laser_if = NULL;
00242     __tb_connection.set_stock_id(Gtk::Stock::CONNECT);
00243     __tb_lines.set_sensitive(false);
00244     __tb_points.set_sensitive(false);
00245     __tb_hull.set_sensitive(false);
00246     __tb_lowres.set_sensitive(false);
00247     __tb_rotation.set_sensitive(false);
00248     __tb_zoom_in.set_sensitive(false);
00249     __tb_zoom_out.set_sensitive(false);
00250   }
00251 
00252   /** Event handler for rotation button. */
00253   void on_rotation_toggled()
00254   {
00255     if ( __tb_rotation.get_active() ) {
00256       __area.set_rotation(M_PI / 2);
00257     } else {
00258       __area.set_rotation(0);
00259     }
00260   }
00261 
00262   /** Event handler for rotation button. */
00263   void on_resolution_toggled()
00264   {
00265     if ( __tb_lowres.get_active() ) {
00266       __area.set_resolution(3);
00267     } else {
00268       __area.set_resolution(1);
00269     }
00270   }
00271 
00272  private:
00273   AllemaniACsAtHomeCairoRobotDrawer  __athome_drawer;
00274   BlackBoard                        *__bb;
00275   Laser360Interface                 *__laser_if;
00276   InterfaceDispatcher               *__ifd;
00277   ConnectionDispatcher               __connection_dispatcher;
00278 
00279   Gtk::Image                         __img_lines;
00280   Gtk::Image                         __img_points;
00281   Gtk::Image                         __img_hull;
00282   Gtk::Image                         __img_lowres;
00283   Gtk::Image                         __img_rotation;
00284   Gtk::ToolButton                    __tb_connection;
00285   Gtk::SeparatorToolItem             __sep_0;
00286   Gtk::RadioToolButton               __tb_lines;
00287   Gtk::RadioToolButton               __tb_points;
00288   Gtk::RadioToolButton               __tb_hull;
00289   Gtk::SeparatorToolItem             __sep_1;
00290   Gtk::ToggleToolButton              __tb_lowres;
00291   Gtk::ToggleToolButton              __tb_rotation;
00292   Gtk::SeparatorToolItem             __sep_2;
00293   Gtk::ToolButton                    __tb_zoom_in;
00294   Gtk::ToolButton                    __tb_zoom_out;
00295   Gtk::Toolbar                       __tbar;
00296 
00297   LaserDrawingArea                   __area;
00298 
00299   bool                               __fullscreen;
00300 };
00301 
00302 int
00303 main(int argc, char** argv)
00304 {
00305   Gtk::Main kit(argc, argv);
00306   Hildon::init();
00307 
00308   osso_context_t* osso_context = osso_initialize("lasergui", "0.1", TRUE /* deprecated parameter */, 0 /* Use default Glib main loop context */);
00309   Glib::set_application_name("Laser GUI");
00310 
00311   LaserGuiHildonWindow window;
00312   kit.run(window);
00313 
00314   osso_deinitialize(osso_context);
00315   return 0;
00316 }