|
What this is
Other links
The source code
/*
* Chunk.java - A syntax token with extra information required for painting it
* on screen
* :tabSize=8:indentSize=8:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* Copyright (C) 2001, 2002 Slava Pestov
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.gjt.sp.jedit.syntax;
//{{{ Imports
import javax.swing.text.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.*;
import org.gjt.sp.jedit.syntax.*;
import org.gjt.sp.jedit.Debug;
//}}}
/**
* A syntax token with extra information required for painting it
* on screen.
* @since jEdit 4.1pre1
*/
public class Chunk extends Token
{
//{{{ paintChunkList() method
/**
* Paints a chunk list.
* @param chunks The chunk list
* @param gfx The graphics context
* @param x The x co-ordinate
* @param y The y co-ordinate
* @return The width of the painted text
* @since jEdit 4.2pre1
*/
public static float paintChunkList(Chunk chunks,
Graphics2D gfx, float x, float y, boolean glyphVector)
{
Rectangle clipRect = gfx.getClipBounds();
float _x = 0.0f;
while(chunks != null)
{
// only paint visible chunks
if(x + _x + chunks.width > clipRect.x
&& x + _x < clipRect.x + clipRect.width)
{
// Useful for debugging purposes
if(Debug.CHUNK_PAINT_DEBUG)
{
gfx.draw(new Rectangle2D.Float(x + _x,y - 10,
chunks.width,10));
}
if(chunks.accessable && chunks.visible)
{
gfx.setFont(chunks.style.getFont());
gfx.setColor(chunks.style.getForegroundColor());
if(glyphVector && chunks.gv != null)
gfx.drawGlyphVector(chunks.gv,x + _x,y);
else if(chunks.str != null)
{
gfx.drawString(chunks.str,
(int)(x + _x),(int)y);
}
}
}
_x += chunks.width;
chunks = (Chunk)chunks.next;
}
return _x;
} //}}}
//{{{ paintChunkBackgrounds() method
/**
* Paints the background highlights of a chunk list.
* @param chunks The chunk list
* @param gfx The graphics context
* @param x The x co-ordinate
* @param y The y co-ordinate
* @return The width of the painted backgrounds
* @since jEdit 4.2pre1
*/
public static float paintChunkBackgrounds(Chunk chunks,
Graphics2D gfx, float x, float y)
{
Rectangle clipRect = gfx.getClipBounds();
float _x = 0.0f;
FontMetrics forBackground = gfx.getFontMetrics();
int ascent = forBackground.getAscent();
int height = forBackground.getHeight();
while(chunks != null)
{
// only paint visible chunks
if(x + _x + chunks.width > clipRect.x
&& x + _x < clipRect.x + clipRect.width)
{
if(chunks.accessable)
{
//{{{ Paint token background color if necessary
Color bgColor = chunks.background;
if(bgColor != null)
{
gfx.setColor(bgColor);
gfx.fill(new Rectangle2D.Float(
x + _x,y - ascent,
_x + chunks.width - _x,
height));
} //}}}
}
}
_x += chunks.width;
chunks = (Chunk)chunks.next;
}
return _x;
} //}}}
//{{{ offsetToX() method
/**
* Converts an offset in a chunk list into an x co-ordinate.
* @param chunks The chunk list
* @param offset The offset
* @since jEdit 4.1pre1
*/
public static float offsetToX(Chunk chunks, int offset)
{
if(chunks != null && offset < chunks.offset)
{
throw new ArrayIndexOutOfBoundsException(offset + " < "
+ chunks.offset);
}
float x = 0.0f;
while(chunks != null)
{
if(chunks.accessable && offset < chunks.offset + chunks.length)
return x + chunks.offsetToX(offset - chunks.offset);
x += chunks.width;
chunks = (Chunk)chunks.next;
}
return x;
} //}}}
//{{{ xToOffset() method
/**
* Converts an x co-ordinate in a chunk list into an offset.
* @param chunks The chunk list
* @param x The x co-ordinate
* @param round Round up to next letter if past the middle of a letter?
* @return The offset within the line, or -1 if the x co-ordinate is too
* far to the right
* @since jEdit 4.1pre1
*/
public static int xToOffset(Chunk chunks, float x, boolean round)
{
float _x = 0.0f;
while(chunks != null)
{
if(chunks.accessable && x < _x + chunks.width)
return chunks.xToOffset(x - _x,round);
_x += chunks.width;
chunks = (Chunk)chunks.next;
}
return -1;
} //}}}
//{{{ Instance variables
public boolean accessable;
public boolean visible;
public boolean initialized;
public boolean monospaced;
public int charWidth;
// set up after init()
public SyntaxStyle style;
// this is either style.getBackgroundColor() or
// styles[defaultID].getBackgroundColor()
public Color background;
public float width;
public GlyphVector gv;
public String str;
//}}}
//{{{ Chunk constructor
public Chunk(float width, int offset, ParserRuleSet rules)
{
super(Token.NULL,offset,0,rules);
this.width = width;
} //}}}
//{{{ Chunk constructor
public Chunk(byte id, int offset, int length, ParserRuleSet rules,
SyntaxStyle[] styles, byte defaultID)
{
super(id,offset,length,rules);
accessable = true;
style = styles[id];
background = style.getBackgroundColor();
if(background == null)
background = styles[defaultID].getBackgroundColor();
} //}}}
//{{{ getPositions() method
public final float[] getPositions()
{
if(gv == null)
return null;
if(positions == null)
positions = gv.getGlyphPositions(0,length,null);
return positions;
} //}}}
//{{{ offsetToX() method
public final float offsetToX(int offset)
{
if(!visible)
return 0.0f;
else if(monospaced)
return offset * charWidth;
else
return getPositions()[offset * 2];
} //}}}
//{{{ xToOffset() method
public final int xToOffset(float x, boolean round)
{
if(!visible)
{
if(round && width - x < x)
return offset + length;
else
return offset;
}
else if(monospaced)
{
x = Math.max(0,x);
float remainder = x % charWidth;
int i = (int)(x / charWidth);
if(round && remainder > charWidth / 2)
return offset + i + 1;
else
return offset + i;
}
else
{
float[] pos = getPositions();
for(int i = 0; i < length; i++)
{
float glyphX = pos[i*2];
float nextX = (i == length - 1
? width : pos[i*2+2]);
if(nextX > x)
{
if(!round || nextX - x > x - glyphX)
return offset + i;
else
return offset + i + 1;
}
}
}
// wtf?
return -1;
} //}}}
//{{{ init() method
public void init(Segment seg, TabExpander expander, float x,
FontRenderContext fontRenderContext)
{
initialized = true;
if(style != null)
charWidth = style.getCharWidth();
if(!accessable)
{
// do nothing
}
else if(length == 1 && seg.array[seg.offset + offset] == '\t')
{
visible = false;
float newX = expander.nextTabStop(x,offset + length);
width = newX - x;
}
else if(charWidth != 0 && !Debug.DISABLE_MONOSPACE_HACK)
{
visible = monospaced = true;
str = new String(seg.array,seg.offset + offset,length);
width = charWidth * length;
}
else
{
visible = true;
str = new String(seg.array,seg.offset + offset,length);
gv = style.getFont().createGlyphVector(
fontRenderContext,str);
width = (float)gv.getLogicalBounds().getWidth();
}
} //}}}
//{{{ Private members
private float[] positions;
//}}}
}
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.