comparison gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ModuleSelection.java @ 8870:c26fb37899ca

Introduced groups for modules. Modules marked with the same group-id, will be put together in the ui. Also using now the localization info from the server instead of localizing the modules again on the client side.
author gernotbelger
date Wed, 07 Feb 2018 11:59:13 +0100
parents 5e38e2924c07
children 60278b5fe4d9
comparison
equal deleted inserted replaced
8869:20b85ea3b524 8870:c26fb37899ca
6 * documentation coming with Dive4Elements River for details. 6 * documentation coming with Dive4Elements River for details.
7 */ 7 */
8 8
9 package org.dive4elements.river.client.client.ui; 9 package org.dive4elements.river.client.client.ui;
10 10
11 import com.google.gwt.core.client.GWT; 11 import java.util.Collection;
12 import com.google.gwt.user.client.rpc.AsyncCallback; 12 import java.util.HashMap;
13 13 import java.util.LinkedHashMap;
14 import com.smartgwt.client.types.VerticalAlignment; 14 import java.util.LinkedList;
15 import com.smartgwt.client.util.SC; 15 import java.util.List;
16 import com.smartgwt.client.widgets.Canvas; 16 import java.util.Map;
17 import com.smartgwt.client.widgets.Label; 17 import java.util.Map.Entry;
18 import com.smartgwt.client.widgets.form.DynamicForm;
19 import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
20 import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
21 import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
22 import com.smartgwt.client.widgets.layout.HLayout;
23 import com.smartgwt.client.widgets.layout.VLayout;
24 18
25 import org.dive4elements.river.client.client.Config; 19 import org.dive4elements.river.client.client.Config;
26 import org.dive4elements.river.client.client.FLYSConstants; 20 import org.dive4elements.river.client.client.FLYSConstants;
27 import org.dive4elements.river.client.client.services.ModuleService; 21 import org.dive4elements.river.client.client.services.ModuleService;
28 import org.dive4elements.river.client.client.services.ModuleServiceAsync; 22 import org.dive4elements.river.client.client.services.ModuleServiceAsync;
30 import org.dive4elements.river.client.shared.model.DataItem; 24 import org.dive4elements.river.client.shared.model.DataItem;
31 import org.dive4elements.river.client.shared.model.DataList; 25 import org.dive4elements.river.client.shared.model.DataList;
32 import org.dive4elements.river.client.shared.model.DefaultData; 26 import org.dive4elements.river.client.shared.model.DefaultData;
33 import org.dive4elements.river.client.shared.model.DefaultDataItem; 27 import org.dive4elements.river.client.shared.model.DefaultDataItem;
34 import org.dive4elements.river.client.shared.model.Module; 28 import org.dive4elements.river.client.shared.model.Module;
35 29 import org.dive4elements.river.client.shared.model.ModuleGroup;
36 import java.util.LinkedHashMap; 30
37 import java.util.List; 31 import com.google.gwt.core.client.GWT;
38 import java.util.Map; 32 import com.google.gwt.user.client.rpc.AsyncCallback;
33 import com.smartgwt.client.types.VerticalAlignment;
34 import com.smartgwt.client.util.SC;
35 import com.smartgwt.client.widgets.Canvas;
36 import com.smartgwt.client.widgets.Label;
37 import com.smartgwt.client.widgets.form.DynamicForm;
38 import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
39 import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
40 import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
41 import com.smartgwt.client.widgets.layout.HLayout;
42 import com.smartgwt.client.widgets.layout.LayoutSpacer;
43 import com.smartgwt.client.widgets.layout.VLayout;
39 44
40 /** 45 /**
41 * The ModuleSelection combines the river selection and the module selection in 46 * The ModuleSelection combines the river selection and the module selection in
42 * one widget. It will display a vertical splitted widget - the upper part will 47 * one widget. It will display a vertical splitted widget - the upper part will
43 * render checkboxes for each module, the lower one will display a combobox at 48 * render checkboxes for each module, the lower one will display a combobox at
48 public class ModuleSelection extends MapSelection { 53 public class ModuleSelection extends MapSelection {
49 54
50 private static final long serialVersionUID = -5634831815175543328L; 55 private static final long serialVersionUID = -5634831815175543328L;
51 56
52 /** The message class that provides i18n strings.*/ 57 /** The message class that provides i18n strings.*/
53 protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class); 58 private FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);
54
55 /** The module checkboxes.*/
56 protected static RadioGroupItem radio;
57
58 /** */
59 protected Module[] modules;
60 59
61 /** The ModuleService used to retrieve the available modules of a user.*/ 60 /** The ModuleService used to retrieve the available modules of a user.*/
62 protected ModuleServiceAsync moduleService = GWT.create( 61 private ModuleServiceAsync moduleService = GWT.create(ModuleService.class);
63 ModuleService.class); 62
64 63 private Map<String, List<String> > modulesRiverMap = new LinkedHashMap<String, List<String> >();
65 private Map<String, List<String> > modulesRiverMap; 64
66 protected Map<String, HLayout> rivers; 65 private Map<String, Module> modulesByName = new HashMap<String, Module>();
67 66
68 /** 67 private Map<ModuleGroup, List<Module>> modulesByGroup = new LinkedHashMap<ModuleGroup, List<Module>>();
69 * The default constructor. 68
70 */ 69 private Map<ModuleGroup, RadioGroupItem> groupToRadios = new LinkedHashMap<ModuleGroup, RadioGroupItem>();
70
71 private Map<ModuleGroup, Canvas> groupToCanvas = new LinkedHashMap<ModuleGroup, Canvas>();
72
73 private Map<String, HLayout> rivers = null;
74
75 private VLayout radioPanel;
76
77 /* TODO: seems that it needs to be static for the callback, is this really necessary?
78 * TODO: what happens if we have several 'new project' windows open in parallel?
79 * */
80 private static Module selectedModule = null;
81
71 public ModuleSelection() { 82 public ModuleSelection() {
72 rivers = null;
73 modulesRiverMap = new LinkedHashMap<String, List<String> >();
74
75 readModules(); 83 readModules();
76 } 84 }
77
78 85
79 /** 86 /**
80 * This method returns a widget that renders the checkboxes for each module 87 * This method returns a widget that renders the checkboxes for each module
81 * and the MapSelection that lets the user choose the river. 88 * and the MapSelection that lets the user choose the river.
82 * 89 *
112 } 119 }
113 120
114 @Override 121 @Override
115 public void onSuccess(Module[] newmodules) { 122 public void onSuccess(Module[] newmodules) {
116 GWT.log("Retrieved " + newmodules.length + " modules."); 123 GWT.log("Retrieved " + newmodules.length + " modules.");
117 modules = newmodules; 124 setModules(newmodules);
118 setModules(); 125 updateRadioPanels();
119 } 126 }
120 }); 127 });
121 } 128 }
122 129
130 // TODO: bad. Too much knowledge spread over the application.
131 // TODO: instead, e.g. use a controller that knows both (ModuleSelection and LinkSelection) and let him do this kind of things
123 private void checkRivers(String selected) { 132 private void checkRivers(String selected) {
124 if (selected == null) { 133 if (rivers == null || rivers.isEmpty() || /*modules == null || */ selected == null )
125 selected = getSelectedModule(); 134 return;
126 } 135
127 if (rivers != null 136 final List<String> allowedRivers = modulesRiverMap.get(selected);
128 && !rivers.isEmpty() 137 if ( allowedRivers == null )
129 && modules != null 138 GWT.log("No configured rivers for module: " + selected);
130 && selected != null 139
131 ) { 140 for (final Map.Entry<String, HLayout> s: rivers.entrySet()) {
132 List<String> allowedRivers = modulesRiverMap.get(selected); 141 if (allowedRivers == null || !allowedRivers.contains(s.getKey())) {
133 if ( allowedRivers == null ) { 142 s.getValue().hide();
134 GWT.log("No configured rivers for module: " + selected); 143 } else {
135 } 144 s.getValue().show();
136 for (Map.Entry<String, HLayout> s: rivers.entrySet()) { 145 }
137 if ( allowedRivers == null ) { 146 }
138 s.getValue().hide(); 147 }
139 continue; 148
140 } 149 protected final void setModules(Module[] newmodules) {
141 if (!allowedRivers.contains(s.getKey())) { 150 modulesRiverMap.clear();
142 s.getValue().hide(); 151
143 } else { 152 if( newmodules == null )
144 s.getValue().show(); 153 return;
145 } 154
146 } 155 for(final Module module : newmodules) {
147 } 156 final String name = module.getName();
148 } 157
149 158 /* remember rivers per module */
150 private void setModules() { 159 modulesRiverMap.put(name, module.getRivers());
151 LinkedHashMap<String, String> values = 160
152 new LinkedHashMap<String, String>(); 161 /* hash by name */
153 162 modulesByName.put(name, module);
154 if (this.modules!= null) { 163
155 for(Module module : this.modules) { 164 /* hash by group */
156 values.put(module.getName(), module.getLocalizedName()); 165 final ModuleGroup group = module.getGroup();
157 if (module.isSelected()) { 166 if( !modulesByGroup.containsKey( group ) )
158 GWT.log("Module " + module.getName() + " is selected."); 167 modulesByGroup.put(group, new LinkedList<Module>());
159 if (radio != null) { 168
160 radio.setDefaultValue(module.getName()); 169 final List<Module> modulesGroup = modulesByGroup.get(group);
161 } 170 modulesGroup.add(module);
162 } 171 }
163 modulesRiverMap.put(module.getName(), module.getRivers());
164 }
165 }
166 if (radio != null) {
167 radio.setValueMap(values);
168 }
169 checkRivers(null);
170 } 172 }
171 173
172 /** 174 /**
173 * Creates a widget that displays a checkbox for each module. 175 * Creates a widget that displays a checkbox for each module.
174 * 176 *
175 * @return a widget with checkboxes. 177 * @return a widget with checkboxes.
176 */ 178 */
177 protected Canvas createWidget() { 179 protected Canvas createWidget() {
178 HLayout layout = new HLayout(); 180
179 181 final HLayout layout = new HLayout();
180 Label label = new Label(MESSAGES.module_selection()); 182
181 DynamicForm form = new DynamicForm(); 183 radioPanel = new VLayout();
182 184
183 radio = new RadioGroupItem("plugin"); 185 final Label label = new Label(MESSAGES.module_selection());
184 radio.addChangeHandler(new ChangeHandler() {
185 @Override
186 public void onChange(ChangeEvent event) {
187 checkRivers((String)event.getValue());
188 }
189 });
190
191 label.setWidth(50); 186 label.setWidth(50);
192 label.setHeight(25); 187 label.setHeight(25);
193 188
194
195 radio.setShowTitle(false);
196 radio.setVertical(true);
197
198 setModules();
199
200 form.setFields(radio);
201
202 layout.addMember(label); 189 layout.addMember(label);
203 layout.addMember(form); 190 layout.addMember(radioPanel);
204 191
192 updateRadioPanels();
193
205 return layout; 194 return layout;
206 } 195 }
207 196
197 protected final void updateRadioPanels() {
198
199 /* first clear existing panels, if any exist */
200 final Collection<Canvas> oldforms = groupToCanvas.values();
201 for (Canvas oldCanvas : oldforms) {
202 radioPanel.removeMember(oldCanvas);
203 oldCanvas.destroy();
204 }
205
206 groupToCanvas.clear();
207 groupToRadios.clear();
208 selectedModule = null;
209
210 if( radioPanel == null )
211 return;
212
213 /* now create radio items per group */
214 int count = 0;
215 for (final Entry<ModuleGroup, List<Module>> groupEntry : modulesByGroup.entrySet()) {
216
217 final ModuleGroup group = groupEntry.getKey();
218 final List<Module> groupModule = groupEntry.getValue();
219
220 final HLayout groupPanel = new HLayout();
221
222 if( group.showGroupFrame() )
223 {
224 final LayoutSpacer spacer = new LayoutSpacer();
225 spacer.setWidth(25);
226 groupPanel.addMember(spacer);
227
228 final Label label = new Label(group.toString());
229 label.setWidth(25);
230 label.setHeight(25);
231 groupPanel.addMember(label);
232 }
233
234 final DynamicForm groupForm = new DynamicForm();
235
236 final RadioGroupItem moduleRadio = new RadioGroupItem("modulegroup" + count++);
237 moduleRadio.setShowTitle(false);
238 moduleRadio.setVertical(true);
239
240 moduleRadio.addChangeHandler(new ChangeHandler() {
241 @Override
242 public void onChange(ChangeEvent event) {
243 final String selectedModuleName = (String) event.getValue();
244 handleModuleSelected(selectedModuleName);
245 }
246 });
247
248 groupForm.setItems(moduleRadio);
249 groupPanel.addMember(groupForm);
250
251 final LinkedHashMap<String, String> values = new LinkedHashMap<String, String>();
252 for(final Module module : groupModule) {
253 values.put(module.getName(), module.getLocalizedName());
254 if (module.isSelected()) {
255 GWT.log("Module " + module.getName() + " is selected.");
256 selectedModule = module;
257 moduleRadio.setValue(module.getName());
258 }
259 }
260
261 this.groupToRadios.put( group, moduleRadio );
262 this.groupToCanvas.put( group, groupPanel );
263
264 moduleRadio.setValueMap(values);
265
266
267 radioPanel.addMember(groupPanel);
268 }
269
270 checkRivers(getSelectedModule());
271 }
272
273 protected void handleModuleSelected(final String selectedModuleName) {
274
275 /* remember selected module for later */
276 selectedModule = modulesByName.get(selectedModuleName);
277
278 /* because radios might in different radio-groups, we need to de-select them manually */
279 final ModuleGroup group = selectedModule.getGroup();
280
281 for (final Entry<ModuleGroup, RadioGroupItem> entry : groupToRadios.entrySet()) {
282 final ModuleGroup radioGroup = entry.getKey();
283
284 if( !group.equals(radioGroup))
285 {
286 final RadioGroupItem groupRadio = entry.getValue();
287 groupRadio.setValue((String)null);
288 }
289 }
290
291 checkRivers(selectedModuleName);
292 }
208 293
209 /** 294 /**
210 * This method prepares the data of two widgets - the module selection and 295 * This method prepares the data of two widgets - the module selection and
211 * the river selection. The returning field will contain the Data that 296 * the river selection. The returning field will contain the Data that
212 * represents the module selection at first position, the second position 297 * represents the module selection at first position, the second position
215 * @return the Data that was chosen in this widget. 300 * @return the Data that was chosen in this widget.
216 */ 301 */
217 @Override 302 @Override
218 protected Data[] getData() { 303 protected Data[] getData() {
219 304
220 String module = radio.getValueAsString(); 305 final Module module = selectedModule;
221 306
222 DataItem[] items = new DefaultDataItem[1]; 307 final DataItem[] items = new DefaultDataItem[] { new DefaultDataItem(module.getLocalizedName(), module.getLocalizedName(), module.getName()) };
223 items[0] = new DefaultDataItem(module, module, module); 308
224 309 final Data data = new DefaultData("module", null, null, items);
225 Data data = new DefaultData("module", null, null, items);
226
227 return new Data[] {data}; 310 return new Data[] {data};
228 } 311 }
229 312
230 public void setRivers(Map<String, HLayout> rivers) { 313 public void setRivers(Map<String, HLayout> rivers) {
231 this.rivers = rivers; 314 this.rivers = rivers;
234 private native void createCallback() /*-{ 317 private native void createCallback() /*-{
235 $wnd.getModule = @org.dive4elements.river.client.client.ui.ModuleSelection::getSelectedModule(); 318 $wnd.getModule = @org.dive4elements.river.client.client.ui.ModuleSelection::getSelectedModule();
236 }-*/; 319 }-*/;
237 320
238 private static String getSelectedModule() { 321 private static String getSelectedModule() {
239 if (radio == null) { 322 if (selectedModule == null) {
240 return null; 323 return null;
241 } 324 }
242 return radio.getValueAsString(); 325 return selectedModule.getName();
243 } 326 }
244 } 327 }
245 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : 328 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org