Back to index

texmacs  1.0.7.15
concat_gui.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : concat_gui.cpp
00004 * DESCRIPTION: Typesetting GUI markup
00005 * COPYRIGHT  : (C) 2007  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 "concater.hpp"
00013 #include "formatter.hpp"
00014 #include "analyze.hpp"
00015 #include "Concat/canvas_properties.hpp"
00016 
00017 /******************************************************************************
00018 * Old-style resize function
00019 ******************************************************************************/
00020 
00021 static SI
00022 resize (edit_env env, SI old, SI minimum, SI maximum, tree new_size) {
00023   if (!is_atomic (new_size)) return old;
00024   string s= new_size->label;
00025   if (N(s)<2) return old;
00026   if (s[0] == '@') s= s (1, N(s));
00027 
00028   bool flag;
00029   SI   offset;
00030   switch (s[0]) {
00031   case 'l':
00032   case 'b':
00033     flag  = true;
00034     offset= minimum;
00035     break;
00036   case 'c':
00037     flag  = true;
00038     offset= (minimum + maximum) >> 1;
00039     break;
00040   case 'r':
00041   case 't':
00042     flag  = true;
00043     offset= maximum;
00044     break;
00045   default:
00046     flag  = false;
00047     offset= 0;
00048   }
00049 
00050   if (flag) {
00051     SI arg= env->as_length (s (2, N(s)));
00052     switch (s[1]) {
00053     case '+': return offset + arg;
00054     case '-': return offset - arg;
00055     case '[': return min (offset, arg);
00056     case ']': return max (offset, arg);
00057     default : return arg;  
00058     }
00059   }
00060   else return env->as_length (s);
00061 }
00062 
00063 /******************************************************************************
00064 * Scrollable canvases
00065 ******************************************************************************/
00066 
00067 canvas_properties
00068 get_canvas_properties (edit_env env, tree t) {
00069   bool printed= (env->get_string (PAGE_PRINTED) == "true");
00070   SI   border = env->get_length (ORNAMENT_BORDER);
00071   SI   pixel  = env->get_int (SFACTOR) * PIXEL;
00072   if (!printed)
00073     border= max (pixel, ((border + pixel/2) / pixel) * pixel);
00074 
00075   canvas_properties props;
00076   props->env        = env;
00077   props->type       = env->get_string (CANVAS_TYPE);
00078   props->x1         = env->exec (t[0]);
00079   props->y1         = env->exec (t[1]);
00080   props->x2         = env->exec (t[2]);
00081   props->y2         = env->exec (t[3]);
00082   props->xt         = env->expand (t[4]);
00083   props->yt         = env->expand (t[5]);
00084   props->scx        = env->exec (props->xt);
00085   props->scy        = env->exec (props->yt);
00086   props->hpadding   = env->get_length (CANVAS_HPADDING);
00087   props->vpadding   = env->get_length (CANVAS_VPADDING);
00088   props->border     = border;
00089   props->bg         = env->read (CANVAS_COLOR);
00090   props->alpha      = env->alpha;
00091   props->sunny      = env->get_color (ORNAMENT_SUNNY_COLOR);
00092   props->shadow     = env->get_color (ORNAMENT_SHADOW_COLOR);
00093   props->bar_width  = env->get_length (CANVAS_BAR_WIDTH);
00094   props->bar_padding= env->get_length (CANVAS_BAR_PADDING);
00095   props->bar_bg     = env->read (CANVAS_BAR_COLOR);
00096   props->bar_button = env->read (ORNAMENT_COLOR);
00097   return props;
00098 }
00099 
00100 void
00101 get_canvas_horizontal (canvas_properties props,
00102                      SI bx1, SI bx2, SI& x1, SI& x2, SI& scx)
00103 {
00104   edit_env env   = props->env;
00105   string   type  = props->type;
00106   SI       bwid  = props->bar_width;
00107   SI       bpad  = props->bar_padding;
00108   SI       border= props->border;
00109   x1= resize (env, bx1, bx1, bx2, props->x1);
00110   x2= resize (env, bx2, bx1, bx2, props->x2);
00111   if (type != "plain") {
00112     if (ends (type, "w") || ends (type, "e"))
00113       x2= max (x1, x2 - (bwid + bpad));
00114     x1 += (border + props->hpadding);
00115     x2 -= (border + props->hpadding);
00116   }
00117   if (is_atomic (props->scx) && ends (props->scx->label, "%")) {
00118     double p= as_double (props->scx->label (0, N(props->scx->label)-1))/100.0;
00119     SI d = ((x2 - x1) - (bx2 - bx1));
00120     SI dx= (d >= 0? 0: (SI) (p * d));
00121     scx  = dx + x1 - bx1;
00122   }
00123   else scx= -env->as_length (props->scx);
00124 }
00125 
00126 void
00127 get_canvas_vertical (canvas_properties props,
00128                    SI by1, SI by2, SI& y1, SI& y2, SI& scy)
00129 {
00130   edit_env env   = props->env;
00131   string   type  = props->type;
00132   SI       bwid  = props->bar_width;
00133   SI       bpad  = props->bar_padding;
00134   SI       border= props->border;
00135   y1= resize (env, by1, by1, by2, props->y1);
00136   y2= resize (env, by2, by1, by2, props->y2);
00137   if (type != "plain") {
00138     if (starts (type, "n") || starts (type, "s"))
00139       y2= max (y1, y2 - (bwid + bpad));
00140     y1 += (border + props->vpadding);
00141     y2 -= (border + props->vpadding);
00142   }
00143   if (is_atomic (props->scy) && ends (props->scy->label, "%")) {
00144     double p= as_double (props->scy->label (0, N(props->scy->label)-1))/100.0;
00145     SI d = ((y2 - y1) - (by2 - by1));
00146     SI dy= (d >= 0? d: (SI) (p * d));
00147     scy  = dy + y1 - by1;
00148   }
00149   else scy= -env->as_length (props->scy);
00150 }
00151 
00152 box
00153 make_hor_bar (canvas_properties props, path ip, SI x1, SI x2, SI X1, SI X2) {
00154   SI    h     = props->bar_width;
00155   SI    border= props->border;
00156   tree  c1    = props->bar_bg;
00157   color c2    = props->sunny;
00158   color c3    = props->shadow;
00159   tree  c4    = props->bar_button;
00160   int   a     = props->alpha;
00161   box   mask1 = empty_box (ip, x1, border, x2, h-border);
00162   box   mask2 = empty_box (ip, X1, 2*border, X2, h-2*border);
00163   box   hl1   = highlight_box (ip, mask1, border, 0, 0, c1, a, c3, c2);
00164   box   hl2   = highlight_box (ip, mask2, border, 0, 0, c4, a, c2, c3);
00165   array<box> bs (2);
00166   array<SI>  xs (2);
00167   array<SI>  ys (2);
00168   bs[0]= hl1; bs[1]= hl2;
00169   xs[0]= xs[1]= 0;
00170   ys[0]= ys[1]= 0;
00171   return composite_box (ip, bs, xs, ys);
00172 }
00173 
00174 box
00175 make_ver_bar (canvas_properties props, path ip, SI y1, SI y2, SI Y1, SI Y2) {
00176   SI    w     = props->bar_width;
00177   SI    border= props->border;
00178   tree  c1    = props->bar_bg;
00179   color c2    = props->sunny;
00180   color c3    = props->shadow;
00181   tree  c4    = props->bar_button;
00182   int   a     = props->alpha;
00183   box   mask1 = empty_box (ip, border, y1, w-border, y2);
00184   box   mask2 = empty_box (ip, 2*border, Y1, w-2*border, Y2);
00185   box   hl1   = highlight_box (ip, mask1, border, 0, 0, c1, a, c3, c2);
00186   box   hl2   = highlight_box (ip, mask2, border, 0, 0, c4, a, c2, c3);
00187   array<box> bs (2);
00188   array<SI>  xs (2);
00189   array<SI>  ys (2);
00190   bs[0]= hl1; bs[1]= hl2;
00191   xs[0]= xs[1]= 0;
00192   ys[0]= ys[1]= 0;
00193   return composite_box (ip, bs, xs, ys);
00194 }
00195 
00196 box
00197 put_scroll_bars (canvas_properties props, box b, path ip,
00198                box inner, SI scx, SI scy)
00199 {
00200   string type  = props->type;
00201   SI     hpad  = props->hpadding;
00202   SI     vpad  = props->vpadding;
00203   SI     bwid  = props->bar_width;
00204   SI     bpad  = props->bar_padding;
00205   SI     border= props->border;
00206   tree   ccol  = props->bg;
00207   int    a     = props->alpha;
00208   color  csun  = props->sunny;
00209   color  cshad = props->shadow;
00210   path   dip   = decorate (ip);
00211   int    hor   = 0;
00212   int    ver   = 0;
00213   if (type != "plain") {
00214     if (starts (type, "s")) hor= -1;
00215     if (starts (type, "n")) hor=  1;
00216     if (ends   (type, "w")) ver= -1;
00217     if (ends   (type, "e")) ver=  1;
00218   }
00219   array<box> bs (1);
00220   array<SI>  xs (1);
00221   array<SI>  ys (1);
00222   b     = resize_box (dip, b, b->x1-hpad, b->y1-vpad, b->x2+hpad, b->y2+vpad);
00223   bs[0] = highlight_box (dip, b, border, 0, 0, ccol, a, cshad, csun);
00224   xs[0] = (ver < 0? bwid + bpad: 0) - border;
00225   ys[0] = (hor < 0? bwid + bpad: 0) + border;
00226   if (hor != 0 && inner->w() > b->w() + 4 - 2*hpad) { 
00227     SI dx= b->x1 + hpad - inner->x1 - scx;
00228     double start= 0.0, end= 1.0;
00229     start= ((double) dx) / ((double) inner->w());
00230     end  = start + ((double) b->w() - 2*hpad) / ((double) inner->w());
00231     SI X1= b->x1 + border + ((SI) (start * (b->w() - 2*border)));
00232     SI X2= b->x1 + border + ((SI) (end   * (b->w() - 2*border)));
00233     box hor_bar= make_hor_bar (props, dip, b->x1, b->x2, X1, X2);
00234     hor_bar= scrollbar_box (dip, hor_bar, false, X2-X1, props->xt);
00235     bs << hor_bar;
00236     xs << (ver < 0? bwid + bpad: 0) - border;
00237     ys << (hor < 0? b->y1: b->y2 + bpad + 2*border);
00238   }
00239   if (ver != 0 && inner->h() > b->h() + 4 - 2*vpad) {
00240     SI dy= b->y1 + vpad - inner->y1 - scy;
00241     double start= 0.0, end= 1.0;
00242     start= ((double) dy) / ((double) inner->h());
00243     end  = start + ((double) b->h() - 2*vpad) / ((double) inner->h());
00244     SI Y1= b->y1 + border + ((SI) (start * (b->h() - 2*border)));
00245     SI Y2= b->y1 + border + ((SI) (end   * (b->h() - 2*border)));
00246     box ver_bar= make_ver_bar (props, dip, b->y1, b->y2, Y1, Y2);
00247     ver_bar= scrollbar_box (dip, ver_bar, true, Y2-Y1, props->yt);
00248     bs << ver_bar;
00249     xs << (ver < 0? b->x1 - 2*border: b->x2 + bpad);
00250     ys << (hor < 0? bwid + bpad: 0) + border;
00251   }
00252   return composite_box (ip, bs, xs, ys);
00253 }
00254 
00255 void
00256 concater_rep::typeset_canvas (tree t, path ip) {
00257   // IDEA: set left, right, bottom, top environment variables
00258   //       and allow doing computations with them
00259   if (N(t) != 7) { typeset_error (t, ip); return; }
00260   canvas_properties props= get_canvas_properties (env, t);
00261   box b= typeset_as_concat (env, t[6], descend (ip, 6));
00262   SI x1, y1, x2, y2, scx, scy;
00263   get_canvas_horizontal (props, b->x1, b->x2, x1, x2, scx);
00264   get_canvas_vertical (props, b->y1, b->y2, y1, y2, scy);
00265   string type= env->get_string (CANVAS_TYPE);
00266   path dip= (type == "plain"? ip: decorate (ip));
00267   box cb= clip_box (dip, b, x1, y1, x2, y2, props->xt, props->yt, scx, scy);
00268   if (type != "plain") cb= put_scroll_bars (props, cb, ip, b, scx, scy);
00269   print (cb);
00270 }
00271 
00272 /******************************************************************************
00273 * Highlighting
00274 ******************************************************************************/
00275 
00276 void
00277 concater_rep::typeset_ornament (tree t, path ip) {
00278   if (N(t) != 1) { typeset_error (t, ip); return; }
00279   SI    w     = env->get_length (ORNAMENT_BORDER);
00280   SI    xpad  = env->get_length (ORNAMENT_HPADDING);
00281   SI    ypad  = env->get_length (ORNAMENT_VPADDING);
00282   tree  bg    = env->read       (ORNAMENT_COLOR);
00283   color alpha = env->alpha;
00284   color sunny = env->get_color  (ORNAMENT_SUNNY_COLOR);
00285   color shadow= env->get_color  (ORNAMENT_SHADOW_COLOR);
00286   box   b     = typeset_as_concat (env, t[0], descend (ip, 0));
00287   print (highlight_box (ip, b, w, xpad, ypad, bg, alpha, sunny, shadow));
00288 }