package org.sigmah.client.ui.presenter.project.indicator; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import com.extjs.gxt.ui.client.event.ButtonEvent; import com.extjs.gxt.ui.client.event.Events; import com.extjs.gxt.ui.client.event.FieldEvent; import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.event.SelectionListener; import com.extjs.gxt.ui.client.widget.form.ComboBox; import com.extjs.gxt.ui.client.widget.form.Field; import com.extjs.gxt.ui.client.widget.form.FieldSet; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.user.client.Event; import com.google.inject.ImplementedBy; import com.google.inject.Inject; import com.google.inject.Singleton; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.sigmah.client.dispatch.CommandResultHandler; import org.sigmah.client.dispatch.monitor.LoadingMask; import org.sigmah.client.event.SiteEvent; import org.sigmah.client.i18n.I18N; import org.sigmah.client.inject.Injector; import org.sigmah.client.page.Page; import org.sigmah.client.page.PageRequest; import org.sigmah.client.page.RequestParameter; import org.sigmah.client.ui.notif.N10N; import org.sigmah.client.ui.presenter.base.AbstractPagePresenter; import org.sigmah.client.ui.presenter.base.HasForm; import org.sigmah.client.ui.view.base.ViewPopupInterface; import org.sigmah.client.ui.view.project.indicator.EditSiteView; import org.sigmah.client.ui.widget.Loadable; import org.sigmah.client.ui.widget.button.Button; import org.sigmah.client.ui.widget.form.FormPanel; import org.sigmah.client.ui.widget.map.Pin; import org.sigmah.client.ui.widget.map.PinDragEndHandler; import org.sigmah.shared.command.BatchCommand; import org.sigmah.shared.command.CreateEntity; import org.sigmah.shared.command.GetAdminEntities; import org.sigmah.shared.command.UpdateEntity; import org.sigmah.shared.command.result.CreateResult; import org.sigmah.shared.command.result.ListResult; import org.sigmah.shared.command.result.Result; import org.sigmah.shared.command.result.VoidResult; import org.sigmah.shared.dto.AdminEntityDTO; import org.sigmah.shared.dto.AdminLevelDTO; import org.sigmah.shared.dto.BoundingBoxDTO; import org.sigmah.shared.dto.SchemaDTO; import org.sigmah.shared.dto.SiteDTO; import org.sigmah.shared.dto.UserDatabaseDTO; import org.sigmah.shared.dto.country.CountryDTO; /** * * @author Raphaƫl Calabro (rcalabro@ideia.fr) */ @Singleton public class EditSitePresenter extends AbstractPagePresenter<EditSitePresenter.View> implements HasForm { /** * Description of the view managed by this presenter. */ @ImplementedBy(EditSiteView.class) public static interface View extends ViewPopupInterface { FormPanel getForm(); // Fields. FieldSet getLocationFieldSet(); ComboBox<AdminEntityDTO> getTopLevelComboBox(); Field<Double> getLatitudeField(); Field<Double> getLongitudeField(); Pin getPin(); Button getSaveButton(); Button getCancelButton(); void panTo(double latitude, double longitude); void setCountry(CountryDTO country, Listener<FieldEvent> selectionListener); BoundingBoxDTO getMapBounds(); void setMapBounds(BoundingBoxDTO bounds); void setPinPosition(double latitude, double longitude); } private Integer projectId; private SiteDTO site; private boolean mainSite; /** * Presenters's initialization. * * @param view * Presenter's view interface. * @param injector * Injected client injector. */ @Inject protected EditSitePresenter(final EditSitePresenter.View view, final Injector injector) { super(view, injector); } /** * {@inheritDoc} */ @Override public Page getPage() { return Page.SITE_EDIT; } /** * {@inheritDoc} */ @Override public FormPanel[] getForms() { return new FormPanel[] { view.getForm() }; } @Override public void onBind() { view.getPin().addPinDragEndHandler(new PinDragEndHandler() { @Override public void onDragEnd(double latitude, double longitude) { onMarkerMoved(latitude, longitude); } }); view.getSaveButton().addSelectionListener(new SelectionListener<ButtonEvent>() { @Override public void componentSelected(ButtonEvent ce) { onSaveAction(); } }); view.getCancelButton().addSelectionListener(new SelectionListener<ButtonEvent>() { @Override public void componentSelected(ButtonEvent ce) { hideView(); } }); final Listener<FieldEvent> latitudeLongitudeChangeListener = new Listener<FieldEvent>() { @Override public void handleEvent(FieldEvent be) { onCoordinatesChanged(view.getLongitudeField().getValue(), view.getLatitudeField().getValue()); } }; view.getLongitudeField().addListener(Events.Change, latitudeLongitudeChangeListener); view.getLatitudeField().addListener(Events.Change, latitudeLongitudeChangeListener); } @Override public void onPageRequest(PageRequest request) { // Reading parameters. projectId = request.getParameterInteger(RequestParameter.ID); mainSite = "main".equals(request.getParameter(RequestParameter.TYPE)); site = request.getData(RequestParameter.DTO); final SchemaDTO schema = request.getData(RequestParameter.MODEL); // Retrieving the current database. final UserDatabaseDTO database = schema.getDatabaseById(projectId); assert database != null; // Sets the popup title if(mainSite) { setPageTitle(I18N.CONSTANTS.projectMainSite()); } else if(site.getId() == null) { setPageTitle(I18N.CONSTANTS.newSite()); } else { setPageTitle(I18N.CONSTANTS.editSite()); } // Creates the admin entities fields. final CountryDTO country = database.getCountry(); view.setCountry(country, new Listener<FieldEvent>() { @Override public void handleEvent(FieldEvent be) { final ComboBox<AdminEntityDTO> comboBox = (ComboBox<AdminEntityDTO>) be.getField(); if(be.getEventTypeInt() == Event.ONKEYUP && ( be.getEvent().getKeyCode() == KeyCodes.KEY_DELETE || be.getEvent().getKeyCode() == KeyCodes.KEY_BACKSPACE)) { comboBox.setValue(null); } updateAdminEntityChild(comboBox); setLatitudeAndLongitude(getAdminEntityBounds(comboBox)); } }); setValues(site); if(site.getId() == null) { updateAdminEntity(view.getTopLevelComboBox()); } else { loadAdminEntities(view.getTopLevelComboBox()); } if(site.getX() != null && site.getY() != null) { // Move to the site coordinates. view.setMapBounds(new BoundingBoxDTO(site.getX(), site.getY())); view.setPinPosition(site.getY(), site.getX()); } else if(country != null) { setLatitudeAndLongitude(country.getBounds()); } } private void onCoordinatesChanged(Double latitude, Double longitude) { if(latitude != null && longitude != null) { view.setPinPosition(latitude, longitude); if(!view.getMapBounds().contains(longitude, latitude)) { view.panTo(latitude, longitude); } } } private void setLatitudeAndLongitude(BoundingBoxDTO boundingBoxDTO) { if(boundingBoxDTO != null) { view.setPinPosition(boundingBoxDTO.getCenterY(), boundingBoxDTO.getCenterX()); onMarkerMoved(boundingBoxDTO.getCenterY(), boundingBoxDTO.getCenterX()); } else { view.setPinPosition(0, 0); onMarkerMoved(0, 0); } view.setMapBounds(boundingBoxDTO); } private void onMarkerMoved(double latitude, double longitude) { view.getLatitudeField().setValue(latitude); view.getLongitudeField().setValue(longitude); } private void onSaveAction() { // -- // Forms validation. // -- if (!FormPanel.valid(view.getForm())) { // Form(s) validation failed. return; } // Save if(site.getId() == null) { saveSite(); } else { updateSite(); } } private void saveSite() { dispatch.execute(new CreateEntity(SiteDTO.ENTITY_NAME, getValues()), new CommandResultHandler<CreateResult>() { @Override protected void onCommandSuccess(CreateResult result) { N10N.infoNotif(I18N.CONSTANTS.saved(), I18N.CONSTANTS.saved()); site.setId((Integer) result.getEntity().getId()); site.setProperties(getValues()); final SiteEvent.Action action = mainSite ? SiteEvent.Action.MAIN_SITE_CREATED : SiteEvent.Action.CREATED; eventBus.fireEvent(new SiteEvent(action, this, site)); hideView(); } }, view.getSaveButton(), view.getCancelButton()); } private void updateSite() { dispatch.execute(new UpdateEntity(site, getValues()), new CommandResultHandler<VoidResult>() { @Override protected void onCommandSuccess(VoidResult result) { N10N.infoNotif(I18N.CONSTANTS.saved(), I18N.CONSTANTS.saved()); site.setProperties(getValues()); final SiteEvent.Action action = mainSite ? SiteEvent.Action.MAIN_SITE_UPDATED : SiteEvent.Action.UPDATED; eventBus.fireEvent(new SiteEvent(action, this, site)); hideView(); } }, view.getSaveButton(), view.getCancelButton()); } private Map<String, Object> getValues() { final Map<String, Object> values = new HashMap<String, Object>(); values.put(SiteDTO.DATABASE_ID, projectId); for(final Field<?> field : view.getForm().getFields()) { values.put(field.getName(), field.getValue()); } values.put(view.getLatitudeField().getName(), view.getLatitudeField().getValue()); values.put(view.getLongitudeField().getName(), view.getLongitudeField().getValue()); return values; } private void setValues(SiteDTO siteDTO) { for(final Field field : view.getForm().getFields()) { field.setOriginalValue(siteDTO.get(field.getName())); field.setValue(siteDTO.get(field.getName())); } view.getLatitudeField().setValue(site.getY()); view.getLongitudeField().setValue(site.getX()); } private void updateAdminEntityChild(ComboBox<AdminEntityDTO> comboBox) { final ComboBox<AdminEntityDTO> childComboBox = comboBox.getData("child"); updateAdminEntity(childComboBox, true, false); } private void updateAdminEntity(final ComboBox<AdminEntityDTO> comboBox) { updateAdminEntity(comboBox, false, true); } private void updateAdminEntity(final ComboBox<AdminEntityDTO> comboBox, boolean resetValue, final boolean forceNoReset) { if(comboBox == null) { return; } final AdminLevelDTO level = comboBox.getData("level"); final ComboBox<AdminEntityDTO> parentComboBox = comboBox.getData("parent"); final ComboBox<AdminEntityDTO> childComboBox = comboBox.getData("child"); final GetAdminEntities getAdminEntities; if(parentComboBox == null) { // Fetch all parent entities getAdminEntities = new GetAdminEntities(level.getId()); } else { final AdminEntityDTO parentAdminEntity = parentComboBox.getValue(); if(parentAdminEntity != null) { // Fetch only the entities related to the parent entity. getAdminEntities = new GetAdminEntities(level.getId(), parentAdminEntity.getId()); } else { getAdminEntities = null; comboBox.setValue(null); } } if(resetValue) { comboBox.setValue(null); } // Remove the current levels. comboBox.getStore().removeAll(); if(getAdminEntities != null) { // Fetch the levels. dispatch.execute(getAdminEntities, new CommandResultHandler<ListResult<AdminEntityDTO>>() { @Override protected void onCommandSuccess(ListResult<AdminEntityDTO> result) { // Update the store and allow selection for this level. comboBox.getStore().add(result.getData()); comboBox.setEnabled(true); updateAdminEntity(childComboBox, !forceNoReset, forceNoReset); } }, new LoadingMask(comboBox)); } else { // No parent level has been selected, disable this combo. comboBox.setEnabled(false); updateAdminEntity(childComboBox, !forceNoReset, forceNoReset); } } private BoundingBoxDTO getAdminEntityBounds(ComboBox<AdminEntityDTO> comboBox) { BoundingBoxDTO bounds = null; ComboBox<AdminEntityDTO> adminEntityComboBox = comboBox; do { final AdminEntityDTO adminEntity = adminEntityComboBox.getValue(); if(adminEntity != null) { bounds = adminEntity.getBounds(); } adminEntityComboBox = comboBox.getData("parent"); } while(bounds == null && adminEntityComboBox != null); return bounds; } private void loadAdminEntities(final ComboBox<AdminEntityDTO> rootComboBox) { final BatchCommand batchCommand = new BatchCommand(); final ArrayList<Loadable> masks = new ArrayList<Loadable>(); final ArrayList<ComboBox<AdminEntityDTO>> affectedComboBoxes = new ArrayList<ComboBox<AdminEntityDTO>>(); ComboBox<AdminEntityDTO> comboBox = rootComboBox; while(comboBox != null) { comboBox.getStore().removeAll(); final AdminLevelDTO level = comboBox.getData("level"); final ComboBox<AdminEntityDTO> parentComboBox = comboBox.getData("parent"); final GetAdminEntities getAdminEntities; if(parentComboBox == null) { // Fetch all parent entities getAdminEntities = new GetAdminEntities(level.getId()); } else { final AdminEntityDTO parentAdminEntity = parentComboBox.getValue(); if(parentAdminEntity != null) { // Fetch only the entities related to the parent entity. getAdminEntities = new GetAdminEntities(level.getId(), parentAdminEntity.getId()); } else { getAdminEntities = null; comboBox.setValue(null); } } if(getAdminEntities != null) { batchCommand.add(getAdminEntities); masks.add(new LoadingMask(comboBox)); affectedComboBoxes.add(comboBox); } comboBox = comboBox.getData("child"); } dispatch.execute(batchCommand, new CommandResultHandler<ListResult<Result>>() { @Override protected void onCommandSuccess(ListResult<Result> listResult) { final List<Result> results = listResult.getList(); for(int index = 0; index < results.size(); index++) { final ComboBox<AdminEntityDTO> comboBox = affectedComboBoxes.get(index); final ListResult<AdminEntityDTO> entities = (ListResult<AdminEntityDTO>) results.get(index); comboBox.getStore().add(entities.getData()); comboBox.setEnabled(true); } } }, masks); } }