Back to index

texmacs  1.0.7.15
lazy_gui.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : lazy_gui.cpp
00004 * DESCRIPTION: Lazy typesetting of GUI primitives
00005 * COPYRIGHT  : (C) 1999  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 "Line/lazy_typeset.hpp"
00013 #include "Line/lazy_vstream.hpp"
00014 #include "Format/format.hpp"
00015 #include "Stack/stacker.hpp"
00016 #include "Boxes/construct.hpp"
00017 #include "analyze.hpp"
00018 #include "Concat/canvas_properties.hpp"
00019 
00020 /******************************************************************************
00021 * Canvases
00022 ******************************************************************************/
00023 
00024 struct lazy_canvas_rep: public lazy_rep {
00025   canvas_properties props;
00026   lazy par;
00027 
00028   lazy_canvas_rep (canvas_properties props2, lazy par2, path ip):
00029     lazy_rep (LAZY_CANVAS, ip), props (props2), par (par2) {}
00030   inline operator tree () { return "Canvas"; }
00031   lazy produce (lazy_type request, format fm);
00032   format query (lazy_type request, format fm);
00033 };
00034 
00035 struct lazy_canvas {
00036 EXTEND_NULL(lazy,lazy_canvas);
00037   inline lazy_canvas (canvas_properties props, lazy par, path ip):
00038     rep (tm_new<lazy_canvas_rep> (props, par, ip)) {
00039       rep->ref_count= 1; }
00040 };
00041 EXTEND_NULL_CODE(lazy,lazy_canvas);
00042 
00043 format
00044 lazy_canvas_rep::query (lazy_type request, format fm) {
00045   if ((request == LAZY_BOX) && (fm->type == QUERY_VSTREAM_WIDTH)) {
00046     format body_fm= par->query (request, fm);
00047     format_width fmw= (format_width) body_fm;
00048     SI width= fmw->width;
00049     edit_env env= props->env;
00050     tree old1= env->local_begin (PAGE_MEDIUM, "papyrus");
00051     tree old2= env->local_begin (PAR_LEFT, "0tmpt");
00052     tree old3= env->local_begin (PAR_RIGHT, "0tmpt");
00053     tree old4= env->local_begin (PAR_MODE, "justify");
00054     tree old5= env->local_begin (PAR_NO_FIRST, "true");
00055     tree old6= env->local_begin (PAR_WIDTH, tree (TMLEN, as_string (width)));
00056     SI x1, x2, scx;
00057     get_canvas_horizontal (props, 0, fmw->width, x1, x2, scx);
00058     env->local_end (PAR_WIDTH, old6);
00059     env->local_end (PAR_NO_FIRST, old5);
00060     env->local_end (PAR_MODE, old4);
00061     env->local_end (PAR_RIGHT, old3);
00062     env->local_end (PAR_LEFT, old2);
00063     env->local_end (PAGE_MEDIUM, old1);
00064     SI delta= 0;
00065     string type= props->type;
00066     if (type != "plain") {
00067       SI hpad= props->hpadding;
00068       SI w   = props->bar_width;
00069       SI pad = props->bar_padding;
00070       SI bor = props->border;
00071       if (ends (type, "w") || ends (type, "e"))
00072        delta= max (0, w + pad);
00073       delta += 2 * bor + 2 * hpad;
00074     }
00075     return make_format_width (x2 - x1 + delta);
00076   }
00077   return lazy_rep::query (request, fm);
00078 }
00079 
00080 lazy
00081 lazy_canvas_rep::produce (lazy_type request, format fm) {
00082   if (request == type) return this;
00083   if (request == LAZY_VSTREAM || request == LAZY_BOX) {
00084     SI delta= 0;
00085     string type= props->type;
00086     if (type != "plain") {
00087       SI hpad= props->hpadding;
00088       SI w   = props->bar_width;
00089       SI pad = props->bar_padding;
00090       SI bor = props->border;
00091       if (ends (type, "w") || ends (type, "e"))
00092        delta= max (0, w + pad);
00093       delta += 2 * bor + 2 * hpad;
00094     }
00095     format bfm= fm;
00096     if (request == LAZY_VSTREAM) {
00097       format_vstream fvs= (format_vstream) fm;
00098       bfm= make_format_width (fvs->width - delta);
00099     }
00100     box b= (box) par->produce (LAZY_BOX, bfm);
00101     format_width fmw= (format_width) bfm;
00102     SI width= fmw->width + delta;
00103     edit_env env= props->env;
00104     tree old1= env->local_begin (PAGE_MEDIUM, "papyrus");
00105     tree old2= env->local_begin (PAR_LEFT, "0tmpt");
00106     tree old3= env->local_begin (PAR_RIGHT, "0tmpt");
00107     tree old4= env->local_begin (PAR_MODE, "justify");
00108     tree old5= env->local_begin (PAR_NO_FIRST, "true");
00109     tree old6= env->local_begin (PAR_WIDTH, tree (TMLEN, as_string (width)));
00110     SI x1, x2, scx;
00111     get_canvas_horizontal (props, b->x1, b->x2, x1, x2, scx);
00112     SI y1, y2, scy;
00113     get_canvas_vertical (props, b->y1, b->y2, y1, y2, scy);
00114     env->local_end (PAR_WIDTH, old6);
00115     env->local_end (PAR_NO_FIRST, old5);
00116     env->local_end (PAR_MODE, old4);
00117     env->local_end (PAR_RIGHT, old3);
00118     env->local_end (PAR_LEFT, old2);
00119     env->local_end (PAGE_MEDIUM, old1);
00120     path dip= (type == "plain"? ip: decorate (ip));
00121     box rb= clip_box (dip, b, x1, y1, x2, y2, props->xt, props->yt, scx, scy);
00122     if (type != "plain") rb= put_scroll_bars (props, rb, ip, b, scx, scy);
00123     if (request == LAZY_BOX) return make_lazy_box (rb);
00124     else {
00125       array<page_item> l;
00126       l << page_item (rb);
00127       return lazy_vstream (ip, "", l, stack_border ());
00128     }
00129   }
00130   return lazy_rep::produce (request, fm);
00131 }
00132 
00133 lazy
00134 make_lazy_canvas (edit_env env, tree t, path ip) {
00135   canvas_properties props= get_canvas_properties (env, t);
00136   lazy par= make_lazy (env, t[6], descend (ip, 6));
00137   return lazy_canvas (props, par, ip);
00138 }
00139 
00140 /******************************************************************************
00141 * Ornaments
00142 ******************************************************************************/
00143 
00144 struct lazy_ornament_rep: public lazy_rep {
00145   edit_env env;             // "current" environment
00146   lazy par;                 // the ornamented body
00147   SI w, xpad, ypad;         // spacing parameters
00148   tree bg;                  // background color or pattern
00149   int alpha;                // alpha transparency of background
00150   color sunny, shadow;      // border colors
00151   lazy_ornament_rep (edit_env env2, lazy par2, path ip,
00152                    SI w2, SI xpad2, SI ypad2,
00153                    tree bg2, int alpha2, color sunny2, color shadow2):
00154     lazy_rep (LAZY_ORNAMENT, ip), env (env2), par (par2),
00155     w (w2), xpad (xpad2), ypad (ypad2),
00156     bg (bg2), alpha (alpha2), sunny (sunny2), shadow (shadow2) {}
00157   
00158   inline operator tree () { return "Ornament"; }
00159   lazy produce (lazy_type request, format fm);
00160   format query (lazy_type request, format fm);
00161 };
00162 
00163 struct lazy_ornament {
00164 EXTEND_NULL(lazy,lazy_ornament);
00165   lazy_ornament (edit_env env, lazy par, path ip,
00166                SI w, SI xpad, SI ypad,
00167                tree bg, int alpha, color sunny, color shadow):
00168     rep (tm_new<lazy_ornament_rep> (env, par, ip, w, xpad, ypad,
00169                                     bg, alpha, sunny, shadow)) {
00170     rep->ref_count= 1; }
00171 };
00172 EXTEND_NULL_CODE(lazy,lazy_ornament);
00173 
00174 format
00175 lazy_ornament_rep::query (lazy_type request, format fm) {
00176   if ((request == LAZY_BOX) && (fm->type == QUERY_VSTREAM_WIDTH)) {
00177     format body_fm= par->query (request, fm);
00178     format_width fmw= (format_width) body_fm;
00179     return make_format_width (fmw->width + 2 * (w + xpad));
00180   }
00181   return lazy_rep::query (request, fm);
00182 }
00183 
00184 lazy
00185 lazy_ornament_rep::produce (lazy_type request, format fm) {
00186   if (request == type) return this;
00187   if (request == LAZY_VSTREAM || request == LAZY_BOX) {
00188     format bfm= fm;
00189     if (request == LAZY_VSTREAM) {
00190       format_vstream fvs= (format_vstream) fm;
00191       bfm= make_format_width (fvs->width - 2 * (w + xpad));
00192     }
00193     box b = (box) par->produce (LAZY_BOX, bfm);
00194     box hb= highlight_box (ip, b, w, xpad, ypad, bg, alpha, sunny, shadow);
00195     // FIXME: this dirty hack ensures that shoving is correct
00196     hb= move_box (decorate (ip), hb, 1, 0);
00197     hb= move_box (decorate (ip), hb, -1, 0);
00198     // End dirty hack
00199     if (request == LAZY_BOX) return make_lazy_box (hb);
00200     else {
00201       array<page_item> l;
00202       l << page_item (hb);
00203       return lazy_vstream (ip, "", l, stack_border ());
00204     }
00205   }
00206   return lazy_rep::produce (request, fm);
00207 }
00208 
00209 lazy
00210 make_lazy_ornament (edit_env env, tree t, path ip) {
00211   SI    w     = env->get_length (ORNAMENT_BORDER);
00212   SI    xpad  = env->get_length (ORNAMENT_HPADDING);
00213   SI    ypad  = env->get_length (ORNAMENT_VPADDING);
00214   tree  bg    = env->read       (ORNAMENT_COLOR);
00215   int   a     = env->alpha;
00216   color sunny = env->get_color  (ORNAMENT_SUNNY_COLOR);
00217   color shadow= env->get_color  (ORNAMENT_SHADOW_COLOR);
00218   lazy  par   = make_lazy (env, t[0], descend (ip, 0));
00219   return lazy_ornament (env, par, ip, w, xpad, ypad, bg, a, sunny, shadow);
00220 }