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

Quick Search    Search Deep

Source code: com/virtuosotechnologies/asaph/standardgui/LineTextView.java


1   /*
2   ================================================================================
3   
4     FILE:  LineTextView.java
5     
6     PROJECT:
7     
8       Virtuoso Utilities
9     
10    CONTENTS:
11    
12      LineMemberView representing a fragment of normal text
13    
14    PROGRAMMERS:
15    
16      Daniel Azuma (DA)  <dazuma@kagi.com>
17    
18    COPYRIGHT:
19    
20      Copyright (C) 2003  Daniel Azuma  (dazuma@kagi.com)
21      
22      This program is free software; you can redistribute it and/or
23      modify it under the terms of the GNU General Public License as
24      published by the Free Software Foundation; either version 2
25      of the License, or (at your option) any later version.
26      
27      This program is distributed in the hope that it will be useful,
28      but WITHOUT ANY WARRANTY; without even the implied warranty of
29      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30      GNU General Public License for more details.
31      
32      You should have received a copy of the GNU General Public
33      License along with this program; if not, write to
34        Free Software Foundation, Inc.
35        59 Temple Place, Suite 330
36        Boston, MA 02111-1307 USA
37  
38  ================================================================================
39  */
40  
41  
42  package com.virtuosotechnologies.asaph.standardgui;
43  
44  
45  import java.awt.Font;
46  import java.awt.Graphics2D;
47  import java.awt.font.TextLayout;
48  import java.awt.font.FontRenderContext;
49  import java.awt.font.TextHitInfo;
50  import java.awt.geom.Line2D;
51  import java.awt.geom.Rectangle2D;
52  
53  import com.virtuosotechnologies.asaph.model.SongLineMember;
54  import com.virtuosotechnologies.asaph.model.TextString;
55  import com.virtuosotechnologies.asaph.model.CommentString;
56  
57  
58  /**
59   * LineMemberView representing a fragment of normal text
60   */
61  /*package*/ class LineTextView
62  extends LineMemberView
63  {
64    private TextLayout textLayout_;
65    private float baseline_;
66    private float leftLimit_;
67    private float rightLimit_;
68    private boolean blank_;
69    private String str_;
70    
71    
72    /**
73     * Constructor
74     */
75    private LineTextView(
76      SongLineMember model,
77      String str,
78      Font font,
79      float xpos,
80      float width,
81      float baseline,
82      FontRenderContext frc)
83    {
84      super(model, xpos, width);
85      baseline_ = baseline;
86      blank_ = false;
87      str_ = str;
88      if (str.length() == 0)
89      {
90        str = " ";
91        blank_ = true;
92      }
93      textLayout_ = new TextLayout(str, font, frc);
94      leftLimit_ = Float.NEGATIVE_INFINITY;
95      rightLimit_ = Float.POSITIVE_INFINITY;
96    }
97    
98    
99    /**
100    * Constructor
101    */
102   /*package*/ LineTextView(
103     TextString model,
104     String str,
105     float xpos,
106     float width,
107     float baseline,
108     FontRenderContext frc)
109   {
110     this(model, str, EditorConstants.TEXT_FONT, xpos, width, baseline, frc);
111   }
112   
113   
114   /**
115    * Constructor
116    */
117   /*package*/ LineTextView(
118     CommentString model,
119     String str,
120     float xpos,
121     float width,
122     float baseline,
123     FontRenderContext frc)
124   {
125     this(model, str, EditorConstants.COMMENT_FONT, xpos, width, baseline, frc);
126   }
127   
128   
129   /**
130    * Get the string
131    */
132   /*package*/ String getText()
133   {
134     return str_;
135   }
136   
137   
138   /**
139    * Set left limit
140    */
141   /*package*/ void setLeftLimit(
142     float leftLimit)
143   {
144     leftLimit_ = leftLimit;
145   }
146   
147   
148   /**
149    * Set right limit
150    */
151   /*package*/ void setRightLimit(
152     float rightLimit)
153   {
154     rightLimit_ = rightLimit;
155   }
156   
157   
158   /**
159    * Accessor for number of characters
160    */
161   /*package*/ int getCharacterCount()
162   {
163     return str_.length();
164   }
165   
166   
167   /**
168    * Accessor for baseline
169    */
170   /*package*/ float getBaseline()
171   {
172     return baseline_;
173   }
174   
175   
176   /**
177    * Accessor for top
178    */
179   /*package*/ float getTop()
180   {
181     return baseline_-textLayout_.getAscent();
182   }
183   
184   
185   /**
186    * Accessor for height
187    */
188   /*package*/ float getHeight()
189   {
190     return textLayout_.getAscent()+textLayout_.getDescent();
191   }
192   
193   
194   /**
195    * Get offset given a position.
196    */
197   /*package*/ int getOffsetForPosition(
198     float x,
199     float y)
200   {
201     if (x < leftLimit_ || x > rightLimit_)
202     {
203       return -1;
204     }
205     if (blank_)
206     {
207       return 0;
208     }
209     TextHitInfo hitInfo = textLayout_.hitTestChar(x-getXPos(), y-baseline_);
210     int ret = hitInfo.getCharIndex();
211     if (!hitInfo.isLeadingEdge())
212     {
213       ++ret;
214     }
215     return ret;
216   }
217   
218   
219   /**
220    * Get offset given a position.
221    */
222   /*package*/ int[] getDoubleClickOffsetsForPosition(
223     float x,
224     float y)
225   {
226     if (x < leftLimit_ || x > rightLimit_)
227     {
228       return null;
229     }
230     if (blank_)
231     {
232       return new int[]{0, 0};
233     }
234     TextHitInfo hitInfo = textLayout_.hitTestChar(x-getXPos(), y-baseline_);
235     int[] ret = new int[2];
236     ret[0] = hitInfo.getCharIndex();
237     if (!hitInfo.isLeadingEdge())
238     {
239       ++ret[0];
240     }
241     if (ret[0] == str_.length())
242     {
243       --ret[0];
244     }
245     ret[1] = ret[0]+1;
246     if (isAlphanumeric(str_.charAt(ret[0])))
247     {
248       while (ret[0] > 0 && isAlphanumeric(str_.charAt(ret[0]-1)))
249       {
250         --ret[0];
251       }
252       int max = str_.length();
253       while (ret[1] < max && isAlphanumeric(str_.charAt(ret[1])))
254       {
255         ++ret[1];
256       }
257     }
258     return ret;
259   }
260   
261   
262   private boolean isAlphanumeric(
263     char ch)
264   {
265     return (ch != ' ');
266   }
267   
268   
269   /**
270    * Get the x position (in coordinates relative to the line, not the component)
271    * for the given offset.
272    */
273   /*package*/ float getXForOffset(
274     int offset)
275   {
276     assert offset >= 0;
277     TextHitInfo hitInfo;
278     if (offset == 0)
279     {
280       hitInfo = TextHitInfo.leading(0);
281     }
282     else
283     {
284       hitInfo = TextHitInfo.trailing(offset-1);
285     }
286     float[] info = textLayout_.getCaretInfo(hitInfo);
287     return info[0]+getXPos();
288   }
289   
290   
291   /**
292    * Accessor for the caret line segment given a character position and
293    * xy offsets.
294    */
295   /*package*/ Line2D getCaretSegment(
296     int offset,
297     float x,
298     float y)
299   {
300     assert offset >= 0;
301     TextHitInfo hitInfo;
302     if (offset == 0)
303     {
304       hitInfo = TextHitInfo.leading(0);
305     }
306     else
307     {
308       hitInfo = TextHitInfo.trailing(offset-1);
309     }
310     float[] info = textLayout_.getCaretInfo(hitInfo);
311     
312     // Hack workaround for Mac OS X bug (radar 3193109)
313     if (info[1] > 0.3f) info[1] = 0.3f;
314     
315     float baselineX = info[0]+getXPos()+x;
316     return new Line2D.Float(
317       baselineX+textLayout_.getAscent()*info[1], baseline_-textLayout_.getAscent()+y,
318       baselineX-textLayout_.getDescent()*info[1], baseline_+textLayout_.getDescent()+y);
319   }
320   
321   
322   /**
323    * Draw
324    */
325   /*package*/ void paint(
326     Graphics2D g2d,
327     float x,
328     float y)
329   {
330     Rectangle2D rect = new Rectangle2D.Float(
331       getXPos()+x-1, baseline_+y-textLayout_.getAscent(),
332       getWidth()+1, textLayout_.getAscent()+textLayout_.getDescent());
333     //g2d.setColor(EditorConstants.BACKGROUND_COLOR);
334     //g2d.fill(rect);
335     g2d.setColor(EditorConstants.LINE_TEXT_BORDER_COLOR);
336     g2d.draw(rect);
337     if (!blank_)
338     {
339       g2d.setColor(EditorConstants.TEXT_COLOR);
340       textLayout_.draw(g2d, getXPos()+x, baseline_+y);
341     }
342   }
343 }