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;
017
018import com.github.gwtbootstrap.client.ui.base.DivWidget;
019import com.github.gwtbootstrap.client.ui.constants.Constants;
020import com.github.gwtbootstrap.client.ui.constants.NavbarConstants;
021import com.github.gwtbootstrap.client.ui.constants.NavbarPosition;
022import com.google.gwt.dom.client.Document;
023import com.google.gwt.user.client.Element;
024import com.google.gwt.user.client.ui.RootPanel;
025import com.google.gwt.user.client.ui.Widget;
026
027//@formatter:off
028
029/**
030 * Navbar with optional text, links and forms.
031 * <p>
032 * The Navbar can be fixed on the top or bottom of the site where it will stay
033 * when the user scrolls the page. For proper rendering, a fixed Navbar cannot
034 * be part of any container! It has to be attached directly to the
035 * {@link RootPanel}.
036 * <p/>
037 * <p>
038 * <h3>UiBinder Usage:</h3>
039 * <p/>
040 * <pre>
041 * {@code
042 * <g:FlowPanel>
043 *     <b:Navbar>
044 *         <b:Brand>Bootstrap</b:Brand>
045 *         <b:Nav>
046 *             <b:NavLink>Link 1</b:NavLink>
047 *             <b:NavLink>Link 2</b:NavLink>
048 *         </b:Nav>
049 *         <b:NavForm size="1" />
050 *         <b:Nav alignment="RIGHT">
051 *             <b:NavLink>Link 3</b:NavLink>
052 *         </b:Nav>
053 *     </b:Navbar>
054 *     <b:Container>
055 *         [...]
056 *     </b:Container>
057 * </g:FlowPanel>
058 *
059 * }
060 * </pre>
061 * </p>
062 *
063 * <b>NOTE</b>: We assume that most people will use the {@linkplain ResponsiveNavbar}, so, we automatically
064 * add a <code>padding-top: 50px</code> in <code>body</code>.If you don't want this, you have to put
065 * a <code>padding-top: 0px;</code> manually in your document <code>body</code> tag.
066 *
067 * @author Dominik Mayer
068 * @author Carlos Alexandro Becker
069 * @see <a href="http://getbootstrap.com/2.3.2/components.html#navbar">Bootstrap documentation</a>
070 * @see ResponsiveNavbar
071 * @since 2.0.4.0
072 */
073//@formatter:on
074public class Navbar extends DivWidget {
075
076        private class NavbarInner extends DivWidget {
077
078                public NavbarInner() {
079                        setStyleName(NavbarConstants.NAVBAR_INNER);
080                }
081        }
082
083        private final Container container = getContainer();
084
085        private final NavbarInner navbarInner = new NavbarInner();
086
087        private Scrollspy spy;
088
089        private boolean scrollspy;
090
091        /**
092         * Creates an empty Navbar.
093         */
094        public Navbar() {
095                setStyleName(NavbarConstants.NAVBAR);
096                navbarInner.add(container);
097                super.add(navbarInner);
098                
099                setId(Document.get().createUniqueId());
100        }
101
102        public void setId(String id) {
103                getElement().setId(id);
104        }
105        
106        public String getId() {
107                return getElement().getId();
108        }
109
110        /**
111         * Defines the default container implementation. You can override this in a
112         * extended class if you want another implementation, like a
113         * {@link FluidContainer}.
114         */
115        protected Container getContainer() {
116                return new Container();
117        }
118
119        /**
120         * Defines whether the Navbar should contain a {@link Scrollspy}.
121         * 
122         * @param scrollspy
123         *            <code>true</code> to include a Scrollspy. Default:
124         *            <code>false</code>
125         */
126        public void setScrollspy(boolean scrollspy) {
127                this.scrollspy = scrollspy;
128                if(scrollspy) {
129                    spy = new Scrollspy(this);
130                }
131        }
132
133        /**
134         * Defines scrollspy target element.
135         * 
136         * @param spyElement
137         *            target element
138         */
139        public void setSpyElement(Element spyElement) {
140
141                assert spyElement != null;
142
143                if (spy == null)
144                        spy = new Scrollspy(this);
145
146                spy.setSpyElement(spyElement);
147                this.scrollspy = true;
148        }
149
150        @Override
151        protected void onAttach() {
152                super.onAttach();
153                if (spy == null)
154                        spy = new Scrollspy(this);
155
156                if (scrollspy) {
157                        spy.configure();
158                }
159                // TODO make a unconfigure feature.
160        }
161
162        /**
163         * Fix the Navbar at the top or bottom of the screen.
164         * <p/>
165         * For this to work properly, the Navbar must not be a child of a
166         * {@link Container}.
167         * 
168         * @param position
169         *            the position of the Navbar
170         */
171        public void setPosition(NavbarPosition position) {
172                for (NavbarPosition p : NavbarPosition.values()) {
173                        if (!p.get().isEmpty()) {
174                                removeStyleName(p.get());
175                        }
176                }
177                addStyle(position);
178        }
179
180        /**
181         * {@inheritDoc}
182         */
183        @Override
184        public void add(Widget child) {
185                container.add(child);
186        }
187
188        /**
189         * Adds a widget to the Navbar element, <b>not</b> the container.
190         * 
191         * @param widget
192         *            widget to add
193         */
194        protected void addWidget(Widget widget) {
195                super.add(widget);
196        }
197    public Scrollspy getSpy() {
198        return spy;
199    }
200    
201    /**
202     * Set inverse style.
203     * @param inverse true:set false:unset
204     */
205    public void setInverse(boolean inverse) {
206        setStyleName(Constants.NAVBAR_INVERSE , inverse);
207    }
208}