package de.unisiegen.tpml.graphics.renderer;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Enumeration;
import de.unisiegen.tpml.core.util.Environment;
/**
* Subclass of the {@link AbstractRenderer} providing the rendering
* of an environment.
*
* @author marcell
* @author michael
*
* @param <S>
* @param <E>
*/
public class EnvironmentRenderer<S, E> extends AbstractRenderer {
/**
* The environment that should be rendered.
*/
private Environment<S, E> environment;
/**
* The width of the brackets around the environment in pixels.
*/
private int bracketSize;
/**
* Holds informatioin whether the environment is collapsed.<br>
* <br>
* Only the first element of the environment is show. If there
* are more than one element, they will only be shown as ", ...".
* Than the collapsed flag is <i>true</i> else it is <i>false</i>.
*/
private boolean collapsed;
/**
* The rectangle describing the area of the ", ...".<br>
* <br>
* Can be used to determin where a ToolTip should be displayed.
*/
private Rectangle collapsedArea;
/**
* Containing all the informations that are not shown. When
* the environment is collpased.
*/
private String collapsedString;
/**
*
*/
private static final String collapsString = ", ...";
/**
*
*
*/
public EnvironmentRenderer() {
//this.bracketSize = AbstractRenderer.fontDescent;
//let the bracket be as width as
this.bracketSize = AbstractRenderer.expFontMetrics.stringWidth("[");
this.collapsed = false;
this.collapsedArea = new Rectangle ();
}
/**
* Sets the environment.
*
* @param pEnvironment
*/
public void setEnvironment (Environment<S, E> pEnvironment) {
this.environment = pEnvironment;
// create the string that can be shown in an tooltip
// on level above in the CompoundExpression
Enumeration<S> env = pEnvironment.symbols();
this.collapsedString = null;
if (env.hasMoreElements()) {
S s = env.nextElement();
E e = pEnvironment.get(s);
this.collapsedString = s.toString() + ": " + e.toString();
while (env.hasMoreElements()) {
s = env.nextElement();
e = pEnvironment.get(s);
this.collapsedString += ", " + s.toString() + ": " + e.toString();
}
}
}
/**
* Returns whether the environment was collapsed.
* @return
*/
public boolean isCollapsed () {
return this.collapsed;
}
/**
* Returns the area whre the ", ..." is diplayed.
* @return
*/
public Rectangle getCollapsedArea () {
return this.collapsedArea;
}
/**
* Returns the information of the environment that
* are not displayed.
*
* @return
*/
public String getCollapsedString () {
return this.collapsedString;
}
/**
* Calculates the size, that is needed to propperly render
* the environment.
*
* @return The size needed to render the environment.
*/
public Dimension getNeededSize () {
Dimension result = new Dimension (2 * this.bracketSize, AbstractRenderer.getAbsoluteHeight ( ));
Enumeration<S> env = this.environment.symbols();
if (!env.hasMoreElements()) {
// secure some space between the two brackets when
// no content is there to be shown
result.width += this.bracketSize;
}
else {
// get the first element
S s = env.nextElement();
E e = this.environment.get(s);
result.width += AbstractRenderer.keywordFontMetrics.stringWidth(s.toString() + ": ");
result.width += AbstractRenderer.envFontMetrics.stringWidth(e.toString());
if (env.hasMoreElements()) {
// if there is more then only one element in the environment
// the rest will only be displayed ass three dots
result.width += AbstractRenderer.expFontMetrics.stringWidth(EnvironmentRenderer.collapsString);
}
}
return result;
}
// public void renderBase (int x, int y, int width, int height, Graphics gc )
// {
// renderer (x, y-(height / 2) - fontAscent / 2, width, height, gc);
// }
/**
* Renders the environment.<br>
* <br>
* The environment is always rendered as a single line. It will appear
* verticaly centered betwean <i>y</i> and <i>(y + height></i>.
*
* @param x The left position where the environment should be displayed
* @param y The top position where the environment should be displayed.
* @param width The width the renderer is given to render the environment.
* @param height The Height the renderer is given to render the envionment.
* @param gc
*/
public void renderer (int x, int y, int width, int height, Graphics gc) {
//
// just render the brackets around the environment
gc.setColor(this.alternativeColor != null ? this.alternativeColor : Color.BLACK);
// the left bracket
int posX = x;
//int posY = y + height / 2;
//posY += AbstractRenderer.fontAscent / 2;
int posY = y + AbstractRenderer.fontAscent;
// if the hight is not bigger then the fonhight normal [ ] are used
// or else the bracket will bew renderd manually. Till now the environments are shorted
// with three dots (...) so they are never warped. To ignor the bigger size made by an
// expression (height <= AbstractRenderer.getAbsoluteHeight()) replaced by if (true)
if (true)
{
gc.setFont(expFont);
gc.drawString("[", x, posY);
posX += expFontMetrics.stringWidth("[");
//the right one
gc.drawString("]", x+width-expFontMetrics.stringWidth("]"), posY);
}
else
{
gc.drawLine (x, y, x + this.bracketSize, y);
gc.drawLine (x, y, x, y + height - 1);
gc.drawLine (x, y + height - 1, x + this.bracketSize, y + height - 1);
// the right bracket
gc.drawLine (x + width - 1, y, x + width - 1 - this.bracketSize, y);
gc.drawLine (x + width - 1, y, x + width - 1, y + height - 1);
gc.drawLine (x + width - 1, y + height - 1, x + width - 1 -this.bracketSize, y + height - 1);
posX += this.bracketSize;
}
// calculate the vertical center of the available space
// find the first element in the enumeration if there is one
this.collapsed = false;
Enumeration<S> env = this.environment.symbols();
if (env.hasMoreElements()) {
// get the first element
S s = env.nextElement();
E e = this.environment.get(s);
// render the symbol
gc.setColor(this.alternativeColor != null ? this.alternativeColor : AbstractRenderer.keywordColor);
gc.setFont(AbstractRenderer.keywordFont);
gc.drawString(s.toString() + ": ", posX, posY);
posX += AbstractRenderer.keywordFontMetrics.stringWidth(s.toString() + ": ");
// render the entry
gc.setColor(this.alternativeColor != null ? this.alternativeColor : AbstractRenderer.envColor);
gc.setFont(AbstractRenderer.envFont);
gc.drawString(e.toString(), posX, posY);
posX += AbstractRenderer.envFontMetrics.stringWidth(e.toString());
if (env.hasMoreElements()) {
this.collapsed = true;
this.collapsedArea.x = posX;
gc.drawString(EnvironmentRenderer.collapsString, posX, posY);
posX += AbstractRenderer.envFontMetrics.stringWidth(collapsString);
this.collapsedArea.width = (posX - this.collapsedArea.x);
//this.collapsedArea.y = posY-(AbstractRenderer.getAbsoluteHeight()-2);
this.collapsedArea.y = posY-(AbstractRenderer.fontAscent);
this.collapsedArea.height = AbstractRenderer.getAbsoluteHeight();
}
}
}
}