ScriptHandler.callFunction( sh, ScriptHandler.AFTER_DRAW_LEGEND_ITEM, lerh, bo, getRunTimeContext( ).getScriptContext( ) ); getRunTimeContext( ).notifyStructureChange( IStructureDefinitionListener.AFTER_DRAW_LEGEND_ITEM, lerh );
	protected final void renderLegendItem( IPrimitiveRenderer ipr, Legend lg,			Label la, Label valueLa, double dX, double dY, double dW,			double dItemHeight, double dFullHeight, double dExtraHeight,			double dColumnWidth, double dLeftInset, double dHorizontalSpacing,			Series se, Fill fPaletteEntry, LegendItemRenderingHints lirh,			int dataIndex ) throws ChartException	{		LegendEntryRenderingHints lerh = new LegendEntryRenderingHints( la,				valueLa,				dataIndex,				fPaletteEntry );		ScriptHandler sh = getRunTimeContext( ).getScriptHandler( );		// TODO replace with LegendEntryRenderingHints		ScriptHandler.callFunction( sh,				ScriptHandler.BEFORE_DRAW_LEGEND_ENTRY,				la,				getRunTimeContext( ).getScriptContext( ) );		getRunTimeContext( ).notifyStructureChange( IStructureDefinitionListener.BEFORE_DRAW_LEGEND_ENTRY,				la );		final Bounds bo = lirh.getLegendGraphicBounds( );		if ( isRightToLeft( ) )		{			bo.setLeft( dX					+ dColumnWidth					- dLeftInset					- 1					- 3					* dItemHeight					/ 2 );		}		else		{			bo.setLeft( dX + dLeftInset + 1 );		}		bo.setTop( dY + 1 + ( dFullHeight - dItemHeight ) / 2 );		bo.setWidth( 3 * dItemHeight / 2 );		bo.setHeight( dItemHeight - 2 );		final BaseRenderer br = lirh.getRenderer( );		br.renderLegendGraphic( ipr, lg, fPaletteEntry, bo );		final TextRenderEvent tre = (TextRenderEvent) ( (EventObjectCache) ir ).getEventObject( StructureSource.createLegend( lg ),				TextRenderEvent.class );		double dLaAngle = la.getCaption( ).getFont( ).getRotation( );		if ( isRightToLeft( ) )		{			dLaAngle = -dLaAngle;		}		double dDeltaHeight = 0;		if ( dLaAngle > 0 && dLaAngle < 90 )		{			dDeltaHeight = ( bo.getHeight( ) + dFullHeight - dItemHeight ) / 2;		}		else if ( dLaAngle < 0 && dLaAngle > -90 )		{			dDeltaHeight = ( bo.getHeight( ) - dFullHeight + dItemHeight ) / 2;		}		else if ( dLaAngle == 0 || dLaAngle == 90 || dLaAngle == -90 )		{			dDeltaHeight = bo.getHeight( ) / 2;		}		if ( isRightToLeft( ) )		{			tre.setLocation( LocationImpl.create( dX					+ dColumnWidth					- dLeftInset					- 3					* dItemHeight					/ 2					- dHorizontalSpacing, bo.getTop( ) + dDeltaHeight ) );			tre.setTextPosition( TextRenderEvent.LEFT );		}		else		{			tre.setLocation( LocationImpl.create( dX					+ dLeftInset					+ ( 3 * dItemHeight / 2 )					+ dHorizontalSpacing, bo.getTop( ) + dDeltaHeight ) );			tre.setTextPosition( TextRenderEvent.RIGHT );		}		if ( la.isVisible( ) )		{			tre.setLabel( la );			tre.setAction( TextRenderEvent.RENDER_TEXT_AT_LOCATION );			ipr.drawText( tre );		}		if ( valueLa != null )		{			Location[] loaBack = new Location[4];			final PolygonRenderEvent pre = (PolygonRenderEvent) ( (EventObjectCache) ir ).getEventObject( StructureSource.createLegend( lg ),					PolygonRenderEvent.class );			pre.setBackground( valueLa.getBackground( ) );			pre.setOutline( valueLa.getOutline( ) );			pre.setPoints( loaBack );			final double dValueWidth = dColumnWidth - 2 * dLeftInset;			loaBack[0] = LocationImpl.create( dX + dLeftInset + 1, dY					+ dFullHeight					+ 1 );			loaBack[1] = LocationImpl.create( dX + dLeftInset + 1, dY					+ dFullHeight					+ dExtraHeight );			loaBack[2] = LocationImpl.create( dX + dLeftInset + dValueWidth, dY					+ dFullHeight					+ dExtraHeight );			loaBack[3] = LocationImpl.create( dX + dLeftInset + dValueWidth, dY					+ dFullHeight					+ 1 );			ipr.fillPolygon( pre );			ipr.drawPolygon( pre );			Label tmpLa = LabelImpl.copyInstance( valueLa );			tmpLa.setOutline( null );			tmpLa.setBackground( null );			TextAlignment ta = TextAlignmentImpl.create( );			ta.setHorizontalAlignment( HorizontalAlignment.CENTER_LITERAL );			ta.setVerticalAlignment( VerticalAlignment.CENTER_LITERAL );			tre.setBlockAlignment( ta );			tre.setBlockBounds( BoundsImpl.create( dX + dLeftInset + 1, dY					+ dFullHeight					+ 1, dValueWidth - 2, dExtraHeight - 1 ) );			tre.setLabel( tmpLa );			tre.setAction( TextRenderEvent.RENDER_TEXT_IN_BLOCK );			ipr.drawText( tre );		}		if ( isInteractivityEnabled( ) )		{			// PROCESS 'SERIES LEVEL' TRIGGERS USING SOURCE='bs'			Trigger tg;			EList elTriggers = lg.getTriggers( );			Location[] loaHotspot = new Location[4];			if ( isRightToLeft( ) )			{				double dTextStartX = tre.getLocation( ).getX( ) + 1;				loaHotspot[0] = LocationImpl.create( dTextStartX, dY );				loaHotspot[1] = LocationImpl.create( dTextStartX - dW, dY + 1 );				loaHotspot[2] = LocationImpl.create( dTextStartX - dW, dY						+ dFullHeight						+ dExtraHeight );				loaHotspot[3] = LocationImpl.create( dTextStartX, dY						+ dFullHeight						+ dExtraHeight );			}			else			{				double dTextStartX = tre.getLocation( ).getX( ) - 1;				loaHotspot[0] = LocationImpl.create( dTextStartX, dY );				loaHotspot[1] = LocationImpl.create( dTextStartX + dW, dY + 1 );				loaHotspot[2] = LocationImpl.create( dTextStartX + dW, dY						+ dFullHeight						+ dExtraHeight );				loaHotspot[3] = LocationImpl.create( dTextStartX, dY						+ dFullHeight						+ dExtraHeight );			}			Trigger buildinTg = null;			if ( cm.getInteractivity( ) != null )			{				boolean customed = false;				switch ( cm.getInteractivity( ).getLegendBehavior( ).getValue( ) )				{					case LegendBehaviorType.HIGHLIGHT_SERIE :						for ( Iterator itr = elTriggers.iterator( ); itr.hasNext( ); )						{							tg = (Trigger) itr.next( );							if ( tg.getCondition( ) == TriggerCondition.ONCLICK_LITERAL									|| tg.getAction( ).getType( ) == ActionType.HIGHLIGHT_LITERAL )							{								customed = true;							}						}						if ( !customed )						{							buildinTg = TriggerImpl.create( TriggerCondition.ONCLICK_LITERAL,									ActionImpl.create( ActionType.HIGHLIGHT_LITERAL,											SeriesValueImpl.create( String.valueOf( se.getSeriesIdentifier( ) ) ) ) );						}						break;					case LegendBehaviorType.TOGGLE_SERIE_VISIBILITY :						for ( Iterator itr = elTriggers.iterator( ); itr.hasNext( ); )						{							tg = (Trigger) itr.next( );							if ( tg.getCondition( ) == TriggerCondition.ONCLICK_LITERAL									|| tg.getAction( ).getType( ) == ActionType.TOGGLE_VISIBILITY_LITERAL )							{								customed = true;							}						}						if ( !customed )						{							buildinTg = TriggerImpl.create( TriggerCondition.ONCLICK_LITERAL,									ActionImpl.create( ActionType.TOGGLE_VISIBILITY_LITERAL,											SeriesValueImpl.create( String.valueOf( se.getSeriesIdentifier( ) ) ) ) );						}						break;					case LegendBehaviorType.NONE :						break;				}			}			if ( !elTriggers.isEmpty( ) || buildinTg != null )			{				final StructureSource source;				if ( this.cm.getLegend( ).getItemType( ) == LegendItemType.CATEGORIES_LITERAL )				{					final DataPointHints dph = new DataPointHints( la,							null,							null,							null,							null,							null,							null,							null,							null,							dataIndex,							null,							0,							null );					source = WrappedStructureSource.createSeriesDataPoint( se,							dph );				}				else				{					source = StructureSource.createSeries( se );				}				final InteractionEvent iev = (InteractionEvent) ( (EventObjectCache) ipr ).getEventObject( source,						InteractionEvent.class );				for ( int t = 0; t < elTriggers.size( ); t++ )				{					tg = TriggerImpl.copyInstance( (Trigger) elTriggers.get( t ) );					processTrigger( tg,							WrappedStructureSource.createLegendEntry( lg, lerh ) );					iev.addTrigger( tg );				}				if ( buildinTg != null )				{					processTrigger( buildinTg,							WrappedStructureSource.createLegendEntry( lg, lerh ) );					iev.addTrigger( buildinTg );				}				final PolygonRenderEvent pre = (PolygonRenderEvent) ( (EventObjectCache) ipr ).getEventObject( source,						PolygonRenderEvent.class );				pre.setPoints( loaHotspot );				iev.setHotSpot( pre );				ipr.enableInteraction( iev );			}		}		ScriptHandler.callFunction( sh,				ScriptHandler.AFTER_DRAW_LEGEND_ENTRY,				la,				getRunTimeContext( ).getScriptContext( ) );		getRunTimeContext( ).notifyStructureChange( IStructureDefinitionListener.AFTER_DRAW_LEGEND_ENTRY,				la );	}