Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: jpicedt/format/latex/parser/LaTeXPutExpression.java


1   /*
2    *  jPicEdt version 1.3.2, a picture editor for LaTeX.
3    *  Copyright (C) 1999-2002  Sylvain Reynal
4    *  This program is free software; you can redistribute it and/or modify
5    *  it under the terms of the GNU General Public License as published by
6    *  the Free Software Foundation; either version 2 of the License, or
7    *  (at your option) any later version.
8    *  This program is distributed in the hope that it will be useful,
9    *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   *  GNU General Public License for more details.
12   *  You should have received a copy of the GNU General Public License
13   *  along with this program; if not, write to the Free Software
14   *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15   *
16   *  Sylvain Reynal
17   *  Département de Physique
18   *  Ecole Nationale Supérieure de l'Electronique et de ses Applications (ENSEA)
19   *  6, avenue du Ponceau
20   *  F-95014 CERGY CEDEX
21   *  Tel : 00 +33 130 736 245
22   *  Fax : 00 +33 130 736 667
23   *  e-mail : reynal@ensea.fr
24   *  jPicEdt web page : http://www.jpicedt.org
25   */
26  package jpicedt.format.latex.parser;
27  
28  import jpicedt.graphic.io.parser.*;
29  import jpicedt.graphic.PicPoint;
30  import jpicedt.graphic.model.*;
31  
32  /**
33   *  \\put(x,y){argument} Depending on the argument found, instanciates :<p> 
34   * - PicText : \\makebox, \\framebox, \\dashbox or LR-argument <p>
35   * - PicPolygon : \\line, \\vector.
36   * - PicEllipse : \\circle
37   *
38   * @author     reynal
39   */
40  public class LaTeXPutExpression extends SequenceExpression implements ExpressionConstants,PicObjectConstants {
41  
42    private Pool pool;
43    private PicPoint putPoint = new PicPoint();// \\put^(x,y)^{...} i.e. location
44    private StringBuffer hrArgument = new StringBuffer(); // used by HRArgument
45  
46    // used by LaTeXBoxExpression :
47    private boolean isFixedSizeBox; 
48    private double boxWidth, boxHeight, boxDash;
49    private String horAlign, vertAlign;
50    // used by LaTeXLineExpression :
51    private double x,y;
52    // use by LaTeXCircleExpression :
53    private boolean filledCircle; 
54  
55    /**
56     * Constructor for the LaTeXPutExpression object
57     * @param  pl  Description of the Parameter
58     */
59    public LaTeXPutExpression(Pool pl) {
60  
61      super(true);
62      pool = pl;
63  
64      add(new LiteralExpression("\\put"));
65      add(WHITE_SPACES_OR_EOL);
66      add(
67        new PicPointExpression("(", ",", ")") {
68          public void action(ParserEvent e) {
69            if (DEBUG) System.out.println(e);
70            putPoint = ((PicPoint) e.getValue()).toMm(pool.getDouble(LaTeXParser.KEY_UNIT_LENGTH));// global var
71          }
72        });
73      add(WHITE_SPACES_OR_EOL);
74      
75      // {stuff} :
76      AlternateExpression putArgs = new AlternateExpression();
77      putArgs.add(new LaTeXBoxExpression());// \\makebox, ...
78      putArgs.add(new LaTeXCircleExpression(false));// \\circle{d}
79      putArgs.add(new LaTeXCircleExpression(true));// \\circle*{d}
80      putArgs.add(new LaTeXOvalExpression());// \\oval(w,h)
81      putArgs.add(new LaTeXLineExpression());// \\line(x,y){len}
82      // [pending] LR-argument, line, vector, ... 
83      putArgs.add(new HRArgument()); // pure HR argument (must always be added last)
84      SequenceExpression putArgsEOL = new SequenceExpression(WHITE_SPACES_OR_EOL, putArgs, false); 
85      add(new EnclosingExpression("{", putArgsEOL, "}"));
86  
87    }
88  
89    /** called when this SequenceExpression was successfully parsed -> reinit locals for next time */
90    public void action(ParserEvent e){
91      if (DEBUG) System.out.println(e);
92      putPoint = new PicPoint();
93      hrArgument = new StringBuffer(); // used by HRArgument
94      horAlign = PicText.CENTER_H;
95      vertAlign = PicText.CENTER_V;
96      isFixedSizeBox = false;
97      filledCircle = false;
98    }
99  
100   public String toString(){
101     return "[LaTeXPutExpression]";
102   }
103   
104   //////////////////////////////////////////// CIRCLE //////////////////////////////////////////////
105   
106   /**
107    *  \circle{diam} -> circle <p>
108    *  \circle*{diam} -> disk (filled)<p> 
109    */
110   class LaTeXCircleExpression extends SequenceExpression {
111 
112     public LaTeXCircleExpression(boolean filled) {
113 
114       super(true);// throw IncompleteExpression
115       filledCircle = filled;
116 
117       if (filled) this.add(new LaTeXInstanciationExpression("\\circle*{", new PicEllipse(), pool));
118       else this.add(new LaTeXInstanciationExpression("\\circle{", new PicEllipse(), pool));
119       this.add(WHITE_SPACES_OR_EOL);
120       this.add(
121         new NumericalExpression(DOUBLE, POSITIVE, "}", true) {
122           public void action(ParserEvent e) {
123             if (DEBUG) System.out.println(e);
124             PicEllipse ell = (PicEllipse)(pool.currentObj);
125             ell.setPoint(PicEllipse.P_CENTER, putPoint);
126             double diam = getValue().doubleValue() * pool.getDouble(LaTeXParser.KEY_UNIT_LENGTH);
127             ell.setWidth(diam);
128             ell.setHeight(diam);
129             if (filledCircle) ell.setAttribute(FILL_STYLE,SOLID); 
130           }
131         }
132       );
133     }
134   }
135 
136   //////////////////////////////////////////// OVAL //////////////////////////////////////////////
137   
138   /**
139    *  \oval(w,h) or \oval(w,h)[align] (for half- or quarter- ovals).
140    * <p>
141    * Shape is centered on putPoint.
142    * [pending] add "rounded corner" capacity to PicRectangle
143    */
144   class LaTeXOvalExpression extends SequenceExpression {
145 
146     public LaTeXOvalExpression() {
147 
148       super(true);// throw IncompleteExpression
149 
150       this.add(new LaTeXInstanciationExpression("\\oval", new PicRectangle(), pool));
151       this.add(WHITE_SPACES_OR_EOL);
152       this.add(
153         new PicPointExpression("(", ",", ")"){
154           public void action(ParserEvent e) {
155             if (DEBUG) System.out.println(e);
156             PicPoint pt = (PicPoint)e.getValue();
157             PicRectangle oval = (PicRectangle)pool.currentObj;
158             oval.setPoint(PicRectangle.P_CENTER, putPoint);
159             double w = pt.x * pool.getDouble(LaTeXParser.KEY_UNIT_LENGTH);
160             oval.setWidth(w);
161             double h = pt.y * pool.getDouble(LaTeXParser.KEY_UNIT_LENGTH);
162             oval.setHeight(h);
163           }
164         }
165       );
166       this.add(WHITE_SPACES_OR_EOL);
167       // [pending] not used so far !!!
168       SequenceExpression alignmentExp = new SequenceExpression(true);// throw IncompleteSequence Exception
169       alignmentExp.add(new LiteralExpression("["));
170       alignmentExp.add(new TextAlignment()); // swallows chars till "]" is found
171       this.add(new OptionalExpression(alignmentExp));
172     }
173   }
174 
175   //////////////////////////////////////////// LINES //////////////////////////////////////////////
176   
177   /**
178    *  \\line(x,y){hor-len} -> line starting at (x,y), and having hor-len as its horizonal extent (except
179    *  for vertical lines, where hor-len specifies the vertical extent.<p>
180    *  \\vector(x,y){hor-len} -> same thing, yet with an arrow
181    */
182   class LaTeXLineExpression extends SequenceExpression {
183 
184     public LaTeXLineExpression() {
185 
186       super(true);// throw IncompleteExpression
187 
188       // \line -> set first polygon point
189       this.add(new AlternateExpression(
190         new LaTeXInstanciationExpression("\\line", new PicPolygon(new PicPoint(),new PicPoint()), pool),
191         new LaTeXInstanciationExpression("\\vector", new PicPolygon(new PicPoint(),new PicPoint()), pool){
192           public void action(ParserEvent e) {
193             super.action(e);
194             pool.currentObj.setAttribute(RIGHT_ARROW, Arrow.ARROW_HEAD);
195         }}));
196       this.add(WHITE_SPACES_OR_EOL);
197       // (x,y) -> set slope
198       this.add(
199         new PicPointExpression("(", ",", ")"){
200           public void action(ParserEvent e) {
201             if (DEBUG) System.out.println(e);
202             PicPoint pt = (PicPoint)e.getValue();
203             x = pt.x ; y = pt.y;
204           }
205         }
206       );
207       this.add(WHITE_SPACES_OR_EOL);
208       // {
209       this.add(new LiteralExpression("{"));
210       // len} -> must be .ge. 0
211       this.add(
212         new NumericalExpression(DOUBLE, POSITIVE, "}", true) {
213           public void action(ParserEvent e) {
214             if (DEBUG) System.out.println(e);
215             // horizontal extent (except for vertical lines) :
216             double len = ((Double)e.getValue()).doubleValue() * pool.getDouble(LaTeXParser.KEY_UNIT_LENGTH);
217             PicPolygon pp = ((PicPolygon)(pool.currentObj));
218             // vertical line :
219             PicPoint pt1 = new PicPoint(putPoint);
220             if (x==0){
221               if (y>=0) pt1.translate(0,len);
222               else pt1.translate(0,-len);  
223             }
224             // other lines :
225             else {
226               if (x>=0) pt1.x += len;
227               else pt1.x -= len;
228               if (y>=0) pt1.y += len * Math.abs(y/x);
229               else pt1.y -= len * Math.abs(y/x);
230             }
231             pp.setPoint(0,putPoint);
232             pp.setPoint(1,pt1);
233           }
234         }
235       );
236     }
237   }
238 
239   //////////////////////////////////////////// BOXES //////////////////////////////////////////////
240   
241   /**
242    * PicText : argument =<br> 
243    * \\makebox(w,h)[vh]{text or LaTeX command}<br> 
244    * \\framebox(w,h)[vh]{text or LaTeX command}<br>
245    * \\dashbox{dash}(w,h)[vh]{text or LaTeX command}<br> 
246    * interpret(c) return false if none of these have been found, and cursor position is left unchanged<br>
247    * Uses "TextAlignement"<BR>
248    * @author     reynal
249    */
250   class LaTeXBoxExpression extends SequenceExpression {
251 
252     public LaTeXBoxExpression() {
253 
254       super(true);// possibly throws IncompleteSequence Exception if only \\XXXXbox was found
255 
256       PicAttributeSet dummy = new PicAttributeSet(); // only here because PicText constructor requires one.
257 
258 
259       // boxtype :
260       AlternateExpression boxType = new AlternateExpression();// \|/ boxed ?
261       
262       // \\makebox
263       boxType.add(new LaTeXInstanciationExpression(
264         "\\makebox", 
265         new PicText(new PicPoint(), "", PicText.NO_FRAME, PicText.CENTER_H, PicText.CENTER_V, dummy), 
266         pool));
267 
268       // \\framebox
269       boxType.add(new LaTeXInstanciationExpression(
270         "\\framebox", 
271         new PicText(new PicPoint(), "", PicText.RECTANGLE, PicText.CENTER_H, PicText.CENTER_V, dummy), 
272         pool));
273 
274       // \\frame (must appear AFTER framebox !!!)
275       boxType.add(new LaTeXInstanciationExpression(
276         "\\frame", 
277         new PicText(new PicPoint(), "", PicText.RECTANGLE, PicText.CENTER_H, PicText.CENTER_V, dummy), 
278         pool));
279 
280       // \\dashbox{dash}
281       boxType.add(new SequenceExpression(
282         new LaTeXInstanciationExpression(
283           "\\dashbox", 
284           new PicText(new PicPoint(), "", PicText.RECTANGLE, PicText.CENTER_H, PicText.CENTER_V, dummy), 
285           pool),
286         WHITE_SPACES_OR_EOL,
287         new SequenceExpression(
288           new LiteralExpression("{"), // {dash}
289           new NumericalExpression(DOUBLE, POSITIVE, "}", true) {
290             public void action(ParserEvent e) {
291               if (DEBUG) System.out.println(e);
292               boxDash = ((Double) e.getValue()).doubleValue() * pool.getDouble(LaTeXParser.KEY_UNIT_LENGTH);
293               pool.currentObj.setAttribute(DASH_OPAQUE, new Double(boxDash));
294               pool.currentObj.setAttribute(DASH_TRANSPARENT, new Double(boxDash));
295             }
296           }, 
297           true),
298         true));// possibly throws IncompleteSequence Exception once "{" was found
299       this.add(boxType);
300       this.add(WHITE_SPACES_OR_EOL);
301       // (w,h) (optional ; if found, we instanciate a PicRectangle and make the previously instanciated
302       //        PicText frameless)
303       this.add(new OptionalExpression(new PicPointExpression("(", ",", ")"){
304         public void action(ParserEvent e){
305           if (DEBUG) System.out.println(e);
306           isFixedSizeBox = true; // flag to inform the EnclosingExpression - see below - it must instanciate a PicRectangle
307           PicPoint pt = (PicPoint)e.getValue();
308           boxWidth = pt.x; boxHeight = pt.y;
309         }}));
310       this.add(WHITE_SPACES_OR_EOL);
311       // optional alignment : [vh] where v = b|t|c|"" and h = r|l|c|"" ("" default to center)
312       SequenceExpression alignmentExp = new SequenceExpression(true);// throw IncompleteSequence Exception
313       alignmentExp.add(new LiteralExpression("["));
314       alignmentExp.add(new TextAlignment()); // swallows chars till "]" is found
315       alignmentExp.add(WHITE_SPACES_OR_EOL);
316       this.add(new OptionalExpression(alignmentExp));
317       // text or LaTeX Command
318       this.add(WHITE_SPACES_OR_EOL);
319       this.add(new BoxEnclosedText());
320     }
321   }
322 
323   /**
324    * Handles text inside a box-command (e.g. \\makebox{text}), after replacing CR by white-spaces as TeX does.
325    */
326   class BoxEnclosedText extends EnclosingExpression {
327     
328     public BoxEnclosedText(){
329       super("{", null, "}");
330     }
331     
332     public void action(ParserEvent e) {
333       if (DEBUG) System.out.println(e);
334       PicText text = ((PicText)pool.currentObj);
335       String s = getEnclosedString().replace('\n',' ');
336       s = Context.removeRedundantWhiteSpaces(s);
337       text.setText(s);
338       text.setVertAlign(vertAlign);
339       text.setHorAlign(horAlign);
340       if (isFixedSizeBox){
341         // change text location  :
342         PicPoint ptText = new PicPoint();
343         if (vertAlign == PicText.TOP) ptText.y = putPoint.y + boxHeight;
344         else if (vertAlign == PicText.BOTTOM) ptText.y = putPoint.y;
345         else ptText.y = putPoint.y + 0.5*boxHeight; // CENTER_V
346         if (horAlign == PicText.LEFT) ptText.x = putPoint.x;
347         else if (horAlign == PicText.RIGHT) ptText.x = putPoint.x + boxWidth;
348         else ptText.x = putPoint.x + 0.5*boxWidth; // CENTER_H
349         text.setPoint(PicText.P_ANCHOR, ptText);
350         // possibly add a box on its own, set its size and location :
351         if (text.getFrameType() == PicText.RECTANGLE){        
352           // suppress box from PicText
353           text.setFrameType(PicText.NO_FRAME);
354           PicPoint pt2 = new PicPoint(putPoint.x + boxWidth, putPoint.y + boxHeight);
355           // copy attribute set from text to box (dash, ...)
356           PicRectangle box = new PicRectangle(putPoint,pt2,text.getAttributeSet());
357           pool.currentGroup.addChild(box);
358           pool.currentObj = box; // only for security reason... (probably useless)
359         }
360         isFixedSizeBox = false;  // reset flag for next time !
361       }
362       else {
363         text.setPoint(PicText.P_ANCHOR, putPoint);
364       }
365     }
366   }
367 
368   /**
369    * handles boxes alignement, e.g. "bc]" ,... First "[" isn't parsed here. 
370    * Modifies global vars "vertAlign" and "horAlign".
371    */
372   class TextAlignment extends WordExpression {
373     
374     public TextAlignment(){
375       super("]", true); // swallows "]" and can return an empty String as in "[]"
376     }
377     
378     public void action(ParserEvent e) {
379       if (DEBUG) System.out.println(e);
380       String s = (String) e.getValue();
381 
382       if (s.indexOf("t")!=-1) vertAlign = PicText.TOP; 
383       else if (s.indexOf("b")!=-1) vertAlign = PicText.BOTTOM;
384       else vertAlign = PicText.CENTER_V;
385 
386       if (s.indexOf("l")!=-1) horAlign = PicText.LEFT;
387       else if (s.indexOf("r")!=-1) horAlign = PicText.RIGHT;
388       else horAlign = PicText.CENTER_H;
389     }
390   }
391 
392   /**
393    * swallow as many chars as possible and push them in "hrArgument" buffer, replacing
394    * CR by whitespaces, as TeX does.
395    */
396   class HRArgumentSucker extends WildCharExpression {
397 
398     public HRArgumentSucker(){ // no jokes, but it really sucks !
399       super(ANY_CHAR_EOL);
400     }
401         public void action(ParserEvent e){
402       if (DEBUG) System.out.println(e);
403       Character cc = getCharacter();
404       if (cc.charValue() == '\n') hrArgument.append(' ');
405       else hrArgument.append(cc);
406     }
407   }
408   
409   /**
410    * handles content of "{stuff}" when no other expression matches, by instanciating a PicText
411    * with "stuff" as the PicText string
412    */
413   class HRArgument extends RepeatExpression {
414     
415     HRArgument(){
416       super(null,0,AT_LEAST);
417       setPattern(new HRArgumentSucker());
418     }
419     
420     public void action(ParserEvent e){
421       if (DEBUG) System.out.println(e);
422       String s = Context.removeRedundantWhiteSpaces(hrArgument.toString());
423       pool.currentObj = new PicText(putPoint, s, PicText.NO_FRAME, PicText.CENTER_H, PicText.CENTER_V, pool.getAttributeSet(LaTeXParser.KEY_ATTRIBUTES));
424       pool.currentGroup.addChild(pool.currentObj);
425     }
426   }
427   
428 }
429