001    package 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    
023    import org.gwtbootstrap3.client.ui.constants.ColumnOffset;
024    import org.gwtbootstrap3.client.ui.constants.ColumnPull;
025    import org.gwtbootstrap3.client.ui.constants.ColumnPush;
026    import org.gwtbootstrap3.client.ui.constants.ColumnSize;
027    import org.gwtbootstrap3.client.ui.html.Div;
028    
029    import com.google.gwt.dom.client.Style;
030    import com.google.gwt.uibinder.client.UiConstructor;
031    import 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     */
041    public 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    }