001package org.gwtbootstrap3.client.ui;
002
003/*
004 * #%L
005 * GwtBootstrap3
006 * %%
007 * Copyright (C) 2013 GwtBootstrap3
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import org.gwtbootstrap3.client.ui.constants.ColumnOffset;
024import org.gwtbootstrap3.client.ui.constants.ColumnPull;
025import org.gwtbootstrap3.client.ui.constants.ColumnPush;
026import org.gwtbootstrap3.client.ui.constants.ColumnSize;
027import org.gwtbootstrap3.client.ui.html.Div;
028
029import com.google.gwt.dom.client.Style;
030import com.google.gwt.uibinder.client.UiConstructor;
031import com.google.gwt.user.client.ui.Widget;
032
033/**
034 * A column of Bootstrap's fluid grid system.
035 *
036 * @author Sven Jacobs
037 * @author Joshua Godi
038 * @author Pontus Enmark
039 * @see Row
040 */
041public class Column extends Div {
042
043    private static final String SEPARATOR = "[, ]+";
044
045    /**
046     * Creates a column with one size, and with one or more additional widgets added.
047     * <p/>
048     * Additional sizes can be added with {@link #addSize(ColumnSize...)}.
049     * Additional widgets can be added with {@link #add(Widget)}.
050     *
051     * @param size         Size of column
052     * @param firstWidget  Widget to add
053     * @param otherWidgets Other widgets to add
054     */
055    public Column(final ColumnSize size, final Widget firstWidget, final Widget... otherWidgets) {
056        this(size);
057
058        add(firstWidget);
059        for (final Widget widget : otherWidgets) {
060            add(widget);
061        }
062    }
063
064    /**
065     * Creates column with one or more additional sizes.
066     * <p/>
067     * Additional sizes can be added with {@link #addSize(ColumnSize...)}
068     *
069     * @param firstSize  Size of column
070     * @param otherSizes Other sizes of column
071     * @see #addSize(ColumnSize...)
072     */
073    public Column(final ColumnSize firstSize, final ColumnSize... otherSizes) {
074        setSize(firstSize, otherSizes);
075    }
076
077    /**
078     * Convenience constructor for UiBinder to create a Column with one or more
079     * sizes.
080     * <p/>
081     * Size needs to be a space-separated String of {@link ColumnSize} enum
082     * names, e.g. "SM_3 LG_3"
083     *
084     * @param size Space-separated String of {@link ColumnSize}
085     * @see ColumnSize
086     */
087    @UiConstructor
088    public Column(final String size) {
089        setSize(size);
090    }
091
092    /**
093     * Adds one or more additional column sizes.
094     *
095     * @param firstSize  Column size
096     * @param otherSizes Additional column sizes
097     */
098    public void setSize(final ColumnSize firstSize, final ColumnSize... otherSizes) {
099        addEnumVarargsValues(new ColumnSize[]{firstSize}, ColumnSize.class, true);
100        addEnumVarargsValues(otherSizes, ColumnSize.class, false);
101    }
102
103    public void setSize(final String sizes) {
104        addEnumStringValues(sizes, ColumnSize.class, true);
105    }
106
107    public void addSize(final ColumnSize... sizes) {
108        addEnumVarargsValues(sizes, ColumnSize.class, false);
109    }
110
111    public void addSize(final String sizes) {
112        addEnumStringValues(sizes, ColumnSize.class, false);
113    }
114
115    public void setPull(final ColumnPull... pulls) {
116        addEnumVarargsValues(pulls, ColumnPull.class, true);
117    }
118
119    public void setPull(final String pulls) {
120        addEnumStringValues(pulls, ColumnPull.class, true);
121    }
122
123    public void addPull(final ColumnPull... pulls) {
124        addEnumVarargsValues(pulls, ColumnPull.class, false);
125    }
126
127    public void addPull(final String pulls) {
128        addEnumStringValues(pulls, ColumnPull.class, false);
129    }
130
131    public void setPush(final ColumnPush... pushes) {
132        addEnumVarargsValues(pushes, ColumnPush.class, true);
133    }
134
135    public void setPush(final String pushes) {
136        addEnumStringValues(pushes, ColumnPush.class, true);
137    }
138
139    public void addPush(final ColumnPush... pushes) {
140        addEnumVarargsValues(pushes, ColumnPush.class, false);
141    }
142
143    public void addPush(final String pushes) {
144        addEnumStringValues(pushes, ColumnPush.class, false);
145    }
146
147    public void setOffset(final ColumnOffset... offsets) {
148        addEnumVarargsValues(offsets, ColumnOffset.class, true);
149    }
150
151    public void setOffset(final String offsets) {
152        addEnumStringValues(offsets, ColumnOffset.class, true);
153    }
154
155    public void addOffset(final ColumnOffset... offsets) {
156        addEnumVarargsValues(offsets, ColumnOffset.class, false);
157    }
158
159    public void addOffset(final String offsets) {
160        addEnumStringValues(offsets, ColumnOffset.class, false);
161    }
162
163    private <E extends Enum<? extends Style.HasCssName>> void addEnumVarargsValues(final E[] values,
164                                                                                   final Class<E> enumClass,
165                                                                                   final boolean clearOld) {
166        if (clearOld) {
167            // Remove the previous values
168            removeStyleNames(enumClass);
169        }
170
171        for (final E value : values) {
172            addStyleName(((Style.HasCssName) value).getCssName());
173        }
174    }
175
176    private <E extends Enum<? extends Style.HasCssName>> void addEnumStringValues(final String values,
177                                                                                  final Class<E> enumClass,
178                                                                                  final boolean clearOld) {
179        if (clearOld) {
180            // Remove the previous values
181            removeStyleNames(enumClass);
182        }
183
184        // Add new ones
185        final String[] valuesSplit = values.split(SEPARATOR);
186        for (final String value : valuesSplit) {
187            for (final E constant : enumClass.getEnumConstants()) {
188                if (value.equalsIgnoreCase(constant.name())) {
189                    addStyleName(((Style.HasCssName) constant).getCssName());
190                }
191            }
192        }
193    }
194
195    private <E extends Enum<? extends Style.HasCssName>> void removeStyleNames(final Class<E> enumClass) {
196        for (final E constant : enumClass.getEnumConstants()) {
197            removeStyleName(((Style.HasCssName) constant).getCssName());
198        }
199    }
200}