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.ArrayList;
import de.unisiegen.tpml.core.prettyprinter.PrettyString;
import de.unisiegen.tpml.core.typechecker.TypeSubstitution;
/**
* Subclass of the {@link AbstractRenderer} providing the rendering
* of the substitutions of the type inference view.
*
* @author michael
*
*/
public class SubstitutionRenderer extends AbstractRenderer
{
/**
* The Substitutions that should be rendered.
*/
private ArrayList<TypeSubstitution> defaultTypeSubstitutionList;
/**
* Holds informatioin whether the substitution is collapsed.<br>
* <br>
* Only the first element of the substitution 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 substitution is collpased.
*/
private String collapsedString;
/**
* The String shown instaed of the rest of the substitution if it is collapsed. <br>
* When the mouse is over it the rest will be whown.
*/
private static final String collapsString = ", ...";
/**
* If the tooltip gets as wide as maxTooltipWidht the tooltip will be broken
*/
private static final int maxTooltipWidht = 100;
/**
* The String isertedt between the singel substitutions in the tootltip
*/
private static final String betweenTypSubstitutions = ", ";
/**
* The constructor
*
*/
public SubstitutionRenderer ()
{
this.collapsed = false;
this.collapsedArea = new Rectangle();
}
/**
* Sets the substitution.
* @param defaultTypeSubstitutionListP
*
* @param substitution
*/
public void setDefaultTypeSubstitutionList(ArrayList<TypeSubstitution> defaultTypeSubstitutionListP)
{
this.defaultTypeSubstitutionList = defaultTypeSubstitutionListP;
// create the string that can be shown in an tooltip
// on level above in the CompoundExpression
this.collapsedString = null;
if (this.defaultTypeSubstitutionList.size() > 0)
{
// count the chars to break the tooltip if it gets to wide
int count = 0;
// html is needed to format the tooltip
this.collapsedString = "<html>";
for (int i = 0; i < this.defaultTypeSubstitutionList.size(); i++)
{
TypeSubstitution thisDetaultTypeSubstitution = this.defaultTypeSubstitutionList.get(i);
String tmp = thisDetaultTypeSubstitution.toString();
count += tmp.length();
PrettyString ps = thisDetaultTypeSubstitution.toPrettyString();
this.collapsedString += PrettyStringToHTML.toHTMLString(ps);
//every but the last gets a ", "
if (i < this.defaultTypeSubstitutionList.size() - 1)
{
this.collapsedString += betweenTypSubstitutions;
}
count += betweenTypSubstitutions.length();
// every but the las line becomes a linebraek ("<br>")
if (count >= maxTooltipWidht)
{
this.collapsedString += "<br>";
count = 0;
}
}
this.collapsedString += "</html>";
}
}
/**
* Returns whether the substitution was collapsed.
* @return boolean is collapsed
*/
public boolean isCollapsed()
{
return this.collapsed;
}
/**
* Returns the area whre the ", ..." is diplayed.
* @return Rectangle of collapsed area
*/
public Rectangle getCollapsedArea()
{
return this.collapsedArea;
}
/**
* Returns the information of the substitution that
* are not displayed.
*
* @return String of not displayed substitutions
*/
public String getCollapsedString()
{
return this.collapsedString;
}
/**
* Calculates the size, that is needed to propperly render
* the substitution.
*
* @return The size needed to render the substitution.
*/
public Dimension getNeededSize()
{
Dimension result = new Dimension(0, 0);
if (this.defaultTypeSubstitutionList.size() == 0)
{
// secure some space when no content is there to be shown
result.width += 10;
result.height = AbstractRenderer.getAbsoluteHeight();
}
else
{
result.height = AbstractRenderer.getAbsoluteHeight();
// get the first element
TypeSubstitution s = this.defaultTypeSubstitutionList.get(0);
result.width += AbstractRenderer.keywordFontMetrics.stringWidth(s.toString());
if (this.defaultTypeSubstitutionList.size() > 1)
{
// if there is more then only one element in the substitution
// the rest will only be displayed ass three dots
result.width += AbstractRenderer.expFontMetrics.stringWidth(SubstitutionRenderer.collapsString);
}
result.width += AbstractRenderer.expFontMetrics.stringWidth("[");
result.width += AbstractRenderer.expFontMetrics.stringWidth("]");
}
return result;
}
/**
* Render the substitution to the baseline
*
* @param x The left position where the substitution should be displayed
* @param y The top position where the substitution should be displayed.
* @param width The width the renderer is given to render the substitution.
* @param height The Height the renderer is given to render the substitution.
* @param gc The Graphics used to render
*/
public void renderBase(int x, int y, int width, int height, Graphics gc)
{
renderer(x, y - (AbstractRenderer.getAbsoluteHeight() / 2), width, height, gc);
}
/**
* Renders the substitution.<br>
* <br>
* The substitution 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 substitution should be displayed
* @param y The top position where the substitution should be displayed.
* @param width The width the renderer is given to render the substitution.
* @param height The Height the renderer is given to render the substitution.
* @param gc The Graphics used to render
*/
public void renderer(int x, int y, int width, int height, Graphics gc)
{
gc.setColor(this.alternativeColor != null ? this.alternativeColor : Color.BLACK);
int posX = x;
int posY = y + AbstractRenderer.fontAscent;
this.collapsed = false;
// if ther is enythuing to render
if (this.defaultTypeSubstitutionList.size() > 0)
{
gc.setColor(this.alternativeColor != null ? this.alternativeColor : AbstractRenderer.expColor); //if then else
gc.setFont(AbstractRenderer.expFont);
//Render the "["
gc.drawString("[", posX, posY);
posX += AbstractRenderer.expFontMetrics.stringWidth("[");
// get the first element
TypeSubstitution s = this.defaultTypeSubstitutionList.get(0);
// render the symbol
gc.setColor(this.alternativeColor != null ? this.alternativeColor : AbstractRenderer.expColor); //if then else
gc.setFont(AbstractRenderer.expFont);
gc.drawString(s.toString(), posX, posY);
posX += AbstractRenderer.expFontMetrics.stringWidth(s.toString());
// if ther are more than one element in the list the rest will be a tooltip.
// the tooltiptext is defined
if (this.defaultTypeSubstitutionList.size() > 1)
{
this.collapsed = true;
gc.drawString(SubstitutionRenderer.collapsString, posX, posY);
this.collapsedArea.x = posX;
posX += AbstractRenderer.expFontMetrics.stringWidth(SubstitutionRenderer.collapsString);
this.collapsedArea.width = (posX - this.collapsedArea.x);
this.collapsedArea.y = posY - fontHeight;
this.collapsedArea.height = fontHeight;
}
//Render the "]"
gc.drawString("]", posX, posY);
posX += AbstractRenderer.expFontMetrics.stringWidth("]");
}
}
}