Skip to content

Commit 5ca0790

Browse files
authored
Merge pull request #22 from coder/fix-progress-icon-on-ide-loading
- the progress icon in the IDE selection combo box was not spinning while IDEs were loading. - there were two reasons: 1. the combo box did not enable animated icons in the renderer 2. the cell renderer implementation did not repaint the icon - resolves #4 - the IDEs combo box is no longer stuck with the text "Retrieving products.." if an exception happens in the code. - instead, exceptions are handled a new custom combo box renderer is installed that tells the user that an error was encountered while retrieving the IDEs. - resolves #10
2 parents a64cb33 + ad50f82 commit 5ca0790

File tree

2 files changed

+49
-28
lines changed

2 files changed

+49
-28
lines changed

src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager
1414
import com.intellij.remote.AuthType
1515
import com.intellij.remote.RemoteCredentialsHolder
1616
import com.intellij.ui.AnimatedIcon
17+
import com.intellij.ui.ColoredListCellRenderer
1718
import com.intellij.ui.components.JBTextField
1819
import com.intellij.ui.dsl.builder.BottomGap
1920
import com.intellij.ui.dsl.builder.RowLayout
2021
import com.intellij.ui.dsl.builder.TopGap
2122
import com.intellij.ui.dsl.builder.panel
2223
import com.intellij.ui.dsl.gridLayout.HorizontalAlign
2324
import com.intellij.util.ui.JBFont
24-
import com.intellij.util.ui.JBUI
2525
import com.intellij.util.ui.UIUtil
2626
import com.jetbrains.gateway.api.GatewayUI
2727
import com.jetbrains.gateway.ssh.CachingProductsJsonWrapper
@@ -47,7 +47,6 @@ class CoderLocateRemoteProjectStepView : CoderWorkspacesWizardStep, Disposable {
4747
private val cs = CoroutineScope(Dispatchers.Main)
4848
private val coderClient: CoderRestClientService = ApplicationManager.getApplication().getService(CoderRestClientService::class.java)
4949

50-
private val spinner = JLabel("", AnimatedIcon.Default(), SwingConstants.LEFT)
5150
private var ideComboBoxModel = DefaultComboBoxModel<IdeWithStatus>()
5251

5352
private lateinit var titleLabel: JLabel
@@ -111,25 +110,35 @@ class CoderLocateRemoteProjectStepView : CoderWorkspacesWizardStep, Disposable {
111110

112111
cs.launch {
113112
logger.info("Retrieving available IDE's for ${selectedWorkspace.name} workspace...")
114-
val workspaceOS = withContext(Dispatchers.IO) {
115-
RemoteCredentialsHolder().apply {
116-
setHost("coder.${selectedWorkspace.name}")
117-
userName = "coder"
118-
authType = AuthType.OPEN_SSH
119-
}.guessOs
120-
}
121-
logger.info("Resolved OS and Arch for ${selectedWorkspace.name} is: $workspaceOS")
122-
val idesWithStatus = IntelliJPlatformProduct.values()
123-
.filter { it.showInGateway }
124-
.flatMap { CachingProductsJsonWrapper.getAvailableIdes(it, workspaceOS) }
125-
.map { ide -> IdeWithStatus(ide.product, ide.buildNumber, IdeStatus.DOWNLOAD, ide.downloadLink, ide.presentableVersion) }
126-
127-
if (idesWithStatus.isEmpty()) {
128-
logger.warn("Could not resolve any IDE for workspace ${selectedWorkspace.name}, probably $workspaceOS is not supported by Gateway")
129-
} else {
130-
cbIDE.remove(spinner)
131-
ideComboBoxModel.addAll(idesWithStatus)
132-
cbIDE.selectedIndex = 0
113+
try {
114+
val workspaceOS = withContext(Dispatchers.IO) {
115+
RemoteCredentialsHolder().apply {
116+
setHost("coder.${selectedWorkspace.name}")
117+
userName = "coder"
118+
authType = AuthType.OPEN_SSH
119+
}.guessOs
120+
}
121+
logger.info("Resolved OS and Arch for ${selectedWorkspace.name} is: $workspaceOS")
122+
val idesWithStatus = IntelliJPlatformProduct.values()
123+
.filter { it.showInGateway }
124+
.flatMap { CachingProductsJsonWrapper.getAvailableIdes(it, workspaceOS) }
125+
.map { ide -> IdeWithStatus(ide.product, ide.buildNumber, IdeStatus.DOWNLOAD, ide.downloadLink, ide.presentableVersion) }
126+
127+
if (idesWithStatus.isEmpty()) {
128+
logger.warn("Could not resolve any IDE for workspace ${selectedWorkspace.name}, probably $workspaceOS is not supported by Gateway")
129+
} else {
130+
ideComboBoxModel.addAll(idesWithStatus)
131+
cbIDE.selectedIndex = 0
132+
}
133+
} catch (e: Exception) {
134+
logger.error("Could not resolve any IDE for workspace ${selectedWorkspace.name}. Reason: $e")
135+
cbIDE.renderer = object : ColoredListCellRenderer<IdeWithStatus>() {
136+
override fun customizeCellRenderer(list: JList<out IdeWithStatus>, value: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean) {
137+
background = UIUtil.getListBackground(isSelected, cellHasFocus)
138+
icon = UIUtil.getBalloonErrorIcon()
139+
append(CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.error.text", selectedWorkspace.name))
140+
}
141+
}
133142
}
134143
}
135144
}
@@ -162,29 +171,39 @@ class CoderLocateRemoteProjectStepView : CoderWorkspacesWizardStep, Disposable {
162171
}
163172

164173
private class IDEComboBox(model: ComboBoxModel<IdeWithStatus>) : ComboBox<IdeWithStatus>(model) {
174+
175+
init {
176+
putClientProperty(AnimatedIcon.ANIMATION_IN_RENDERER_ALLOWED, true)
177+
}
178+
165179
override fun getSelectedItem(): IdeWithStatus? {
166180
return super.getSelectedItem() as IdeWithStatus?
167181
}
168182
}
169183

170184
private class IDECellRenderer : ListCellRenderer<IdeWithStatus> {
185+
private val loadingComponentRenderer: ListCellRenderer<IdeWithStatus> = object : ColoredListCellRenderer<IdeWithStatus>() {
186+
override fun customizeCellRenderer(list: JList<out IdeWithStatus>, value: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean) {
187+
background = UIUtil.getListBackground(isSelected, cellHasFocus)
188+
icon = AnimatedIcon.Default.INSTANCE
189+
append(CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.loading.text"))
190+
}
191+
}
192+
171193
override fun getListCellRendererComponent(list: JList<out IdeWithStatus>?, ideWithStatus: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean): Component {
172194
return if (ideWithStatus == null && index == -1) {
173-
JPanel().apply {
174-
layout = FlowLayout(FlowLayout.LEFT)
175-
add(JLabel("Retrieving products...", AnimatedIcon.Default(), SwingConstants.LEFT))
176-
}
195+
loadingComponentRenderer.getListCellRendererComponent(list, null, -1, isSelected, cellHasFocus)
177196
} else if (ideWithStatus != null) {
178197
JPanel().apply {
179198
layout = FlowLayout(FlowLayout.LEFT)
180199
add(JLabel(ideWithStatus.product.ideName, ideWithStatus.product.icon, SwingConstants.LEFT))
181200
add(JLabel("${ideWithStatus.product.productCode} ${ideWithStatus.presentableVersion} ${ideWithStatus.buildNumber} | ${ideWithStatus.status.name.toLowerCase()}").apply {
182201
foreground = UIUtil.getLabelDisabledForeground()
183202
})
184-
background = JBUI.CurrentTheme.List.background(isSelected, cellHasFocus)
203+
background = UIUtil.getListBackground(isSelected, cellHasFocus)
185204
}
186205
} else {
187-
JPanel()
206+
panel { }
188207
}
189208
}
190209
}

src/main/resources/messages/CoderGatewayBundle.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ gateway.connector.view.login.token.label=Session Token:
1010
gateway.connector.view.coder.auth.next.text=Connect
1111
gateway.connector.view.login.cli.downloader.dialog.title=Authenticate and setup coder
1212
gateway.connector.view.coder.workspaces.next.text=Select IDE and Project
13-
gateway.connector.view.coder.remoteproject.next.text=Download and Start IDE
1413
gateway.connector.view.coder.workspaces.choose.text=Choose a workspace
14+
gateway.connector.view.coder.remoteproject.loading.text=Retrieving products...
15+
gateway.connector.view.coder.remoteproject.ide.error.text=Could not retrieve any IDE for workspace {0} because an error was encountered
16+
gateway.connector.view.coder.remoteproject.next.text=Download and Start IDE
1517
gateway.connector.view.coder.remoteproject.choose.text=Choose IDE and project for workspace {0}
1618
gateway.connector.recentconnections.title=Recent Coder Workspaces
1719
gateway.connector.recentconnections.remove.button.tooltip=Remove from Recent Connections

0 commit comments

Comments
 (0)