/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.projecttype.wizard.categoriespage; import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.google.inject.Inject; import org.eclipse.che.api.core.model.project.NewProjectConfig; import org.eclipse.che.api.project.shared.dto.ProjectTypeDto; import org.eclipse.che.api.project.templates.shared.dto.ProjectTemplateDescriptor; import org.eclipse.che.api.workspace.shared.dto.NewProjectConfigDto; import org.eclipse.che.ide.api.app.AppContext; import org.eclipse.che.ide.api.project.MutableProjectConfig; import org.eclipse.che.ide.api.project.NewProjectConfigImpl; import org.eclipse.che.ide.api.project.type.ProjectTemplateRegistry; import org.eclipse.che.ide.api.project.type.ProjectTypeRegistry; import org.eclipse.che.ide.api.project.type.wizard.PreSelectedProjectTypeManager; import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode; import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistry; import org.eclipse.che.ide.api.resources.Resource; import org.eclipse.che.ide.api.wizard.AbstractWizardPage; import org.eclipse.che.ide.resource.Path; import org.eclipse.che.ide.resources.selector.SelectPathPresenter; import org.eclipse.che.ide.resources.selector.SelectionPathHandler; import org.eclipse.che.ide.util.NameUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import static com.google.common.base.Strings.isNullOrEmpty; import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode.CREATE; import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardMode.UPDATE; import static org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistrar.WIZARD_MODE_KEY; /** * Main page for project wizard. * * @author Evgen Vidolob * @author Artem Zatsarynnyi * @author Dmitry Shnurenko * @author Vlad Zhukovskyi */ public class CategoriesPagePresenter extends AbstractWizardPage<MutableProjectConfig> implements CategoriesPageView.ActionDelegate { public final static String DEFAULT_TEMPLATE_CATEGORY = "Samples"; private final CategoriesPageView view; private final ProjectTypeRegistry projectTypeRegistry; private final ProjectTemplateRegistry projectTemplateRegistry; private final ProjectWizardRegistry wizardRegistry; private final PreSelectedProjectTypeManager preSelectedProjectTypeManager; private final SelectPathPresenter selectPathPresenter; private final AppContext appContext; private ProjectTypeDto selectedProjectType; private ProjectTemplateDescriptor selectedProjectTemplate; private ProjectTypeSelectionListener projectTypeSelectionListener; private ProjectTemplateSelectionListener projectTemplateSelectionListener; private boolean initialized; private Path originParent; @Inject public CategoriesPagePresenter(CategoriesPageView view, ProjectTypeRegistry projectTypeRegistry, ProjectTemplateRegistry projectTemplateRegistry, ProjectWizardRegistry wizardRegistry, PreSelectedProjectTypeManager preSelectedProjectTypeManager, SelectPathPresenter selectPathPresenter, AppContext appContext) { super(); this.view = view; this.projectTypeRegistry = projectTypeRegistry; this.projectTemplateRegistry = projectTemplateRegistry; this.wizardRegistry = wizardRegistry; this.preSelectedProjectTypeManager = preSelectedProjectTypeManager; this.selectPathPresenter = selectPathPresenter; this.appContext = appContext; view.setDelegate(this); loadProjectTypesAndTemplates(); } @Override public void init(MutableProjectConfig dataObject) { super.init(dataObject); // this page may be reused so need to init it only once if (initialized) { return; } initialized = true; final ProjectWizardMode wizardMode = ProjectWizardMode.parse(context.get(WIZARD_MODE_KEY)); originParent = Path.valueOf(dataObject.getPath()).parent(); view.setParentPath(originParent); if (CREATE == wizardMode) { // set pre-selected project type final String preSelectedProjectTypeId; if (dataObject.getType() != null) { preSelectedProjectTypeId = dataObject.getType(); } else { preSelectedProjectTypeId = preSelectedProjectTypeManager.getPreSelectedProjectTypeId(); } if (wizardRegistry.getWizardRegistrar(preSelectedProjectTypeId) != null) { dataObject.setType(preSelectedProjectTypeId); } } view.updateCategories(CREATE == wizardMode); } @Override public boolean isCompleted() { final String projectName = dataObject.getName(); return projectName != null && NameUtils.checkProjectName(projectName) && (selectedProjectType != null || selectedProjectTemplate != null); } @Override public void go(final AcceptsOneWidget container) { container.setWidget(view); updateView(); } /** Updates view from data-object. */ private void updateView() { if (dataObject.getType() != null && (selectedProjectType == null || !selectedProjectType.getId().equals(dataObject.getType()))) { view.selectProjectType(dataObject.getType()); } view.setName(dataObject.getName()); view.setDescription(dataObject.getDescription()); final ProjectWizardMode wizardMode = ProjectWizardMode.parse(context.get(WIZARD_MODE_KEY)); view.setNameFieldReadOnly(wizardMode == UPDATE); } @Override public void projectTypeSelected(ProjectTypeDto typeDescriptor) { selectedProjectType = typeDescriptor; selectedProjectTemplate = null; if (projectTypeSelectionListener != null) { projectTypeSelectionListener.onProjectTypeSelected(typeDescriptor); } updateDelegate.updateControls(); } @Override public void projectTemplateSelected(ProjectTemplateDescriptor templateDescriptor) { selectedProjectType = null; selectedProjectTemplate = templateDescriptor; if (projectTemplateSelectionListener != null) { projectTemplateSelectionListener.onProjectTemplateSelected(templateDescriptor); } updateProjectConfigs(dataObject.getPath(), selectedProjectTemplate); updateDelegate.updateControls(); } @Override public void projectNameChanged(String name) { final String newProjectPath = originParent.append(name).toString(); if (selectedProjectTemplate != null) { updateProjectConfigs(newProjectPath, selectedProjectTemplate); } dataObject.setName(name); dataObject.setPath(newProjectPath); updateDelegate.updateControls(); if (NameUtils.checkProjectName(name)) { view.removeNameError(); } else { view.showNameError(); } } @Override public void projectDescriptionChanged(String projectDescription) { dataObject.setDescription(projectDescription); updateDelegate.updateControls(); } @Override public void selectPathClicked() { selectPathPresenter.show(new Resource[]{appContext.getWorkspaceRoot()}, false, new SelectionPathHandler() { @Override public void onPathSelected(Path path) { originParent = path; dataObject.setPath(!isNullOrEmpty(dataObject.getName()) ? path.append(dataObject.getName()).toString() : path.toString()); view.setParentPath(path); view.focusSelectPathButton(); } @Override public void onSelectionCancelled() { view.focusSelectPathButton(); } }); } public void setProjectTypeSelectionListener(ProjectTypeSelectionListener listener) { projectTypeSelectionListener = listener; } public void setProjectTemplateSelectionListener(ProjectTemplateSelectionListener listener) { projectTemplateSelectionListener = listener; } private void updateProjectConfigs(String newProjectPath, ProjectTemplateDescriptor projectTemplate) { final List<NewProjectConfigDto> configDtoList = projectTemplate.getProjects(); if (newProjectPath.equals("/")) { return; } final String templatePath = projectTemplate.getPath(); final List<NewProjectConfig> updatedConfigs = new ArrayList<>(configDtoList.size()); for (NewProjectConfigDto configDto : configDtoList) { final NewProjectConfig newConfig = new NewProjectConfigImpl(configDto); final String projectPath = configDto.getPath(); if (projectPath.startsWith(templatePath)) { final String path = projectPath.replaceFirst(templatePath, newProjectPath); newConfig.setPath(path); } updatedConfigs.add(newConfig); } dataObject.setProjects(updatedConfigs); } private void loadProjectTypesAndTemplates() { List<ProjectTypeDto> projectTypes = projectTypeRegistry.getProjectTypes(); Map<String, Set<ProjectTypeDto>> typesByCategory = new HashMap<>(); Map<String, Set<ProjectTemplateDescriptor>> templatesByCategory = new HashMap<>(); for (ProjectTypeDto type : projectTypes) { if (wizardRegistry.getWizardRegistrar(type.getId()) != null) { final String category = wizardRegistry.getWizardCategory(type.getId()); if (!typesByCategory.containsKey(category)) { typesByCategory.put(category, new HashSet<ProjectTypeDto>()); } typesByCategory.get(category).add(type); } List<ProjectTemplateDescriptor> templateDescriptors = projectTemplateRegistry.getTemplateDescriptors(type.getId()); for (ProjectTemplateDescriptor template : templateDescriptors) { final String category = template.getCategory() == null ? DEFAULT_TEMPLATE_CATEGORY : template.getCategory(); if (!templatesByCategory.containsKey(category)) { templatesByCategory.put(category, new HashSet<ProjectTemplateDescriptor>()); } templatesByCategory.get(category).add(template); } } view.setProjectTypes(projectTypes); view.setCategories(typesByCategory, templatesByCategory); } public interface ProjectTypeSelectionListener { /** Called when project type selected. */ void onProjectTypeSelected(ProjectTypeDto projectTypeDto); } public interface ProjectTemplateSelectionListener { /** Called when project template selected. */ void onProjectTemplateSelected(ProjectTemplateDescriptor projectTemplateDescriptor); } }