Skip to content

Fix: progress icon spin in combo box #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager
import com.intellij.remote.AuthType
import com.intellij.remote.RemoteCredentialsHolder
import com.intellij.ui.AnimatedIcon
import com.intellij.ui.ColoredListCellRenderer
import com.intellij.ui.components.JBTextField
import com.intellij.ui.dsl.builder.BottomGap
import com.intellij.ui.dsl.builder.RowLayout
import com.intellij.ui.dsl.builder.TopGap
import com.intellij.ui.dsl.builder.panel
import com.intellij.ui.dsl.gridLayout.HorizontalAlign
import com.intellij.util.ui.JBFont
import com.intellij.util.ui.JBUI
import com.intellij.util.ui.UIUtil
import com.jetbrains.gateway.api.GatewayUI
import com.jetbrains.gateway.ssh.CachingProductsJsonWrapper
Expand All @@ -47,7 +47,6 @@ class CoderLocateRemoteProjectStepView : CoderWorkspacesWizardStep, Disposable {
private val cs = CoroutineScope(Dispatchers.Main)
private val coderClient: CoderRestClientService = ApplicationManager.getApplication().getService(CoderRestClientService::class.java)

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

private lateinit var titleLabel: JLabel
Expand Down Expand Up @@ -111,25 +110,35 @@ class CoderLocateRemoteProjectStepView : CoderWorkspacesWizardStep, Disposable {

cs.launch {
logger.info("Retrieving available IDE's for ${selectedWorkspace.name} workspace...")
val workspaceOS = withContext(Dispatchers.IO) {
RemoteCredentialsHolder().apply {
setHost("coder.${selectedWorkspace.name}")
userName = "coder"
authType = AuthType.OPEN_SSH
}.guessOs
}
logger.info("Resolved OS and Arch for ${selectedWorkspace.name} is: $workspaceOS")
val idesWithStatus = IntelliJPlatformProduct.values()
.filter { it.showInGateway }
.flatMap { CachingProductsJsonWrapper.getAvailableIdes(it, workspaceOS) }
.map { ide -> IdeWithStatus(ide.product, ide.buildNumber, IdeStatus.DOWNLOAD, ide.downloadLink, ide.presentableVersion) }

if (idesWithStatus.isEmpty()) {
logger.warn("Could not resolve any IDE for workspace ${selectedWorkspace.name}, probably $workspaceOS is not supported by Gateway")
} else {
cbIDE.remove(spinner)
ideComboBoxModel.addAll(idesWithStatus)
cbIDE.selectedIndex = 0
try {
val workspaceOS = withContext(Dispatchers.IO) {
RemoteCredentialsHolder().apply {
setHost("coder.${selectedWorkspace.name}")
userName = "coder"
authType = AuthType.OPEN_SSH
}.guessOs
}
logger.info("Resolved OS and Arch for ${selectedWorkspace.name} is: $workspaceOS")
val idesWithStatus = IntelliJPlatformProduct.values()
.filter { it.showInGateway }
.flatMap { CachingProductsJsonWrapper.getAvailableIdes(it, workspaceOS) }
.map { ide -> IdeWithStatus(ide.product, ide.buildNumber, IdeStatus.DOWNLOAD, ide.downloadLink, ide.presentableVersion) }

if (idesWithStatus.isEmpty()) {
logger.warn("Could not resolve any IDE for workspace ${selectedWorkspace.name}, probably $workspaceOS is not supported by Gateway")
} else {
ideComboBoxModel.addAll(idesWithStatus)
cbIDE.selectedIndex = 0
}
} catch (e: Exception) {
logger.error("Could not resolve any IDE for workspace ${selectedWorkspace.name}. Reason: $e")
cbIDE.renderer = object : ColoredListCellRenderer<IdeWithStatus>() {
override fun customizeCellRenderer(list: JList<out IdeWithStatus>, value: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean) {
background = UIUtil.getListBackground(isSelected, cellHasFocus)
icon = UIUtil.getBalloonErrorIcon()
append(CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.error.text", selectedWorkspace.name))
}
}
}
}
}
Expand Down Expand Up @@ -162,29 +171,39 @@ class CoderLocateRemoteProjectStepView : CoderWorkspacesWizardStep, Disposable {
}

private class IDEComboBox(model: ComboBoxModel<IdeWithStatus>) : ComboBox<IdeWithStatus>(model) {

init {
putClientProperty(AnimatedIcon.ANIMATION_IN_RENDERER_ALLOWED, true)
}

override fun getSelectedItem(): IdeWithStatus? {
return super.getSelectedItem() as IdeWithStatus?
}
}

private class IDECellRenderer : ListCellRenderer<IdeWithStatus> {
private val loadingComponentRenderer: ListCellRenderer<IdeWithStatus> = object : ColoredListCellRenderer<IdeWithStatus>() {
override fun customizeCellRenderer(list: JList<out IdeWithStatus>, value: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean) {
background = UIUtil.getListBackground(isSelected, cellHasFocus)
icon = AnimatedIcon.Default.INSTANCE
append(CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.loading.text"))
}
}

override fun getListCellRendererComponent(list: JList<out IdeWithStatus>?, ideWithStatus: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean): Component {
return if (ideWithStatus == null && index == -1) {
JPanel().apply {
layout = FlowLayout(FlowLayout.LEFT)
add(JLabel("Retrieving products...", AnimatedIcon.Default(), SwingConstants.LEFT))
}
loadingComponentRenderer.getListCellRendererComponent(list, null, -1, isSelected, cellHasFocus)
} else if (ideWithStatus != null) {
JPanel().apply {
layout = FlowLayout(FlowLayout.LEFT)
add(JLabel(ideWithStatus.product.ideName, ideWithStatus.product.icon, SwingConstants.LEFT))
add(JLabel("${ideWithStatus.product.productCode} ${ideWithStatus.presentableVersion} ${ideWithStatus.buildNumber} | ${ideWithStatus.status.name.toLowerCase()}").apply {
foreground = UIUtil.getLabelDisabledForeground()
})
background = JBUI.CurrentTheme.List.background(isSelected, cellHasFocus)
background = UIUtil.getListBackground(isSelected, cellHasFocus)
}
} else {
JPanel()
panel { }
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/resources/messages/CoderGatewayBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ gateway.connector.view.login.token.label=Session Token:
gateway.connector.view.coder.auth.next.text=Connect
gateway.connector.view.login.cli.downloader.dialog.title=Authenticate and setup coder
gateway.connector.view.coder.workspaces.next.text=Select IDE and Project
gateway.connector.view.coder.remoteproject.next.text=Download and Start IDE
gateway.connector.view.coder.workspaces.choose.text=Choose a workspace
gateway.connector.view.coder.remoteproject.loading.text=Retrieving products...
gateway.connector.view.coder.remoteproject.ide.error.text=Could not retrieve any IDE for workspace {0} because an error was encountered
gateway.connector.view.coder.remoteproject.next.text=Download and Start IDE
gateway.connector.view.coder.remoteproject.choose.text=Choose IDE and project for workspace {0}
gateway.connector.recentconnections.title=Recent Coder Workspaces
gateway.connector.recentconnections.remove.button.tooltip=Remove from Recent Connections
Expand Down