From 1bf9b9a0e9da96c768de03bde03240ac2fe90b51 Mon Sep 17 00:00:00 2001 From: Roman Nikitenko Date: Sat, 24 Feb 2018 13:06:42 +0200 Subject: [PATCH] CHE-7975. Fix displaying Pull Request Panel Signed-off-by: Roman Nikitenko --- .../general/AbstractPerspective.java | 59 +++-- .../statepersistance/AppStateConstants.java | 31 +++ .../ide/statepersistance/AppStateManager.java | 108 +++++++- .../che/ide/workspace/WorkspacePresenter.java | 8 +- .../statepersistance/AppStateManagerTest.java | 8 +- .../che-plugin-pullrequest-ide/pom.xml | 4 + .../client/ContributionMixinProvider.java | 248 ++++++++++-------- .../ContributePartDisplayingModeAction.java | 1 + .../contribute/ContributePartPresenter.java | 2 + 9 files changed, 319 insertions(+), 150 deletions(-) create mode 100644 ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/statepersistance/AppStateConstants.java diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/part/perspectives/general/AbstractPerspective.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/part/perspectives/general/AbstractPerspective.java index 0bb540a1d45..d17f147646c 100644 --- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/part/perspectives/general/AbstractPerspective.java +++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/part/perspectives/general/AbstractPerspective.java @@ -15,6 +15,13 @@ import static org.eclipse.che.ide.api.parts.PartStackType.INFORMATION; import static org.eclipse.che.ide.api.parts.PartStackType.NAVIGATION; import static org.eclipse.che.ide.api.parts.PartStackType.TOOLING; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.ACTIVE_PART; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.HIDDEN_STATE; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.PART_CLASS_NAME; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.PART_STACKS; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.PART_STACK_PARTS; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.PART_STACK_SIZE; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.PART_STACK_STATE; import com.google.inject.Provider; import com.google.web.bindery.event.shared.EventBus; @@ -332,9 +339,9 @@ public JsonObject getState() { JsonObject state = Json.createObject(); JsonObject partStacks = Json.createObject(); if (activePart != null) { - state.put("ACTIVE_PART", activePart.getClass().getName()); + state.put(ACTIVE_PART, activePart.getClass().getName()); } - state.put("PART_STACKS", partStacks); + state.put(PART_STACKS, partStacks); partStacks.put( PartStackType.INFORMATION.name(), @@ -352,24 +359,23 @@ public JsonObject getState() { private JsonObject getPartStackState( PartStack partStack, WorkBenchPartController partController) { JsonObject state = Json.createObject(); - state.put("SIZE", partController.getSize()); - state.put("STATE", partStack.getPartStackState().name()); + state.put(PART_STACK_SIZE, partController.getSize()); + state.put(PART_STACK_STATE, partStack.getPartStackState().name()); if (partStack.getParts().isEmpty()) { - state.put("HIDDEN", true); + state.put(HIDDEN_STATE, true); } else { if (partStack.getActivePart() != null) { - state.put("ACTIVE_PART", partStack.getActivePart().getClass().getName()); + state.put(ACTIVE_PART, partStack.getActivePart().getClass().getName()); } - - state.put("HIDDEN", partController.isHidden()); + state.put(HIDDEN_STATE, partController.isHidden()); JsonArray parts = Json.createArray(); - state.put("PARTS", parts); + state.put(PART_STACK_PARTS, parts); int i = 0; for (PartPresenter entry : partStack.getParts()) { JsonObject presenterState = Json.createObject(); - presenterState.put("CLASS", entry.getClass().getName()); + presenterState.put(PART_CLASS_NAME, entry.getClass().getName()); parts.set(i++, presenterState); } } @@ -378,8 +384,8 @@ private JsonObject getPartStackState( @Override public Promise loadState(@NotNull JsonObject state) { - if (state.hasKey("PART_STACKS")) { - JsonObject partStacksState = state.getObject("PART_STACKS"); + if (state.hasKey(PART_STACKS)) { + JsonObject partStacksState = state.getObject(PART_STACKS); // Don't restore part dimensions if perspective is maximized. boolean perspectiveMaximized = isPerspectiveMaximized(partStacksState); @@ -411,8 +417,8 @@ public Promise loadState(@NotNull JsonObject state) { } // restore perspective's active part - if (state.hasKey("ACTIVE_PART")) { - String activePart = state.getString("ACTIVE_PART"); + if (state.hasKey(ACTIVE_PART)) { + String activePart = state.getString(ACTIVE_PART); Provider provider = dynaProvider.getProvider(activePart); if (provider != null) { setActivePart(provider.get()); @@ -431,8 +437,8 @@ public Promise loadState(@NotNull JsonObject state) { private boolean isPerspectiveMaximized(JsonObject partStacksState) { for (String partStackType : partStacksState.keys()) { JsonObject partStackState = partStacksState.getObject(partStackType); - if (partStackState.hasKey("STATE") - && PartStack.State.MAXIMIZED.name().equals(partStackState.getString("STATE"))) { + if (partStackState.hasKey(PART_STACK_STATE) + && PartStack.State.MAXIMIZED.name().equals(partStackState.getString(PART_STACK_STATE))) { return true; } } @@ -453,13 +459,14 @@ private void loadPartStackState( WorkBenchPartController controller, JsonObject partStackState, boolean skipRestoreDimensions) { - if (partStackState.hasKey("PARTS")) { - JsonArray parts = partStackState.get("PARTS"); + + if (partStackState.hasKey(PART_STACK_PARTS)) { + JsonArray parts = partStackState.get(PART_STACK_PARTS); for (int i = 0; i < parts.length(); i++) { JsonObject value = parts.get(i); - if (value.hasKey("CLASS")) { - String className = value.getString("CLASS"); + if (value.hasKey(PART_CLASS_NAME)) { + String className = value.getString(PART_CLASS_NAME); Provider provider = dynaProvider.getProvider(className); if (provider != null) { PartPresenter partPresenter = provider.get(); @@ -472,8 +479,8 @@ private void loadPartStackState( } // restore part stack's active part - if (partStackState.hasKey("ACTIVE_PART")) { - String activePart = partStackState.getString("ACTIVE_PART"); + if (partStackState.hasKey(ACTIVE_PART)) { + String activePart = partStackState.getString(ACTIVE_PART); Provider provider = dynaProvider.getProvider(activePart); if (provider != null) { partStack.setActivePart(provider.get()); @@ -490,13 +497,15 @@ private void loadPartStackState( return; } - if (partStackState.hasKey("HIDDEN") && partStackState.getBoolean("HIDDEN")) { + if (partStackState.hasKey(HIDDEN_STATE) && partStackState.getBoolean(HIDDEN_STATE)) { + partStack.hide(); + controller.setHidden(true); return; } - if (partStackState.hasKey("SIZE")) { - double size = partStackState.getNumber("SIZE"); + if (partStackState.hasKey(PART_STACK_SIZE)) { + double size = partStackState.getNumber(PART_STACK_SIZE); // Size of the part must not be less 100 pixels. if (size <= MIN_PART_SIZE) { diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/statepersistance/AppStateConstants.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/statepersistance/AppStateConstants.java new file mode 100644 index 00000000000..8054adfbafa --- /dev/null +++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/statepersistance/AppStateConstants.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * 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: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.ide.statepersistance; + +/** + * Constants for the mappings in user preferences to store/restore app state. + * + * @author Roman Nikitenko + */ +public final class AppStateConstants { + + public static final String APP_STATE = "IdeAppStates"; + public static final String PERSPECTIVES = "perspectives"; + public static final String PART_STACKS = "PART_STACKS"; + public static final String PART_STACK_STATE = "STATE"; + public static final String PART_STACK_PARTS = "PARTS"; + public static final String PART_STACK_SIZE = "SIZE"; + public static final String ACTIVE_PART = "ACTIVE_PART"; + public static final String PART_CLASS_NAME = "CLASS"; + public static final String HIDDEN_STATE = "HIDDEN"; + + private AppStateConstants() {} +} diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/statepersistance/AppStateManager.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/statepersistance/AppStateManager.java index d15ad7801ab..31ab4995308 100644 --- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/statepersistance/AppStateManager.java +++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/statepersistance/AppStateManager.java @@ -10,6 +10,10 @@ */ package org.eclipse.che.ide.statepersistance; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.APP_STATE; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.PART_STACKS; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.PERSPECTIVES; + import com.google.common.annotations.VisibleForTesting; import com.google.gwt.user.client.Timer; import com.google.inject.Inject; @@ -24,9 +28,15 @@ import org.eclipse.che.api.core.model.workspace.Workspace; import org.eclipse.che.api.promises.client.Promise; import org.eclipse.che.api.promises.client.PromiseProvider; +import org.eclipse.che.api.promises.client.callback.AsyncPromiseHelper; +import org.eclipse.che.commons.annotation.Nullable; +import org.eclipse.che.ide.DelayedTask; import org.eclipse.che.ide.api.WindowActionEvent; import org.eclipse.che.ide.api.WindowActionHandler; import org.eclipse.che.ide.api.app.AppContext; +import org.eclipse.che.ide.api.parts.PartStackStateChangedEvent; +import org.eclipse.che.ide.api.parts.PartStackType; +import org.eclipse.che.ide.api.parts.PerspectiveManager; import org.eclipse.che.ide.api.preferences.PreferencesManager; import org.eclipse.che.ide.api.statepersistance.StateComponent; import org.eclipse.che.ide.api.workspace.WorkspaceReadyEvent; @@ -48,30 +58,41 @@ public class AppStateManager { private static final String WORKSPACE = "workspace"; + private final Provider perspectiveManagerProvider; private final Provider stateComponentRegistry; private final PreferencesManager preferencesManager; private final JsonFactory jsonFactory; private final PromiseProvider promises; + private EventBus eventBus; private final AppContext appContext; private JsonObject allWsState; + private final DelayedTask persistWorkspaceStateTask = + new DelayedTask() { + @Override + public void onExecute() { + persistWorkspaceState(); + } + }; @Inject public AppStateManager( + Provider perspectiveManagerProvider, Provider stateComponentRegistryProvider, PreferencesManager preferencesManager, JsonFactory jsonFactory, PromiseProvider promises, EventBus eventBus, AppContext appContext) { + this.perspectiveManagerProvider = perspectiveManagerProvider; this.stateComponentRegistry = stateComponentRegistryProvider; this.preferencesManager = preferencesManager; this.jsonFactory = jsonFactory; this.promises = promises; + this.eventBus = eventBus; this.appContext = appContext; - // delay is required because we need to wait some time while different components initialized - eventBus.addHandler(WorkspaceReadyEvent.getType(), e -> restoreWorkspaceStateWithDelay()); + eventBus.addHandler(WorkspaceReadyEvent.getType(), this::onWorkspaceReady); eventBus.addHandler( WindowActionEvent.TYPE, @@ -90,7 +111,7 @@ public void onWindowClosed(WindowActionEvent event) {} } public void readStateFromPreferences() { - final String json = preferencesManager.getValue(PREFERENCE_PROPERTY_NAME); + final String json = preferencesManager.getValue(APP_STATE); if (json == null) { allWsState = jsonFactory.createObject(); } else { @@ -103,13 +124,68 @@ public void readStateFromPreferences() { } } - private void restoreWorkspaceStateWithDelay() { - new Timer() { - @Override - public void run() { - restoreWorkspaceState(); - } - }.schedule(1000); + /** + * Gets cached state for given {@code partStackType}. Use {@link #readStateFromPreferences()} + * first to get not cached state + */ + @Nullable + public JsonObject getStateFor(PartStackType partStackType) { + String workspaceId = appContext.getWorkspace().getId(); + if (!allWsState.hasKey(workspaceId)) { + return null; + } + + JsonObject preferences = allWsState.getObject(workspaceId); + if (!preferences.hasKey(WORKSPACE)) { + return null; + } + + JsonObject workspace = preferences.getObject(WORKSPACE); + if (!workspace.hasKey(WORKSPACE)) { + return null; + } + + JsonObject workspaceState = workspace.getObject(WORKSPACE); + if (!workspaceState.hasKey(PERSPECTIVES)) { + return null; + } + + String perspectiveId = perspectiveManagerProvider.get().getPerspectiveId(); + JsonObject perspectives = workspaceState.getObject(PERSPECTIVES); + if (!perspectives.hasKey(perspectiveId)) { + return null; + } + + JsonObject projectPerspective = perspectives.getObject(perspectiveId); + if (!projectPerspective.hasKey(PART_STACKS)) { + return null; + } + + JsonObject partStacks = projectPerspective.getObject(PART_STACKS); + if (!partStacks.hasKey(partStackType.name())) { + return null; + } + + return partStacks.getObject(partStackType.name()); + } + + private Promise restoreWorkspaceStateWithDelay() { + return AsyncPromiseHelper.createFromAsyncRequest( + callback -> + new Timer() { + @Override + public void run() { + restoreWorkspaceState() + .then( + arg -> { + callback.onSuccess(null); + }) + .catchError( + arg -> { + callback.onFailure(arg.getCause()); + }); + } + }.schedule(1000)); } @VisibleForTesting @@ -171,7 +247,7 @@ public Promise persistWorkspaceState() { private Promise writeStateToPreferences(JsonObject state) { final String json = state.toJson(); - preferencesManager.setValue(PREFERENCE_PROPERTY_NAME, json); + preferencesManager.setValue(APP_STATE, json); return preferencesManager .flushPreferences() .catchError( @@ -186,4 +262,14 @@ private Promise writeStateToPreferences(JsonObject state) { public boolean hasStateForWorkspace(String wsId) { return allWsState.hasKey(wsId); } + + private void onWorkspaceReady(WorkspaceReadyEvent workspaceReadyEvent) { + // delay is required because we need to wait some time while different components initialized + restoreWorkspaceStateWithDelay() + .then( + ignored -> { + eventBus.addHandler( + PartStackStateChangedEvent.TYPE, event -> persistWorkspaceStateTask.delay(500)); + }); + } } diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspacePresenter.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspacePresenter.java index 0f544caf800..ad52942fc08 100644 --- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspacePresenter.java +++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspacePresenter.java @@ -10,6 +10,8 @@ */ package org.eclipse.che.ide.workspace; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.PERSPECTIVES; + import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.google.inject.Inject; import com.google.inject.Provider; @@ -168,7 +170,7 @@ public PartPresenter getActivePart() { public JsonObject getState() { JsonObject state = Json.createObject(); JsonObject perspectivesJs = Json.createObject(); - state.put("perspectives", perspectivesJs); + state.put(PERSPECTIVES, perspectivesJs); Map perspectives = perspectiveManagerProvider.get().getPerspectives(); for (Map.Entry entry : perspectives.entrySet()) { // store only default perspective @@ -181,8 +183,8 @@ public JsonObject getState() { @Override public Promise loadState(JsonObject state) { - if (state.hasKey("perspectives")) { - JsonObject perspectives = state.getObject("perspectives"); + if (state.hasKey(PERSPECTIVES)) { + JsonObject perspectives = state.getObject(PERSPECTIVES); Map perspectiveMap = perspectiveManagerProvider.get().getPerspectives(); ArrayOf> perspectivePromises = Collections.arrayOf(); for (String key : perspectives.keys()) { diff --git a/ide/che-core-ide-app/src/test/java/org/eclipse/che/ide/statepersistance/AppStateManagerTest.java b/ide/che-core-ide-app/src/test/java/org/eclipse/che/ide/statepersistance/AppStateManagerTest.java index 5c80f778709..8a5dbfca52d 100644 --- a/ide/che-core-ide-app/src/test/java/org/eclipse/che/ide/statepersistance/AppStateManagerTest.java +++ b/ide/che-core-ide-app/src/test/java/org/eclipse/che/ide/statepersistance/AppStateManagerTest.java @@ -10,6 +10,7 @@ */ package org.eclipse.che.ide.statepersistance; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.APP_STATE; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.nullable; @@ -31,6 +32,7 @@ import org.eclipse.che.api.promises.client.Promise; import org.eclipse.che.api.promises.client.PromiseProvider; import org.eclipse.che.ide.api.app.AppContext; +import org.eclipse.che.ide.api.parts.PerspectiveManager; import org.eclipse.che.ide.api.preferences.PreferencesManager; import org.eclipse.che.ide.api.statepersistance.StateComponent; import org.eclipse.che.ide.api.workspace.model.WorkspaceImpl; @@ -55,6 +57,7 @@ public class AppStateManagerTest { @Mock private StateComponentRegistry stateComponentRegistry; @Mock private Provider stateComponentRegistryProvider; + @Mock private Provider perspectiveManagerProvider; @Mock private StateComponent component1; @Mock private StateComponent component2; @Mock private Provider component1Provider; @@ -97,10 +100,11 @@ public void setUp() { when(component1.getId()).thenReturn("component1"); when(component2.getId()).thenReturn("component2"); when(preferencesManager.flushPreferences()).thenReturn(promise); - when(preferencesManager.getValue(AppStateManager.PREFERENCE_PROPERTY_NAME)).thenReturn(""); + when(preferencesManager.getValue(APP_STATE)).thenReturn(""); when(jsonFactory.parse(anyString())).thenReturn(pref = Json.createObject()); appStateManager = new AppStateManager( + perspectiveManagerProvider, stateComponentRegistryProvider, preferencesManager, jsonFactory, @@ -160,7 +164,7 @@ public void restoreShouldReadFromPreferences() throws Exception { pref.put(WS_ID, Json.createObject()); appStateManager.restoreWorkspaceState(); - verify(preferencesManager).getValue(AppStateManager.PREFERENCE_PROPERTY_NAME); + verify(preferencesManager).getValue(APP_STATE); } @Test diff --git a/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/pom.xml b/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/pom.xml index cd863c80041..471b38c7f17 100644 --- a/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/pom.xml +++ b/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/pom.xml @@ -29,6 +29,10 @@ com.google.guava guava + + com.google.gwt + gwt-elemental + com.google.gwt gwt-user diff --git a/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/ContributionMixinProvider.java b/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/ContributionMixinProvider.java index 07dd0a3b603..f160a44b0af 100644 --- a/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/ContributionMixinProvider.java +++ b/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/ContributionMixinProvider.java @@ -11,8 +11,10 @@ package org.eclipse.che.plugin.pullrequest.client; import static java.util.Collections.singletonList; +import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.RUNNING; import static org.eclipse.che.ide.api.constraints.Constraints.FIRST; import static org.eclipse.che.ide.api.parts.PartStackType.TOOLING; +import static org.eclipse.che.ide.statepersistance.AppStateConstants.HIDDEN_STATE; import static org.eclipse.che.plugin.pullrequest.shared.ContributionProjectTypeConstants.CONTRIBUTE_TO_BRANCH_VARIABLE_NAME; import static org.eclipse.che.plugin.pullrequest.shared.ContributionProjectTypeConstants.CONTRIBUTION_PROJECT_TYPE_ID; @@ -21,12 +23,16 @@ import com.google.inject.Singleton; import com.google.web.bindery.event.shared.EventBus; import com.google.web.bindery.event.shared.HandlerRegistration; +import elemental.json.JsonObject; import org.eclipse.che.api.core.model.workspace.WorkspaceStatus; import org.eclipse.che.api.promises.client.Promise; import org.eclipse.che.api.promises.client.PromiseProvider; import org.eclipse.che.ide.api.app.AppContext; import org.eclipse.che.ide.api.factory.FactoryAcceptedEvent; +import org.eclipse.che.ide.api.parts.PartPresenter; import org.eclipse.che.ide.api.parts.PartStack; +import org.eclipse.che.ide.api.parts.PartStack.State; +import org.eclipse.che.ide.api.parts.PartStackStateChangedEvent; import org.eclipse.che.ide.api.parts.WorkspaceAgent; import org.eclipse.che.ide.api.project.MutableProjectConfig; import org.eclipse.che.ide.api.resources.Project; @@ -35,6 +41,7 @@ import org.eclipse.che.ide.api.selection.SelectionChangedEvent; import org.eclipse.che.ide.api.workspace.WorkspaceReadyEvent; import org.eclipse.che.ide.api.workspace.event.WorkspaceStoppedEvent; +import org.eclipse.che.ide.statepersistance.AppStateManager; import org.eclipse.che.ide.ui.smartTree.data.HasDataObject; import org.eclipse.che.ide.util.loging.Log; import org.eclipse.che.plugin.pullrequest.client.parts.contribute.ContributePartPresenter; @@ -57,6 +64,7 @@ public class ContributionMixinProvider { private final EventBus eventBus; private final AppContext appContext; private final WorkspaceAgent workspaceAgent; + private final AppStateManager appStateManager; private final ContributePartPresenter contributePart; private final WorkflowExecutor workflowExecutor; private final VcsServiceProvider vcsServiceProvider; @@ -73,6 +81,7 @@ public ContributionMixinProvider( EventBus eventBus, AppContext appContext, WorkspaceAgent workspaceAgent, + AppStateManager appStateManager, ContributePartPresenter contributePart, WorkflowExecutor workflowExecutor, VcsServiceProvider vcsServiceProvider, @@ -82,6 +91,7 @@ public ContributionMixinProvider( this.eventBus = eventBus; this.appContext = appContext; this.workspaceAgent = workspaceAgent; + this.appStateManager = appStateManager; this.contributePart = contributePart; this.workflowExecutor = workflowExecutor; this.vcsServiceProvider = vcsServiceProvider; @@ -89,122 +99,129 @@ public ContributionMixinProvider( this.promiseProvider = promiseProvider; this.messages = messages; + eventBus.addHandler(WorkspaceStoppedEvent.TYPE, this::onWorkspaceStopped); + eventBus.addHandler(PartStackStateChangedEvent.TYPE, this::onPartStackStateChanged); + if (appContext.getFactory() != null) { eventBus.addHandler(FactoryAcceptedEvent.TYPE, event -> subscribeToSelectionChangedEvent()); } else { eventBus.addHandler( WorkspaceReadyEvent.getType(), event -> subscribeToSelectionChangedEvent()); } - - eventBus.addHandler( - WorkspaceStoppedEvent.TYPE, - event -> { - lastSelected = null; - contributePart.showStub(""); - if (selectionHandlerReg != null) { - selectionHandlerReg.removeHandler(); - } - }); } - private void subscribeToSelectionChangedEvent() { - selectionHandlerReg = - eventBus.addHandler( - SelectionChangedEvent.TYPE, event -> processCurrentProject(event.getSelection())); + private void onPartStackStateChanged(PartStackStateChangedEvent event) { + PartStack toolingPartStack = workspaceAgent.getPartStack(TOOLING); + if (event.getPartStack() != toolingPartStack || isPartStackHidden(toolingPartStack)) { + return; + } + + PartPresenter activePart = toolingPartStack.getActivePart(); + if (activePart == null || activePart == contributePart) { + handleCurrentProject(); + } } - private void processCurrentProject(Selection selection) { - if (WorkspaceStatus.RUNNING != appContext.getWorkspace().getStatus()) { + private void onSelectionChanged(Selection selection) { + WorkspaceStatus workspaceStatus = appContext.getWorkspace().getStatus(); + if (RUNNING != workspaceStatus + || !isSupportedSelection(selection) + || isContributePartHiddenByUser()) { return; } - if (!isSupportedSelection(selection)) { + if (appContext.getRootProject() != null) { + handleCurrentProject(); return; } - final Project rootProject = appContext.getRootProject(); + String message = + selection.isMultiSelection() + ? messages.stubTextShouldBeSelectedOnlyOneProject() + : messages.stubTextProjectIsNotSelected(); - if (lastSelected != null && lastSelected.equals(rootProject) && hasVcsService(rootProject)) { + contributePart.showStub(message); + invalidateContext(lastSelected); + } + + private void handleCurrentProject() { + Project project = appContext.getRootProject(); + if (project == null) { + invalidateContext(lastSelected); + contributePart.showStub(messages.stubTextProjectIsNotSelected()); return; } - contributePart.showStub(messages.stubTextLoading()); - - if (rootProject == null) { - invalidateContext(lastSelected); - lastSelected = null; - if (selection.isMultiSelection()) { - contributePart.showStub(messages.stubTextShouldBeSelectedOnlyOneProject()); - } else { - contributePart.showStub(messages.stubTextProjectIsNotSelected()); - } - } else if (hasVcsService(rootProject)) { - handleProjectWithVCS(rootProject); + if (hasVcsService(project)) { + initializeContributionWorkflow(project); } else { - invalidateContext(rootProject); + invalidateContext(project); contributePart.showStub(messages.stubTextProjectNotProvideSupportedVCS()); - lastSelected = null; } } - private boolean isSupportedSelection(Selection selection) { - if (selection instanceof Selection.NoSelectionProvided) { - return false; + private void initializeContributionWorkflow(Project project) { + if (lastSelected != null && lastSelected.equals(project) && hasVcsService(lastSelected)) { + return; } - Object headElem = selection.getHeadElement(); + vcsHostingServiceProvider + .getVcsHostingService(project) + .then( + vcsHostingService -> { + provideMixin(project) + .then( + updatedProject -> { + workflowExecutor.init(vcsHostingService, updatedProject); + lastSelected = updatedProject; + setContributePart(); + }) + .catchError( + error -> { + handleVCSError( + project, + messages.failedToApplyVCSMixin(project.getName(), error.getMessage())); + }); + }) + .catchError( + error -> { + handleVCSError( + project, messages.failedToGetVCSService(project.getName(), error.getMessage())); + }); + } - boolean isResourceSelection = headElem instanceof Resource; - boolean isHasDataWithResource = - headElem instanceof HasDataObject - && ((HasDataObject) headElem).getData() instanceof Resource; + private void setContributePart() { + PartStack partStack = workspaceAgent.getPartStack(TOOLING); + if (!partStack.containsPart(contributePart)) { + partStack.addPart(contributePart, FIRST); + } - return headElem == null || isResourceSelection || isHasDataWithResource; + PartPresenter activePart = partStack.getActivePart(); + if (activePart != contributePart) { + partStack.setActivePart(contributePart); + } + + contributePart.showContent(); } - private void handleProjectWithVCS(Project prj) { - if (hasContributionMixin(prj)) { - vcsHostingServiceProvider - .getVcsHostingService(prj) - .then( - vcsHostingService -> { - workflowExecutor.init(vcsHostingService, prj); - addPart(); - contributePart.showContent(); - - lastSelected = prj; - }) - .catchError( - err -> { - handleVCSError( - prj, messages.failedToGetVCSService(prj.getName(), err.getMessage())); - }); - } else { - vcsHostingServiceProvider - .getVcsHostingService(prj) - .then( - vcsHostingService -> { - addMixin(prj) - .then( - prjWithMixin -> { - workflowExecutor.init(vcsHostingService, prjWithMixin); - addPart(); - contributePart.showContent(); - - lastSelected = prjWithMixin; - }) - .catchError( - err -> { - handleVCSError( - prj, messages.failedToApplyVCSMixin(prj.getName(), err.getMessage())); - }); - }) - .catchError( - err -> { - handleVCSError( - prj, messages.failedToGetVCSService(prj.getName(), err.getMessage())); - }); + private Promise provideMixin(Project project) { + VcsService vcsService = vcsServiceProvider.getVcsService(project); + if (!hasVcsService(project) || hasContributionMixin(project)) { + return promiseProvider.resolve(project); } + + return vcsService + .getBranchName(project) + .thenPromise( + branchName -> { + MutableProjectConfig mutableConfig = new MutableProjectConfig(project); + mutableConfig.getMixins().add(CONTRIBUTION_PROJECT_TYPE_ID); + mutableConfig + .getAttributes() + .put(CONTRIBUTE_TO_BRANCH_VARIABLE_NAME, singletonList(branchName)); + + return project.update().withBody(mutableConfig).send(); + }); } private void handleVCSError(Project project, String logError) { @@ -220,16 +237,7 @@ private void invalidateContext(Project project) { workflowExecutor.invalidateContext(context.get().getProject()); } } - } - - private void addPart() { - PartStack partStack = workspaceAgent.getPartStack(TOOLING); - if (!partStack.containsPart(contributePart)) { - partStack.addPart(contributePart, FIRST); - if (partStack.getActivePart() == null) { - partStack.setActivePart(contributePart); - } - } + lastSelected = null; } private boolean hasVcsService(Project project) { @@ -240,24 +248,46 @@ private boolean hasContributionMixin(Project project) { return project.getMixins().contains(CONTRIBUTION_PROJECT_TYPE_ID); } - private Promise addMixin(final Project project) { - final VcsService vcsService = vcsServiceProvider.getVcsService(project); + private boolean isPartStackHidden(PartStack partStack) { + State partStackState = partStack.getPartStackState(); + return partStackState == State.HIDDEN || partStackState == State.MINIMIZED; + } - if (vcsService == null || project.getMixins().contains(CONTRIBUTION_PROJECT_TYPE_ID)) { - return promiseProvider.resolve(project); + private boolean isSupportedSelection(Selection selection) { + if (selection instanceof Selection.NoSelectionProvided) { + return false; } - return vcsService - .getBranchName(project) - .thenPromise( - branchName -> { - MutableProjectConfig mutableConfig = new MutableProjectConfig(project); - mutableConfig.getMixins().add(CONTRIBUTION_PROJECT_TYPE_ID); - mutableConfig - .getAttributes() - .put(CONTRIBUTE_TO_BRANCH_VARIABLE_NAME, singletonList(branchName)); + Object headElem = selection.getHeadElement(); - return project.update().withBody(mutableConfig).send(); - }); + boolean isResourceSelection = headElem instanceof Resource; + boolean isHasDataWithResource = + headElem instanceof HasDataObject + && ((HasDataObject) headElem).getData() instanceof Resource; + + return headElem == null || isResourceSelection || isHasDataWithResource; + } + + private boolean isContributePartHiddenByUser() { + JsonObject toolingPartStackState = appStateManager.getStateFor(TOOLING); + if (toolingPartStackState != null && toolingPartStackState.hasKey(HIDDEN_STATE)) { + return toolingPartStackState.getBoolean(HIDDEN_STATE); + } + + return false; + } + + private void subscribeToSelectionChangedEvent() { + selectionHandlerReg = + eventBus.addHandler( + SelectionChangedEvent.TYPE, event -> onSelectionChanged(event.getSelection())); + } + + private void onWorkspaceStopped(WorkspaceStoppedEvent event) { + lastSelected = null; + contributePart.showStub(""); + if (selectionHandlerReg != null) { + selectionHandlerReg.removeHandler(); + } } } diff --git a/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/actions/ContributePartDisplayingModeAction.java b/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/actions/ContributePartDisplayingModeAction.java index fcabe09c176..33537e38548 100644 --- a/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/actions/ContributePartDisplayingModeAction.java +++ b/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/actions/ContributePartDisplayingModeAction.java @@ -78,6 +78,7 @@ public void actionPerformed(ActionEvent e) { workspaceAgent.openPart(contributePartPresenter, TOOLING); workspaceAgent.setActivePart(contributePartPresenter); + contributePartPresenter.showContent(); } @Override diff --git a/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/parts/contribute/ContributePartPresenter.java b/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/parts/contribute/ContributePartPresenter.java index 06803b8040a..70b3bb9b810 100644 --- a/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/parts/contribute/ContributePartPresenter.java +++ b/plugins/plugin-pullrequest-parent/che-plugin-pullrequest-ide/src/main/java/org/eclipse/che/plugin/pullrequest/client/parts/contribute/ContributePartPresenter.java @@ -59,6 +59,7 @@ import org.eclipse.che.plugin.pullrequest.client.workflow.Step; import org.eclipse.che.plugin.pullrequest.client.workflow.WorkflowExecutor; import org.eclipse.che.plugin.pullrequest.client.workflow.WorkflowStatus; +import org.eclipse.che.providers.DynaObject; import org.vectomatic.dom.svg.ui.SVGResource; /** @@ -67,6 +68,7 @@ * @author Kevin Pollet */ @Singleton +@DynaObject public class ContributePartPresenter extends BasePresenter implements ContributePartView.ActionDelegate, StepHandler,