package org.atdl4j.ui.swing.impl; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.Vector; import javax.swing.AbstractButton; import javax.swing.ButtonGroup; import javax.swing.JPanel; 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.swing.SwingWidget; import org.atdl4j.ui.swing.widget.SwingButtonWidget; /** * Swing-specific UI representation for a Strategy object. * */ public class SwingStrategyUI extends AbstractStrategyUI { protected static final Logger logger = Logger.getLogger(SwingStrategyUI.class); protected Map<String, SwingWidget<?>> swingWidgetMap; protected Map<String, SwingWidget<?>> swingWidgetWithParameterMap; private JPanel parentComponent; protected List<SwingStateListener> stateListenerList; protected Map<SwingWidget<?>, Set<SwingStateListener>> widgetStateListenerMap; protected Map<String, ButtonGroup> radioGroupMap; private SwingStrategyPanelFactory strategyPanelFactory = new SwingStrategyPanelFactory(); /* * (non-Javadoc) * * @see org.atdl4j.ui.StrategyUI#relayoutCollapsibleStrategyPanels() */ @Override public void relayoutCollapsibleStrategyPanels() { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#buildAtdl4jWidgetMap(java.util.List) */ @Override protected void buildAtdl4jWidgetMap(List<StrategyPanelT> aStrategyPanelList) throws FIXatdlFormatException { parentComponent.setLayout(new GridBagLayout()); GridBagConstraints gc = new GridBagConstraints(); gc.gridx = 0; int row = 0; JPanel tmp = new JPanel(); Map<String, SwingWidget< ? >> tempSwingWidgetMap = new HashMap<String, SwingWidget< ? >>(); // build panels and widgets recursively for (StrategyPanelT panel : aStrategyPanelList) { Map<String, SwingWidget< ? >> strategyPanelAndWidgets = strategyPanelFactory .createStrategyPanelAndWidgets(tmp, panel, getParameterMap(), 0, getAtdl4jWidgetFactory()); tempSwingWidgetMap.putAll(strategyPanelAndWidgets); JPanel container = strategyPanelFactory.createStrategyPanel(new JPanel(new GridBagLayout()), panel, 0, strategyPanelAndWidgets, 0); gc.gridy = row; gc.weightx = 1; gc.fill = GridBagConstraints.HORIZONTAL; gc.gridwidth = GridBagConstraints.REMAINDER; parentComponent.add(container, gc); row++; } swingWidgetMap = tempSwingWidgetMap; } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#getAtdl4jWidgetMap() */ @Override public Map<String, Atdl4jWidget<?>> getAtdl4jWidgetMap() { if ( swingWidgetMap != null ) { return new HashMap<String, Atdl4jWidget<?>>( swingWidgetMap ); } else { return null; } } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#getAtdl4jWidgetWithParameterMap() */ @Override public Map<String, Atdl4jWidget<?>> getAtdl4jWidgetWithParameterMap() { if ( swingWidgetWithParameterMap != null ) { return new HashMap<String, Atdl4jWidget<?>>( swingWidgetWithParameterMap ); } else { return null; } } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#initBegin(java.lang.Object) */ @Override protected void initBegin(Object parentContainer) { parentComponent = (JPanel) parentContainer; swingWidgetWithParameterMap = new HashMap<String, SwingWidget<?>>(); widgetStateListenerMap = new HashMap<SwingWidget<?>, Set<SwingStateListener>>(); } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#buildAtdl4jWidgetMap() */ @Override protected void buildAtdl4jWidgetMap() throws FIXatdlFormatException { if (getStrategy() == null) { throw new FIXatdlFormatException("getStrategy() was null."); } if (getStrategy().getStrategyLayout() == null) { throw new FIXatdlFormatException("getStrategy().getStrategyLayout() was null (verify <lay:StrategyLayout>)"); } if (getStrategy().getStrategyLayout() == null) { throw new FIXatdlFormatException("getStrategy().getStrategyLayout().getStrategyPanel() was null (verify <lay:StrategyLayout> <lay:StrategyPanel>)"); } buildAtdl4jWidgetMap(getStrategy().getStrategyLayout().getStrategyPanel()); } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#createRadioGroups() */ @Override protected void createRadioGroups() { Map<String, ButtonGroup> tempRadioGroupMap = new HashMap<String, ButtonGroup>(); for ( SwingWidget<?> widget : swingWidgetMap.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 ButtonGroup() ); if ( widget instanceof SwingButtonWidget ) { tempRadioGroupMap.get( rg ).add(((SwingButtonWidget) widget).getButton() ); } } } radioGroupMap = tempRadioGroupMap; } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#buildAtdl4jWidgetWithParameterMap() */ @Override protected void buildAtdl4jWidgetWithParameterMap() { Map<String, SwingWidget<?>> tempSwingWidgetWithParameterMap = new HashMap<String, SwingWidget<?>>(); // loop through all UI controls for ( SwingWidget<?> widget : swingWidgetMap.values() ) { if ( widget.getParameter() != null ) { // validate that a parameter is not being added twice String tempParameterName = widget.getParameter().getName(); if ( tempSwingWidgetWithParameterMap.containsKey( tempParameterName ) ) { throw new IllegalStateException( "Cannot add parameter \"" + tempParameterName + "\" to two separate controls." ); } tempSwingWidgetWithParameterMap.put( tempParameterName, widget ); } } swingWidgetWithParameterMap = tempSwingWidgetWithParameterMap; } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#attachGlobalStateRulesToControls() */ @Override protected void attachGlobalStateRulesToControls() throws FIXatdlFormatException { List<SwingStateListener> tempStateListenerList = new Vector<SwingStateListener>(); // loop through all UI controls for ( SwingWidget<?> widget : swingWidgetMap.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() ) { SwingWidget<?> affectedWidget = swingWidgetMap.get( control.getID() ); SwingStateListener stateListener = new SwingStateListener( affectedWidget, stateRule, swingWidgetMap, 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(); } } } stateListenerList = tempStateListenerList; } private void attachRuleToControls(ValidationRule rule, SwingStateListener 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, SwingStateListener stateRuleListener) { if ( field != null ) { SwingWidget<?> targetParameterWidget = swingWidgetMap.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 ( SwingWidget<?> widget : swingWidgetMap.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 ); } } } } } private void putStateListener(SwingWidget<?> widget, SwingStateListener stateListener) { if ( !widgetStateListenerMap.containsKey( widget ) ) widgetStateListenerMap.put( widget, new HashSet<SwingStateListener>() ); if ( !widgetStateListenerMap.get( widget ).contains( stateListener ) ) widgetStateListenerMap.get( widget ).add( stateListener ); } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#attachStateListenersToAllAtdl4jWidgets() */ @Override protected void attachStateListenersToAllAtdl4jWidgets() { for ( Entry<SwingWidget<?>, Set<SwingStateListener>> entry : widgetStateListenerMap.entrySet() ) { for ( SwingStateListener listener : entry.getValue() ) entry.getKey().addListener( listener ); } } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#initEnd() */ @Override protected void initEnd() { } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#addToAtdl4jWidgetMap(java.lang.String, org.atdl4j.ui.Atdl4jWidget) */ @Override protected void addToAtdl4jWidgetMap(String aName, Atdl4jWidget<?> aAtdl4jWidget) { swingWidgetMap.put(aName, (SwingWidget<?>)aAtdl4jWidget); } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#addToAtdl4jWidgetWithParameterMap(java.lang.String, * org.atdl4j.ui.Atdl4jWidget) */ @Override protected void addToAtdl4jWidgetWithParameterMap(String aName, Atdl4jWidget<?> aAtdl4jWidget) { swingWidgetWithParameterMap.put(aName, (SwingWidget<?>)aAtdl4jWidget); } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#removeFromAtdl4jWidgetMap(java.lang.String) */ @Override protected void removeFromAtdl4jWidgetMap(String aName) { swingWidgetMap.remove(aName); } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#removeFromAtdl4jWidgetWithParameterMap(java.lang.String) */ @Override protected void removeFromAtdl4jWidgetWithParameterMap(String aName) { swingWidgetWithParameterMap.remove(aName); } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#setCxlReplaceMode(boolean) */ @Override public void setCxlReplaceMode(boolean cxlReplaceMode) { // enable/disable non-mutable parameters for ( SwingWidget<?> widget : swingWidgetWithParameterMap.values() ) { if ( !widget.getParameter().isMutableOnCxlRpl() ){ widget.setEnabled( !cxlReplaceMode ); } } // set all CxlRpl on all state listeners and fire // once for good measure for ( SwingStateListener stateListener : stateListenerList ) { stateListener.setCxlReplaceMode( cxlReplaceMode ); stateListener.handleEvent(); } } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#fireStateListeners() */ @Override protected void fireStateListeners() { // fire state listeners once for good measure for ( SwingStateListener stateListener : stateListenerList ) stateListener.handleEvent(); } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#fireStateListenersForAtdl4jWidget(org.atdl4j.ui.Atdl4jWidget) */ @Override protected void fireStateListenersForAtdl4jWidget(Atdl4jWidget<?> aAtdl4jWidget) { for ( SwingStateListener stateListener : stateListenerList ) { if ( aAtdl4jWidget.equals( stateListener.getAffectedWidget() ) ) { stateListener.handleEvent(); } } } /* * (non-Javadoc) * * @see * org.atdl4j.ui.impl.AbstractStrategyUI#fireLoadFixMessageStateListenersForAtdl4jWidget(org.atdl4j.ui.Atdl4jWidget) */ @Override protected void fireLoadFixMessageStateListenersForAtdl4jWidget(Atdl4jWidget<?> aAtdl4jWidget) { for ( SwingStateListener stateListener : stateListenerList ) { if ( aAtdl4jWidget.equals( stateListener.getAffectedWidget() ) ) { stateListener.handleLoadFixMessageEvent(); } } } /* * (non-Javadoc) * * @see org.atdl4j.ui.impl.AbstractStrategyUI#applyRadioGroupRules() */ @Override protected void applyRadioGroupRules() { if ( radioGroupMap != null ) { for ( ButtonGroup tempSwingRadioButtonListener : radioGroupMap.values() ) { // -- If no RadioButtons within the radioGroup are selected, then first one in list will be selected -- if (tempSwingRadioButtonListener.getSelection() == null){ AbstractButton ab = tempSwingRadioButtonListener.getElements().nextElement(); if (ab != null) { ab.setSelected(true); } } } } } }