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     */
016    package com.github.gwtbootstrap.client.ui.base;
017    
018    import com.github.gwtbootstrap.client.ui.Close;
019    import com.github.gwtbootstrap.client.ui.constants.AlertType;
020    import com.github.gwtbootstrap.client.ui.constants.Constants;
021    import com.github.gwtbootstrap.client.ui.constants.DismissType;
022    import com.github.gwtbootstrap.client.ui.event.CloseEvent;
023    import com.github.gwtbootstrap.client.ui.event.CloseHandler;
024    import com.github.gwtbootstrap.client.ui.event.ClosedEvent;
025    import com.github.gwtbootstrap.client.ui.event.ClosedHandler;
026    import com.github.gwtbootstrap.client.ui.event.HasCloseHandlers;
027    import com.google.gwt.dom.client.Element;
028    import com.google.gwt.event.shared.HandlerRegistration;
029    import com.google.gwt.safehtml.shared.SafeHtmlUtils;
030    import com.google.gwt.user.client.ui.HTMLPanel;
031    import 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     */
045    public 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            setHandlerFunctions(getElement());
092        }
093    
094        /**
095         * Initializes an Alert of given Type with a close icon.
096         * 
097         * @param type
098         *            of the Alert
099         */
100        public AlertBase(AlertType type) {
101            this();
102            setType(type);
103        }
104    
105        /**
106         * Sets whether the Alert has a close icon or not.
107         * 
108         * @param hasClose
109         *            <code>false</code> if you don't want to have a close icon.
110         *            Default: <code>true</code>
111         */
112        public void setClose(boolean hasClose) {
113            
114            this.hasClose = hasClose;
115            
116            if(!isAttached()) {
117                return;
118            }
119            
120            if (hasClose) {
121                if(close == null) {
122                    close = new Close(DismissType.ALERT);
123                    getElement().replaceChild(close.getElement(), closeReplacement.getElement());
124                }
125            } else {
126                if (close != null) {
127                    getElement().replaceChild(closeReplacement.getElement(), close.getElement());
128                    close = null;
129                }
130            }
131        }
132        
133        /**
134         * {@inheritDoc}
135         */
136        @Override
137        protected void onAttach() {
138            super.onAttach();
139            setClose(hasClose);
140        }
141        
142        /**
143         * has Close
144         * @return true:has close false:does not has close
145         */
146        public boolean hasClose() {
147            return hasClose;
148        }
149    
150    
151        /**
152         * Gets heading's container widget
153         * @return heading's container
154         */
155        protected HasWidgets getHeadingContainer() {
156            return headingContainer;
157        }
158    
159        /**
160         * This method is called immediately when the widget's close method is
161         * executed.
162         */
163        protected void onClose() {
164            fireEvent(new CloseEvent());
165        }
166    
167        /**
168         * This method is called once the widget is completely closed.
169         */
170        protected void onClosed() {
171            fireEvent(new ClosedEvent());
172        }
173    
174        /**
175         * Sets the type of the Alert.
176         * 
177         * @param type
178         */
179        public void setType(AlertType type) {
180            StyleHelper.changeStyle(this, type, AlertType.class);
181        }
182    
183        /**
184         * Sets the text of an optional heading. The implementation depends on the
185         * subclass.
186         * 
187         * @param text
188         *            the new heading
189         */
190        public void setHeading(String text) {
191            headingContainer.clear();
192            headingContainer.add(new HTMLPanel("span", text));
193        }
194    
195        /**
196         * Sets whether the Alert should be animated.
197         * 
198         * @param animated
199         *            <code>true</code> if the Alert should fade out. Default:
200         *            <code>false</code>
201         */
202        public void setAnimation(boolean animated) {
203            this.fade = animated;
204            setFade();
205        }
206    
207        /**
208         * {@inheritDoc}
209         */
210        public boolean getAnimation() {
211            return fade;
212        }
213    
214        /**
215         * Delete the whole content of the Alert. This includes text, heading and
216         * close icon.
217         */
218        @Override
219        public void clear() {
220            container.clear();
221        }
222    
223        /**
224         * Sets the classes that define whether the Alert fades or not.
225         */
226        private void setFade() {
227            if (fade) {
228                addStyleName("fade");
229                addStyleName("in");
230            } else {
231                removeStyleName("fade");
232                removeStyleName("in");
233            }
234        }
235    
236        /**
237         * {@inheritDoc}
238         */
239        public String getText() {
240            return container.getElement().getInnerText();
241        }
242    
243        /**
244         * {@inheritDoc}
245         */
246        public void setText(String text) {
247            setHTML(SafeHtmlUtils.htmlEscape(text));
248        }
249    
250        /**
251         * {@inheritDoc}
252         */
253        public String getHTML() {
254            return container.getElement().getInnerHTML();
255        }
256    
257        public void setHTML(String html) {
258            container.clear();
259            container.add(new HTMLPanel("span" , html));
260        }
261    
262        /**
263         * Close this alert.
264         */
265        public void close() {
266            close(getElement());
267        }
268    
269        /**
270         * {@inheritDoc}
271         */
272        @Override
273        protected void onLoad() {
274            super.onLoad();
275            configure(getElement());
276        }
277    
278        /**
279         * {@inheritDoc}
280         */
281        public HandlerRegistration addCloseHandler(CloseHandler handler) {
282            return addHandler(handler, CloseEvent.getType());
283        }
284    
285        /**
286         * {@inheritDoc}
287         */
288        public HandlerRegistration addClosedHandler(ClosedHandler handler) {
289            return addHandler(handler, ClosedEvent.getType());
290        }
291        
292        //@formatter:off
293        /**
294         * Adds the Java functions that fire the Events to document. It is a
295         * convenience method to have a cleaner code later on.
296         */
297        private native void setHandlerFunctions(Element e) /*-{
298            var that = this;
299            $wnd
300                    .jQuery(e)
301                    .bind(
302                            'close',
303                            function() {
304                                [email protected]::onClose()();
305                            });
306            $wnd
307                    .jQuery(e)
308                    .bind(
309                            'closed',
310                            function() {
311                                [email protected]::onClosed()();
312                            });
313        }-*/;
314    
315        private native void configure(Element e) /*-{
316            $wnd.jQuery(e).alert(e);
317        }-*/;
318    
319        private native void close(Element e)/*-{
320            $wnd.jQuery(e).alert('close');
321        }-*/;
322        //@formatter:on
323    
324    }