From ab7b2a0ecf99ca4aaae39dec9ca3f97d7874a1f7 Mon Sep 17 00:00:00 2001 From: Michael Golubev Date: Fri, 30 May 2014 15:20:18 +0200 Subject: [PATCH] IDEA-122962 - Clouds: perform connection test in background - auto-reload in frameworks --- .../RemoteServerConfigurable.java | 121 +++++++++--------- .../util/CloudAccountSelectionEditor.java | 53 ++++++++ .../remoteServer/util/CloudDataLoader.java | 36 ++++++ .../util/CloudSupportConfigurableBase.java | 30 +++-- .../remoteServer/util/DelayedRunner.java | 78 +++++++++++ 5 files changed, 250 insertions(+), 68 deletions(-) create mode 100644 platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDataLoader.java create mode 100644 platform/remote-servers/impl/src/com/intellij/remoteServer/util/DelayedRunner.java diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java index 2c1734a28995..a614c4e642c9 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java @@ -1,6 +1,5 @@ package com.intellij.remoteServer.impl.configuration; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.UnnamedConfigurable; @@ -14,8 +13,9 @@ import com.intellij.remoteServer.runtime.ServerConnection; import com.intellij.remoteServer.runtime.ServerConnectionManager; import com.intellij.remoteServer.runtime.ServerConnector; import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance; +import com.intellij.remoteServer.util.CloudDataLoader; +import com.intellij.remoteServer.util.DelayedRunner; import com.intellij.ui.components.JBLabel; -import com.intellij.util.Alarm; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.ui.UIUtil; import com.intellij.util.xmlb.XmlSerializerUtil; @@ -36,9 +36,6 @@ public class RemoteServerConfigurable extends NamedConfigurable> private static final String HELP_TOPIC_ID = "reference.settings.clouds"; - private static final int CHANGES_CHECK_TIME = 500; - private static final int CONNECTION_CHECK_TIME = 2000; - private static final int NO_CHANGES = -1; private final UnnamedConfigurable myConfigurable; private final RemoteServer myServer; @@ -48,14 +45,17 @@ public class RemoteServerConfigurable extends NamedConfigurable> private JPanel mySettingsPanel; private JBLabel myConnectionStatusLabel; - private final Alarm myAlarm; - private int myChangesPastTime = NO_CHANGES; + private final DelayedRunner myRunner; private ConnectionTester myConnectionTester; private final RemoteServer myInnerServer; private boolean myInnerApplied; private boolean myUncheckedApply; + private boolean myConnected; + + private CloudDataLoader myDataLoader = CloudDataLoader.NULL; + public RemoteServerConfigurable(RemoteServer server, Runnable treeUpdater, boolean isNew) { super(true, treeUpdater); myServer = server; @@ -69,64 +69,69 @@ public class RemoteServerConfigurable extends NamedConfigurable> myConfigurable = server.getType().createConfigurable(innerConfiguration); - myAlarm = new Alarm().setActivationComponent(myMainPanel); - queueChangesCheck(); - } - - private void queueChangesCheck() { - if (myAlarm.isDisposed()) { - return; - } - myAlarm.addRequest(new Runnable() { + myConnected = false; + myRunner = new DelayedRunner(myMainPanel) { @Override - public void run() { - checkChanges(); - queueChangesCheck(); + protected boolean wasChanged() { + boolean modified = myConfigurable.isModified(); + boolean result = modified || myUncheckedApply; + if (result) { + myUncheckedApply = false; + + setConnectionStatus(""); + myConnectionTester = null; + + if (modified) { + try { + myConfigurable.apply(); + myInnerApplied = true; + } + catch (ConfigurationException e) { + setConnectionStatus(e.getMessage()); + } + } + } + return result; } - }, CHANGES_CHECK_TIME, ModalityState.any()); + + @Override + protected void run() { + setConnectionStatus("Connecting..."); + + myConnectionTester = new ConnectionTester(); + myConnectionTester.testConnection(); + } + }; } - private void checkChanges() { - boolean modified = myConfigurable.isModified(); - if (modified || myUncheckedApply) { - myUncheckedApply = false; + private void setConnectionStatus(String text) { + setConnectionStatus(false, text); + } - setConnectionStatusText(""); - myConnectionTester = null; + private void setConnectionStatus(boolean connected, String text) { + boolean changed = myConnected != connected; + myConnected = connected; + myConnectionStatusLabel.setText(UIUtil.toHtml(text)); + if (changed) { + notifyDataLoader(); + } + } - if (modified) { - try { - myConfigurable.apply(); - myInnerApplied = true; - } - catch (ConfigurationException e) { - LOG.debug(e); - return; - } - } + public void setDataLoader(CloudDataLoader dataLoader) { + myDataLoader = dataLoader; + notifyDataLoader(); + } - myChangesPastTime = 0; + private void notifyDataLoader() { + if (myConnected) { + myDataLoader.loadCloudData(); } else { - if (myChangesPastTime != NO_CHANGES) { - myChangesPastTime += CHANGES_CHECK_TIME; - if (myChangesPastTime >= CONNECTION_CHECK_TIME) { - myChangesPastTime = NO_CHANGES; - - setConnectionStatusText("Connecting..."); - - myConnectionTester = new ConnectionTester(); - myConnectionTester.testConnection(); - } - } + myDataLoader.clearCloudData(); } } - private void setConnectionStatusText(String text) { - myConnectionStatusLabel.setText(UIUtil.toHtml(text)); - } - @Override public RemoteServer getEditableObject() { return myServer; @@ -183,7 +188,7 @@ public class RemoteServerConfigurable extends NamedConfigurable> @Override public void disposeUIResources() { myConfigurable.disposeUIResources(); - Disposer.dispose(myAlarm); + Disposer.dispose(myRunner); } @Nullable @@ -232,17 +237,13 @@ public class RemoteServerConfigurable extends NamedConfigurable> @Override public void run() { - showConnectionStatus(connected, connection.getStatusText()); + if (myConnectionTester == ConnectionTester.this) { + setConnectionStatus(connected, connected ? "Connection successful" : "Cannot connect: " + connection.getStatusText()); + } } }); } }.queue(); } - - private void showConnectionStatus(boolean connected, String statusText) { - if (myConnectionTester == this) { - setConnectionStatusText(connected ? "Connection successful" : "Cannot connect: " + statusText); - } - } } } diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java index 92f4d0627a5c..7bd38b481cbb 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java @@ -26,6 +26,7 @@ import com.intellij.openapi.module.ModulePointerManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Disposer; import com.intellij.remoteServer.ServerType; import com.intellij.remoteServer.configuration.RemoteServer; import com.intellij.remoteServer.configuration.RemoteServersManager; @@ -57,12 +58,18 @@ public class CloudAccountSelectionEditor myNewServer; private RemoteServerConfigurable myServerConfigurable; + + private DelayedRunner myRunner; + + private CloudDataLoader myDataLoader = CloudDataLoader.NULL; + public CloudAccountSelectionEditor(ST cloudType) { myCloudType = cloudType; } private void createUIComponents() { myServerConfigurablePanel = createServerConfigurablePanel(); + myServerConfigurablePanel.setVisible(false); } public void initUI() { @@ -78,6 +85,51 @@ public class CloudAccountSelectionEditor, ST extends ServerType> - extends FrameworkSupportConfigurable { + extends FrameworkSupportConfigurable implements CloudDataLoader { private final ST myCloudType; private final Project myModelProject; @@ -58,8 +59,14 @@ public abstract class CloudSupportConfigurableBase< getAccountSelectionEditor().initUI(); } - protected void reloadExistingApplications() { - Collection deployments = new ConnectionTask>("Loading existing applications list") { + @Override + public void clearCloudData() { + getExistingComboBox().removeAllItems(); + } + + @Override + public void loadCloudData() { + new ConnectionTask>("Loading existing applications list") { @Override protected void run(final ServerConnection connection, @@ -75,6 +82,14 @@ public abstract class CloudSupportConfigurableBase< public void run() { result.set(connection.getDeployments()); semaphore.up(); + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + if (!Disposer.isDisposed(CloudSupportConfigurableBase.this)) { + setupExistingApplications(result.get()); + } + } + }); } }); } @@ -91,12 +106,10 @@ public abstract class CloudSupportConfigurableBase< protected Collection run(SR serverRuntimeInstance) throws ServerRuntimeException { return null; } - }.performSync(); - - if (deployments == null) { - return; - } + }.performAsync(); + } + private void setupExistingApplications(Collection deployments) { JComboBox existingComboBox = getExistingComboBox(); existingComboBox.removeAllItems(); for (Deployment deployment : deployments) { @@ -151,6 +164,7 @@ public abstract class CloudSupportConfigurableBase< getNotifier().showMessage(e.getMessage(), MessageType.ERROR); } }; + myAccountSelectionEditor.setDataLoader(this); } return myAccountSelectionEditor; } diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/DelayedRunner.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/DelayedRunner.java new file mode 100644 index 000000000000..8ece5b9b3551 --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/DelayedRunner.java @@ -0,0 +1,78 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.remoteServer.util; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.util.Disposer; +import com.intellij.util.Alarm; + +import javax.swing.*; + +public abstract class DelayedRunner implements Disposable { + + private static final int CHANGES_CHECK_TIME = 500; + private static final int RUN_DELAY_TIME = 2000; + private static final int NO_CHANGES = -1; + + private final Alarm myAlarm; + + private int myChangesPastTime = NO_CHANGES; + + public DelayedRunner(JComponent activationComponent) { + myAlarm = new Alarm().setActivationComponent(activationComponent); + queueChangesCheck(); + } + + private void queueChangesCheck() { + if (myAlarm.isDisposed()) { + return; + } + myAlarm.addRequest(new Runnable() { + + @Override + public void run() { + checkChanges(); + queueChangesCheck(); + } + }, CHANGES_CHECK_TIME, ModalityState.any()); + } + + private void checkChanges() { + if (wasChanged()) { + myChangesPastTime = 0; + } + else { + if (myChangesPastTime != NO_CHANGES) { + myChangesPastTime += CHANGES_CHECK_TIME; + if (myChangesPastTime >= RUN_DELAY_TIME) { + myChangesPastTime = NO_CHANGES; + + run(); + } + } + } + } + + @Override + public void dispose() { + Disposer.dispose(myAlarm); + } + + protected abstract boolean wasChanged(); + + protected abstract void run(); +}