Back to index

texmacs  1.0.7.15
ink_widget.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : ink_widget.cpp
00004 * DESCRIPTION: Widget for inking
00005 * COPYRIGHT  : (C) 2012  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "Widkit/attribute_widget.hpp"
00013 #include "Widkit/layout.hpp"
00014 #include "handwriting.hpp"
00015 #include "scheme.hpp"
00016 
00017 /******************************************************************************
00018 * Ink widget
00019 ******************************************************************************/
00020 
00021 class ink_widget_rep: public attribute_widget_rep {
00022   command cb;
00023   contours shs;
00024   bool dragging;
00025 
00026 public:
00027   ink_widget_rep (command cb);
00028   operator tree ();
00029   void refresh_last ();
00030   void commit ();
00031   void handle_get_size (get_size_event ev);
00032   void handle_repaint (repaint_event ev);
00033   void handle_mouse (mouse_event ev);
00034 };
00035 
00036 /******************************************************************************
00037 * Routines for ink_widgets
00038 ******************************************************************************/
00039 
00040 ink_widget_rep::ink_widget_rep (command cb2):
00041   attribute_widget_rep (), cb (cb2), shs (), dragging (false) {}
00042 
00043 ink_widget_rep::operator tree () {
00044   return tree (TUPLE, "ink");
00045 }
00046 
00047 void
00048 ink_widget_rep::handle_get_size (get_size_event ev) {
00049   ev->w= 600 * PIXEL;
00050   ev->h= 400 * PIXEL;
00051   if (ev->mode == 1) {
00052     ev->w= 1280 * PIXEL;
00053     ev->h= 400 * PIXEL;
00054   }
00055   abs_round (ev->w, ev->h);
00056 }
00057 
00058 void
00059 ink_widget_rep::handle_repaint (repaint_event ev) { (void) ev;
00060   renderer ren= win->get_renderer ();
00061   layout_pastel (ren, ev->x1, ev->y1, ev->x2, ev->y2);
00062   ren->set_color (black);
00063   ren->set_line_style (2 * PIXEL);
00064   for (int i=0; i<N(shs); i++) {
00065     poly_line sh= shs[i];
00066     int n= N(sh);
00067     if (n == 1) {
00068       array<SI> x (2);
00069       array<SI> y (2);
00070       x[0]= x[1]= (SI) (sh[0][0] * PIXEL);
00071       y[0]= y[1]= (SI) (sh[0][1] * PIXEL);
00072       ren->lines (x, y);
00073     }
00074     else if (n>1) {
00075       array<SI> x (n);
00076       array<SI> y (n);
00077       for (int j=0; j<n; j++) {
00078         x[j]= (SI) (sh[j][0] * PIXEL);
00079         y[j]= (SI) (sh[j][1] * PIXEL);
00080       }
00081       ren->lines (x, y);
00082     }
00083   }
00084   /*
00085   for (int i=0; i<N(shs); i++) {
00086     poly_line pl= shs[i];
00087     array<double> ts= vertices (pl);
00088     double len= length (pl);
00089     for (int j=0; j<N(ts); j++) {
00090       ren->set_color (red);
00091       point p= access (pl, ts[j] * len);
00092       SI x= p[0] * PIXEL;
00093       SI y= p[1] * PIXEL;
00094       ren->fill (x - 2*PIXEL, y - 2*PIXEL, x + 2*PIXEL, y + 2*PIXEL);
00095     }
00096   }
00097   */
00098 }
00099 
00100 void
00101 ink_widget_rep::refresh_last () {
00102   if (N(shs) > 0) {
00103     poly_line& sh= shs [N(shs)-1];
00104     point& p = sh [max (0, N(sh)-2)];
00105     point& q = sh [N(sh)-1];
00106     SI x1= min (p[0], q[0]) * PIXEL;
00107     SI y1= min (p[1], q[1]) * PIXEL;
00108     SI x2= max (p[0], q[0]) * PIXEL;
00109     SI y2= max (p[1], q[1]) * PIXEL;
00110     this << emit_invalidate (x1 - 3*PIXEL, y1 - 3*PIXEL,
00111                              x2 + 3*PIXEL, y2 + 3*PIXEL);
00112   }
00113 }
00114 
00115 void
00116 ink_widget_rep::handle_mouse (mouse_event ev) {
00117   string type= ev->type;
00118   SI     x= ev->x, y= ev->y;
00119   bool   erase= ev->pressed ("right");
00120 
00121   //cout << type << ", " << x/PIXEL << ", " << y/PIXEL << "\n";
00122   if (erase) {
00123     int n= N(shs);
00124     contours nshs;
00125     for (int i=0; i<N(shs); i++)
00126       if (!nearby (point (x/PIXEL, y/PIXEL), shs[i]))
00127         nshs << shs[i];
00128     shs= nshs;
00129     if (N(nshs) != n) {
00130       this << emit_invalidate_all ();
00131       commit ();
00132     }
00133   }
00134   else if (type == "press-left") {
00135     poly_line sh (0);
00136     sh << point (x/PIXEL, y/PIXEL);
00137     shs << sh;
00138     refresh_last ();
00139     dragging= true;
00140   }
00141   else if (type == "leave" && (ev->x < 0 || ev->x >= w)) {
00142     if (ev->x >= w) cb (list_object (object (true)));
00143     shs= contours (0);
00144     this << emit_invalidate_all ();
00145     if (ev->x < 0) commit ();
00146   }
00147   else if (type == "move" || type == "release-left" || type == "leave")
00148     if (dragging && N(shs) > 0) {
00149       poly_line& sh= shs [N(shs)-1];
00150       point& p = sh [N(sh)-1];
00151       if (p[0] != (x/PIXEL) || p[1] != (y/PIXEL)) {
00152         sh << point (x/PIXEL, y/PIXEL);
00153         refresh_last ();
00154       }
00155       if (type != "move") {
00156         dragging= false;
00157         commit ();
00158       }
00159       this << emit_invalidate_all ();
00160     }
00161 }
00162 
00163 void
00164 ink_widget_rep::commit () {
00165   object l= null_object ();
00166   for (int k= N(shs)-1; k>=0; k--) {
00167     poly_line sh= shs[k];
00168     object obj= null_object ();
00169     for (int i=N(sh)-1; i>=0; i--) {
00170       object p= list_object (object (sh[i][0]), object (sh[i][1]));
00171       obj= cons (p, obj);
00172     }
00173     l= cons (obj, l);
00174   }
00175   cb (list_object (l));
00176 }
00177 
00178 /******************************************************************************
00179 * Interface
00180 ******************************************************************************/
00181 
00182 wk_widget
00183 ink_wk_widget (command cb) {
00184   return tm_new<ink_widget_rep> (cb);
00185 }