package org.atdl4j.ui.swing.impl; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.JLabel; import javax.swing.JPanel; import org.apache.log4j.Logger; import org.atdl4j.data.exception.FIXatdlFormatException; import org.atdl4j.fixatdl.core.ParameterT; import org.atdl4j.fixatdl.layout.ControlT; import org.atdl4j.fixatdl.layout.PanelOrientationT; import org.atdl4j.fixatdl.layout.StrategyPanelT; import org.atdl4j.ui.Atdl4jWidgetFactory; import org.atdl4j.ui.swing.SwingWidget; /** * * This class contains the data associated with the <code>SwingStrategyPanelFactory</code>. * * Creation date: (Oct 4, 2010 9:05:33 PM) * @author Scott Atwell */ public class SwingStrategyPanelFactory { protected static final Logger logger = Logger.getLogger( SwingStrategyPanelFactory.class ); private static SwingWidgetFactory swingWidgetFactory = new SwingWidgetFactory(); // Given a panel, recursively populates a map of Panels and Parameter widgets // Can also process options for a group frame instead of a single panel public Map<String, SwingWidget<?>> createStrategyPanelAndWidgets(JPanel parent, StrategyPanelT panel, Map<String, ParameterT> parameters, int style, Atdl4jWidgetFactory aAtdl4jWidgetFactory) throws FIXatdlFormatException { logger.debug( "createStrategyPanelAndWidgets(Composite parent, StrategyPanelT panel, Map<String, ParameterT> parameters, int style)" + " invoked with parms parent: " + parent + " panel: " + panel + " parameters: " + parameters + " style: " + style ); Map<String, SwingWidget<?>> controlWidgets = new HashMap<String, SwingWidget<?>>(); // -- Handles StrategyPanel's Collapsible, Title, Border, etc. Sets its layout and layoutData and data. -- JPanel c = SwingStrategyPanelHelper.createStrategyPanelContainer( panel, parent, style ); parent.add(c); if ( panel.getStrategyPanel().size() > 0 && panel.getControl().size() > 0 ) { // -- Wrap each Control with an auto-built StrategyPanel if setting is true -- if ( aAtdl4jWidgetFactory.getAtdl4jOptions().isAccommodateMixOfStrategyPanelsAndControls() ) { // -- FIXatdl 1.1 spec recommends against vs. prohibits. Mixed list may not be displayed 'in sequence' of file. -- logger.warn( "StrategyPanel contains both StrategyPanel (" + panel.getStrategyPanel().size() +") and Control ( " + panel.getControl().size() + " elements.\nSee Atdl4jOptions.setAccommodateMixOfStrategyPanelsAndControls() as potential work-around, though Controls will appear after StrategyPanels." ); StrategyPanelT tempPanel = new StrategyPanelT(); tempPanel.setCollapsible( Boolean.FALSE ); tempPanel.setCollapsed( Boolean.FALSE ); tempPanel.setOrientation( panel.getOrientation() ); tempPanel.setColor( panel.getColor() ); logger.warn( "Creating a StrategyPanel to contain " + panel.getControl().size() + " Controls." ); tempPanel.getControl().addAll( panel.getControl() ); panel.getControl().clear(); panel.getStrategyPanel().add( tempPanel ); } else { // 7/20/2010 -- original behavior: throw new FIXatdlFormatException( "StrategyPanel may not contain both StrategyPanel and Control elements." ); } } // build panels widgets recursively for ( StrategyPanelT p : panel.getStrategyPanel() ) { Map<String, SwingWidget<?>> widgets = createStrategyPanelAndWidgets( c, p, parameters, style, aAtdl4jWidgetFactory ); // check for duplicate IDs for ( String newID : widgets.keySet() ) { for ( String existingID : controlWidgets.keySet() ) { if ( newID.equals( existingID ) ) throw new FIXatdlFormatException( "Duplicate Control ID: \"" + newID + "\"" ); } } controlWidgets.putAll( widgets ); } // build control widgets recursively for ( ControlT control : panel.getControl() ) { ParameterT parameter = null; if ( control.getParameterRef() != null ) { parameter = parameters.get( control.getParameterRef() ); if ( parameter == null ) throw new FIXatdlFormatException( "Cannot find Parameter \"" + control.getParameterRef() + "\" for Control ID: \"" + control.getID() + "\"" ); } SwingWidget<?> widget = swingWidgetFactory.createWidget( c, control, parameter, style, aAtdl4jWidgetFactory ); widget.setParentStrategyPanel( panel ); widget.setParent( c ); // check for duplicate Control IDs if ( control.getID() != null ) { // check for duplicate Control IDs for ( SwingWidget<?> w : controlWidgets.values() ) { if ( w.getControl().getID().equals( control.getID() ) ) throw new FIXatdlFormatException( "Duplicate Control ID: \"" + control.getID() + "\"" ); } controlWidgets.put( control.getID(), widget ); } else { throw new FIXatdlFormatException( "Control Type: \"" + control.getClass().getSimpleName() + "\" is missing ID" ); } } return controlWidgets; } /** * Display panel's children inside the given parent * @param parent * @param panel * @param parameters * @param style * @param aAtdl4jWidgetFactory * @param widgets * @param depth * @return * @throws FIXatdlFormatException */ public JPanel layoutStrategyPanel(JPanel parent, StrategyPanelT panel, int style, Map<String, SwingWidget< ? >> widgets, int depth, ConstraintsUpdater gcUpdater) throws FIXatdlFormatException { GridBagConstraints gc = new GridBagConstraints(); // Pre-requisite : Given StrategyPanelT parameter should contain // either child StrategyPanelTs OR child controls, not both int rowIndex = 0; // Call recursively on sub-panels for (StrategyPanelT sp : panel.getStrategyPanel()) { gc = gcUpdater.panel(rowIndex, gc); gc.weightx = 1; gc.weighty = 1; gc.fill = GridBagConstraints.BOTH; gc = gcUpdater.remainder(gc); // create a container JPanel c = SwingStrategyPanelHelper.createStrategyPanelContainer(sp, parent, style); c.setLayout(new GridBagLayout()); // recursive call JPanel childPanel = layoutStrategyPanel(c, sp, style, widgets, depth + 1, new ConstraintsUpdater(sp .getOrientation())); parent.add(childPanel, gc); rowIndex++; } gc = gcUpdater.size(1, gc); for (ControlT c : panel.getControl()) { gc = gcUpdater.panel(rowIndex, gc); if (logger.isDebugEnabled()) { logger.debug("Control :" + c.getLabel() + " rowIndex=" + rowIndex); } SwingWidget< ? > swingWidget = widgets.get(c.getID()); List< ? extends Component> brickComponents = swingWidget .getBrickComponents(); if (!brickComponents.isEmpty()) { gc.insets = new Insets(1, 2, 1, 3); gc = gcUpdater.fill(gc); int size = brickComponents.size(); int compIndex = 0; for (Component comp : brickComponents) { if (logger.isDebugEnabled()) { if (comp instanceof JLabel) { logger.debug("Label " + ((JLabel) comp).getText()); } } if (compIndex == (size - 1)) { // last component : use remainder space gc = gcUpdater.weight(1, gc); gc = gcUpdater.remainder(gc); } else { gc = gcUpdater.weight(0, gc); gc = gcUpdater.size(1, gc); } gc = gcUpdater.widget(compIndex, gc); parent.add(comp, gc); compIndex++; gc = gcUpdater.relative(gc); } rowIndex++; } } gc.fill = GridBagConstraints.BOTH; gc.weightx = 1; gc.weighty = 1; gc = gcUpdater.panel(rowIndex, gc); gc = gcUpdater.remainder(gc); parent.add(new JPanel(), gc); return parent; } public JPanel createStrategyPanel(JPanel parent, StrategyPanelT panel, int style, Map<String, SwingWidget< ? >> widgets, int depth) throws FIXatdlFormatException { return layoutStrategyPanel(parent, panel, style, widgets, depth, new ConstraintsUpdater(panel.getOrientation())); } static class ConstraintsUpdater { PanelOrientationT orientation; public ConstraintsUpdater(PanelOrientationT orientation) { super(); this.orientation = orientation; } public GridBagConstraints fill(GridBagConstraints gc) { if (orientation == PanelOrientationT.VERTICAL) { gc.fill = GridBagConstraints.HORIZONTAL; } else { gc.gridheight = GridBagConstraints.VERTICAL; } return gc; } public GridBagConstraints size(int i, GridBagConstraints gc) { if (orientation == PanelOrientationT.VERTICAL) { gc.gridwidth = i; } else { gc.gridheight = i; } return gc; } public GridBagConstraints remainder(GridBagConstraints gc) { if (orientation == PanelOrientationT.VERTICAL) { gc.gridwidth = GridBagConstraints.REMAINDER; } else { gc.gridheight = GridBagConstraints.REMAINDER; } return gc; } public GridBagConstraints weight(double w, GridBagConstraints gc) { if (orientation == PanelOrientationT.VERTICAL) { gc.weightx = w; } else { gc.weighty = w; } return gc; } public GridBagConstraints relative(GridBagConstraints gc) { if (orientation == PanelOrientationT.VERTICAL) { gc.gridy = GridBagConstraints.RELATIVE; } else { gc.gridx = GridBagConstraints.RELATIVE; } return gc; } GridBagConstraints panel(int i, GridBagConstraints gc) { if (orientation == PanelOrientationT.VERTICAL) { gc.gridy = i; } else { gc.gridx = i; } return gc; } GridBagConstraints widget(int i, GridBagConstraints gc) { if (orientation == PanelOrientationT.VERTICAL) { gc.gridx = i; } else { gc.gridy = i; } return gc; } } }