001/*
002 * #%L
003 * GwtMaterial
004 * %%
005 * Copyright (C) 2015 - 2017 GwtMaterialDesign
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 * 
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 * 
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package gwt.material.design.client.ui;
021
022import com.google.gwt.dom.client.Style;
023import com.google.gwt.user.client.ui.Panel;
024import com.google.gwt.user.client.ui.RootPanel;
025import gwt.material.design.client.constants.CssName;
026import gwt.material.design.client.constants.LoaderType;
027import gwt.material.design.client.constants.SpinnerColor;
028import gwt.material.design.client.ui.html.Div;
029
030//@formatter:off
031
032/**
033 * <p>If you have content that will take a long time to load, you should give the user feedback. For this reason we provide a number activity + progress indicators.</p>
034 * <h3>Java Usage:</h3>
035 *
036 * <pre>
037 * {@code
038 *
039 * // FOR CIRCULAR LOADER
040 * MaterialLoader.showLoading(true);
041 * // FOR PROGRESS LOADER
042 * MaterialLoader.showProgress(true);
043 *
044 * // INSTANTIATE THE LOADER COMPONENT
045 * MaterialLoader loader = new MaterialLoader();
046 * loader.setContainer(target);
047 * loader.setType(LoaderType.CIRCULAR);
048 * loader.setScrollDisabled(true);
049 * loader.show();
050 * Timer t = new Timer()
051 * { @Override
052 * public void run() {
053 * loader.hide();
054 * }
055 * };
056 * t.schedule(2000);
057 * }
058 * </pre>
059 *
060 * @author kevzlou7979
061 * @author Ben Dol
062 *
063 * @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#loader">Material Loaders</a>
064 * @see <a href="https://material.io/guidelines/components/progress-activity.html">Material Design Specification</a>
065 * }
066 */
067//@formatter:on
068public class MaterialLoader {
069
070    private static MaterialLoader loader = new MaterialLoader(LoaderType.CIRCULAR);
071
072    private boolean scrollDisabled;
073    private Div div = new Div();
074    private MaterialPreLoader preLoader = new MaterialPreLoader();
075    private MaterialProgress progress = new MaterialProgress();
076    private Panel container = RootPanel.get();
077    private LoaderType type = LoaderType.CIRCULAR;
078
079    public MaterialLoader(LoaderType type) {
080        this();
081        setType(type);
082    }
083
084    public MaterialLoader() {
085        build();
086    }
087
088    protected void build() {
089        div.setStyleName(CssName.VALIGN_WRAPPER + " " + CssName.LOADER_WRAPPER);
090        preLoader.getElement().getStyle().setProperty("margin", "auto");
091        preLoader.add(new MaterialSpinner(SpinnerColor.BLUE));
092        preLoader.add(new MaterialSpinner(SpinnerColor.RED));
093        preLoader.add(new MaterialSpinner(SpinnerColor.YELLOW));
094        preLoader.add(new MaterialSpinner(SpinnerColor.GREEN));
095    }
096
097    /**
098     * Shows the Loader component
099     */
100    public void show() {
101        if (!(container instanceof RootPanel)) {
102            container.getElement().getStyle().setPosition(Style.Position.RELATIVE);
103            div.getElement().getStyle().setPosition(Style.Position.ABSOLUTE);
104        }
105        if (scrollDisabled) {
106            RootPanel.get().getElement().getStyle().setOverflow(Style.Overflow.HIDDEN);
107        }
108        if (type == LoaderType.CIRCULAR) {
109            div.setStyleName(CssName.VALIGN_WRAPPER + " " + CssName.LOADER_WRAPPER);
110            div.add(preLoader);
111        } else if (type == LoaderType.PROGRESS) {
112            div.setStyleName(CssName.VALIGN_WRAPPER + " " + CssName.PROGRESS_WRAPPER);
113            progress.getElement().getStyle().setProperty("margin", "auto");
114            div.add(progress);
115        }
116        container.add(div);
117    }
118
119    /**
120     * Hides the Loader component
121     */
122    public void hide() {
123        div.removeFromParent();
124        if (scrollDisabled) {
125            RootPanel.get().getElement().getStyle().setOverflow(Style.Overflow.AUTO);
126        }
127        if (type == LoaderType.CIRCULAR) {
128            preLoader.removeFromParent();
129        } else if (type == LoaderType.PROGRESS) {
130            progress.removeFromParent();
131        }
132    }
133
134    /**
135     * Static helper class that shows / hides a circular loader
136     */
137    public static void loading(boolean visible) {
138        loading(visible, RootPanel.get());
139    }
140
141    /**
142     * Static helper class that shows / hides a circular loader within a container
143     */
144    public static void loading(boolean visible, Panel container) {
145        loader.setType(LoaderType.CIRCULAR);
146        loader.setContainer(container);
147        if (visible) {
148            loader.show();
149        } else {
150            loader.hide();
151        }
152    }
153
154    /**
155     * Static helper class that shows / hides a progress loader
156     */
157    public static void progress(boolean visible) {
158        progress(visible, RootPanel.get());
159    }
160
161    /**
162     * Static helper class that shows / hides a progress loader within a container
163     */
164    public static void progress(boolean visible, Panel container) {
165        loader.setType(LoaderType.PROGRESS);
166        loader.setContainer(container);
167        if (visible) {
168            loader.show();
169        } else {
170            loader.hide();
171        }
172    }
173
174    /**
175     * Get the type of the MaterialLoader (Default CIRCULAR)
176     */
177    public LoaderType getType() {
178        return type;
179    }
180
181    /**
182     * Set the type of the MaterialLoader
183     *
184     * @param type There are two types of Loader (CIRCULAR and PROGRESS)
185     */
186    public void setType(LoaderType type) {
187        this.type = type;
188    }
189
190    /**
191     * Get the Container that wraps the MaterialLoader (Default RootPanel)
192     */
193    public Panel getContainer() {
194        return container;
195    }
196
197    /**
198     * Set the Container of the MaterialLoader
199     */
200    public void setContainer(Panel container) {
201        this.container = container;
202    }
203
204    /**
205     * Get the value whether the scroll is enabled or disabled (Default false)
206     */
207    public boolean isScrollDisabled() {
208        return scrollDisabled;
209    }
210
211    /**
212     * Set whether the loader will allow a body scroll when it is shown
213     */
214    public void setScrollDisabled(boolean scrollDisabled) {
215        this.scrollDisabled = scrollDisabled;
216    }
217}