PageRenderTime 46ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/org/gjt/sp/jedit/syntax/Chunk.java

#
Java | 323 lines | 193 code | 45 blank | 85 comment | 48 complexity | 4f67871b46771ae58abcc09502751ee0 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * Chunk.java - A syntax token with extra information required for painting it
  3. * on screen
  4. * :tabSize=8:indentSize=8:noTabs=false:
  5. * :folding=explicit:collapseFolds=1:
  6. *
  7. * Copyright (C) 2001, 2002 Slava Pestov
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. */
  23. package org.gjt.sp.jedit.syntax;
  24. //{{{ Imports
  25. import javax.swing.text.*;
  26. import java.awt.font.*;
  27. import java.awt.geom.*;
  28. import java.awt.*;
  29. import org.gjt.sp.jedit.Debug;
  30. //}}}
  31. /**
  32. * A syntax token with extra information required for painting it
  33. * on screen.
  34. * @since jEdit 4.1pre1
  35. */
  36. public class Chunk extends Token
  37. {
  38. //{{{ paintChunkList() method
  39. /**
  40. * Paints a chunk list.
  41. * @param chunks The chunk list
  42. * @param gfx The graphics context
  43. * @param x The x co-ordinate
  44. * @param y The y co-ordinate
  45. * @return The width of the painted text
  46. * @since jEdit 4.2pre1
  47. */
  48. public static float paintChunkList(Chunk chunks,
  49. Graphics2D gfx, float x, float y, boolean glyphVector)
  50. {
  51. Rectangle clipRect = gfx.getClipBounds();
  52. float _x = 0.0f;
  53. while(chunks != null)
  54. {
  55. // only paint visible chunks
  56. if(x + _x + chunks.width > clipRect.x
  57. && x + _x < clipRect.x + clipRect.width)
  58. {
  59. // Useful for debugging purposes
  60. if(Debug.CHUNK_PAINT_DEBUG)
  61. {
  62. gfx.draw(new Rectangle2D.Float(x + _x,y - 10,
  63. chunks.width,10));
  64. }
  65. if(chunks.accessable && chunks.visible)
  66. {
  67. gfx.setFont(chunks.style.getFont());
  68. gfx.setColor(chunks.style.getForegroundColor());
  69. if(glyphVector && chunks.gv != null)
  70. gfx.drawGlyphVector(chunks.gv,x + _x,y);
  71. else if(chunks.str != null)
  72. {
  73. gfx.drawString(chunks.str,
  74. (int)(x + _x),(int)y);
  75. }
  76. }
  77. }
  78. _x += chunks.width;
  79. chunks = (Chunk)chunks.next;
  80. }
  81. return _x;
  82. } //}}}
  83. //{{{ paintChunkBackgrounds() method
  84. /**
  85. * Paints the background highlights of a chunk list.
  86. * @param chunks The chunk list
  87. * @param gfx The graphics context
  88. * @param x The x co-ordinate
  89. * @param y The y co-ordinate
  90. * @return The width of the painted backgrounds
  91. * @since jEdit 4.2pre1
  92. */
  93. public static float paintChunkBackgrounds(Chunk chunks,
  94. Graphics2D gfx, float x, float y)
  95. {
  96. Rectangle clipRect = gfx.getClipBounds();
  97. float _x = 0.0f;
  98. FontMetrics forBackground = gfx.getFontMetrics();
  99. int ascent = forBackground.getAscent();
  100. int height = forBackground.getHeight();
  101. while(chunks != null)
  102. {
  103. // only paint visible chunks
  104. if(x + _x + chunks.width > clipRect.x
  105. && x + _x < clipRect.x + clipRect.width)
  106. {
  107. if(chunks.accessable)
  108. {
  109. //{{{ Paint token background color if necessary
  110. Color bgColor = chunks.background;
  111. if(bgColor != null)
  112. {
  113. gfx.setColor(bgColor);
  114. gfx.fill(new Rectangle2D.Float(
  115. x + _x,y - ascent,
  116. _x + chunks.width - _x,
  117. height));
  118. } //}}}
  119. }
  120. }
  121. _x += chunks.width;
  122. chunks = (Chunk)chunks.next;
  123. }
  124. return _x;
  125. } //}}}
  126. //{{{ offsetToX() method
  127. /**
  128. * Converts an offset in a chunk list into an x co-ordinate.
  129. * @param chunks The chunk list
  130. * @param offset The offset
  131. * @since jEdit 4.1pre1
  132. */
  133. public static float offsetToX(Chunk chunks, int offset)
  134. {
  135. if(chunks != null && offset < chunks.offset)
  136. {
  137. throw new ArrayIndexOutOfBoundsException(offset + " < "
  138. + chunks.offset);
  139. }
  140. float x = 0.0f;
  141. while(chunks != null)
  142. {
  143. if(chunks.accessable && offset < chunks.offset + chunks.length)
  144. return x + chunks.offsetToX(offset - chunks.offset);
  145. x += chunks.width;
  146. chunks = (Chunk)chunks.next;
  147. }
  148. return x;
  149. } //}}}
  150. //{{{ xToOffset() method
  151. /**
  152. * Converts an x co-ordinate in a chunk list into an offset.
  153. * @param chunks The chunk list
  154. * @param x The x co-ordinate
  155. * @param round Round up to next letter if past the middle of a letter?
  156. * @return The offset within the line, or -1 if the x co-ordinate is too
  157. * far to the right
  158. * @since jEdit 4.1pre1
  159. */
  160. public static int xToOffset(Chunk chunks, float x, boolean round)
  161. {
  162. float _x = 0.0f;
  163. while(chunks != null)
  164. {
  165. if(chunks.accessable && x < _x + chunks.width)
  166. return chunks.xToOffset(x - _x,round);
  167. _x += chunks.width;
  168. chunks = (Chunk)chunks.next;
  169. }
  170. return -1;
  171. } //}}}
  172. //{{{ Instance variables
  173. public boolean accessable;
  174. public boolean visible;
  175. public boolean initialized;
  176. // set up after init()
  177. public SyntaxStyle style;
  178. // this is either style.getBackgroundColor() or
  179. // styles[defaultID].getBackgroundColor()
  180. public Color background;
  181. public float width;
  182. public GlyphVector gv;
  183. public String str;
  184. //}}}
  185. //{{{ Chunk constructor
  186. public Chunk(float width, int offset, ParserRuleSet rules)
  187. {
  188. super(Token.NULL,offset,0,rules);
  189. this.width = width;
  190. } //}}}
  191. //{{{ Chunk constructor
  192. public Chunk(byte id, int offset, int length, ParserRuleSet rules,
  193. SyntaxStyle[] styles, byte defaultID)
  194. {
  195. super(id,offset,length,rules);
  196. accessable = true;
  197. style = styles[id];
  198. background = style.getBackgroundColor();
  199. if(background == null)
  200. background = styles[defaultID].getBackgroundColor();
  201. } //}}}
  202. //{{{ getPositions() method
  203. public final float[] getPositions()
  204. {
  205. if(gv == null)
  206. return null;
  207. if(positions == null)
  208. positions = gv.getGlyphPositions(0,length,null);
  209. return positions;
  210. } //}}}
  211. //{{{ offsetToX() method
  212. public final float offsetToX(int offset)
  213. {
  214. if(!visible)
  215. return 0.0f;
  216. else
  217. return getPositions()[offset * 2];
  218. } //}}}
  219. //{{{ xToOffset() method
  220. public final int xToOffset(float x, boolean round)
  221. {
  222. if(!visible)
  223. {
  224. if(round && width - x < x)
  225. return offset + length;
  226. else
  227. return offset;
  228. }
  229. else
  230. {
  231. float[] pos = getPositions();
  232. for(int i = 0; i < length; i++)
  233. {
  234. float glyphX = pos[i*2];
  235. float nextX = (i == length - 1
  236. ? width : pos[i*2+2]);
  237. if(nextX > x)
  238. {
  239. if(!round || nextX - x > x - glyphX)
  240. return offset + i;
  241. else
  242. return offset + i + 1;
  243. }
  244. }
  245. }
  246. // wtf?
  247. return -1;
  248. } //}}}
  249. //{{{ init() method
  250. public void init(Segment seg, TabExpander expander, float x,
  251. FontRenderContext fontRenderContext)
  252. {
  253. initialized = true;
  254. if(!accessable)
  255. {
  256. // do nothing
  257. }
  258. else if(length == 1 && seg.array[seg.offset + offset] == '\t')
  259. {
  260. visible = false;
  261. float newX = expander.nextTabStop(x,offset + length);
  262. width = newX - x;
  263. }
  264. else
  265. {
  266. visible = true;
  267. str = new String(seg.array,seg.offset + offset,length);
  268. Rectangle2D logicalBounds;
  269. gv = style.getFont().createGlyphVector(
  270. fontRenderContext, str);
  271. logicalBounds = gv.getLogicalBounds();
  272. width = (float)logicalBounds.getWidth();
  273. }
  274. } //}}}
  275. //{{{ Private members
  276. private float[] positions;
  277. //}}}
  278. }