/** *************************************************************
*
* Draw the actual text and bars onto the pie chart.
*
* occurrs by generating the appropriate set of CIUPrimitives
* and drawing them onto the IUGraphicsContext.
*
* A cache is used for the CIUText primitives so they can be
* resused. These are expensive primitives to generate.
*
* @exception Exception On fatal rendering error
* @throws Exception On fatal rendering error
*
*/
public boolean pollUpdate() throws Exception
{
CIUCacheEntry cacheEntry = null; // A cache entry
CIUPrimitive gp = null; // The current primitive to draw
String key = null;
int NC = CIUGraphicsContext.NoClip; // ID for "no clipping"
int HC = CIUGraphicsContext.HClip; // ID for horizontal clipping
int VC = CIUGraphicsContext.VClip; // ID for vertical clipping
int HVC = CIUGraphicsContext.HVClip; // IF for clipping in both directions
int resize = NC;
int counter = 0;
boolean horzClip = false; // Was there horizontal clipping?
boolean vertClip = false; // Was there vertical clipping?
int iStrMaxWidth; // Max width [in pixels] of a string
byte black; // The LUT index for black
int MARGIN = 5; // The size [in pixels] of the margin
int cX = MARGIN; // Current x-position
int cY = MARGIN; // Current y-position
int H; // The height of a primitive
int W; // The width of a primitive
PollDraw.consoleLog("\nPieChart::pollUpdate> begin");
//
// Get the 4 necessary CIUFonts
//
this.retrieveIUFonts( m_IUFontHash );
//
// Some initializations
//
StrMaxWidth = m_width - (MARGIN*2);
black = (byte)m_cc.toLUTIndex( "000000" );
//
// I need a graphics context to draw on
//
m_gc = new CIUGraphicsContext( m_width, cY, m_bgcolor, m_cc );
PollDraw.consoleLog("PieChart::pollUpdate> gc is " + m_width + " by " + cY + " big");
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Add the title as a child
if(m_strTitle != null)
{
key = null;
cacheEntry = null;
key = ( m_strTitle + m_cfTitle.key() );
cacheEntry = m_primitiveCache.get( key );
if ( null == cacheEntry )
{
gp = new CIUText( m_strTitle, iStrMaxWidth, m_cfTitle, m_frame, black ).translate( cX, cY );
m_primitiveCache.add( key, gp );
}
else
{
gp = (CIUPrimitive)cacheEntry.m_object;
gp.zero().translate( cX, cY );
}
if ( null!=gp )
{
m_gc.draw( gp );
cY += ( gp.height() + MARGIN );
gp = null;
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Add the question as a child
String question = m_PollQuestionData.getQuestion();
cacheEntry = null;
key = null;
key = ( question + m_cfText.key() );
cacheEntry = m_primitiveCache.get( key );
if ( null == cacheEntry )
{
gp = new CIUText( question, iStrMaxWidth, m_cfText, m_frame, black ).translate( cX, cY );
m_primitiveCache.add( key, gp );
}
else
{
gp = (CIUPrimitive)cacheEntry.m_object;
gp.zero().translate( cX, cY );
}
m_gc.draw( gp );
cY += ( gp.height() + MARGIN + MARGIN);
gp = null;
// Dereference the poll answers
PollAnswer[] answers = m_PollQuestionData.getAnswers();
float top_percent = answers[0].percentage();
double [] sizes = new double[ answers.length ];
for( int a = 0; a < answers.length; ++a )
sizes[a] = (double)answers[a].percentage();
// Draw The pie chart....
int radius = (int) ((m_width/2.0) - MARGIN*2);
gp = new CIUPieChart( radius, false, sizes, m_frame, m_pieColors, "000000", m_bgcolor, m_cc ).translate( cX+MARGIN, cY );
m_gc.draw( gp );
cY += ( gp.height() + MARGIN*3 );
gp = null;
// Draw the poll answers themselves
for( int a = 0; a < answers.length; ++a )
{
// Some preparatory values
float fPer = answers[a].percentage();
byte byteColor = (byte)m_cc.toLUTIndex( m_pieColors[a % m_pieColors.length] );
int intColor = CIUBitArray.byteToInt( byteColor );
PollDraw.consoleLog("PieChart::pollUpdate> color: " + m_pieColors[a % m_pieColors.length] );
PollDraw.consoleLog("PieChart::pollUpdate> color: " + intColor );
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Draw percentage string.
//
String sPer = getPercentString( fPer );
cacheEntry = null;
key = null;
key = ( sPer + m_cfPercent.key() );
cacheEntry = m_primitiveCache.get( key );
if ( null == cacheEntry )
{
PollDraw.consoleLog("PieChart::pollUpdate> Did not find cache entry: " + sPer);
gp = new CIUText( sPer, 1000, m_cfPercent, m_frame, black ).translate( cX, cY );
}
else
{
PollDraw.consoleLog("PieChart::pollUpdate> Found cache entry: " + sPer);
gp = (CIUPrimitive)cacheEntry.m_object;
gp.zero().translate( cX, cY );
}
m_gc.draw( gp );
cY += gp.height();
gp = null;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Draw the answer
String answer = answers[a].answer();
cacheEntry = null;
key = null;
key = ( answer + m_cfText.key() + intColor );
cacheEntry = m_primitiveCache.get( key );
if ( null == cacheEntry )
{
PollDraw.consoleLog("PieChart::pollUpdate> Did not find cache entry: " + answer);
gp = new CIUText( answer, iStrMaxWidth, m_cfText, m_frame, byteColor ).translate( cX, cY );
m_primitiveCache.add( key, gp );
}
else
{
PollDraw.consoleLog("PieChart::pollUpdate> Found cache entry: " + answer);
gp = (CIUPrimitive)cacheEntry.m_object;
gp.zero().translate( cX, cY );
}
m_gc.draw( gp );
cY += ( MARGIN + gp.height() );
gp = null;
}
// Translate
cY += MARGIN;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Draw the string for the total votes...
String total = "Total Votes: ";
cacheEntry = null;
key = null;
key = ( total + m_cfTotal.key() );
cacheEntry = m_primitiveCache.get( key );
if ( null == cacheEntry )
{
PollDraw.consoleLog("PieChart::pollUpdate> Did not find cache entry: " + total);
gp = new CIUText( total, iStrMaxWidth, m_cfTotal, m_frame, black ).translate( cX, cY );
m_primitiveCache.add( key, gp );
}
else
{
PollDraw.consoleLog("PieChart::pollUpdate> Found cache entry: " + total);
gp = (CIUPrimitive)cacheEntry.m_object;
gp.zero().translate( cX, cY );
}
m_gc.draw( gp );
W = gp.width();
gp = null;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Draw the string for the number of votes...
//
String votes = commaAbsInteger( m_PollQuestionData.totalVotes() );
cacheEntry = null;
key = null;
key = ( votes + m_cfTotal.key() );
cacheEntry = m_primitiveCache.get( key );
if ( null == cacheEntry )
{
PollDraw.consoleLog("PieChart::pollUpdate> Did not find cache entry: " + votes );
gp = new CIUText( votes, iStrMaxWidth, m_cfTotal, m_frame, black ).translate( (cX + W), cY );
m_primitiveCache.add( key, gp );
}
else
{
PollDraw.consoleLog("PieChart::pollUpdate> Found cache entry: " + votes );
gp = (CIUPrimitive)cacheEntry.m_object;
gp.zero().translate( (cX + W), cY );
}
m_gc.draw( gp );
cY += ( MARGIN + gp.height() );
gp = null;
cacheEntry = null;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Resize the GC so we know it is big enough....
//
resize = m_gc.resize( m_width, cY );
if ( VC == resize ) { vertClip=true; }
else if ( HC == resize ) { horzClip=true; }
else if ( HVC == resize ) { horzClip=true; vertClip=true; }
PollDraw.consoleLog("PieChart::pollUpdate> gc is " + m_width + " by " + cY + " big");
PollDraw.consoleLog("PieChart::pollUpdate> clip: h:" + horzClip + " v:" + vertClip );
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// For very small polls, the GC can clip the percentage text.
// Try to resize horizontally 3 times... if we need any more
// than 3 tries (15 pixels), then there's more wrong here
// than simple resizing.
//
while ( (HC==resize) && (counter<4) )
{
++counter;
m_width+=MARGIN;
resize = m_gc.resize( m_width, cY );
if ( VC == resize ) { vertClip=true; }
else if ( HC == resize ) { horzClip=true; }
else if ( HVC == resize ) { horzClip=true; vertClip=true; }
PollDraw.consoleLog("PieChart::pollUpdate> gc is " + m_width + " by " + cY + " big");
PollDraw.consoleLog("PieChart::pollUpdate> clip: h:" + horzClip + " v:" + vertClip );
}
PollDraw.consoleLog("PieChart::pollUpdate> end\n");
return true;
}