View Javadoc

1   /*
2    *  File: TextRenderer.java 
3    *  Copyright (c) 2004-2007  Peter Kliem (Peter.Kliem@jaret.de)
4    *  A commercial license is available, see http://www.jaret.de.
5    *
6    * All rights reserved. This program and the accompanying materials
7    * are made available under the terms of the Common Public License v1.0
8    * which accompanies this distribution, and is available at
9    * http://www.eclipse.org/legal/cpl-v10.html
10   */
11  package de.jaret.util.swt;
12  
13  import java.util.ArrayList;
14  import java.util.Iterator;
15  import java.util.List;
16  import java.util.StringTokenizer;
17  
18  import org.eclipse.swt.graphics.GC;
19  import org.eclipse.swt.graphics.Rectangle;
20  
21  /**
22   * Simple utility class for rendering a multiline text.
23   * 
24   * @author Peter Kliem
25   * @version $Id: TextRenderer.java 623 2007-11-01 15:23:45Z kliem $
26   */
27  public class TextRenderer {
28      public static final int LEFT = 0;
29      public static final int RIGHT = 1;
30      public static final int CENTER = 2;
31      public static final int TOP = 0;
32      public static final int BOTTOM = 1;
33  
34      public static void renderText(GC gc, Rectangle rect, boolean wrap, boolean ellipsis, String text) {
35          renderText(gc, rect, wrap, ellipsis, text, LEFT, TOP);
36      }
37  
38      public static void renderText(GC gc, Rectangle rect, boolean wrap, boolean ellipsis, String text, int halign,
39              int valign) {
40          Rectangle clipSave = gc.getClipping();
41          gc.setClipping(rect.intersection(clipSave));
42          List<String> lines = breakInLines(gc, rect.width, wrap, text);
43  
44          // for (String string : lines) {
45          // System.out.println(string);
46          // }
47          //        
48          int height = getHeight(gc, rect.width, wrap, lines);
49          int offy = 0;
50          if (height < rect.height) {
51              if (valign == CENTER) {
52                  offy = (rect.height - height) / 2;
53              } else if (valign == BOTTOM) {
54                  offy = rect.height - height;
55              }
56          }
57  
58          int lineheight = SwtGraphicsHelper.getStringDrawingHeight(gc, "WgyAqQ");
59          int lineSpacing = 3;
60          for (int row = 0; row < lines.size(); row++) {
61              int y = rect.y + row * lineheight + row * lineSpacing;
62              drawLine(gc, rect.x, y + offy, rect.width, lines.get(row), halign);
63              // System.out.println("Line "+row+"y"+y+"'"+(String)lines.get(row)+"'");
64          }
65          gc.setClipping(clipSave);
66      }
67  
68      public static int getHeight(GC gc, int width, boolean wrap, String text) {
69          List<String> lines = breakInLines(gc, width, wrap, text);
70          return getHeight(gc, width, wrap, lines);
71      }
72  
73      private static int getHeight(GC gc, int width, boolean wrap, List<String> lines) {
74          if (lines.size() == 0) {
75              return 0;
76          }
77          int lineheight = SwtGraphicsHelper.getStringDrawingHeight(gc, lines.get(0));
78          int lineSpacing = 3;
79          int height = lines.size() * lineheight + ((lines.size() - 1) * lineSpacing);
80          return height;
81      }
82  
83      private static void drawLine(GC gc, int x, int y, int width, String string, int halign) {
84          int xx;
85          int textWidth = SwtGraphicsHelper.getStringDrawingWidth(gc, string);
86          switch (halign) {
87          case LEFT:
88              xx = x;
89              break;
90          case RIGHT:
91              xx = x + (width - textWidth);
92              break;
93          case CENTER:
94              xx = x + (width - textWidth) / 2;
95              break;
96          default:
97              throw new RuntimeException("illegal alignment");
98          }
99          gc.drawText(string, xx, y, true);
100 
101     }
102 
103     public static List<String> breakInLines(GC gc, int width, boolean wrap, String text) {
104         List<String> result = new ArrayList<String>();
105         StringTokenizer tokenizer = new StringTokenizer(text, "\n", false);
106         while (tokenizer.hasMoreTokens()) {
107             result.add(tokenizer.nextToken());
108         }
109         if (wrap) {
110             List<String> brokenLines = new ArrayList<String>();
111             Iterator it = result.iterator();
112             while (it.hasNext()) {
113                 String line = (String) it.next();
114                 List<String> brLines = wrapLines(gc, width, line);
115                 brokenLines.addAll(brLines);
116             }
117 
118             return brokenLines;
119         } else {
120             return result;
121         }
122     }
123 
124     /**
125      * @param gc
126      * @param width
127      * @param text
128      * @return
129      */
130     private static List<String> wrapLines(GC gc, int width, String text) {
131         List<String> result = new ArrayList<String>();
132         StringTokenizer tokenizer = new StringTokenizer(text, " ", true);
133         StringBuffer buf = new StringBuffer();
134         int count = 0;
135         while (tokenizer.hasMoreTokens()) {
136             String token = tokenizer.nextToken();
137             if (SwtGraphicsHelper.getStringDrawingWidth(gc, buf.toString() + token) < width) {
138                 buf.append(token);
139                 count++;
140             } else if (count == 0) {
141                 // a single word did not fit
142                 List<String> brWord = breakWord(gc, width, token);
143                 for (int i = 0; i < brWord.size() - 1; i++) {
144                     result.add(brWord.get(i));
145                 }
146                 buf.append(brWord.get(brWord.size() - 1));
147                 count = 1;
148             } else {
149                 result.add(buf.toString());
150                 buf = new StringBuffer();
151                 buf.append(token);
152                 count = 1;
153             }
154         }
155         if (buf.length() > 0) {
156             result.add(buf.toString());
157         }
158 
159         return result;
160     }
161 
162     /**
163      * break a word into strings fitting into width.
164      * 
165      * @param gc
166      * @param width
167      * @param word
168      * @return
169      */
170     private static List<String> breakWord(GC gc, int width, String word) {
171         List<String> result = new ArrayList<String>();
172 
173         int bidx = 0;
174         int eidx = 0;
175         while (eidx < word.length()) {
176             while (SwtGraphicsHelper.getStringDrawingWidth(gc, word.substring(bidx, eidx)) < width
177                     && eidx < word.length()) {
178                 eidx++;
179             }
180             if (eidx == 0) {
181                 // could not fit a single character
182                 result.add(word);
183                 return result;
184             }
185             result.add(word.substring(bidx, eidx));
186             bidx = eidx;
187         }
188 
189         return result;
190     }
191 
192 }