View Javadoc
1   /**
2    * This file Copyright (c) 2010-2014 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.ui.vaadin.gwt.client.form.widget;
35  
36  import info.magnolia.ui.vaadin.gwt.client.form.tab.widget.FormTabWidget;
37  import info.magnolia.ui.vaadin.gwt.client.tabsheet.event.ActiveTabChangedEvent;
38  import info.magnolia.ui.vaadin.gwt.client.tabsheet.event.TabSetChangedEvent;
39  import info.magnolia.ui.vaadin.gwt.client.tabsheet.tab.widget.MagnoliaTabWidget;
40  import info.magnolia.ui.vaadin.gwt.client.tabsheet.widget.MagnoliaTabSheetView;
41  
42  import java.util.ArrayList;
43  import java.util.List;
44  
45  import com.google.gwt.event.dom.client.ClickEvent;
46  import com.google.gwt.event.dom.client.ClickHandler;
47  import com.google.gwt.event.dom.client.FocusEvent;
48  import com.google.gwt.event.dom.client.FocusHandler;
49  import com.google.gwt.user.client.DOM;
50  import com.google.gwt.user.client.Element;
51  import com.google.gwt.user.client.Event;
52  import com.google.gwt.user.client.ui.FlowPanel;
53  import com.google.gwt.user.client.ui.HTML;
54  import com.google.gwt.user.client.ui.Widget;
55  import com.vaadin.client.Util;
56  
57  /**
58   * Actual client side implementation of the form view. Provides the methods for
59   * the client side presenter {@link com.vaadin.client.ui.form.FormConnector}.
60   */
61  public class FormViewImpl extends FlowPanel implements FormView {
62  
63      private static final String CLASSNAME = "form-panel";
64  
65      private static final String CLASSNAME_CONTENT = "form-content";
66  
67      private static final String ClASSNAME_ERROR = "form-error";
68  
69      private final List<FormTabWidget> formTabs = new ArrayList<FormTabWidget>();
70  
71      private final Element contentEl = DOM.createDiv();
72  
73      private FormFieldWrapper lastFocused = null;
74  
75      private MagnoliaTabSheetView tabSheet;
76  
77      private Presenter presenter;
78  
79      private boolean hasErrors = false;
80  
81      private FlowPanel errorPanel = new FlowPanel();
82  
83      private String errorsLabel;
84  
85      private String nextErrorLabel;
86  
87      public FormViewImpl() {
88          super();
89          setStylePrimaryName(CLASSNAME);
90  
91          errorPanel.addStyleName(ClASSNAME_ERROR);
92          errorPanel.setVisible(false);
93          add(errorPanel);
94  
95          contentEl.addClassName(CLASSNAME_CONTENT);
96          getElement().appendChild(contentEl);
97      }
98  
99      @Override
100     public void setContent(Widget contentWidget) {
101         if (contentWidget instanceof MagnoliaTabSheetView) {
102             if (tabSheet != null) {
103                 remove(tabSheet);
104             }
105 
106             this.tabSheet = (MagnoliaTabSheetView) contentWidget;
107             tabSheet.addTabSetChangedHandler(new TabSetChangedEvent.Handler() {
108                 @Override
109                 public void onTabSetChanged(TabSetChangedEvent event) {
110                     final List<MagnoliaTabWidget> tabs = event.getTabSheet().getTabs();
111                     formTabs.clear();
112                     for (final MagnoliaTabWidget tab : tabs) {
113                         if (tab instanceof FormTabWidget) {
114                             formTabs.add((FormTabWidget) tab);
115                         }
116                     }
117                 }
118             });
119 
120             tabSheet.addActiveTabChangedHandler(new ActiveTabChangedEvent.Handler() {
121                 @Override
122                 public void onActiveTabChanged(ActiveTabChangedEvent event) {
123                     // Focus the first field on the form of the current tab.
124                     if (!hasErrors){
125                         if (!event.isShowingAllTabs()) {
126                             focusFirstFieldInTab((FormTabWidget) event.getTab());
127                         } else {
128                             focusFirstFieldInTab(formTabs.get(0));
129                         }
130                     }
131 
132                     // Keep track of last focused field by adding focus handlers to every field.
133                     lastFocused = null;
134                     if (!event.isShowingAllTabs()) {
135                         setFieldFocusHandler((FormTabWidget) event.getTab());
136                     } else {
137                         for (FormTabWidget tab : formTabs) {
138                             setFieldFocusHandler(tab);
139                         }
140                     }
141                 }
142 
143                 private void focusFirstFieldInTab(FormTabWidget tab){
144                     FormFieldWrapper firstField = tab.getFields().get(0);
145                     firstField.focusField();
146                 }
147 
148                 private void setFieldFocusHandler(FormTabWidget tab) {
149                     final List<FormFieldWrapper> fields = tab.getFields();
150                     for (final FormFieldWrapper field : fields) {
151                         field.addFocusHandler(new FocusHandler() {
152                             @Override
153                             public void onFocus(FocusEvent event) {
154                                 final Element target = event.getRelativeElement().cast();
155                                 lastFocused = Util.findWidget(target, FormFieldWrapper.class);
156                             }
157                         });
158                     }
159                 }
160             });
161             add(tabSheet.asWidget(), contentEl);
162         }
163     }
164 
165     @Override
166     public void setErrorsLabel(String errorsLabel) {
167         this.errorsLabel = errorsLabel;
168     }
169 
170     @Override
171     public void setNextErrorLabel(String nextErrorLabel) {
172         this.nextErrorLabel = nextErrorLabel;
173     }
174 
175     @Override
176     public void setErrorAmount(int totalProblematicFields) {
177         hasErrors = (totalProblematicFields > 0);
178 
179         errorPanel.setVisible(totalProblematicFields > 0);
180         if (totalProblematicFields > 0) {
181             String formattedTotal = String.valueOf(totalProblematicFields);
182             errorPanel.getElement().setInnerHTML("<span>" + errorsLabel.replaceFirst("#", formattedTotal) + "</span>");
183             final HTML errorButton = new HTML("[" + nextErrorLabel + "]");
184             errorButton.setStyleName("action-jump-to-next-error");
185             DOM.sinkEvents(errorButton.getElement(), Event.MOUSEEVENTS);
186             errorButton.addDomHandler(new ClickHandler() {
187                 @Override
188                 public void onClick(ClickEvent event) {
189                     jumpToNextError();
190                 }
191             }, ClickEvent.getType());
192             errorPanel.add(errorButton);
193         }
194     }
195 
196     @Override
197     public void setPresenter(final Presenter presenter) {
198         this.presenter = presenter;
199     }
200 
201     @Override
202     public void setDescriptionVisible(boolean isVisible) {
203         for (final FormTabWidget tab : formTabs) {
204             tab.setDescriptionVisible(isVisible);
205         }
206     }
207 
208     public void jumpToNextError() {
209         presenter.jumpToNextError(lastFocused);
210     }
211 
212     @Override
213     public void setMaxHeight(int height) {
214         this.tabSheet.setMaxHeight(height);
215     }
216 }