package org.atdl4j.ui.swt.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import org.atdl4j.data.ValidationRule;
import org.atdl4j.data.exception.FIXatdlFormatException;
import org.atdl4j.data.validation.Field2OperatorValidationRule;
import org.atdl4j.data.validation.LogicalOperatorValidationRule;
import org.atdl4j.data.validation.ValueOperatorValidationRule;
import org.atdl4j.fixatdl.flow.StateRuleT;
import org.atdl4j.fixatdl.layout.ControlT;
import org.atdl4j.fixatdl.layout.RadioButtonT;
import org.atdl4j.fixatdl.layout.StrategyPanelT;
import org.atdl4j.ui.Atdl4jWidget;
import org.atdl4j.ui.impl.AbstractStrategyUI;
import org.atdl4j.ui.swt.SWTWidget;
import org.atdl4j.ui.swt.widget.SWTButtonWidget;
import org.atdl4j.ui.swt.widget.SWTRadioButtonListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ExpandBar;
/**
* SWT-specific UI representation for a Strategy object.
*
*/
public class SWTStrategyUI
extends AbstractStrategyUI
{
protected static final Logger logger = Logger.getLogger( SWTStrategyUI.class );
protected Map<String, SWTWidget<?>> swtWidgetMap;
Map<String, SWTWidget<?>> swtWidgetWithParameterMap;
protected Map<String, SWTRadioButtonListener> radioGroupMap;
protected List<SWTStateListener> stateListenerList;
protected Map<SWTWidget<?>, Set<SWTStateListener>> widgetStateListenerMap;
private Composite parent;
private List<ExpandBar> expandBarList;
/*
* Call init() after invoking the no arg constructor
*/
public SWTStrategyUI()
{
}
/**
* @param parentContainer (should be swt.Composite)
*/
public void initBegin(Object parentContainer)
{
setParent( (Composite) parentContainer );
setSWTWidgetWithParameterMap( new HashMap<String, SWTWidget<?>>() );
//TODO !!! verify, as it does not appear that getWidgetStateListenerMap() is ever being populated (though, is being initialized)
setWidgetStateListenerMap( new HashMap<SWTWidget<?>, Set<SWTStateListener>>() );
}
protected void buildAtdl4jWidgetMap()
{
if ( getStrategy() == null )
{
throw new IllegalStateException("Unexpected error: getStrategy() was null.");
}
if ( getStrategy().getStrategyLayout() == null )
{
throw new IllegalStateException("Unexpected error: getStrategy().getStrategyLayout() was null . (verify <lay:StrategyLayout>)");
}
if ( getStrategy().getStrategyLayout() == null )
{
throw new IllegalStateException("Unexpected error: getStrategy().getStrategyLayout().getStrategyPanel() was null . (verify <lay:StrategyLayout> <lay:StrategyPanel>)");
}
buildAtdl4jWidgetMap( getStrategy().getStrategyLayout().getStrategyPanel() );
}
public void initEnd()
{
}
// Set screen how it should look when in CxlRpl
public void setCxlReplaceMode(boolean cxlReplaceMode)
{
// enable/disable non-mutable parameters
for ( SWTWidget<?> widget : getSWTWidgetWithParameterMap().values() )
{
if ( !widget.getParameter().isMutableOnCxlRpl() )
widget.setEnabled( !cxlReplaceMode );
}
// set all CxlRpl on all state listeners and fire
// once for good measure
for ( SWTStateListener stateListener : getStateListenerList() )
{
stateListener.setCxlReplaceMode( cxlReplaceMode );
stateListener.handleEvent( null );
}
}
// Create a map of StateListeners to be added to each widget. This is to
// ensure that each StateListener is only added once to a given widget.
private void putStateListener(SWTWidget<?> widget, SWTStateListener stateListener)
{
if ( !getWidgetStateListenerMap().containsKey( widget ) )
getWidgetStateListenerMap().put( widget, new HashSet<SWTStateListener>() );
if ( !getWidgetStateListenerMap().get( widget ).contains( stateListener ) )
getWidgetStateListenerMap().get( widget ).add( stateListener );
}
private void attachRuleToControls(ValidationRule rule, SWTStateListener stateRuleListener)
{
if ( rule instanceof LogicalOperatorValidationRule )
{
for ( ValidationRule innerRule : ( (LogicalOperatorValidationRule) rule ).getRules() )
{
attachRuleToControls( innerRule, stateRuleListener );
}
}
else if ( rule instanceof ValueOperatorValidationRule )
{
attachFieldToControls( ( (ValueOperatorValidationRule) rule ).getField(), stateRuleListener );
}
else if ( rule instanceof Field2OperatorValidationRule )
{
attachFieldToControls( ( (Field2OperatorValidationRule) rule ).getField(), stateRuleListener );
attachFieldToControls( ( (Field2OperatorValidationRule) rule ).getField2(), stateRuleListener );
}
}
private void attachFieldToControls(String field, SWTStateListener stateRuleListener)
{
if ( field != null )
{
SWTWidget<?> targetParameterWidget = getSWTWidgetMap().get( field );
if ( targetParameterWidget == null )
throw new IllegalStateException( "Error generating a State Rule => Control: " + field + " does not exist in Strategy: " + getStrategy().getName() );
putStateListener( targetParameterWidget, stateRuleListener );
// -- RadioButtonT requires adding all associated RadioButtonTs in the radioGroup --
if ( targetParameterWidget.getControl() instanceof RadioButtonT
&& ( (RadioButtonT) targetParameterWidget.getControl() ).getRadioGroup() != null
&& ( ! "".equals( ( (RadioButtonT) targetParameterWidget.getControl() ).getRadioGroup() ) ) )
{
String rg = ( (RadioButtonT) targetParameterWidget.getControl() ).getRadioGroup();
for ( SWTWidget<?> widget : getSWTWidgetMap().values() )
{
if ( widget.getControl() instanceof RadioButtonT && ( (RadioButtonT) widget.getControl() ).getRadioGroup() != null
&& ( (RadioButtonT) widget.getControl() ).getRadioGroup() != null
&& ( ! "".equals( ( (RadioButtonT) widget.getControl() ).getRadioGroup() ) )
&& ( (RadioButtonT) widget.getControl() ).getRadioGroup().equals( rg ) )
{
putStateListener( widget, stateRuleListener );
}
}
}
}
}
/**
* Note invoking this method results in object construction as a result of down-casting
* our own map of a specific templatized instance (SWTWidget<?>) of Atdl4jWidget<?> --
* @return
*/
public Map<String, Atdl4jWidget<?>> getAtdl4jWidgetWithParameterMap()
{
if ( getSWTWidgetWithParameterMap() != null )
{
return new HashMap<String, Atdl4jWidget<?>>( getSWTWidgetWithParameterMap() );
}
else
{
return null;
}
}
/**
* Note invoking this method results in object construction as a result of down-casting
* our own map of a specific templatized instance (SWTWidget<?>) of Atdl4jWidget<?> --
* @return
*/
public Map<String, Atdl4jWidget<?>> getAtdl4jWidgetMap()
{
if ( getSWTWidgetMap() != null )
{
return new HashMap<String, Atdl4jWidget<?>>( getSWTWidgetMap() );
}
else
{
return null;
}
}
/**
* @return the swtWidgetMap
*/
public Map<String, SWTWidget<?>> getSWTWidgetMap()
{
return this.swtWidgetMap;
}
/**
* @param aSWTWidgetMap the swtWidgetMap to set
*/
protected void setSWTWidgetMap(Map<String, SWTWidget<?>> aSWTWidgetMap)
{
this.swtWidgetMap = aSWTWidgetMap;
}
/**
* @param aStrategyPanelList
* @return
* @throws Atdl4jClassLoadException
*/
protected void buildAtdl4jWidgetMap( List<StrategyPanelT> aStrategyPanelList )
{
Map<String, SWTWidget<?>> tempSWTWidgetMap = new HashMap<String, SWTWidget<?>>();
setExpandBarList( new ArrayList<ExpandBar>() );
// build panels and widgets recursively
for ( StrategyPanelT panel : aStrategyPanelList )
{
tempSWTWidgetMap.putAll( SWTStrategyPanelFactory.createStrategyPanelAndWidgets( getParent(), panel, getParameterMap(), SWT.NONE, getExpandBarList(), getAtdl4jWidgetFactory() ) );
}
// 3/13/2010 John Shields HACK: make the first panel take the full width of the window
Composite c = getParent();
for ( Control child : c.getChildren() )
{
if (child instanceof Composite)
{
Composite composite = (Composite) child;
composite.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
}
}
setSWTWidgetMap( tempSWTWidgetMap );
}
public void relayoutCollapsibleStrategyPanels()
{
// -- avoid lots of 'thrash' during initial build/load of the various Strategy panels containing one or more collapsible panels --
for ( ExpandBar tempExpandBar : getExpandBarList() )
{
// -- Force re-sizing (to support non-collapsed, collapsible ExpandBar components) --
if ( tempExpandBar.getItem( 0 ).getExpanded() )
{
SWTStrategyPanelHelper.relayoutExpandBar( tempExpandBar, false );
}
}
}
protected void createRadioGroups()
{
Map<String, SWTRadioButtonListener> tempRadioGroupMap = new HashMap<String, SWTRadioButtonListener>();
for ( SWTWidget<?> widget : getSWTWidgetMap().values() )
{
if ( widget.getControl() instanceof RadioButtonT && ( (RadioButtonT) widget.getControl() ).getRadioGroup() != null
&& ( (RadioButtonT) widget.getControl() ).getRadioGroup() != "" )
{
String rg = ( (RadioButtonT) widget.getControl() ).getRadioGroup();
if ( !tempRadioGroupMap.containsKey( rg ) )
tempRadioGroupMap.put( rg, new SWTRadioButtonListener() );
if ( widget instanceof SWTButtonWidget )
{
tempRadioGroupMap.get( rg ).addButton( (SWTButtonWidget) widget );
((SWTButtonWidget) widget).setRadioButtonListener( tempRadioGroupMap.get( rg ) );
}
}
}
setRadioGroupMap( tempRadioGroupMap );
}
/**
* @return the radioGroupMap
*/
public Map<String, SWTRadioButtonListener> getRadioGroupMap()
{
return this.radioGroupMap;
}
/**
* @param aRadioGroupMap the radioGroupMap to set
*/
protected void setRadioGroupMap(Map<String, SWTRadioButtonListener> aRadioGroupMap)
{
this.radioGroupMap = aRadioGroupMap;
}
protected void addToAtdl4jWidgetMap( String aName, Atdl4jWidget<?> aAtdl4jWidget )
{
getSWTWidgetMap().put( aName, (SWTWidget<?>) aAtdl4jWidget );
}
protected void addToAtdl4jWidgetWithParameterMap( String aName, Atdl4jWidget<?> aAtdl4jWidget )
{
getSWTWidgetWithParameterMap().put( aName, (SWTWidget<?>) aAtdl4jWidget );
}
protected void removeFromAtdl4jWidgetMap( String aName )
{
getSWTWidgetMap().remove( aName );
}
protected void removeFromAtdl4jWidgetWithParameterMap( String aName )
{
getSWTWidgetWithParameterMap().remove( aName );
}
/**
*
*/
protected void buildAtdl4jWidgetWithParameterMap()
{
Map<String, SWTWidget<?>> tempSWTWidgetWithParameterMap = new HashMap<String, SWTWidget<?>>();
// loop through all UI controls
for ( SWTWidget<?> widget : getSWTWidgetMap().values() )
{
if ( widget.getParameter() != null )
{
// validate that a parameter is not being added twice
String tempParameterName = widget.getParameter().getName();
if ( tempSWTWidgetWithParameterMap.containsKey( tempParameterName ) )
{
throw new IllegalStateException( "Cannot add parameter \"" + tempParameterName + "\" to two separate controls." );
}
tempSWTWidgetWithParameterMap.put( tempParameterName, widget );
}
}
setSWTWidgetWithParameterMap( tempSWTWidgetWithParameterMap );
}
/**
* @throws FIXatdlFormatException
*/
protected void attachGlobalStateRulesToControls() throws FIXatdlFormatException
{
List<SWTStateListener> tempStateListenerList = new Vector<SWTStateListener>();
// loop through all UI controls
for ( SWTWidget<?> widget : getSWTWidgetMap().values() )
{
// parameter state rules that have an id should be included in
// the rules map
ControlT control = widget.getControl();
if ( control.getStateRule() != null )
{
for ( StateRuleT stateRule : control.getStateRule() )
{
SWTWidget<?> affectedWidget = getSWTWidgetMap().get( control.getID() );
SWTStateListener stateListener = new SWTStateListener( affectedWidget, stateRule, getSWTWidgetMap(), getCompleteValidationRuleMap() );
// attach the stateListener's rule to controls
attachRuleToControls( stateListener.getRule(), stateListener );
tempStateListenerList.add( stateListener );
// run the state rule to check if any parameter needs to be
// enabled/disabled or hidden/unhidden before being rendered
stateListener.handleEvent( null );
}
}
}
setStateListenerList( tempStateListenerList );
}
/**
* @return the swtWidgetWithParameterMap
*/
public Map<String, SWTWidget<?>> getSWTWidgetWithParameterMap()
{
return this.swtWidgetWithParameterMap;
}
/**
* @param aSWTWidgetWithParameterMap the swtWidgetWithParameterMap to set
*/
protected void setSWTWidgetWithParameterMap(Map<String, SWTWidget<?>> aSWTWidgetWithParameterMap)
{
this.swtWidgetWithParameterMap = aSWTWidgetWithParameterMap;
}
/**
* @return the stateListenerList
*/
protected List<SWTStateListener> getStateListenerList()
{
return this.stateListenerList;
}
/**
* @param aStateListenerList the stateListenerList to set
*/
protected void setStateListenerList(List<SWTStateListener> aStateListenerList)
{
this.stateListenerList = aStateListenerList;
}
/**
* @return the widgetStateListenerMap
*/
protected Map<SWTWidget<?>, Set<SWTStateListener>> getWidgetStateListenerMap()
{
return this.widgetStateListenerMap;
}
/**
* @param aWidgetStateListenerMap the widgetStateListenerMap to set
*/
protected void setWidgetStateListenerMap(Map<SWTWidget<?>, Set<SWTStateListener>> aWidgetStateListenerMap)
{
this.widgetStateListenerMap = aWidgetStateListenerMap;
}
/**
*
*/
protected void attachStateListenersToAllAtdl4jWidgets()
{
//TODO !!! verify, as it does not appear that getWidgetStateListenerMap() is ever being populated (though, is being initialized)
// add all StateListeners to the controls
for ( Entry<SWTWidget<?>, Set<SWTStateListener>> entry : getWidgetStateListenerMap().entrySet() )
{
for ( SWTStateListener listener : entry.getValue() )
entry.getKey().addListener( listener );
}
}
/**
* @return the parent
*/
public Composite getParent()
{
return this.parent;
}
/**
* @param aParent the parent to set
*/
protected void setParent(Composite aParent)
{
this.parent = aParent;
}
protected void fireStateListeners()
{
// fire state listeners once for good measure
for ( SWTStateListener stateListener : getStateListenerList() )
stateListener.handleEvent( null );
}
protected void fireStateListenersForAtdl4jWidget( Atdl4jWidget<?> aAtdl4jWidget )
{
for ( SWTStateListener stateListener : getStateListenerList() )
{
if ( aAtdl4jWidget.equals( stateListener.getAffectedWidget() ) )
{
stateListener.handleEvent( null );
}
}
}
/**
* Invokes SWTStateListener.handleLoadFixMessageEvent() for aAtdl4jWidget
* @param aAtdl4jWidget
*/
protected void fireLoadFixMessageStateListenersForAtdl4jWidget( Atdl4jWidget<?> aAtdl4jWidget )
{
for ( SWTStateListener stateListener : getStateListenerList() )
{
if ( aAtdl4jWidget.equals( stateListener.getAffectedWidget() ) )
{
stateListener.handleLoadFixMessageEvent( null );
}
}
}
/* If no RadioButtons within a radioGroup are selected, then first one in list will be selected
* @see org.atdl4j.ui.impl.AbstractStrategyUI#applyRadioGroupRules()
*/
protected void applyRadioGroupRules()
{
if ( getRadioGroupMap() != null )
{
for ( SWTRadioButtonListener tempSWTRadioButtonListener : getRadioGroupMap().values() )
{
// -- If no RadioButtons within the radioGroup are selected, then first one in list will be selected --
tempSWTRadioButtonListener.processReinit();
}
}
}
/**
* @return the expandBarList
*/
protected List<ExpandBar> getExpandBarList()
{
return this.expandBarList;
}
/**
* @param aExpandBarList the expandBarList to set
*/
protected void setExpandBarList(List<ExpandBar> aExpandBarList)
{
this.expandBarList = aExpandBarList;
}
}