diff --git a/.gitignore b/.gitignore index fe79b54bb74..2ee3893d0df 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,7 @@ out/ target/ /.idea/ +build/ +*.iml .DS_Store -Build/ +Build/ \ No newline at end of file diff --git a/src/main/kotlin/com/amazonaws/intellij/aws/AwsResourceManager.kt b/src/main/kotlin/com/amazonaws/intellij/aws/AwsResourceManager.kt index 9cb3d5a8929..89e66c43a3f 100644 --- a/src/main/kotlin/com/amazonaws/intellij/aws/AwsResourceManager.kt +++ b/src/main/kotlin/com/amazonaws/intellij/aws/AwsResourceManager.kt @@ -40,7 +40,7 @@ class AwsResourceBundle internal constructor() : S3ClientProvider, LambdaClientP } private class AwsResources(val region: String) { - val s3Client: AmazonS3 = AmazonS3Client() //AmazonS3ClientBuilder.standard().withRegion(region).build() + val s3Client: AmazonS3 = AmazonS3Client() //AmazonS3ClientBuilder.standard().withRegion(region).parse() val lambdaClient: AWSLambda = AWSLambdaClientBuilder.standard().withRegion(region).build() val iamClient: AmazonIdentityManagement = AmazonIdentityManagementClientBuilder.standard().withRegion(region).build() } diff --git a/src/main/kotlin/com/amazonaws/intellij/core/region/AwsDefaultRegionProvider.kt b/src/main/kotlin/com/amazonaws/intellij/core/region/AwsDefaultRegionProvider.kt new file mode 100644 index 00000000000..59bf2a76a1d --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/core/region/AwsDefaultRegionProvider.kt @@ -0,0 +1,33 @@ +package com.amazonaws.intellij.core.region + +import com.intellij.openapi.components.PersistentStateComponent +import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.components.State +import com.intellij.openapi.components.Storage +import com.intellij.openapi.project.Project + +@State(name = "region", storages = arrayOf(Storage("aws.xml"))) +class AwsDefaultRegionProvider(): + PersistentStateComponent { + + data class RegionState(var currentRegion: String? = AwsRegionManager.defaultRegion.id) + private var regionState: RegionState = RegionState() + var currentRegion: AwsRegion + get() = AwsRegionManager.lookupRegionById(regionState.currentRegion?: AwsRegionManager.defaultRegion.id) + set(value) { regionState.currentRegion = value.id } + + override fun loadState(regionState: RegionState) { + this.regionState.currentRegion = regionState.currentRegion + } + + override fun getState(): RegionState { + return regionState + } + + companion object { + @JvmStatic + fun getInstance(project: Project): AwsDefaultRegionProvider { + return ServiceManager.getService(project, AwsDefaultRegionProvider::class.java) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/amazonaws/intellij/core/region/AwsRegion.kt b/src/main/kotlin/com/amazonaws/intellij/core/region/AwsRegion.kt new file mode 100644 index 00000000000..e582146d54b --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/core/region/AwsRegion.kt @@ -0,0 +1,36 @@ +package com.amazonaws.intellij.core.region + +import com.amazonaws.regions.Region +import com.amazonaws.regions.RegionUtils +import com.amazonaws.regions.Regions +import com.intellij.openapi.util.IconLoader +import javax.swing.Icon + +data class AwsRegion private constructor(val id: String, val name: String, val icon: Icon) { + private companion object { + val UNKNOWN_REGION_FLAG = "/icons/aws-box.gif" + val REGION_FLAG_MAPPING = mapOf( + "us-east-1" to "/icons/flags/us.png", + "us-east-2" to "/icons/flags/us.png", + "us-west-1" to "/icons/flags/us.png", + "us-west-2" to "/icons/flags/us.png", + "ap-northeast-1" to "/icons/flags/japan.png", + "ap-southeast-1" to "/icons/flags/singapore.png", + "ap-southeast-2" to "/icons/flags/australia.png", + "eu-west-1" to "/icons/flags/ireland.png", + "eu-central-1" to "/icons/flags/eu.png", + "eu-west-2" to "/icons/flags/eu.png" + ) + } + + constructor(id: String, name: String): + this(id, name, IconLoader.getIcon (REGION_FLAG_MAPPING.getOrDefault(id, UNKNOWN_REGION_FLAG))) + + override fun toString(): String { + return name + } + + fun isServiceSupported(serviceId: String): Boolean { + return RegionUtils.getRegion(id).isServiceSupported(serviceId) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/amazonaws/intellij/core/region/AwsRegionManager.kt b/src/main/kotlin/com/amazonaws/intellij/core/region/AwsRegionManager.kt new file mode 100644 index 00000000000..a4e3f4f2b90 --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/core/region/AwsRegionManager.kt @@ -0,0 +1,63 @@ +package com.amazonaws.intellij.core.region + +import com.amazonaws.intellij.utils.notifyException +import com.amazonaws.partitions.model.Partitions +import com.amazonaws.regions.RegionUtils +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.MapperFeature +import com.fasterxml.jackson.databind.ObjectMapper +import com.google.common.collect.ImmutableMap +import com.intellij.openapi.diagnostic.Logger +import java.io.IOException + +object AwsRegionManager { + private const val DEFAULT_REGION = "us-west-2" + val regions: Map + val defaultRegion: AwsRegion + + init { + val partitions = PartitionLoader.parse() + + val mutableRegionMap = mutableMapOf() + partitions?.partitions?.forEach { + it.regions?.forEach { key, region -> mutableRegionMap.put(key, AwsRegion(key, region.description))} + } + + regions = ImmutableMap.copyOf(mutableRegionMap) + //TODO Is there a better way to notify the customer and report the error to us instead of just crash? + defaultRegion = regions.get(DEFAULT_REGION)!! + } + + fun lookupRegionById(regionId: String): AwsRegion { + return regions[regionId]?: defaultRegion + } + + fun isServiceSupported(region: String, serviceName: String): Boolean { + return RegionUtils.getRegion(region).isServiceSupported(serviceName) + } +} + +private object PartitionLoader { + //TODO This endpoint file should be update-to-date file + private const val JAVA_SDK_PARTITION_RESOURCE_PATH = "com/amazonaws/partitions/endpoints.json" + private val LOG = Logger.getInstance(PartitionLoader::class.java) + + private val mapper = ObjectMapper() + .disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS) + .disable(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS) + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .enable(JsonParser.Feature.ALLOW_COMMENTS) + + fun parse(): Partitions? { + PartitionLoader::class.java.classLoader.getResourceAsStream(JAVA_SDK_PARTITION_RESOURCE_PATH).use { + return try { + mapper.readValue(it, Partitions::class.java) + } catch (e: IOException) { + LOG.error("Error: failed to load file from $JAVA_SDK_PARTITION_RESOURCE_PATH !", e) + notifyException("Failed to load region endpoint file", e) + null + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/amazonaws/intellij/lambda/explorer/AwsExplorerLambdaNode.kt b/src/main/kotlin/com/amazonaws/intellij/lambda/explorer/AwsExplorerLambdaNode.kt new file mode 100644 index 00000000000..ffcf531e50a --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/lambda/explorer/AwsExplorerLambdaNode.kt @@ -0,0 +1,39 @@ +package com.amazonaws.intellij.lambda.explorer + +import com.amazonaws.intellij.ui.LAMBDA_SERVICE_ICON +import com.amazonaws.intellij.ui.SQS_QUEUE_ICON +import com.amazonaws.intellij.ui.explorer.AwsExplorerNode +import com.amazonaws.intellij.ui.explorer.AwsExplorerServiceRootNode +import com.amazonaws.services.lambda.AWSLambda +import com.amazonaws.services.lambda.AWSLambdaClientBuilder +import com.amazonaws.services.lambda.model.FunctionConfiguration +import com.intellij.ide.util.treeView.AbstractTreeNode +import com.intellij.openapi.project.Project + +class AwsExplorerLambdaRootNode(project: Project, region: String): + AwsExplorerServiceRootNode(project, "AWS Lambda", region, LAMBDA_SERVICE_ICON) { + + //TODO we need to move to ClientFactory for initializing service client + private val client: AWSLambda = AWSLambdaClientBuilder.standard() + .withRegion(region) + .build() + + override fun loadResources(): Collection { + //TODO We need to list all the functions, not just one page + return client.listFunctions().functions + } + + override fun mapResourceToNode(resource: FunctionConfiguration) = AwsExplorerFunctionNode(project!!, resource, region) +} + +class AwsExplorerFunctionNode(project: Project, private val function: FunctionConfiguration, region: String): + AwsExplorerNode(project, function, region, SQS_QUEUE_ICON) { //TODO replace to Function icon + + override fun getChildren(): Collection> { + return emptyList() + } + + override fun toString(): String { + return function.functionName + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/amazonaws/intellij/s3/explorer/AwsExplorerS3Node.kt b/src/main/kotlin/com/amazonaws/intellij/s3/explorer/AwsExplorerS3Node.kt new file mode 100644 index 00000000000..2679543c8f8 --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/s3/explorer/AwsExplorerS3Node.kt @@ -0,0 +1,39 @@ +package com.amazonaws.intellij.s3.explorer + +import com.amazonaws.intellij.ui.S3_BUCKET_ICON +import com.amazonaws.intellij.ui.S3_SERVICE_ICON +import com.amazonaws.intellij.ui.explorer.AwsExplorerNode +import com.amazonaws.intellij.ui.explorer.AwsExplorerServiceRootNode +import com.amazonaws.services.s3.AmazonS3 +import com.amazonaws.services.s3.AmazonS3ClientBuilder +import com.amazonaws.services.s3.model.Bucket +import com.intellij.ide.util.treeView.AbstractTreeNode +import com.intellij.openapi.project.Project + +class AwsExplorerS3RootNode(project: Project, region: String): + AwsExplorerServiceRootNode(project, "Amazon S3", region, S3_SERVICE_ICON) { + + //TODO use a ClientFactory instead + private var client: AmazonS3 = AmazonS3ClientBuilder.standard() + .withRegion(region) + .build() + + //TODO we need to load all the buckets + override fun loadResources(): Collection { + return client.listBuckets() + } + + override fun mapResourceToNode(resource: Bucket) = AwsExplorerBucketNode(project!!, resource, region) +} + +class AwsExplorerBucketNode(project: Project, private val bucket: Bucket, region: String): + AwsExplorerNode(project, bucket, region, S3_BUCKET_ICON) { + + override fun getChildren(): Collection> { + return emptyList() + } + + override fun toString(): String { + return bucket.name + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerFactory.kt b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerFactory.kt new file mode 100644 index 00000000000..604813d66c0 --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerFactory.kt @@ -0,0 +1,15 @@ +package com.amazonaws.intellij.ui.explorer + +import com.intellij.openapi.project.DumbAware +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.SimpleToolWindowPanel +import com.intellij.openapi.wm.ToolWindow +import com.intellij.openapi.wm.ToolWindowFactory +import com.intellij.ui.components.panels.Wrapper + +class AwsExplorerFactory : ToolWindowFactory, DumbAware { + + override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) { + toolWindow.component.parent.add(ExplorerToolWindow(project)) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerMain.kt b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerMain.kt index 5e85b14c114..453bf2dc7d6 100644 --- a/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerMain.kt +++ b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerMain.kt @@ -53,6 +53,7 @@ class AwsExplorerMainView(eventHandler: AwsExplorerMainEventHandler, s3DetailsVi main.leftComponent.preferredSize = Dimension(500, 100) main.dividerSize = 2 add(main) + add(resources) } fun updateResources(root: TreeNode) { diff --git a/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerNode.kt b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerNode.kt new file mode 100644 index 00000000000..58e68519e29 --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerNode.kt @@ -0,0 +1,99 @@ +package com.amazonaws.intellij.ui.explorer + +import com.amazonaws.intellij.core.region.AwsRegionManager +import com.amazonaws.intellij.ui.AWS_ICON +import com.intellij.ide.projectView.PresentationData +import com.intellij.ide.util.treeView.AbstractTreeNode +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.ClearableLazyValue +import com.intellij.ui.SimpleTextAttributes +import javax.swing.Icon + +/** + * Created by zhaoxiz on 7/27/17. + */ +abstract class AwsExplorerNode(project: Project, value: T, val region: String, val awsIcon: Icon?): + AbstractTreeNode(project, value) { + + override fun update(presentation: PresentationData?) { + presentation?.setIcon(awsIcon) + } + + override fun toString() = value.toString() +} + +class AwsExplorerRootNode(project: Project, region: String): + AwsExplorerNode(project, "ROOT", region, AWS_ICON) { + + override fun getChildren(): Collection> { + val childrenList = mutableListOf>() + AwsExplorerService.values() + .filter { AwsRegionManager.isServiceSupported(region, it.serviceId) } + .mapTo(childrenList) { it.buildServiceRootNode(project!!, region) } + + return childrenList + } +} + +abstract class AwsExplorerServiceRootNode(project: Project, value: String, region: String, awsIcon: Icon): + AwsExplorerNode(project, value, region, awsIcon) { + val cache: ClearableLazyValue>> + + init { + cache = object : ClearableLazyValue>>() { + override fun compute(): Collection> { + return try { + val resources = loadResources() + if (resources.isEmpty()) { + // Return EmptyNode as the single node of the list + listOf(AwsExplorerEmptyNode(project, region)) + } else { + resources.map { mapResourceToNode(it) } + } + } catch (e: Exception) { + // Return the ErrorNode as the single Node of the list + listOf(AwsExplorerErrorNode(project, e, region)) + } + } + } + } + + override fun getChildren(): Collection> { + return cache.value + } + + // This method may throw RuntimeException, must handle it + abstract fun loadResources(): Collection + + abstract fun mapResourceToNode(resource: Resource): AwsExplorerNode +} + +class AwsExplorerErrorNode(project: Project, exception: Exception, region: String): + AwsExplorerNode(project, exception, region, null) { + + override fun getChildren(): Collection> { + return emptyList() + } + + override fun toString(): String { + return "Error Loading Resources..." + } + + override fun update(presentation: PresentationData?) { + super.update(presentation) + presentation?.tooltip = value.message + presentation?.addText(toString(), SimpleTextAttributes.ERROR_ATTRIBUTES) + } +} + +class AwsExplorerEmptyNode(project: Project, region: String): AwsExplorerNode(project, "empty", region, null) { + + override fun getChildren(): Collection> { + return emptyList() + } + + override fun update(presentation: PresentationData?) { + super.update(presentation) + presentation?.addText(toString(), SimpleTextAttributes.GRAYED_ATTRIBUTES) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerService.kt b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerService.kt new file mode 100644 index 00000000000..de9ab7c0e98 --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerService.kt @@ -0,0 +1,24 @@ +package com.amazonaws.intellij.ui.explorer + +import com.amazonaws.intellij.lambda.explorer.AwsExplorerLambdaRootNode +import com.amazonaws.intellij.s3.explorer.AwsExplorerS3RootNode +import com.amazonaws.services.lambda.AWSLambda +import com.amazonaws.services.s3.AmazonS3 +import com.intellij.ide.util.treeView.AbstractTreeNode +import com.intellij.openapi.project.Project + +enum class AwsExplorerService(val serviceId: String) { + S3(AmazonS3.ENDPOINT_PREFIX) { + override fun buildServiceRootNode(project: Project, region: String): AwsExplorerS3RootNode { + return AwsExplorerS3RootNode(project, region) + } + }, + LAMBDA(AWSLambda.ENDPOINT_PREFIX) { + override fun buildServiceRootNode(project: Project, region: String): AwsExplorerLambdaRootNode { + return AwsExplorerLambdaRootNode(project, region) + } + }, + ; + + abstract fun buildServiceRootNode(project: Project, region: String): AbstractTreeNode +} \ No newline at end of file diff --git a/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerToolWindowFactory.kt b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerToolWindowFactory.kt index b6d3e6954da..0df59d2442c 100644 --- a/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerToolWindowFactory.kt +++ b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerToolWindowFactory.kt @@ -28,7 +28,11 @@ interface HasIcon { val icon: Icon } -class AwsTreeNode(override val icon: Icon, val value: T, toName: (T) -> String = { it.toString() }) : HasIcon, DefaultMutableTreeNode(toName(value)) +open class AwsTreeNode( + override val icon: Icon, + val value: T, + toName: (T) -> String = { it.toString() } +) : HasIcon, DefaultMutableTreeNode(toName(value)) class TreeCellRenderer : DefaultTreeCellRenderer() { override fun getTreeCellRendererComponent(tree: JTree?, value: Any?, sel: Boolean, expanded: Boolean, leaf: Boolean, row: Int, hasFocus: Boolean): Component { diff --git a/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerTreeBuilder.kt b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerTreeBuilder.kt new file mode 100644 index 00000000000..32e12b90af4 --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerTreeBuilder.kt @@ -0,0 +1,17 @@ +package com.amazonaws.intellij.ui.explorer + +import com.intellij.ide.util.treeView.AbstractTreeBuilder +import com.intellij.ide.util.treeView.NodeDescriptor +import com.intellij.openapi.project.Project +import javax.swing.JTree +import javax.swing.tree.DefaultTreeModel + +class AwsExplorerTreeBuilder(tree: JTree, treeModel: DefaultTreeModel, private val project: Project, private val region: String): + AbstractTreeBuilder(tree, treeModel, AwsExplorerTreeStructure(project, region), null, false) { + + init { + initRootNode() + } + + override fun isAlwaysShowPlus(descriptor: NodeDescriptor<*>?) = descriptor is AwsExplorerServiceRootNode<*> +} diff --git a/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerTreeStructure.kt b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerTreeStructure.kt new file mode 100644 index 00000000000..2b6b48a3cc5 --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/AwsExplorerTreeStructure.kt @@ -0,0 +1,27 @@ +package com.amazonaws.intellij.ui.explorer + +import com.intellij.ide.projectView.TreeStructureProvider +import com.intellij.ide.util.treeView.AbstractTreeStructureBase +import com.intellij.openapi.project.Project + +class AwsExplorerTreeStructure(project: Project, val region: String) : AbstractTreeStructureBase(project) { + + override fun getProviders(): List? { + return emptyList() + } + + override fun getRootElement(): AwsExplorerRootNode { + return AwsExplorerRootNode(myProject, region) + } + + override fun commit() { + } + + override fun hasSomethingToCommit(): Boolean { + return false + } + + override fun isToBuildChildrenInBackground(element: Any?): Boolean { + return true + } +} diff --git a/src/main/kotlin/com/amazonaws/intellij/ui/explorer/ExplorerToolWindow.kt b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/ExplorerToolWindow.kt new file mode 100644 index 00000000000..de2cf2909b8 --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/ui/explorer/ExplorerToolWindow.kt @@ -0,0 +1,66 @@ +package com.amazonaws.intellij.ui.explorer +import com.amazonaws.intellij.core.region.AwsDefaultRegionProvider +import com.amazonaws.intellij.ui.widgets.AwsRegionPanel +import com.intellij.ide.util.treeView.NodeDescriptor +import com.intellij.ide.util.treeView.NodeRenderer +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.SimpleToolWindowPanel +import com.intellij.openapi.util.Disposer +import com.intellij.ui.components.JBScrollPane +import com.intellij.ui.components.panels.Wrapper +import com.intellij.ui.treeStructure.Tree +import com.intellij.util.ui.UIUtil +import java.awt.FlowLayout +import java.awt.event.ActionListener +import javax.swing.JPanel +import javax.swing.JTree +import javax.swing.tree.DefaultMutableTreeNode +import javax.swing.tree.DefaultTreeModel + +class ExplorerToolWindow(val project: Project): + SimpleToolWindowPanel(true, false) { + + private val treePanelWrapper: Wrapper = Wrapper(); + private val regionProvider: AwsDefaultRegionProvider = AwsDefaultRegionProvider.getInstance(project) + private val regionPanel: AwsRegionPanel + private val mainPanel: JPanel + + init{ + regionPanel = AwsRegionPanel(regionProvider.currentRegion) + regionPanel.addActionListener(ActionListener { onAwsRegionComboSelected() }) + + mainPanel = JPanel(FlowLayout(FlowLayout.LEADING, 0, 0)) + mainPanel.add(regionPanel.regionPanel) + setToolbar(mainPanel) + setContent(treePanelWrapper) + onAwsRegionComboSelected() + } + + private fun onAwsRegionComboSelected() { + val selectedRegion = regionPanel.getSelectedRegion() ?: return + val model = DefaultTreeModel(DefaultMutableTreeNode()) + val awsTree = createTree() + val builder = AwsExplorerTreeBuilder(awsTree, model, project, selectedRegion.id) + Disposer.register(project, builder) + treePanelWrapper.setContent(JBScrollPane(awsTree)) + regionProvider.currentRegion = selectedRegion + } + + private fun createTree(): JTree { + val awsTree = Tree() + UIUtil.setLineStyleAngled(awsTree) + awsTree.isRootVisible = false + awsTree.autoscrolls = true + awsTree.cellRenderer = AwsTreeCellRenderer() + return awsTree + } + + private class AwsTreeCellRenderer:NodeRenderer() { + override fun customizeCellRenderer(tree: JTree, value: Any, selected: Boolean, expanded: Boolean, leaf: Boolean, row: Int, hasFocus: Boolean) { + super.customizeCellRenderer(tree, value, selected, expanded, leaf, row, hasFocus) + if (value is DefaultMutableTreeNode && value.userObject is NodeDescriptor<*>) { + icon = (value.userObject as NodeDescriptor<*>).icon + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/amazonaws/intellij/ui/widgets/AwsRegionPanel.kt b/src/main/kotlin/com/amazonaws/intellij/ui/widgets/AwsRegionPanel.kt new file mode 100644 index 00000000000..801887f4442 --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/ui/widgets/AwsRegionPanel.kt @@ -0,0 +1,45 @@ +package com.amazonaws.intellij.ui.widgets + +import com.amazonaws.intellij.core.region.AwsRegion +import com.amazonaws.intellij.core.region.AwsRegionManager +import com.intellij.openapi.ui.ComboBox +import com.intellij.ui.CollectionComboBoxModel +import com.intellij.ui.ListCellRendererWrapper +import java.awt.FlowLayout +import java.awt.event.ActionListener +import javax.swing.JLabel +import javax.swing.JList +import javax.swing.JPanel + +class AwsRegionPanel(private val defaultRegion: AwsRegion) { + val regionPanel: JPanel = JPanel() + private val regionCombo: ComboBox = ComboBox() + private val regionModel = CollectionComboBoxModel(AwsRegionManager.regions.values.toList()) + + init { + regionCombo.renderer = object : ListCellRendererWrapper() { + override fun customize(list: JList<*>, value: AwsRegion, index: Int, selected: Boolean, hasFocus: Boolean) { + setIcon(value.icon) + } + } + setupUI() + regionCombo.model = regionModel + regionModel.selectedItem = defaultRegion + } + + fun addActionListener(actionListener: ActionListener) { + regionCombo.addActionListener(actionListener) + } + + fun getSelectedRegion(): AwsRegion? { + return regionModel.selected + } + + private fun setupUI() { + regionPanel.layout = FlowLayout(FlowLayout.CENTER, 0, 0) + val regionLabel = JLabel("Region") + regionPanel.add(regionLabel) + regionPanel.add(regionCombo) + regionLabel.labelFor = regionCombo + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/amazonaws/intellij/utils/ErrorReport.kt b/src/main/kotlin/com/amazonaws/intellij/utils/ErrorReport.kt new file mode 100644 index 00000000000..b5a871b7803 --- /dev/null +++ b/src/main/kotlin/com/amazonaws/intellij/utils/ErrorReport.kt @@ -0,0 +1,7 @@ +package com.amazonaws.intellij.utils + +import com.intellij.notification.Notification +import com.intellij.notification.NotificationType +import com.intellij.notification.Notifications + +fun notifyException(action: String, e: Exception) = Notifications.Bus.notify(Notification("AWS Tookit", action, e.message ?: e.javaClass.name, NotificationType.ERROR)) \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 2bf67fcaafc..1952e0e0354 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -28,13 +28,19 @@ + + + + + @@ -50,4 +56,4 @@ - \ No newline at end of file +