/*******************************************************************************
* Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Innoopract Informationssysteme GmbH - initial API and implementation
******************************************************************************/
package com.w4t.webcardlayoutkit;
import java.io.IOException;
import java.util.List;
import java.util.Vector;
import org.eclipse.rwt.Adaptable;
import org.eclipse.rwt.internal.lifecycle.HtmlResponseWriter;
import org.eclipse.rwt.internal.service.ContextProvider;
import org.eclipse.rwt.internal.util.HTML;
import com.w4t.*;
import com.w4t.developer.AreaSelector;
import com.w4t.event.WebActionEvent;
import com.w4t.event.WebActionListener;
import com.w4t.internal.adaptable.IRenderInfoAdapter;
import com.w4t.renderinfo.CardLayoutRenderInfo;
import com.w4t.types.TabConfig;
import com.w4t.weblayoutkit.LayoutRenderer;
/** <p>the superclass for all renderers that render
* {@link org.eclipse.rwt.WebCardLayout WebCardLayout}.</p>
*/
public abstract class WebCardLayoutRenderer extends LayoutRenderer {
private static final String CARD_COUNT = "cardCount";
private static final String CARD_LIST = "cardList";
private static final String BORDER_SIZE = "borderSize";
private static final String DESIGN_CARD = "designCard";
public void render( final WebComponent component ) throws IOException {
WebContainer parent = ( WebContainer )component;
getRenderInfoAdapter( parent ).clearRenderState();
getLayout( parent ).setEnabled( parent.isEnabled() );
checkBorderSizeInDesignTime( parent );
// fill the cardList with the actual cards listed in
// the parent Webcontainer
fillCardList( parent );
// get the card to display
WebComponent card = findCard( parent );
WebTableCell contentCell = new WebTableCell();
contentCell.setAlign( HTML.CENTER );
contentCell.setVAlign( HTML.TOP );
contentCell.setBgColor( getLayout( parent ).getCardColor() );
contentCell.setStyle( getLayout( parent ).getCardStyle() );
if( card != null ) {
contentCell.addContentElement( card );
}
WebTableCell tabsCell = new WebTableCell();
tabsCell.setValueEncoded( true );
WebTableRow tableRow = new WebTableRow();
createTableOpener( parent );
HtmlResponseWriter out = getResponseWriter();
if( getPos( parent ).equals( TabConfig.POSITION_TOP ) ) {
tabsCell.setAlign( getAlign( parent ) );
tabsCell.setValue( buildHorizontalSelection( parent ) );
tableRow.addCell( tabsCell );
tableRow.render();
tableRow.removeCell( 0 );
tableRow.addCell( contentCell );
} else if( getPos( parent ).equals( TabConfig.POSITION_BOTTOM ) ) {
tableRow.addCell( contentCell );
tableRow.render();
tableRow.removeCell( 0 );
tabsCell.setAlign( getAlign( parent ) );
tabsCell.setValue( buildHorizontalSelection( parent ) );
tableRow.addCell( tabsCell );
} else if( getPos( parent ).equals( TabConfig.POSITION_LEFT ) ) {
tabsCell.setVAlign( getAlign( parent ) );
tabsCell.setValue( buildVerticalSelection( parent ) );
tableRow.addCell( tabsCell );
tableRow.addCell( contentCell );
} else if( getPos( parent ).equals( TabConfig.POSITION_RIGHT ) ) {
tableRow.addCell( contentCell );
tabsCell.setVAlign( getAlign( parent ) );
tabsCell.setValue( buildVerticalSelection( parent ) );
tableRow.addCell( tabsCell );
}
tableRow.render();
createTableCloser( out );
restoreBorderBuffer( parent );
}
public void scheduleRendering( final WebComponent component ) {
WebContainer container = ( WebContainer )component;
WebCardLayout layout = ( WebCardLayout )container.getWebLayout();
String displayCard = layout.getDisplayCard();
for( int i = 0; i < container.getWebComponentCount(); i++ ) {
Object constraint = null;
try {
constraint = container.getConstraint( container.get( i ) );
} catch( final Exception shouldNotHappen ) {
throw new RuntimeException( shouldNotHappen );
}
if( constraint.equals( displayCard ) ) {
getRenderingSchedule().schedule( container.get( i ) );
}
}
}
public static void applyBorderSettings( final WebContainer parent,
final Style cellStyle )
{
// everything but the opposite
String pos = getLayout( parent ).getTabConfig().getTabPosition();
if( pos.equals( TabConfig.POSITION_TOP ) ) {
cellStyle.setBorderTop( getBorderString( parent ) );
cellStyle.setBorderRight( getBorderString( parent ) );
cellStyle.setBorderLeft( getBorderString( parent ) );
} else if( pos.equals( TabConfig.POSITION_LEFT ) ) {
cellStyle.setBorderTop( getBorderString( parent ) );
cellStyle.setBorderBottom( getBorderString( parent ) );
cellStyle.setBorderLeft( getBorderString( parent ) );
} else if( pos.equals( TabConfig.POSITION_RIGHT ) ) {
cellStyle.setBorderTop( getBorderString( parent ) );
cellStyle.setBorderBottom( getBorderString( parent ) );
cellStyle.setBorderRight( getBorderString( parent ) );
} else if( pos.equals( TabConfig.POSITION_BOTTOM ) ) {
cellStyle.setBorderBottom( getBorderString( parent ) );
cellStyle.setBorderRight( getBorderString( parent ) );
cellStyle.setBorderLeft( getBorderString( parent ) );
}
}
static String getBorderString( final WebContainer parent ) {
StringBuffer buffer = new StringBuffer();
buffer.append( "solid " );
buffer.append( String.valueOf( getLayout( parent ).getBorderWidth() ) );
buffer.append( "px " );
buffer.append( getLayout( parent ).getBorderColor().toString() );
return buffer.toString();
}
void setCardCount( final WebContainer parent, final int cardCount ){
IRenderInfoAdapter adapter = getRenderInfoAdapter( parent );
adapter.addRenderState( CARD_COUNT, new Integer( cardCount ) );
}
int getCardCount( final WebContainer parent ) {
IRenderInfoAdapter adapter = getRenderInfoAdapter( parent );
Object renderState = adapter.getRenderState( CARD_COUNT );
int result = 0;
if( renderState != null ) {
result = ( ( Integer )renderState ).intValue();
}
return result;
}
void setCardList( final WebContainer parent, final WebButton[] cardList ) {
IRenderInfoAdapter adapter = getRenderInfoAdapter( parent );
adapter.addRenderState( CARD_LIST, cardList );
}
WebButton[] getCardList( final WebContainer parent ) {
IRenderInfoAdapter adapter = getRenderInfoAdapter( parent );
return ( WebButton[] )adapter.getRenderState( CARD_LIST );
}
void setBorderSize( final WebContainer parent, final String borderSize ) {
IRenderInfoAdapter adapter = getRenderInfoAdapter( parent );
adapter.addRenderState( BORDER_SIZE, borderSize );
}
String getBorderSize( final WebContainer parent ) {
IRenderInfoAdapter adapter = getRenderInfoAdapter( parent );
return ( String )adapter.getRenderState( BORDER_SIZE );
}
void setDesignCard( final WebContainer parent,
final AreaSelector designCard )
{
IRenderInfoAdapter adapter = getRenderInfoAdapter( parent );
adapter.addRenderState( DESIGN_CARD, designCard );
}
AreaSelector getDesignCard( final WebContainer parent ) {
IRenderInfoAdapter adapter = getRenderInfoAdapter( parent );
return ( AreaSelector )adapter.getRenderState( DESIGN_CARD );
}
IRenderInfoAdapter getRenderInfoAdapter( final WebContainer parent ) {
Adaptable adaptable = getLayout( parent );
Class clazz = IRenderInfoAdapter.class;
return ( IRenderInfoAdapter )adaptable.getAdapter( clazz );
}
static WebCardLayout getLayout( final WebContainer parent ) {
return ( WebCardLayout )parent.getWebLayout();
}
CardLayoutRenderInfo getInfo( final WebContainer parent ) {
return ( CardLayoutRenderInfo )getRenderInfoAdapter( parent ).getInfo();
}
/** <p>Creates the (intermediate) button that allows switching from one card
* (aka tab page) to another. Subclasses may override.</p> */
WebButton createCardButton( final String label, final WebContainer parent ) {
WebButton result = new WebButton( label, parent );
result.setEnabled( getLayout( parent ).isEnabled() );
result.setLink( true );
result.setUseTrim( false );
return result;
}
void createLeftSpacer( final WebContainer parent,
final WebTableRow tableRow )
{
// do nothing here, but in subclasses
}
void createRightSpacer( final WebContainer parent,
final WebTableRow tableRow )
{
// do nothing here, but in subclasses
}
void addDesignCard( final WebContainer parent ,
final WebTableRow tableRow )
{
setDesignCard( parent, null );
if( parent.isDesignTime() ) {
setDesignCard( parent, new AreaSelector() );
getDesignCard( parent ).setContainer( parent );
String constraint = "Card"
+ String.valueOf( getVisibleCardCount( parent ) );
getDesignCard( parent ).setConstraint( constraint );
parent.add( getDesignCard( parent ), "develop" );
WebTableCell tableCell
= createSelectionCell( parent, getDesignCard( parent ) );
tableRow.addCell( tableCell );
}
}
void removeDesignCard( final WebContainer parent ) {
if( parent.isDesignTime() ) {
parent.remove( getDesignCard( parent ) );
}
}
/** <p>creates a selection bar tab cell, which has the correct styles,
* borders etc.</p> */
WebTableCell createSelectionCell( final WebContainer parent,
final WebButton card )
{
WebTableCell result = new WebTableCell();
if( isDisplayCard( parent, card ) ) {
result.setBgColor( getLayout( parent ).getCardColor() );
result.setStyle( getLayout( parent ).getActiveTabStyle() );
card.setStyle( getLayout( parent ).getActiveTabLinkStyle() );
} else {
result.setBgColor( getLayout( parent ).getInactiveTabColor() );
result.setStyle( getLayout( parent ).getInactiveTabStyle() );
result.setSpacing( "0" );
result.setPadding( "3" );
card.setStyle( getLayout( parent ).getInactiveTabLinkStyle() );
}
result.addContentElement( card );
return result;
}
boolean isDisplayCard( final WebContainer parent,
final WebButton card )
{
return getLayout( parent ).getDisplayCard().equals( card.getLabel() );
}
String getAlign( final WebContainer parent ) {
return getLayout( parent ).getTabConfig().getTabAlignment();
}
boolean isModernType( final WebContainer parent ) {
int type = getLayout( parent ).getTabConfig().getType();
return type == TabConfig.TYPE_MODERN;
}
private static void createCardButtonEventListener( final WebContainer parent,
final WebButton card )
{
final String label = card.getLabel();
card.addWebActionListener( new WebActionListener() {
WebCardLayout layout = getLayout( parent );
WebContainer container = parent;
public void webActionPerformed( final WebActionEvent e ) {
layout.setDisplayCard( label );
// if an actionlistener is set, fire the event
if( WebActionEvent.hasListener( layout ) ) {
// get a reference to the clicked tab
for( int j = 0; j < container.getWebComponentCount(); j++ ) {
String constraint = ( String )container.getConstraint( j );
if( constraint.equals( label ) ) {
WebComponent wc = container.get( j );
WebActionEvent evt
= new WebActionEvent( wc, WebActionEvent.ACTION_PERFORMED );
Object[] lsnr = WebActionEvent.getListeners( layout );
for( int i = 0; i < lsnr.length; i++ ) {
// TODO: [fappel] Exception handling?
( ( WebActionListener )lsnr[ i ] ).webActionPerformed( evt );
}
}
}
}
}
} );
}
private void checkBorderSizeInDesignTime( final WebContainer parent ) {
// buffer border size
setBorderSize( parent, getLayout( parent ).getBorder() );
boolean useBorderSize_1 = false;
if( parent.isDesignTime() ) {
useBorderSize_1 = true;
try {
if( Integer.parseInt( getLayout( parent ).getBorder() ) > 1 ) {
useBorderSize_1 = false;
}
} catch( Exception e ) {
}
}
if( useBorderSize_1 ) {
getLayout( parent ).setBorder( "1" );
}
}
private void restoreBorderBuffer( final WebContainer parent ) {
getLayout( parent ).setBorder( getBorderSize( parent ) );
}
/** lookup the WebComponent to display as card */
private static WebComponent findCard( final WebContainer parent ) {
WebComponent card = null;
String displayCard;
boolean found = false;
for( int i = 0; !found && i < parent.getWebComponentCount(); i++ ) {
displayCard = getLayout( parent ).getDisplayCard();
if( displayCard.equals( parent.getConstraint( i ) ) ) {
card = parent.get( i );
found = true;
}
}
return card;
}
/** fills a cardList with WebButtons for the selection part of
* the WebCardLayout */
private void fillCardList( final WebContainer parent ) {
List vecTemp = new Vector();
setCardCount( parent, parent.getWebComponentCount() );
for( int i = 0; i < getCardCount( parent ); i++ ) {
final String label = ( String )parent.getConstraint( i );
WebButton card = createCardButton( label, parent );
// if the WebButton is clicked, bring the selected card to front
if( getLayout( parent ).isEnabled() ) {
createCardButtonEventListener( parent, card );
}
// prepare all visible cards for rendering
for( int j = 0; j < parent.getWebComponentCount(); j++ ) {
String compConstraint = ( String )parent.getConstraint( j );
if( compConstraint.equals( label ) ) {
WebComponent wc = parent.get( j );
if( wc.isVisible() ) {
vecTemp.add( card );
if( getLayout( parent ).isCardEnabledByComponent() ) {
card.setEnabled( wc.isEnabled() );
}
}
}
}
}
setCardCount( parent, vecTemp.size() );
setCardList( parent, new WebButton[ getCardCount( parent ) ] );
for( int i = 0; i < getCardCount( parent ); i++ ) {
getCardList( parent )[ i ] = ( WebButton )vecTemp.get( i );
}
}
/** creates the selection part with horizontal alignment */
private String buildHorizontalSelection( final WebContainer parent )
throws IOException
{
WebTableRow tableRow = new WebTableRow();
// build the table
HtmlResponseWriter tempOut = new HtmlResponseWriter();
HtmlResponseWriter out = getResponseWriter();
ContextProvider.getStateInfo().setResponseWriter( tempOut );
try {
createInnerTableOpener( tempOut );
// spacer
if( getVisibleCardCount( parent ) > 0 ) {
createLeftSpacer( parent, tableRow );
}
for( int i = 0; i < getVisibleCardCount( parent ); i++ ) {
WebButton card = getVisibleCard( parent, i );
WebTableCell tableCell = createSelectionCell( parent, card );
tableCell.setNowrap( true );
tableRow.addCell( tableCell );
}
addDesignCard( parent, tableRow );
// spacer
if( getVisibleCardCount( parent ) > 0 ) {
createRightSpacer( parent, tableRow );
}
tableRow.render();
removeDesignCard( parent );
createTableCloser( tempOut );
} finally {
ContextProvider.getStateInfo().setResponseWriter( out );
}
out.mergeRegisteredCssClasses( tempOut.getCssClasses() );
return toString( tempOut );
}
/** creates the selection part with vertical alignment */
private String buildVerticalSelection( final WebContainer parent )
throws IOException
{
HtmlResponseWriter tempOut = new HtmlResponseWriter();
HtmlResponseWriter out = getResponseWriter();
ContextProvider.getStateInfo().setResponseWriter( tempOut );
try {
// build the table
createInnerTableOpener( tempOut );
for( int i = 0; i < getCardCount( parent ); i++ ) {
WebTableRow tableRow = new WebTableRow();
WebButton card = getVisibleCard( parent, i );
WebTableCell tableCell = createSelectionCell( parent, card );
tableCell.setNowrap( true );
tableRow.addCell( tableCell );
tableRow.render();
}
createTableCloser( tempOut );
} finally {
ContextProvider.getStateInfo().setResponseWriter( out );
}
getResponseWriter().mergeRegisteredCssClasses( tempOut.getCssClasses() );
return toString( tempOut );
}
private int getVisibleCardCount( final WebContainer parent ) {
return getCardList( parent ).length;
}
private WebButton getVisibleCard( final WebContainer parent,
final int index )
{
return getCardList( parent )[ index ];
}
private static void createTableOpener( final WebContainer parent )
throws IOException
{
HtmlResponseWriter out = ContextProvider.getStateInfo().getResponseWriter();
out.startElement( HTML.TABLE, null );
RenderUtil.writeUniversalAttributes( parent );
RenderUtil.writeTableAttributes( getLayout( parent ) );
out.writeAttribute( HTML.ID, parent.getUniqueID(), null );
}
private static void createTableCloser( final HtmlResponseWriter out )
throws IOException
{
out.endElement( HTML.TABLE );
}
private static void createInnerTableOpener( final HtmlResponseWriter out )
throws IOException
{
out.startElement( HTML.TABLE, null );
out.writeAttribute( HTML.CELLSPACING, "0", null );
out.writeAttribute( HTML.CELLPADDING, "1", null );
out.writeAttribute( HTML.BORDER, "0", null );
}
private static String getPos( final WebContainer parent ) {
return getLayout( parent ).getTabConfig().getTabPosition();
}
private static String toString( final HtmlResponseWriter out ) {
StringBuffer result = new StringBuffer();
for( int i = 0; i < out.getBodySize(); i++ ) {
result.append( out.getBodyToken( i ) );
}
return result.toString();
}
}