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