/******************************************************************************* * 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.preferences; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; import org.eclipse.che.api.promises.client.Function; import org.eclipse.che.api.promises.client.FunctionException; import org.eclipse.che.api.promises.client.Operation; import org.eclipse.che.api.promises.client.OperationException; import org.eclipse.che.api.promises.client.Promise; import org.eclipse.che.api.promises.client.PromiseError; import org.eclipse.che.api.promises.client.js.Promises; import org.eclipse.che.ide.CoreLocalizationConstant; import org.eclipse.che.ide.api.notification.NotificationManager; import org.eclipse.che.ide.api.preferences.PreferencePagePresenter; import org.eclipse.che.ide.api.preferences.PreferencesManager; import org.eclipse.che.ide.api.dialogs.CancelCallback; import org.eclipse.che.ide.api.dialogs.ConfirmCallback; import org.eclipse.che.ide.api.dialogs.DialogFactory; 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 org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.FLOAT_MODE; import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL; /** * PreferencesPresenter is presentation of preference pages. * It manages preference pages. It's responsible for the communication user and wizard page. * In typical usage, the client instantiates this class with list of preferences. * The presenter serves as the preference page container and orchestrates the * presentation of its pages. * * @author <a href="mailto:aplotnikov@exoplatform.com">Andrey Plotnikov</a> */ @Singleton public class PreferencesPresenter implements PreferencesView.ActionDelegate, PreferencePagePresenter.DirtyStateListener { private final PreferencesView view; private final Set<PreferencePagePresenter> preferences; private final Set<PreferencesManager> managers; private final Provider<NotificationManager> notificationManagerProvider; private Map<String, Set<PreferencePagePresenter>> preferencesMap; private DialogFactory dialogFactory; private CoreLocalizationConstant locale; /** * Create presenter. * <p/> * For tests. * * @param view * @param preferences * @param dialogFactory * @param locale * @param managers */ @Inject protected PreferencesPresenter(PreferencesView view, Set<PreferencePagePresenter> preferences, DialogFactory dialogFactory, CoreLocalizationConstant locale, Set<PreferencesManager> managers, Provider<NotificationManager> notificationManagerProvider) { this.view = view; this.preferences = preferences; this.dialogFactory = dialogFactory; this.locale = locale; this.managers = managers; this.notificationManagerProvider = notificationManagerProvider; this.view.setDelegate(this); for (PreferencePagePresenter preference : preferences) { preference.setUpdateDelegate(this); } } /** {@inheritDoc} */ @Override public void onDirtyChanged() { for (PreferencePagePresenter p : preferences) { if (p.isDirty()) { view.enableSaveButton(true); return; } } view.enableSaveButton(false); } /** {@inheritDoc} */ @Override public void onPreferenceSelected(PreferencePagePresenter preference) { preference.go(view.getContentPanel()); } /** Shows preferences. */ public void showPreferences() { if (preferencesMap != null) { view.show(); return; } preferencesMap = new HashMap<>(); for (PreferencePagePresenter preference : preferences) { Set<PreferencePagePresenter> prefsList = preferencesMap.get(preference.getCategory()); if (prefsList == null) { prefsList = new HashSet<PreferencePagePresenter>(); preferencesMap.put(preference.getCategory(), prefsList); } prefsList.add(preference); } view.setPreferences(preferencesMap); view.show(); view.enableSaveButton(false); view.selectPreference(preferencesMap.entrySet().iterator().next().getValue().iterator().next()); } @Override public void onSaveClicked() { for (PreferencePagePresenter preference : preferences) { if (preference.isDirty()) { preference.storeChanges(); } } Promise<Void> promise = Promises.resolve(null); final List<PromiseError> promiseErrorList = new ArrayList<>(); for (final PreferencesManager preferencesManager : managers) { promise = promise.thenPromise(new Function<Void, Promise<Void>>() { @Override public Promise<Void> apply(Void arg) throws FunctionException { return preferencesManager.flushPreferences().catchError(new Operation<PromiseError>() { @Override public void apply(PromiseError error) throws OperationException { notificationManagerProvider.get().notify(locale.unableToSavePreference(), error.getMessage(), FAIL, FLOAT_MODE); promiseErrorList.add(error); } }); } }); } promise.then(new Operation<Void>() { @Override public void apply(Void aVoid) throws OperationException { if (promiseErrorList.isEmpty()) { view.enableSaveButton(false); } } }); } @Override public void onRefreshClicked() { Promise<Map<String, String>> promise = Promises.resolve(null); for (final PreferencesManager preferencesManager : managers) { promise = promise.thenPromise(new Function<Map<String, String>, Promise<Map<String, String>>>() { @Override public Promise<Map<String, String>> apply(Map<String, String> arg) throws FunctionException { return preferencesManager.loadPreferences().catchError(new Operation<PromiseError>() { @Override public void apply(PromiseError error) throws OperationException { notificationManagerProvider.get().notify(locale.unableToLoadPreference(), error.getMessage(), FAIL, FLOAT_MODE); } }); } }); } /** * Revert changes on every preference page */ promise.then(new Operation<Map<String, String>>() { @Override public void apply(Map<String, String> arg) throws OperationException { for (PreferencePagePresenter p : PreferencesPresenter.this.preferences) { p.revertChanges(); } } }); } /** {@inheritDoc} */ @Override public void onCloseClicked() { boolean haveUnsavedData = false; for (PreferencePagePresenter preference : preferences) { if (preference.isDirty()) { haveUnsavedData = true; break; } } if (haveUnsavedData) { dialogFactory.createConfirmDialog("", locale.messagesPromptSaveChanges(), locale.yesButtonTitle(), locale.noButtonTitle(), getConfirmCallback(), getCancelCallback()).show(); } else { view.close(); } } private ConfirmCallback getConfirmCallback() { return new ConfirmCallback() { @Override public void accepted() { for (PreferencePagePresenter preference : preferences) { if (preference.isDirty()) { preference.storeChanges(); } } view.enableSaveButton(false); view.close(); } }; } private CancelCallback getCancelCallback() { return new CancelCallback() { @Override public void cancelled() { for (PreferencePagePresenter preference : preferences) { if (preference.isDirty()) { preference.revertChanges(); } } view.close(); } }; } /** {@inheritDoc} */ @Override public void onCloseWindow() { onCloseClicked(); } }