teichmann@5861: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5861: * Software engineering by Intevation GmbH teichmann@5861: * teichmann@5993: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5861: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5993: * documentation coming with Dive4Elements River for details. teichmann@5861: */ teichmann@5861: teichmann@5835: package org.dive4elements.river.client.client.ui; ingo@30: gernotbelger@8870: import java.util.Collection; gernotbelger@8870: import java.util.HashMap; gernotbelger@8870: import java.util.LinkedHashMap; gernotbelger@8870: import java.util.LinkedList; gernotbelger@8870: import java.util.List; gernotbelger@8870: import java.util.Map; gernotbelger@8870: import java.util.Map.Entry; ingo@30: teichmann@5835: import org.dive4elements.river.client.client.Config; teichmann@5835: import org.dive4elements.river.client.client.FLYSConstants; teichmann@5835: import org.dive4elements.river.client.client.services.ModuleService; teichmann@5835: import org.dive4elements.river.client.client.services.ModuleServiceAsync; teichmann@5835: import org.dive4elements.river.client.shared.model.Data; teichmann@5835: import org.dive4elements.river.client.shared.model.DataItem; teichmann@5835: import org.dive4elements.river.client.shared.model.DataList; teichmann@5835: import org.dive4elements.river.client.shared.model.DefaultData; teichmann@5835: import org.dive4elements.river.client.shared.model.DefaultDataItem; teichmann@5835: import org.dive4elements.river.client.shared.model.Module; gernotbelger@8870: import org.dive4elements.river.client.shared.model.ModuleGroup; ingo@30: gernotbelger@8870: import com.google.gwt.core.client.GWT; gernotbelger@8870: import com.google.gwt.user.client.rpc.AsyncCallback; gernotbelger@8870: import com.smartgwt.client.types.VerticalAlignment; gernotbelger@8870: import com.smartgwt.client.util.SC; gernotbelger@8870: import com.smartgwt.client.widgets.Canvas; gernotbelger@8870: import com.smartgwt.client.widgets.Label; gernotbelger@8870: import com.smartgwt.client.widgets.form.DynamicForm; gernotbelger@8870: import com.smartgwt.client.widgets.form.fields.RadioGroupItem; gernotbelger@8870: import com.smartgwt.client.widgets.form.fields.events.ChangeEvent; gernotbelger@8870: import com.smartgwt.client.widgets.form.fields.events.ChangeHandler; gernotbelger@8870: import com.smartgwt.client.widgets.layout.HLayout; gernotbelger@8870: import com.smartgwt.client.widgets.layout.LayoutSpacer; gernotbelger@8870: import com.smartgwt.client.widgets.layout.VLayout; ingo@30: ingo@30: /** ingo@30: * The ModuleSelection combines the river selection and the module selection in ingo@30: * one widget. It will display a vertical splitted widget - the upper part will ingo@30: * render checkboxes for each module, the lower one will display a combobox at ingo@30: * the left and a map panel on the right to choose the river. ingo@30: * ingo@30: * @author Ingo Weinzierl ingo@30: */ ingo@30: public class ModuleSelection extends MapSelection { ingo@30: christian@4131: private static final long serialVersionUID = -5634831815175543328L; christian@4131: ingo@30: /** The message class that provides i18n strings.*/ gernotbelger@8870: private FLYSConstants MESSAGES = GWT.create(FLYSConstants.class); bjoern@3518: bjoern@3518: /** The ModuleService used to retrieve the available modules of a user.*/ gernotbelger@8870: private ModuleServiceAsync moduleService = GWT.create(ModuleService.class); ingo@30: gernotbelger@8870: private Map > modulesRiverMap = new LinkedHashMap >(); gernotbelger@8870: gernotbelger@8870: private Map modulesByName = new HashMap(); gernotbelger@8870: gernotbelger@8870: private Map> modulesByGroup = new LinkedHashMap>(); gernotbelger@8870: gernotbelger@8870: private Map groupToRadios = new LinkedHashMap(); gernotbelger@8870: gernotbelger@8870: private Map groupToCanvas = new LinkedHashMap(); gernotbelger@8870: gernotbelger@8870: private Map rivers = null; gernotbelger@8870: gernotbelger@8870: private VLayout radioPanel; gernotbelger@8870: gernotbelger@8870: /* TODO: seems that it needs to be static for the callback, is this really necessary? gernotbelger@8870: * TODO: what happens if we have several 'new project' windows open in parallel? gernotbelger@8870: * */ gernotbelger@8870: private static Module selectedModule = null; gernotbelger@8870: ingo@30: public ModuleSelection() { bjoern@3518: readModules(); ingo@30: } ingo@30: ingo@30: /** ingo@30: * This method returns a widget that renders the checkboxes for each module ingo@30: * and the MapSelection that lets the user choose the river. ingo@30: * ingo@30: * @param data The provided rivers. ingo@30: * ingo@30: * @return the module selection combined with the river selection. ingo@30: */ christian@4131: @Override ingo@51: public Canvas create(DataList data) { bjoern@3518: GWT.log("ModuleSelection - create()"); rrenkert@6133: createCallback(); ingo@30: VLayout newLayout = new VLayout(); ingo@30: newLayout.setMembersMargin(10); raimund@282: newLayout.setAlign(VerticalAlignment.TOP); ingo@30: Canvas moduleSelection = createWidget(); ingo@30: raimund@282: moduleSelection.setHeight(100); raimund@282: newLayout.setHeight(70); ingo@30: newLayout.addMember(moduleSelection); ingo@30: ingo@30: return newLayout; ingo@30: } ingo@30: bjoern@3518: private void readModules() { bjoern@3518: Config config = Config.getInstance(); bjoern@3518: String locale = config.getLocale(); bjoern@3518: bjoern@3518: moduleService.list(locale, new AsyncCallback() { bjoern@3518: @Override bjoern@3518: public void onFailure(Throwable caught) { bjoern@3518: GWT.log("Could not recieve a list of modules."); bjoern@3518: SC.warn(MSG.getString(caught.getMessage())); bjoern@3518: } bjoern@3518: bjoern@3518: @Override bjoern@3518: public void onSuccess(Module[] newmodules) { bjoern@3518: GWT.log("Retrieved " + newmodules.length + " modules."); gernotbelger@8870: setModules(newmodules); gernotbelger@8870: updateRadioPanels(); bjoern@3518: } bjoern@3518: }); bjoern@3518: } bjoern@3518: gernotbelger@8870: // TODO: bad. Too much knowledge spread over the application. gernotbelger@8870: // TODO: instead, e.g. use a controller that knows both (ModuleSelection and LinkSelection) and let him do this kind of things andre@8528: private void checkRivers(String selected) { gernotbelger@8870: if (rivers == null || rivers.isEmpty() || /*modules == null || */ selected == null ) gernotbelger@8870: return; gernotbelger@8870: gernotbelger@8870: final List allowedRivers = modulesRiverMap.get(selected); gernotbelger@8870: if ( allowedRivers == null ) gernotbelger@8870: GWT.log("No configured rivers for module: " + selected); gernotbelger@8870: gernotbelger@8870: for (final Map.Entry s: rivers.entrySet()) { gernotbelger@8870: if (allowedRivers == null || !allowedRivers.contains(s.getKey())) { gernotbelger@8870: s.getValue().hide(); gernotbelger@8870: } else { gernotbelger@8870: s.getValue().show(); andre@8528: } andre@8528: } andre@8528: } gernotbelger@8870: gernotbelger@8870: protected final void setModules(Module[] newmodules) { gernotbelger@8870: modulesRiverMap.clear(); gernotbelger@8870: gernotbelger@8870: if( newmodules == null ) gernotbelger@8870: return; gernotbelger@8870: gernotbelger@8870: for(final Module module : newmodules) { gernotbelger@8870: final String name = module.getName(); gernotbelger@8870: gernotbelger@8870: /* remember rivers per module */ gernotbelger@8870: modulesRiverMap.put(name, module.getRivers()); bjoern@3530: gernotbelger@8870: /* hash by name */ gernotbelger@8870: modulesByName.put(name, module); gernotbelger@8870: gernotbelger@8870: /* hash by group */ gernotbelger@8870: final ModuleGroup group = module.getGroup(); gernotbelger@8870: if( !modulesByGroup.containsKey( group ) ) gernotbelger@8870: modulesByGroup.put(group, new LinkedList()); gernotbelger@8870: gernotbelger@8870: final List modulesGroup = modulesByGroup.get(group); gernotbelger@8870: modulesGroup.add(module); bjoern@3518: } bjoern@3518: } ingo@30: ingo@30: /** ingo@30: * Creates a widget that displays a checkbox for each module. ingo@30: * ingo@30: * @return a widget with checkboxes. ingo@30: */ ingo@30: protected Canvas createWidget() { gernotbelger@8870: gernotbelger@8870: final HLayout layout = new HLayout(); gernotbelger@8870: gernotbelger@8870: radioPanel = new VLayout(); ingo@30: gernotbelger@8870: final Label label = new Label(MESSAGES.module_selection()); ingo@30: label.setWidth(50); raimund@282: label.setHeight(25); ingo@30: ingo@30: layout.addMember(label); gernotbelger@8870: layout.addMember(radioPanel); gernotbelger@8870: gernotbelger@8870: updateRadioPanels(); gernotbelger@8870: ingo@30: return layout; ingo@30: } ingo@30: gernotbelger@8870: protected final void updateRadioPanels() { gernotbelger@8870: gernotbelger@8870: /* first clear existing panels, if any exist */ gernotbelger@8870: final Collection oldforms = groupToCanvas.values(); gernotbelger@8870: for (Canvas oldCanvas : oldforms) { gernotbelger@8870: radioPanel.removeMember(oldCanvas); gernotbelger@8870: oldCanvas.destroy(); gernotbelger@8870: } gernotbelger@8870: gernotbelger@8870: groupToCanvas.clear(); gernotbelger@8870: groupToRadios.clear(); gernotbelger@8870: selectedModule = null; gernotbelger@8870: gernotbelger@8870: if( radioPanel == null ) gernotbelger@8870: return; gernotbelger@8870: gernotbelger@8870: /* now create radio items per group */ gernotbelger@8870: int count = 0; gernotbelger@8870: for (final Entry> groupEntry : modulesByGroup.entrySet()) { gernotbelger@8870: gernotbelger@8870: final ModuleGroup group = groupEntry.getKey(); gernotbelger@8870: final List groupModule = groupEntry.getValue(); gernotbelger@8870: gernotbelger@8870: final HLayout groupPanel = new HLayout(); gernotbelger@8870: gernotbelger@8870: if( group.showGroupFrame() ) gernotbelger@8870: { gernotbelger@8870: final LayoutSpacer spacer = new LayoutSpacer(); gernotbelger@8870: spacer.setWidth(25); gernotbelger@8870: groupPanel.addMember(spacer); gernotbelger@8870: gernotbelger@8870: final Label label = new Label(group.toString()); gernotbelger@8870: label.setWidth(25); gernotbelger@8870: label.setHeight(25); gernotbelger@8870: groupPanel.addMember(label); gernotbelger@8870: } gernotbelger@8870: gernotbelger@8870: final DynamicForm groupForm = new DynamicForm(); gernotbelger@8870: gernotbelger@8870: final RadioGroupItem moduleRadio = new RadioGroupItem("modulegroup" + count++); gernotbelger@8870: moduleRadio.setShowTitle(false); gernotbelger@8870: moduleRadio.setVertical(true); gernotbelger@8870: gernotbelger@8870: moduleRadio.addChangeHandler(new ChangeHandler() { gernotbelger@8870: @Override gernotbelger@8870: public void onChange(ChangeEvent event) { gernotbelger@8870: final String selectedModuleName = (String) event.getValue(); gernotbelger@8870: handleModuleSelected(selectedModuleName); gernotbelger@8870: } gernotbelger@8870: }); gernotbelger@8870: gernotbelger@8870: groupForm.setItems(moduleRadio); gernotbelger@8870: groupPanel.addMember(groupForm); gernotbelger@8870: gernotbelger@8870: final LinkedHashMap values = new LinkedHashMap(); gernotbelger@8870: for(final Module module : groupModule) { gernotbelger@8870: values.put(module.getName(), module.getLocalizedName()); gernotbelger@8870: if (module.isSelected()) { gernotbelger@8870: GWT.log("Module " + module.getName() + " is selected."); gernotbelger@8870: selectedModule = module; gernotbelger@8870: moduleRadio.setValue(module.getName()); gernotbelger@8870: } gernotbelger@8870: } gernotbelger@8870: gernotbelger@8870: this.groupToRadios.put( group, moduleRadio ); gernotbelger@8870: this.groupToCanvas.put( group, groupPanel ); gernotbelger@8870: gernotbelger@8870: moduleRadio.setValueMap(values); gernotbelger@8870: gernotbelger@8870: gernotbelger@8870: radioPanel.addMember(groupPanel); gernotbelger@8870: } gernotbelger@8870: gernotbelger@8870: checkRivers(getSelectedModule()); gernotbelger@8870: } gernotbelger@8870: gernotbelger@8870: protected void handleModuleSelected(final String selectedModuleName) { gernotbelger@8870: gernotbelger@8870: /* remember selected module for later */ gernotbelger@8870: selectedModule = modulesByName.get(selectedModuleName); gernotbelger@8870: gernotbelger@8870: /* because radios might in different radio-groups, we need to de-select them manually */ gernotbelger@8870: final ModuleGroup group = selectedModule.getGroup(); gernotbelger@8870: gernotbelger@8870: for (final Entry entry : groupToRadios.entrySet()) { gernotbelger@8870: final ModuleGroup radioGroup = entry.getKey(); gernotbelger@8870: gernotbelger@8870: if( !group.equals(radioGroup)) gernotbelger@8870: { gernotbelger@8870: final RadioGroupItem groupRadio = entry.getValue(); gernotbelger@8870: groupRadio.setValue((String)null); gernotbelger@8870: } gernotbelger@8870: } gernotbelger@8870: gernotbelger@8870: checkRivers(selectedModuleName); gernotbelger@8870: } ingo@30: ingo@30: /** ingo@30: * This method prepares the data of two widgets - the module selection and ingo@30: * the river selection. The returning field will contain the Data that ingo@30: * represents the module selection at first position, the second position ingo@30: * stores the Data object that represents the river selection. ingo@30: * ingo@30: * @return the Data that was chosen in this widget. ingo@30: */ christian@4131: @Override ingo@30: protected Data[] getData() { ingo@30: gernotbelger@8870: final Module module = selectedModule; ingo@30: gernotbelger@8870: final DataItem[] items = new DefaultDataItem[] { new DefaultDataItem(module.getLocalizedName(), module.getLocalizedName(), module.getName()) }; ingo@30: gernotbelger@8870: final Data data = new DefaultData("module", null, null, items); raimund@282: return new Data[] {data}; ingo@30: } rrenkert@5928: rrenkert@6119: public void setRivers(Map rivers) { rrenkert@5928: this.rivers = rivers; rrenkert@5928: } rrenkert@6133: rrenkert@6133: private native void createCallback() /*-{ rrenkert@6133: $wnd.getModule = @org.dive4elements.river.client.client.ui.ModuleSelection::getSelectedModule(); rrenkert@6133: }-*/; rrenkert@6133: rrenkert@6133: private static String getSelectedModule() { gernotbelger@8870: if (selectedModule == null) { andre@8528: return null; andre@8528: } gernotbelger@8870: return selectedModule.getName(); rrenkert@6133: } ingo@30: } ingo@30: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :