001/*
002 *  Copyright 2012 GWT-Bootstrap
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.github.gwtbootstrap.client.ui.base;
017
018import com.github.gwtbootstrap.client.ui.Close;
019import com.github.gwtbootstrap.client.ui.constants.AlertType;
020import com.github.gwtbootstrap.client.ui.constants.Constants;
021import com.github.gwtbootstrap.client.ui.constants.DismissType;
022import com.github.gwtbootstrap.client.ui.event.CloseEvent;
023import com.github.gwtbootstrap.client.ui.event.CloseHandler;
024import com.github.gwtbootstrap.client.ui.event.ClosedEvent;
025import com.github.gwtbootstrap.client.ui.event.ClosedHandler;
026import com.github.gwtbootstrap.client.ui.event.HasCloseHandlers;
027import com.google.gwt.dom.client.Element;
028import com.google.gwt.event.shared.HandlerRegistration;
029import com.google.gwt.safehtml.shared.SafeHtmlUtils;
030import com.google.gwt.user.client.ui.HTMLPanel;
031import com.google.gwt.user.client.ui.HasWidgets;
032
033/**
034 * Base class for Alert widgets.
035 * 
036 * @since 2.0.4.0
037 * 
038 * @author Dominik Mayer
039 * @author Carlos Alexandro Becker
040 * 
041 * @see <a
042 *      href="http://twitter.github.com/bootstrap/components.html#alerts">Bootstrap
043 *      documentation</a>
044 */
045public abstract class AlertBase extends HtmlWidget implements IsAnimated,
046        HasCloseHandlers, HasType<AlertType> {
047
048    private Close close;
049
050    private HTMLPanel closeReplacement = new HTMLPanel("span", "");
051
052    private HTMLPanel headingContainer = new HTMLPanel("span", "");
053
054    private HTMLPanel container;
055
056    private boolean fade;
057
058    private boolean hasClose;
059
060    /**
061     * Initializes an Alert with a close icon.
062     */
063    public AlertBase() {
064        this("", true);
065    }
066
067    /**
068     * Initializes an Alert with a inner HTML.
069     * @param html inner HTML
070     */
071    public AlertBase(String html) {
072        this(html, true);
073    }
074
075    /**
076     * Initializes an Alert with an optional close icon.
077     * 
078     * @param html inner HTML
079     * @param hasClose
080     *            whether the Alert should have a close icon.
081     */
082    public AlertBase(String html, boolean hasClose) {
083        super("div", "");
084
085        super.add(closeReplacement);
086        super.add(headingContainer);
087        container = new HTMLPanel("span",html);
088        super.add(container);
089        super.setStyleName(Constants.ALERT);
090        setClose(hasClose);
091    }
092
093    /**
094     * Initializes an Alert of given Type with a close icon.
095     * 
096     * @param type
097     *            of the Alert
098     */
099    public AlertBase(AlertType type) {
100        this();
101        setType(type);
102    }
103
104    /**
105     * Sets whether the Alert has a close icon or not.
106     * 
107     * @param hasClose
108     *            <code>false</code> if you don't want to have a close icon.
109     *            Default: <code>true</code>
110     */
111    public void setClose(boolean hasClose) {
112        
113        this.hasClose = hasClose;
114        
115        if(!isAttached()) {
116            return;
117        }
118        
119        if (hasClose) {
120            if(close == null) {
121                close = new Close(DismissType.ALERT);
122                getElement().replaceChild(close.getElement(), closeReplacement.getElement());
123            }
124        } else {
125            if (close != null) {
126                getElement().replaceChild(closeReplacement.getElement(), close.getElement());
127                close = null;
128            }
129        }
130    }
131    
132    /**
133     * {@inheritDoc}
134     */
135    @Override
136    protected void onAttach() {
137        super.onAttach();
138        setClose(hasClose);
139        configure(getElement());
140        setHandlerFunctions(getElement());
141    }
142    
143    /**
144     * has Close
145     * @return true:has close false:does not has close
146     */
147    public boolean hasClose() {
148        return hasClose;
149    }
150
151
152    /**
153     * Gets heading's container widget
154     * @return heading's container
155     */
156    protected HasWidgets getHeadingContainer() {
157        return headingContainer;
158    }
159
160    /**
161     * This method is called immediately when the widget's close method is
162     * executed.
163     */
164    protected void onClose() {
165        fireEvent(new CloseEvent());
166    }
167
168    /**
169     * This method is called once the widget is completely closed.
170     */
171    protected void onClosed() {
172        fireEvent(new ClosedEvent());
173    }
174
175    /**
176     * Sets the type of the Alert.
177     * 
178     * @param type
179     */
180    public void setType(AlertType type) {
181        StyleHelper.changeStyle(this, type, AlertType.class);
182    }
183
184    /**
185     * Sets the text of an optional heading. The implementation depends on the
186     * subclass.
187     * 
188     * @param text
189     *            the new heading
190     */
191    public void setHeading(String text) {
192        headingContainer.clear();
193        headingContainer.add(new HTMLPanel("span", text));
194    }
195
196    /**
197     * Sets whether the Alert should be animated.
198     * 
199     * @param animated
200     *            <code>true</code> if the Alert should fade out. Default:
201     *            <code>false</code>
202     */
203    public void setAnimation(boolean animated) {
204        this.fade = animated;
205        setFade();
206    }
207
208    /**
209     * {@inheritDoc}
210     */
211    public boolean getAnimation() {
212        return fade;
213    }
214
215    /**
216     * Delete the whole content of the Alert. This includes text, heading and
217     * close icon.
218     */
219    @Override
220    public void clear() {
221        container.clear();
222    }
223
224    /**
225     * Sets the classes that define whether the Alert fades or not.
226     */
227    private void setFade() {
228        if (fade) {
229            addStyleName("fade");
230            addStyleName("in");
231        } else {
232            removeStyleName("fade");
233            removeStyleName("in");
234        }
235    }
236
237    /**
238     * {@inheritDoc}
239     */
240    public String getText() {
241        return container.getElement().getInnerText();
242    }
243
244    /**
245     * {@inheritDoc}
246     */
247    public void setText(String text) {
248        setHTML(SafeHtmlUtils.htmlEscape(text));
249    }
250
251    /**
252     * {@inheritDoc}
253     */
254    public String getHTML() {
255        return container.getElement().getInnerHTML();
256    }
257
258    public void setHTML(String html) {
259        container.clear();
260        container.add(new HTMLPanel("span" , html));
261    }
262
263    /**
264     * Close this alert.
265     */
266    public void close() {
267        close(getElement());
268    }
269
270    /**
271     * {@inheritDoc}
272     */
273    public HandlerRegistration addCloseHandler(CloseHandler handler) {
274        
275        return addHandler(handler, CloseEvent.getType());
276    }
277
278    /**
279     * {@inheritDoc}
280     */
281    public HandlerRegistration addClosedHandler(ClosedHandler handler) {
282        return addHandler(handler, ClosedEvent.getType());
283    }
284    
285    //@formatter:off
286    /**
287     * Adds the Java functions that fire the Events to document. It is a
288     * convenience method to have a cleaner code later on.
289     */
290    private native void setHandlerFunctions(Element e) /*-{
291        var that = this;
292        $wnd
293                .jQuery(e)
294                .bind(
295                        'close',
296                        function() {
297                            [email protected]::onClose()();
298                        });
299        $wnd
300                .jQuery(e)
301                .bind(
302                        'closed',
303                        function() {
304                            [email protected]::onClosed()();
305                        });
306    }-*/;
307
308    private native void configure(Element e) /*-{
309        $wnd.jQuery(e).alert(e);
310    }-*/;
311
312    private native void close(Element e)/*-{
313        $wnd.jQuery(e).alert('close');
314    }-*/;
315    //@formatter:on
316
317}