Back to index

texmacs  1.0.7.15
choice_widget.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : choice_widget.cpp
00004 * DESCRIPTION: Select one or more items from a list
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 "window.hpp"
00013 #include "Widkit/basic_widget.hpp"
00014 #include "Widkit/layout.hpp"
00015 #include "scheme.hpp"
00016 #include "font.hpp"
00017 
00018 /******************************************************************************
00019 * choice widgets
00020 ******************************************************************************/
00021 
00022 class choice_widget_rep: public basic_widget_rep {
00023   command       cb;
00024   array<string> names;
00025   array<string> selected;
00026   bool          multiple;
00027   int           over;
00028 
00029 public:
00030   choice_widget_rep (command cb, array<string> n, array<string> a, bool mc);
00031   operator tree ();
00032   bool active (string s);
00033   int  find (SI y);
00034   void handle_get_size (get_size_event ev);
00035   void handle_repaint (repaint_event ev);
00036   void handle_mouse (mouse_event ev);
00037 };
00038 
00039 /******************************************************************************
00040 * Implementation of choice widgets
00041 ******************************************************************************/
00042 
00043 choice_widget_rep::choice_widget_rep
00044   (command cb2, array<string> n, array<string> a, bool mc):
00045     basic_widget_rep (),
00046     cb (cb2), names (n), selected (a), multiple (mc), over (-1) {}
00047 
00048 choice_widget_rep::operator tree () {
00049   return "choice";
00050 }
00051 
00052 bool
00053 choice_widget_rep::active (string s) {
00054   for (int i=0; i<N(selected); i++)
00055     if (selected[i] == s) return true;
00056   return false;
00057 }
00058 
00059 int
00060 choice_widget_rep::find (SI ypos) {
00061   int i;
00062   SI y= 0, search= ypos*3;
00063   metric ex;
00064   font fn= get_default_font ();
00065   for (i=0; i<N(names); i++) {
00066     fn->var_get_extents (names[i], ex);
00067     if ((search >= (y+ fn->y1- fn->y2- 12*PIXEL)) && (search < y)) break;
00068     y += fn->y1- fn->y2- 12*PIXEL;
00069   }
00070   if (i == N(names)) return -1;
00071   return i;
00072 }
00073 
00074 void
00075 choice_widget_rep::handle_get_size (get_size_event ev) {
00076   int i;
00077   metric ex;
00078   font fn= get_default_font ();
00079   ev->w= ev->h= 0;
00080   for (i=0; i<N(names); i++) {
00081     fn->var_get_extents (names[i], ex);
00082     ev->w  = max (ev->w, ((ex->x2- ex->x1+ 2)/3) + (6*PIXEL));
00083     ev->h += ((fn->y2- fn->y1+ 2)/3) + (4*PIXEL);
00084   }
00085   if (ev->mode == 1)
00086     gui_maximal_extents (ev->w, ev->h);
00087   abs_round (ev->w, ev->h);
00088 }
00089 
00090 void
00091 choice_widget_rep::handle_repaint (repaint_event ev) { (void) ev;
00092   renderer ren= win->get_renderer ();
00093   int i; 
00094   metric ex;
00095   ren->set_background (white);
00096   ren->clear (0, -h, w, 0);
00097   font fn= get_default_font ();
00098   SI dy= fn->y1- fn->y2- 12*PIXEL;
00099   ren->set_shrinking_factor (3);
00100   SI y= 0;
00101   for (i=0; i<N(names); i++) {
00102     if (active (names[i])) {
00103       color blued= rgb_color (224, 224, 248);
00104       ren->set_background (blued);
00105       ren->clear (0, y + dy, 3*w, y);
00106       ren->set_background (white);
00107     }
00108     if (i == over) layout_dark_outline (ren, 0, y + dy, 3*w, y);
00109     ren->set_color (black);
00110     fn->var_get_extents (names[i], ex);
00111     fn ->draw (ren, names[i], 9*PIXEL, y-fn->y2-6*PIXEL);
00112     y += dy;
00113   }
00114   ren->set_shrinking_factor (1);
00115 }
00116 
00117 void
00118 choice_widget_rep::handle_mouse (mouse_event ev) {
00119   string type= ev->type;
00120 
00121   if ((type == "release-left") || (type == "release-right")) {
00122     int i= find (ev->y);
00123     if (i < 0) return;
00124     if (!multiple) selected= array<string> ();
00125     if (active (names[i])) {
00126       for (int j=0; j<N(selected); j++)
00127         if (selected[j] == names[i]) {
00128           selected= append (range (selected, 0, j),
00129                             range (selected, j+1, N(selected)));
00130           break;
00131         }
00132     }
00133     else selected << names[i];
00134     if (!multiple) cb (list_object (object (names[i])));
00135     else {
00136       object l= null_object ();
00137       for (int i=N(selected)-1; i>=0; i--)
00138         l= cons (selected[i], l);
00139       cb (list_object (l));
00140     }
00141     this << emit_invalidate_all ();
00142   }
00143 
00144   int new_over= over;
00145   if (type == "leave") new_over= -1;
00146   if (type == "enter" || type == "move") new_over= find (ev->y);
00147   if (new_over != over) {
00148     over= new_over;
00149     this << emit_invalidate_all ();
00150   }
00151 }
00152 
00153 /******************************************************************************
00154 * Public interface
00155 ******************************************************************************/
00156 
00157 wk_widget
00158 choice_wk_widget (command cb, array<string> vals, string cur) {
00159   array<string> ch (1);
00160   ch[0]= cur;
00161   return tm_new<choice_widget_rep> (cb, vals, ch, false);
00162 }
00163 
00164 wk_widget
00165 choice_wk_widget (command cb, array<string> vals, array<string> mc) {
00166   return tm_new<choice_widget_rep> (cb, vals, mc, true);
00167 }