/**
* Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
*
* Project home : http://code.daikit.com/daikit4gxt
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.daikit.daikit4gxt.client.ui.forms;
import java.util.ArrayList;
import java.util.List;
import com.daikit.commons.shared.exception.DkUnsupportedMethodException;
import com.daikit.daikit4gxt.client.DkMain;
import com.daikit.daikit4gxt.client.log.BaseLogger;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.core.client.dom.ScrollSupport.ScrollMode;
import com.sencha.gxt.widget.core.client.Component;
import com.sencha.gxt.widget.core.client.container.Container;
import com.sencha.gxt.widget.core.client.container.FlowLayoutContainer;
import com.sencha.gxt.widget.core.client.container.MarginData;
import com.sencha.gxt.widget.core.client.event.AddEvent;
import com.sencha.gxt.widget.core.client.event.AddEvent.AddHandler;
import com.sencha.gxt.widget.core.client.form.FieldLabel;
import com.sencha.gxt.widget.core.client.form.FormPanel.LabelAlign;
/**
* A simple form panel
*
* @author tcaselli
* @version $Revision$ Last modifier: $Author$ Last commit: $Date$
*/
public class MyFixedFormPanel implements IsWidget
{
/**
* Default label align
*/
public final static LabelAlign DEFAULT_LABEL_ALIGN = LabelAlign.LEFT;
private final int marginVeryLeft = 8;
private final int marginVeryRight = 8;
private final int marginVeryTop = 8;
private final int marginBottom = 5;
private final int marginRight = 15;
private int labelWidth;
private int columnWidth;
private int columnWrapWidth;
private static final int x = 56;
private boolean scrollable = true;
private int originalTotalWidth;
private LabelAlign labelAlign;
private final FlowLayoutContainer widget;
private HorizontalPanel currentHorizontalPanel;
private int numberOfColumns = 1;
private final List<Component> formComponents = new ArrayList<Component>();
/**
* Constructor
*
* @param numberOfColumns
*/
public MyFixedFormPanel(final int numberOfColumns)
{
this(numberOfColumns, DkMain.config().getApplicationWidth());
}
/**
* Constructor
*
* @param numberOfColumns
* the number of columns
* @param totalWidth
* total panel width
*/
public MyFixedFormPanel(final int numberOfColumns, final int totalWidth)
{
widget = new FlowLayoutContainer();
widget.addStyleName("fill-this-background-color");
widget.setScrollMode(ScrollMode.AUTOY);
this.numberOfColumns = numberOfColumns;
labelWidth = numberOfColumns < 3 ? DkMain.config().getFormLabelWidth() : DkMain.config()
.getFormMoreThan3ColumnsLabelWidth();
labelAlign = DEFAULT_LABEL_ALIGN;
widget.addAddHandler(new ChangeLabelPropsAddHandler());
setWidth(totalWidth);
}
/**
* This method must only be called before adding any field to the form panel.
*
* @param totalWidth
* the total width
*/
public void setWidth(final int totalWidth)
{
if (widget.getWidgetCount() > 0)
{
throw new DkUnsupportedMethodException("This method must only be called before adding any field to the form panel.");
}
widget.setWidth(totalWidth);
this.columnWrapWidth = getWidthFor1Column(totalWidth);
this.columnWidth = numberOfColumns == 1 ? columnWrapWidth : getWidthForNColumns(totalWidth, numberOfColumns);
this.originalTotalWidth = totalWidth;
}
/**
* set to false if you are sure there will be no scroll bar to be displayed, default is false.
*
* @param scrollable
*/
public void setKeepScrollableWidth(final boolean scrollable)
{
this.scrollable = scrollable;
setWidth(originalTotalWidth);
}
private int getWidthFor1Column(final int totalWidth)
{
return totalWidth - x + (scrollable ? 0 : 25);
}
private int getWidthForNColumns(final int totalWidth, final int numberOfColumns)
{
return Double.valueOf(
getWidthFor1Column(totalWidth) / Double.valueOf(numberOfColumns) - marginRight / Double.valueOf(numberOfColumns))
.intValue();
}
@Override
public Widget asWidget()
{
return widget;
}
/**
* @return this popup as a {@link Component}
*/
public Component asComponent()
{
return widget;
}
private void createNewHorizontalPanel()
{
currentHorizontalPanel = new HorizontalPanel();
widget.add(currentHorizontalPanel, new MarginData(widget.getWidgetCount() == 0 ? marginVeryTop : 0, marginVeryRight, 0,
marginVeryLeft));
for (int i = 0; i < numberOfColumns; i++)
{
final FlowLayoutContainer column = new FlowLayoutContainer();
column.setWidth(columnWidth);
if (i < numberOfColumns - 1)
{
column.getElement().getStyle().setMarginRight(marginRight, Unit.PX);
}
currentHorizontalPanel.add(column);
column.addAddHandler(new ChangeLabelPropsAddHandler());
}
}
/**
* Set the same label width for all children {@link FieldLabel} no matter at which level of sub hierarchy they are
* added
*
* @author tcaselli
* @version $Revision$ Last modifier: $Author$ Last commit: $Date$
*/
private class ChangeLabelPropsAddHandler implements AddHandler
{
@Override
public void onAdd(final AddEvent event)
{
final Widget addedWidget = event.getWidget();
if (addedWidget instanceof FieldLabel)
{
final FieldLabel label = (FieldLabel) addedWidget;
if (labelWidth > 0)
{
label.setLabelWidth(labelWidth);
}
if (label.getWidget() instanceof Component)
{
final Component labeLWidget = (Component) label.getWidget();
labeLWidget.setWidth(columnWidth - labelWidth - label.getLabelPad());
}
label.setLabelAlign(labelAlign);
// final Widget widget = label.getWidget() ;
}
else if (addedWidget instanceof Container)
{
final Container container = (Container) addedWidget;
container.addAddHandler(new ChangeLabelPropsAddHandler());
}
}
}
/**
*
*/
public void addNewRow()
{
currentHorizontalPanel = null;
}
/**
* Add a child widget to this widget with custom margins
*
* @param component
*/
public void add(final Component component)
{
component.addStyleName("fixedform-component");
component.getElement().getStyle().setPosition(Position.RELATIVE);
currentHorizontalPanel = null;
component.setWidth(columnWrapWidth);
this.widget.add(component, new MarginData(widget.getWidgetCount() == 0 ? marginVeryTop : 0, marginVeryRight, marginBottom,
marginVeryLeft));
formComponents.add(component);
}
/**
* Add the given component in given column with no margin
*
* @param component
* the component to be added
* @param columnIndex
* starting from 0 and should be strictly less than this.numberOfColumns
*/
public void add(final Component component, final int columnIndex)
{
add(component, columnIndex, false);
}
/**
* Add the given component in given column
*
* @param component
* the component to be added
* @param columnIndex
* starting from 0 and should be strictly less than this.numberOfColumns
* @param addMargins
* to indicate whether to add margins or not
*/
public void add(final Component component, final int columnIndex, final boolean addMargins)
{
component.addStyleName("fixedform-component");
if (numberOfColumns > 1 && columnIndex >= 0 && columnIndex < numberOfColumns)
{
if (currentHorizontalPanel == null)
{
createNewHorizontalPanel();
}
final FlowLayoutContainer flc = (FlowLayoutContainer) currentHorizontalPanel.getWidget(columnIndex);
flc.add(component, addMargins ? new MarginData(widget.getWidgetCount() == 0 ? marginVeryTop : 0, 0, marginBottom, 0)
: null);
formComponents.add(component);
}
else if (numberOfColumns == 1 && columnIndex == 0)
{
add(component);
formComponents.add(component);
}
else
{
BaseLogger.error(getClass(), "inconsistency in number of column and given column index : numberOfColumns="
+ numberOfColumns + ", columnIndex=" + columnIndex);
}
}
/**
* @return the formComponents
*/
public List<Component> getFormComponents()
{
return formComponents;
}
/**
* @param labelWidth
* the labelWidth to set
*/
public void setLabelWidth(final int labelWidth)
{
this.labelWidth = labelWidth;
}
/**
*
* @param labelAlign
* the {@link LabelAlign}
*/
public void setLabelAlign(final LabelAlign labelAlign)
{
this.labelAlign = labelAlign;
}
}