View Javadoc

1   /*
2    * Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton,
3    * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
4    *
5    * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
6    * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
7    * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
8    * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
9    * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
10   * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
11   * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
12   * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
13   * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
14   * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
15   * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
16   * OR MODIFICATIONS.
17   * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
18   * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
19   * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
20   * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
21   */
22  
23  package de.desy.acop.chart;
24  import java.awt.Font;
25  import java.awt.FontMetrics;
26  import java.awt.Graphics2D;
27  import java.awt.Rectangle;
28  import java.awt.geom.AffineTransform;
29  
30  public class AcopText
31  {   
32  	protected  boolean	textON,			// on or off
33  			outside,
34  			scalable;					// go with coordinates
35  	protected  int	xcenter,					// x input: left(0), center(1) or right(2)
36  			ycenter,					// y input: bottom(0), center(1) or top(2)
37        moveable,
38        rotationDegree,   // 0 - 365degree
39  			prePrint,					// textprint prio ondraw!
40  			width,
41  			height,
42  			length;						// char width and string length
43    protected  double	text_x, text_y,		// user units??
44  			conv_x, conv_y,             // starting print position
45        lastTextx, lastTexty;
46    protected  double	xsize, ysize;		// user display rectangle
47  	protected  double	scaleFactor;
48    protected  int	saveHeight, saveWidth, lfHeight, lfWidth, lfAscent, lfDescent;
49  	protected  int		dev_x, dev_y;		// device units??
50    protected  java.awt.Color   textColor;
51    protected  java.lang.String	textstr;
52  	protected  java.awt.Font	textFont, inputFont;
53  	protected  Rectangle	textRect;
54    protected  int rescaleFlag;
55  
56    protected  double rotateGrad;
57    protected  int    offsetX, offsetY;   // device units??
58    protected  double sin, cos;
59    protected  double  xOffset,yOffset;      // for text area computation
60    protected  double  heightSin, heightCos, lengthSin, lengthCos;
61   
62    private Acop acop;
63      
64    public AcopText(Acop acop)
65  	{
66      this.acop = acop;
67  	  
68  	  textON=false;
69  	  text_x=0;
70  	  text_y=0;
71  	  length=0;
72  	  prePrint=0;
73  	  outside=true;
74  	  scalable=false;
75  	  moveable=0;
76  	  xcenter=0;
77  	  ycenter=0;
78      rescaleFlag = 1;
79        
80      textRect = new Rectangle();
81  		//{{INIT_CONTROLS
82  		//}}
83  	}
84  	//{{DECLARE_CONTROLS
85  	protected java.lang.String getPrintedText(double[] leftBottom, double[] size, double[] position)
86  	{
87      if ( position != null )
88      {
89        position[0] = text_x;
90  	    if ( position.length > 1 ) position[1] = text_y;
91  	  }
92      if ( size != null )
93      {
94        size[0] = textRect.width * acop.sca[0].dispSize / acop.aFrame.dxwidth;
95        if ( size.length > 1 ) size[1] = textRect.height * acop.sca[1].dispSize / acop.aFrame.histRect.height;
96      }
97      if ( leftBottom != null )
98      {
99        leftBottom[0] = (textRect.x-acop.aFrame.histRect.x) * acop.sca[0].dispSize / acop.aFrame.dxwidth + acop.sca[0].min;
100       if ( leftBottom.length > 1 ) leftBottom[1] = (textRect.height-textRect.y+acop.aFrame.histRect.y) * acop.sca[1].dispSize / acop.aFrame.histRect.height + acop.sca[1].min;
101     }
102 	  return textstr;
103 	}
104         
105   protected void printUserText(java.awt.Graphics2D a)
106   { boolean nullFlag;
107     
108     if ( acop.textFlag == false || textON == false || outside == true ) return;
109     if ( rescaleFlag != 0 ) rescaleText(rescaleFlag);
110 	  if ( a == null )
111 	  {
112 	    a = (Graphics2D)acop.getGraphics();
113       a.clipRect(acop.histRoundRect.x, acop.histRoundRect.y, acop.histRoundRect.width, acop.histRoundRect.height);
114       a.translate(acop.aFrame.histRect.x, acop.aFrame.histRect.y);
115 	    nullFlag = true;
116 	  }
117 	  else nullFlag = false;
118     
119 //    a.clipRect(textRect.x, textRect.y, textRect.width, textRect.height);
120     	  
121     a.setFont(textFont);
122     a.setColor(textColor);
123     if ( rotationDegree != 0 )
124     {
125       AffineTransform oldTransform = a.getTransform();
126       a.translate(dev_x, dev_y);
127       a.rotate(-rotateGrad); 
128       a.drawString(textstr, offsetX, offsetY - lfDescent);
129       a.setTransform(oldTransform);
130     } else a.drawString(textstr, dev_x+offsetX, dev_y+offsetY - lfDescent);
131      
132     if ( nullFlag )
133     {
134       a.translate(-acop.aFrame.histRect.x, -acop.aFrame.histRect.y);
135       a.dispose();
136 	  }
137   }
138   
139   protected int printText(java.lang.String Text, double Xposition, double Yposition, java.awt.Color c, java.awt.Font font)
140   { int resca, lineFit;      
141     int i, move, localxcenter, localycenter, localRotation;
142     boolean localscalable;
143       
144     lineFit = Text.indexOf(13);
145       
146     move = acop.printTextStickyAttribute & AcopConst.TEXT_MOVE;
147     if ( acop.printTextStickyAttribute == 4 ) move = AcopConst.TEXT_MOVE;
148 	  localxcenter = acop.printTextLocation % 3;
149 	  if ( acop.printTextLocation < 3 ) localycenter = 0;
150 	  else if ( acop.printTextLocation < 6 ) localycenter = 1;
151 	  else localycenter = 2;
152     localRotation = acop.printTextRotation;
153     
154     localscalable = move == AcopConst.TEXT_MOVE ? true : false;
155     if ( acop.printTextStickyAttribute == 4 ) localscalable = false;
156 
157     moveable = 0;
158     scalable = false;
159 
160     if ( textON == true )		// get rid of old text
161     {
162     	textON = false;
163     	if ( outside == false ) acop.repaint( textRect.x, textRect.y, textRect.width, textRect.height);
164     }
165       
166     // check if location or ration have been changed?
167     resca = (localxcenter != xcenter || localycenter != ycenter) ? 1 : 0 ;
168     if ( Math.abs(Xposition - text_x) > AcopConst.zero_check ) resca++;
169 	  text_x = Xposition;
170     if ( Math.abs(Yposition - text_y) > AcopConst.zero_check ) resca++;
171 	  text_y = Yposition;
172     if ( localRotation != rotationDegree ) resca++;
173  
174     if ( lineFit > 0 ) {		// if text + linefeed, then remove linefeed
175     	Text = Text.substring(0,lineFit-1);
176   	  lineFit = 1;
177     } else lineFit = 0;
178 
179     rotationDegree = localRotation;
180     rotateGrad = rotationDegree * Math.PI / 180;
181     if ( rotationDegree == 0 )
182     {
183       cos = 1;
184       sin = 0;
185     }
186     else
187     {
188       cos = Math.cos(rotateGrad);
189       sin = Math.sin(rotateGrad);
190     }
191     
192     textColor = c;
193     textFont = font;
194     inputFont = font;
195     textstr = Text;
196     xcenter = localxcenter;
197     ycenter = localycenter;
198     if ( xcenter == 0 ) xOffset = 0;  // set rotation calculation parameters
199     else if ( xcenter == 1 ) xOffset = 0.5;
200     else xOffset = 1;
201     if ( ycenter == 0 ) yOffset = 1;
202     else if ( ycenter == 1 ) yOffset = 0.5;
203     else yOffset = 0;
204     
205     textON = true;
206     if ( resca != 0 || rescaleFlag != 0 )
207     {
208     	length = Text.length();
209     	rescaleText(AcopConst.NEW_PRINT_WINDOW);
210     }
211     else if ( length != Text.length() )
212     {
213 	    length = Text.length();
214       setTextAttribute(true,conv_x);
215     }
216     lastTextx = text_x;       //store last text coordinates
217     if ( lineFit != 0 )
218     {
219       lastTexty = acop.sca[1].dispSize * lfHeight / acop.aFrame.histRect.height;
220       if ( acop.sca[1].log != 0 ) lastTexty = Math.pow ( 10.0, lastTexty );
221       lastTexty = text_y - lastTexty;
222     } else lastTexty = text_y;
223 
224     acop.textFlag = true;
225     moveable = move;
226     scalable = localscalable;
227       
228     if ( scalable )	// store origin display area
229     {
230     	xsize = acop.sca[0].dispSize;
231     	ysize = acop.sca[1].dispSize;
232       scaleFactor = 1;
233 	    saveHeight = lfHeight;
234     	saveWidth = lfWidth;
235     }
236 
237     if ( acop.drawTicks )
238     {
239       acop.repaint();
240       acop.drawTicks = false;
241     }
242     else  printUserText(null);
243 
244 //      if ( de.desy.acop.chart.disp[0] == null && scalecall < 2 )
245 //      {
246 //    	InvalidateControl(NULL);		// draw ticks and grid...if no histo at all
247 //    	scalecall = 2;
248 //      }
249     return ( 0 );
250   }
251 
252   protected void refreshText(java.lang.String Text)
253   { int scaled = 0;
254 
255     if ( textON )    // get rid of old text
256     {
257       if ( Text.compareTo(textstr) == 0 && rescaleFlag == 0 ) return;  // already on
258     	if ( outside == false )
259     	{
260     	  textON = false;
261         acop.repaint( textRect.x, textRect.y, textRect.width, textRect.height);
262     	}
263     }
264     else
265     {
266       if ( rescaleFlag != 0 && (moveable != 0  || scalable) )
267       {
268         textON = true;
269     	  length = Text.length();
270         rescaleText(0);
271 	      scaled = 1;
272       }
273 	    acop.textFlag = true;
274     }
275     textON = true;
276     textstr = Text;
277     if ( scaled == 0 && length != Text.length() )
278     {
279 	    length = Text.length();
280       setTextAttribute(true,conv_x);
281     }
282     printUserText(null);
283   }
284 
285   protected void setTextRotationParameters()
286   {   
287     Graphics2D a = (Graphics2D)acop.getGraphics();
288     java.awt.Font tempFont = a.getFont();
289     a.setFont(textFont);
290     FontMetrics fMetrix = a.getFontMetrics();
291     a.setFont(tempFont);
292     a.dispose();
293     
294     lfWidth = fMetrix.stringWidth(textstr);
295     lfHeight = fMetrix.getHeight(); // fMetrix.getAscent() + fMetrix.getDescent();
296     lfAscent = fMetrix.getAscent();
297     lfDescent = fMetrix.getDescent();
298     
299     heightSin = lfHeight * sin;
300     heightCos = lfHeight * cos;
301     lengthSin = lfWidth * sin;
302     lengthCos = lfWidth * cos;
303     
304     if ( xcenter == 0 ) offsetX = 0;
305     else if ( xcenter == 1 ) offsetX = - lfWidth /2 ;
306     else offsetX = -lfWidth;
307 
308     if ( ycenter == 0 ) offsetY = 0;
309     else if ( ycenter == 1 ) offsetY = lfHeight /2 ;
310     else offsetY = lfHeight;
311   }
312 
313   protected void setTextAttribute(boolean newText, double xInput)
314   { double xtemp = xInput;     // can be conv_x or input after wrapText()
315     double ytemp = conv_y;
316     int x,y;
317     int tmp;
318     int topLeft_cx, topLeft_cy, bottomLeft_cx, bottomLeft_cy;
319     int topRight_cx, topRight_cy, bottomRight_cx, bottomRight_cy;
320  
321     if ( newText  ) setTextRotationParameters();
322 
323     // rescale to device units
324     dev_x = (int)((xtemp - acop.sca[0].min) / acop.sca[0].dispSize * acop.aFrame.dxwidth + acop.aFrame.xleft + 0.01);
325     dev_y = (int)(acop.aFrame.histRect.height - ( (ytemp - acop.sca[1].min) / acop.sca[1].dispSize * acop.aFrame.histRect.height ));
326     
327     y = (int) (dev_y - yOffset * heightCos + xOffset * lengthSin) + acop.aFrame.histRect.y;// + lfDescent;
328     x = (int) (dev_x - yOffset * heightSin - xOffset * lengthCos) + acop.aFrame.histRect.x ;
329 
330     topLeft_cx = x;
331     topLeft_cy = y;
332 
333     bottomLeft_cx = (int)(x + heightSin);
334     bottomLeft_cy = (int)(y + heightCos);
335 
336     topRight_cx = (int)(x + lengthCos);
337     topRight_cy = (int)(y - lengthSin);
338 
339     bottomRight_cx = (int)(x + heightSin + lengthCos);
340     bottomRight_cy = (int)(y + heightCos - lengthSin);
341 
342     tmp = x;
343     if ( tmp > bottomLeft_cx ) tmp = bottomLeft_cx;
344     if ( tmp > topRight_cx ) tmp = topRight_cx;
345     if ( tmp > bottomRight_cx ) tmp = bottomRight_cx;
346     textRect.x = tmp;
347 
348     tmp = x;
349     if ( tmp < bottomLeft_cx ) tmp = bottomLeft_cx;
350     if ( tmp < topRight_cx ) tmp = topRight_cx;
351     if ( tmp < bottomRight_cx ) tmp = bottomRight_cx;
352     textRect.width = tmp - textRect.x;
353 
354     tmp = y;
355     if ( tmp > bottomLeft_cy ) tmp = bottomLeft_cy;
356     if ( tmp > topRight_cy ) tmp = topRight_cy;
357     if ( tmp > bottomRight_cy ) tmp = bottomRight_cy;
358     textRect.y = tmp;
359 
360     tmp = y;
361     if ( tmp < bottomLeft_cy ) tmp = bottomLeft_cy;
362     if ( tmp < topRight_cy ) tmp = topRight_cy;
363     if ( tmp < bottomRight_cy ) tmp = bottomRight_cy;
364     textRect.height = tmp - textRect.y;
365 
366     outside = textRect.intersects( acop.histRoundRect ) ? false : true;
367   }
368 
369   protected void scaleFont()
370   { double x,y;
371       
372     // relative to original size
373     x = acop.sca[0].dispSize / xsize;
374 	  y = acop.sca[1].dispSize / ysize;
375     if ( Math.abs(scaleFactor - y) <= AcopConst.zero_check ||
376       Math.abs(scaleFactor - x) <= AcopConst.zero_check ) return;
377     if ( x > 1 && y > 1 )
378 	  {
379 	    if ( x < y ) y = x;
380     }
381     else if ( x > y ) y = x;
382 
383     scaleFactor = y;    // store new factor for next comparison
384 	  textFont = new Font(inputFont.getName(), inputFont.getStyle(), (int)(inputFont.getSize() / y));
385 
386     lfHeight = (int)(saveHeight / y);
387 	  lfWidth = (int)(saveWidth / x);
388   }
389 
390   protected void adjustXY(int flag)
391   { int xflag = flag & 0x1;
392 	  int yflag = flag & 0x2;
393 	  
394 	  if ( xflag != 0 )
395       conv_x = acop.sca[0].log != 0 ? Math.log( AcopConst.log_check(text_x) )/Math.log(10) : text_x;
396 	  if ( yflag != 0 )
397       conv_y = acop.sca[1].log != 0 ? Math.log( AcopConst.log_check(text_y) )/Math.log(10) : text_y;
398       
399     if ( xflag != 0 || yflag != 0 ) setTextRotationParameters();
400   }
401 
402   protected double wrapText()
403   { int i;
404     double x = conv_x;
405     AcopHisto h = acop.histo[acop.m_histstart];
406       
407 	  i = h.wraphigh < 0 ? -(h.wraphigh + 1) : h.wraphigh;
408     if ( h.wraphigh < 0 )
409     {
410   		if ( x >= h.x[i] )
411 	   	{
412 		    if ( h.xaryFlag == 1 ) x += (acop.wrapxmax - acop.wrapxmin);
413 		    else x -= (acop.wrapxmax - acop.wrapxmin);
414   		}
415     }
416     else if (x < h.x[i])
417     {
418   	 	if ( h.xaryFlag == 1 ) x -= (acop.wrapxmax - acop.wrapxmin);
419 	   	else x += (acop.wrapxmax - acop.wrapxmin);
420 	  }
421 	  return x;
422   }
423         
424   protected void rescaleText(int rescaleTextFlag)
425   { double x;
426       
427     // resize, framewidth and printtext(3); Zoom (2); move(1)
428     if ( textON == false )
429     {
430       rescaleFlag = rescaleTextFlag;  // store flag
431       return;
432     }
433       
434     // load flag
435     if ( rescaleTextFlag == 0 )
436     {
437       if ( rescaleFlag == 0 ) return;
438       rescaleTextFlag = rescaleFlag;
439       return;
440     }
441       
442     // new font
443     if ( rescaleTextFlag == AcopConst.NEW_ZOOM_WINDOW && scalable ) scaleFont();
444     // new device window
445     if ( rescaleTextFlag == AcopConst.NEW_PRINT_WINDOW ) adjustXY(AcopConst.TEXT_MOVE);
446     else if ( rescaleTextFlag != AcopConst.NEW_MOVE_WINDOW && moveable != 0 ) adjustXY(moveable);
447     // wrap
448     if ( ( rescaleTextFlag == AcopConst.NEW_PRINT_WINDOW || (moveable & 0x1) != 0) &&
449                 acop.wrapAround && acop.histo[acop.m_histstart] != null && acop.sca[0].log == 0 && acop.histo[acop.m_histstart].wraphigh != 0 ) x = wrapText();
450     else x = conv_x;
451     // map
452     if ( rescaleTextFlag == AcopConst.NEW_PRINT_WINDOW || (moveable & 0x1) != 0 ) setTextAttribute(false, x);
453       
454     rescaleFlag = 0 ;     // reset flag
455   }
456 	//}}
457 }
458