mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[clonedialog] Introduce new clone dialog and its API
New API is designed to provide two abilities for implementators: 1. Extending clone dialog with custom external components (e.g. for some cloud VCS hosting providers, like Github, Bitbucket, GitLab, etc). For each new extensions it is required to implement `VcsCloneDialogExtension` and `VcsCloneDialogExtensionComponent` interfaces. 2. Extending the existing "Repository URL" clone dialog component with UI for clone process initiating for any VCS based on `CheckoutProvider`. It is required to implement `com.intellij.openapi.vcs.CheckoutProvider#buildVcsCloneComponent`. GitOrigin-RevId: 997db50dca810cdf802c0c7bf6aabc3a9c523a6b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b77f28e5f1
commit
5803710c02
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="2" height="8.386" x="7.532" y="3.269" fill="#6E6E6E" transform="rotate(45 8.532 7.462)"/>
|
||||
<polygon fill="#6E6E6E" points="4 5 11 12 4 12"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 297 B |
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="2" height="8.386" x="7.532" y="3.269" fill="#AFB1B3" transform="rotate(45 8.532 7.462)"/>
|
||||
<polygon fill="#AFB1B3" points="4 5 11 12 4 12"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 297 B |
@@ -105,6 +105,8 @@
|
||||
<extensionPoint name="vcsRepositoryInitializer" interface="com.intellij.vcs.VcsRepositoryInitializer"/>
|
||||
<extensionPoint name="openapi.vcs.changes.vcsPreservingExecutor"
|
||||
interface="com.intellij.openapi.vcs.changes.VcsPreservingExecutor"/>
|
||||
<extensionPoint qualifiedName="com.intellij.openapi.vcs.ui.cloneDialog.VcsCloneDialogExtension"
|
||||
interface="com.intellij.openapi.vcs.ui.cloneDialog.VcsCloneDialogExtension"/>
|
||||
|
||||
</extensionPoints>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -140,6 +140,11 @@
|
||||
<nonProjectFileWritingAccessExtension implementation="com.intellij.openapi.vcs.changes.IgnoredFileWritingAccessExtension"/>
|
||||
|
||||
<statistics.applicationUsagesCollector implementation="com.intellij.openapi.vcs.statistics.VcsApplicationOptionsUsagesCollector"/>
|
||||
|
||||
<openapi.vcs.ui.cloneDialog.VcsCloneDialogExtension
|
||||
id="com.intellij.util.ui.cloneDialog.RepositoryUrlCloneDialogExtension"
|
||||
implementation="com.intellij.util.ui.cloneDialog.RepositoryUrlCloneDialogExtension"
|
||||
order="first"/>
|
||||
</extensions>
|
||||
|
||||
<applicationListeners>
|
||||
|
||||
@@ -346,6 +346,11 @@
|
||||
icon="AllIcons.Welcome.FromVCS">
|
||||
<add-to-group group-id="WelcomeScreen.QuickStart" anchor="first"/>
|
||||
</action>
|
||||
<action id="WelcomeScreen.NewGetFromVcs" class="com.intellij.openapi.wm.impl.welcomeScreen.RunVcsCloneDialogAction"
|
||||
icon="AllIcons.Vcs.Clone"
|
||||
internal="true">
|
||||
<add-to-group group-id="WelcomeScreen.QuickStart" anchor="last"/>
|
||||
</action>
|
||||
|
||||
<action id="Vcs.CopyRevisionNumberAction" class="com.intellij.openapi.vcs.history.actions.CopyRevisionNumberAction"
|
||||
text="Copy Revision Number" description="Copy short revision numbers of selected commits to the clipboard"
|
||||
|
||||
@@ -534,6 +534,10 @@ vcs.process.externally.added.files.description=Process externally added files. A
|
||||
vcs.propose.add.ignored.directories.to.exclude=false
|
||||
vcs.propose.add.ignored.directories.to.exclude.description=Show notification with proposal to add ignored (but not excluded) directories to exclude.
|
||||
|
||||
vcs.use.new.clone.dialog=false
|
||||
vcs.use.new.clone.dialog.description=Use new clone dialog
|
||||
vcs.use.new.clone.dialog.restartRequired=true
|
||||
|
||||
psi.incremental.reparse.depth.limit=1000
|
||||
psi.deferIconLoading=true
|
||||
|
||||
|
||||
@@ -3133,6 +3133,7 @@ public class AllIcons {
|
||||
/** 16x16 */ public static final Icon Arrow_right = load("/vcs/arrow_right.svg");
|
||||
/** 16x16 */ public static final Icon Branch = load("/vcs/branch.svg");
|
||||
/** 16x16 */ public static final Icon Changelist = load("/vcs/changelist.svg");
|
||||
/** 16x16 */ public static final Icon Clone = load("/vcs/clone.svg");
|
||||
/** 16x16 */ public static final Icon CommitNode = load("/vcs/commitNode.svg");
|
||||
/** 16x16 */ public static final Icon Equal = load("/vcs/equal.svg");
|
||||
/** 16x16 */ public static final Icon Folders = load("/vcs/folders.svg");
|
||||
|
||||
@@ -17,6 +17,8 @@ package com.intellij.openapi.vcs;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.ui.VcsCloneComponent;
|
||||
import com.intellij.openapi.vcs.ui.VcsCloneComponentStub;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -49,4 +51,9 @@ public interface CheckoutProvider {
|
||||
return getTextWithoutMnemonicEscaping(o1.getVcsName()).compareTo(getTextWithoutMnemonicEscaping(o2.getVcsName()));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
default VcsCloneComponent buildVcsCloneComponent(@NotNull Project project) {
|
||||
return new VcsCloneComponentStub(this, "Clone");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.vcs.ui
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.ValidationInfo
|
||||
import com.intellij.openapi.vcs.CheckoutProvider
|
||||
import javax.swing.JComponent
|
||||
|
||||
/**
|
||||
* Provides UI and dialog action handling for specific VCS
|
||||
*/
|
||||
interface VcsCloneComponent {
|
||||
/**
|
||||
* Component that would be placed on center of dialog panel
|
||||
*/
|
||||
fun getView(): JComponent
|
||||
|
||||
fun doClone(project: Project, listener: CheckoutProvider.Listener)
|
||||
|
||||
fun isOkEnabled(): Boolean
|
||||
|
||||
fun doValidateAll(): List<ValidationInfo>
|
||||
|
||||
fun getOkButtonText(): String = "Clone"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.vcs.ui
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.ValidationInfo
|
||||
import com.intellij.openapi.vcs.CheckoutProvider
|
||||
import java.awt.FlowLayout
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JPanel
|
||||
|
||||
class VcsCloneComponentStub(private val checkoutProvider: CheckoutProvider,
|
||||
private val primaryActionText: String = "Clone") : VcsCloneComponent {
|
||||
override fun getView(): JComponent {
|
||||
val panel = JPanel(FlowLayout(FlowLayout.LEADING))
|
||||
// todo: replace with better help text
|
||||
// todo: or add additional button closer to vcs combo
|
||||
panel.add(JLabel("Click \"$primaryActionText\" to continue"))
|
||||
return panel
|
||||
}
|
||||
|
||||
override fun doClone(project: Project, listener: CheckoutProvider.Listener) = checkoutProvider.doCheckout(project, listener)
|
||||
|
||||
override fun isOkEnabled() = true
|
||||
|
||||
override fun doValidateAll() = emptyList<ValidationInfo>()
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.vcs.ui.cloneDialog
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.project.Project
|
||||
import javax.swing.Icon
|
||||
|
||||
/**
|
||||
* Extension point that provide an ability to add integration with specific cloud repository hosting/service (e.g "GitHub", "BitBucket", etc)
|
||||
*/
|
||||
interface VcsCloneDialogExtension {
|
||||
companion object {
|
||||
val EP_NAME =
|
||||
ExtensionPointName.create<VcsCloneDialogExtension>("com.intellij.openapi.vcs.ui.cloneDialog.VcsCloneDialogExtension")
|
||||
}
|
||||
|
||||
/**
|
||||
* Visible name of extension (e.g. "Repository URL", "GitHub", etc)
|
||||
*/
|
||||
fun getName(): String
|
||||
|
||||
/**
|
||||
* Visible icon of extension
|
||||
*/
|
||||
fun getIcon(): Icon
|
||||
|
||||
/**
|
||||
* Builds [VcsCloneDialogExtensionComponent] that would be displayed on center of get-from-vcs dialog when extension is selected.
|
||||
* Will be called lazily and once on first choosing of extension.
|
||||
*/
|
||||
fun createMainComponent(project: Project): VcsCloneDialogExtensionComponent
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.vcs.ui.cloneDialog
|
||||
|
||||
import com.intellij.openapi.ui.ValidationInfo
|
||||
import javax.swing.JComponent
|
||||
|
||||
/**
|
||||
* Main component for get-from-vcs extensions.
|
||||
* It's responsible for:
|
||||
* 1. Providing extension-specific UI for get-from-vcs dialog by [getView]
|
||||
* 2. handling commands that would be provided from top-level [com.intellij.openapi.ui.DialogWrapper]
|
||||
*/
|
||||
interface VcsCloneDialogExtensionComponent {
|
||||
|
||||
/**
|
||||
* Return main [JComponent] that will be displayed in center of get-from-vcs dialog when extension is selected.
|
||||
*
|
||||
* It is called once when extension is selected first time
|
||||
*/
|
||||
fun getView(): JComponent
|
||||
|
||||
/**
|
||||
* Checks that is possible to perform ok action in current state of component
|
||||
*
|
||||
* Would be called form [com.intellij.openapi.ui.DialogWrapper.isOKActionEnabled] when extension is selected
|
||||
*/
|
||||
fun isOkEnabled(): Boolean
|
||||
|
||||
/**
|
||||
* Perform primary clone/checkout action.
|
||||
* would be called from [com.intellij.openapi.ui.DialogWrapper.doOKAction] when extension is selected
|
||||
*
|
||||
* @see com.intellij.openapi.ui.DialogWrapper.doOKAction
|
||||
*/
|
||||
fun doOk()
|
||||
|
||||
/**
|
||||
* would be called from [com.intellij.openapi.ui.DialogWrapper.doValidateAll] when extension is selected
|
||||
*
|
||||
* @see com.intellij.openapi.ui.DialogWrapper.doValidateAll
|
||||
*/
|
||||
fun doValidateAll(): List<ValidationInfo>
|
||||
|
||||
/**
|
||||
* Text that represents dialog primary action
|
||||
*/
|
||||
fun getOkButtonText(): String = "Clone"
|
||||
}
|
||||
+7
-1
@@ -3,12 +3,17 @@ package com.intellij.openapi.wm.impl.welcomeScreen;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vcs.CheckoutProvider;
|
||||
import com.intellij.openapi.vcs.checkout.CheckoutActionGroup;
|
||||
import com.intellij.ui.UIBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class GetFromVcsAction extends WelcomePopupAction{
|
||||
/**
|
||||
* @deprecated superseded by {@link RunVcsCloneDialogAction}
|
||||
*/
|
||||
@Deprecated
|
||||
public class GetFromVcsAction extends WelcomePopupAction {
|
||||
|
||||
@Override
|
||||
protected void fillActions(DefaultActionGroup group) {
|
||||
@@ -32,6 +37,7 @@ public class GetFromVcsAction extends WelcomePopupAction{
|
||||
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
e.getPresentation().setVisible(!Registry.is("vcs.use.new.clone.dialog"));
|
||||
e.getPresentation().setEnabled(CheckoutProvider.EXTENSION_POINT_NAME.hasAnyExtensions());
|
||||
}
|
||||
}
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.wm.impl.welcomeScreen
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.vcs.CheckoutProvider
|
||||
import com.intellij.util.ui.cloneDialog.VcsCloneDialog
|
||||
|
||||
class RunVcsCloneDialogAction : DumbAwareAction("Get from Version Control") {
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
e.presentation.isEnabled = CheckoutProvider.EXTENSION_POINT_NAME.hasAnyExtensions()
|
||||
e.presentation.isVisible = Registry.`is`("vcs.use.new.clone.dialog")
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.getData(CommonDataKeys.PROJECT) ?: ProjectManager.getInstance().defaultProject
|
||||
VcsCloneDialog.Builder(project)
|
||||
.forExtension()
|
||||
.showAndGet()
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util.ui.cloneDialog
|
||||
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
import com.intellij.openapi.ui.ValidationInfo
|
||||
import com.intellij.openapi.vcs.CheckoutProvider
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager
|
||||
import com.intellij.openapi.vcs.ui.VcsCloneComponent
|
||||
import com.intellij.openapi.vcs.ui.cloneDialog.VcsCloneDialogExtension
|
||||
import com.intellij.openapi.vcs.ui.cloneDialog.VcsCloneDialogExtensionComponent
|
||||
import com.intellij.ui.SimpleListCellRenderer
|
||||
import com.intellij.ui.layout.*
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.CardLayout
|
||||
import java.awt.event.ItemEvent
|
||||
import java.util.*
|
||||
import javax.swing.Icon
|
||||
import javax.swing.JPanel
|
||||
|
||||
class RepositoryUrlCloneDialogExtension : VcsCloneDialogExtension {
|
||||
override fun getIcon(): Icon = AllIcons.Welcome.FromVCS
|
||||
|
||||
override fun getName() = "Repository URL"
|
||||
|
||||
override fun createMainComponent(project: Project): RepositoryUrlMainExtensionComponent {
|
||||
return RepositoryUrlMainExtensionComponent(project)
|
||||
}
|
||||
|
||||
class RepositoryUrlMainExtensionComponent(private val project: Project) : VcsCloneDialogExtensionComponent {
|
||||
private val vcsComponents = HashMap<String, VcsCloneComponent>()
|
||||
private val cardLayout = CardLayout()
|
||||
private val mainPanel = JPanel(BorderLayout())
|
||||
private val comboBox: ComboBox<CheckoutProvider> = ComboBox<CheckoutProvider>().apply {
|
||||
renderer = SimpleListCellRenderer.create<CheckoutProvider>("") { it.vcsName.removePrefix("_") }
|
||||
}
|
||||
|
||||
init {
|
||||
mainPanel.border = JBUI.Borders.emptyRight(UIUtil.DEFAULT_VGAP)
|
||||
val northPanel = panel {
|
||||
row("Version control:") { comboBox() }
|
||||
}
|
||||
mainPanel.add(northPanel, BorderLayout.NORTH)
|
||||
|
||||
val centerPanel = JPanel(cardLayout)
|
||||
mainPanel.add(centerPanel, BorderLayout.CENTER)
|
||||
|
||||
comboBox.addItemListener { e: ItemEvent ->
|
||||
if (e.stateChange == ItemEvent.SELECTED) {
|
||||
val provider = e.item as CheckoutProvider
|
||||
cardLayout.show(centerPanel, provider.vcsName)
|
||||
}
|
||||
}
|
||||
|
||||
for (checkoutProvider in CheckoutProvider.EXTENSION_POINT_NAME.extensions) {
|
||||
comboBox.addItem(checkoutProvider)
|
||||
val vcsComponent = checkoutProvider.buildVcsCloneComponent(project)
|
||||
vcsComponents[checkoutProvider.vcsName] = vcsComponent
|
||||
val view = vcsComponent.getView()
|
||||
centerPanel.add(view, checkoutProvider.vcsName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getView() = mainPanel
|
||||
|
||||
override fun getOkButtonText(): String {
|
||||
return getCurrentVcsComponent()?.getOkButtonText() ?: "Clone"
|
||||
}
|
||||
|
||||
fun openForVcs(clazz: Class<out CheckoutProvider>): RepositoryUrlMainExtensionComponent {
|
||||
comboBox.selectedItem = CheckoutProvider.EXTENSION_POINT_NAME.findExtension(clazz)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun doOk() {
|
||||
val listener = ProjectLevelVcsManager.getInstance(project).compositeCheckoutListener
|
||||
getCurrentVcsComponent()?.doClone(project, listener)
|
||||
}
|
||||
|
||||
override fun isOkEnabled(): Boolean {
|
||||
return getCurrentVcsComponent()?.isOkEnabled() ?: true
|
||||
}
|
||||
|
||||
override fun doValidateAll(): List<ValidationInfo> {
|
||||
return getCurrentVcsComponent()?.doValidateAll() ?: emptyList()
|
||||
}
|
||||
|
||||
private fun getCurrentVcsComponent() = vcsComponents[getCurrentVcsName()]
|
||||
|
||||
private fun getCurrentVcsName(): String {
|
||||
val checkoutProvider = comboBox.selectedItem as CheckoutProvider
|
||||
return checkoutProvider.vcsName
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util.ui.cloneDialog
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.DialogWrapper
|
||||
import com.intellij.openapi.ui.ValidationInfo
|
||||
import com.intellij.openapi.vcs.CheckoutProvider
|
||||
import com.intellij.openapi.vcs.ui.cloneDialog.VcsCloneDialogExtension
|
||||
import com.intellij.openapi.vcs.ui.cloneDialog.VcsCloneDialogExtensionComponent
|
||||
import com.intellij.openapi.wm.impl.welcomeScreen.FlatWelcomeFrame
|
||||
import com.intellij.openapi.wm.impl.welcomeScreen.FlatWelcomeFrame.getSeparatorColor
|
||||
import com.intellij.ui.CollectionListModel
|
||||
import com.intellij.ui.ScrollPaneFactory
|
||||
import com.intellij.ui.ScrollingUtil
|
||||
import com.intellij.ui.border.CustomLineBorder
|
||||
import com.intellij.util.ui.JBEmptyBorder
|
||||
import com.intellij.util.ui.JBInsets
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import com.intellij.util.ui.cloneDialog.RepositoryUrlCloneDialogExtension.RepositoryUrlMainExtensionComponent
|
||||
import java.awt.CardLayout
|
||||
import java.util.*
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
import javax.swing.ScrollPaneConstants
|
||||
import javax.swing.event.ListSelectionListener
|
||||
|
||||
/**
|
||||
* Top-level UI-component for new clone/checkout dialog
|
||||
*/
|
||||
internal class VcsCloneDialog private constructor(private val project: Project,
|
||||
initialExtensionClass: Class<out VcsCloneDialogExtension>,
|
||||
private var initialVcs: Class<out CheckoutProvider>? = null) : DialogWrapper(project) {
|
||||
private lateinit var extensionList: VcsCloneDialogExtensionList
|
||||
private val cardLayout = CardLayout()
|
||||
private val mainPanel = JPanel(cardLayout)
|
||||
private val extensionComponents: MutableMap<String, VcsCloneDialogExtensionComponent> = HashMap()
|
||||
|
||||
init {
|
||||
init()
|
||||
title = "Get From Version Control"
|
||||
JBUI.size(FlatWelcomeFrame.MAX_DEFAULT_WIDTH, FlatWelcomeFrame.DEFAULT_HEIGHT).let {
|
||||
rootPane.minimumSize = it
|
||||
rootPane.preferredSize = it
|
||||
}
|
||||
|
||||
val withoutRightInset = UIUtil.PANEL_REGULAR_INSETS.let {
|
||||
// use empty right inset to align the scroll bar to the edge of panel
|
||||
JBInsets(it.top, it.left, it.bottom, 0)
|
||||
}
|
||||
mainPanel.border = JBEmptyBorder(withoutRightInset)
|
||||
|
||||
VcsCloneDialogExtension.EP_NAME.findExtension(initialExtensionClass)?.let {
|
||||
ScrollingUtil.selectItem(extensionList, it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStyle() = DialogStyle.COMPACT
|
||||
|
||||
override fun createCenterPanel(): JComponent {
|
||||
val extensions = VcsCloneDialogExtension.EP_NAME.extensionList
|
||||
val listModel = CollectionListModel<VcsCloneDialogExtension>(extensions)
|
||||
|
||||
extensionList = VcsCloneDialogExtensionList(listModel).apply {
|
||||
addListSelectionListener(ListSelectionListener { e ->
|
||||
val source = e.source as VcsCloneDialogExtensionList
|
||||
switchComponent(source.selectedValue)
|
||||
})
|
||||
}
|
||||
val scrollableList = ScrollPaneFactory.createScrollPane(extensionList, true).apply {
|
||||
border = CustomLineBorder(getSeparatorColor(), JBUI.insetsRight(1))
|
||||
}
|
||||
return JBUI.Panels.simplePanel()
|
||||
.addToCenter(mainPanel)
|
||||
.addToLeft(scrollableList).apply {
|
||||
border = CustomLineBorder(getSeparatorColor(), JBUI.insetsBottom(1))
|
||||
}
|
||||
}
|
||||
|
||||
override fun isOKActionEnabled(): Boolean {
|
||||
return getSelectedComponent()?.isOkEnabled() ?: false
|
||||
}
|
||||
|
||||
override fun doOKAction() {
|
||||
getSelectedComponent()?.doOk()
|
||||
}
|
||||
|
||||
override fun doValidateAll(): List<ValidationInfo> {
|
||||
return getSelectedComponent()?.doValidateAll() ?: emptyList()
|
||||
}
|
||||
|
||||
private fun switchComponent(extension: VcsCloneDialogExtension) {
|
||||
val extensionId = extension.javaClass.name
|
||||
val mainComponent = extensionComponents.getOrPut(extensionId, {
|
||||
val component = extension.createMainComponent(project)
|
||||
val scrollableMainPanel = ScrollPaneFactory.createScrollPane(component.getView(), true)
|
||||
scrollableMainPanel.verticalScrollBarPolicy = ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED
|
||||
scrollableMainPanel.horizontalScrollBarPolicy = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
|
||||
mainPanel.add(scrollableMainPanel, extensionId)
|
||||
component
|
||||
})
|
||||
|
||||
setOKButtonText(mainComponent.getOkButtonText())
|
||||
if (mainComponent is RepositoryUrlMainExtensionComponent) {
|
||||
initialVcs?.let { mainComponent.openForVcs(it) }
|
||||
}
|
||||
cardLayout.show(mainPanel, extensionId)
|
||||
}
|
||||
|
||||
private fun getSelectedComponent(): VcsCloneDialogExtensionComponent? {
|
||||
return extensionComponents[extensionList.selectedValue.javaClass.name]
|
||||
}
|
||||
|
||||
class Builder(private val project: Project) {
|
||||
fun forExtension(clazz: Class<out VcsCloneDialogExtension> = RepositoryUrlCloneDialogExtension::class.java): VcsCloneDialog {
|
||||
return VcsCloneDialog(project, clazz, null)
|
||||
}
|
||||
|
||||
fun forVcs(clazz: Class<out CheckoutProvider>): VcsCloneDialog {
|
||||
return VcsCloneDialog(project, RepositoryUrlCloneDialogExtension::class.java, clazz)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util.ui.cloneDialog
|
||||
|
||||
import com.intellij.openapi.vcs.ui.cloneDialog.VcsCloneDialogExtension
|
||||
import com.intellij.ui.ScrollingUtil
|
||||
import com.intellij.ui.SingleSelectionModel
|
||||
import com.intellij.ui.components.JBList
|
||||
import com.intellij.util.ui.ListUiUtil
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import java.awt.Component
|
||||
import java.awt.FlowLayout
|
||||
import javax.swing.*
|
||||
import javax.swing.border.EmptyBorder
|
||||
|
||||
class VcsCloneDialogExtensionList(listModel: ListModel<VcsCloneDialogExtension>) : JBList<VcsCloneDialogExtension>(listModel) {
|
||||
init {
|
||||
selectionModel = SingleSelectionModel()
|
||||
cellRenderer = Renderer()
|
||||
|
||||
ScrollingUtil.installActions(this)
|
||||
}
|
||||
|
||||
class Renderer : ListCellRenderer<VcsCloneDialogExtension> {
|
||||
val component = VcsCloneDialogExtensionListItem
|
||||
val wrapper: JComponent
|
||||
|
||||
init {
|
||||
wrapper = JPanel(FlowLayout(FlowLayout.LEADING)).apply {
|
||||
border = EmptyBorder(UIUtil.PANEL_REGULAR_INSETS)
|
||||
add(component)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getListCellRendererComponent(list: JList<out VcsCloneDialogExtension>,
|
||||
value: VcsCloneDialogExtension,
|
||||
index: Int,
|
||||
isSelected: Boolean,
|
||||
cellHasFocus: Boolean): Component {
|
||||
component.setTitle(value.getName())
|
||||
component.setTitleForeground(ListUiUtil.WithTallRow.foreground(list, isSelected))
|
||||
component.setIcon(value.getIcon())
|
||||
UIUtil.setBackgroundRecursively(wrapper, ListUiUtil.WithTallRow.background(list, isSelected))
|
||||
return wrapper
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util.ui.cloneDialog
|
||||
|
||||
import com.intellij.util.IconUtil
|
||||
import com.intellij.util.ui.GridBag
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import java.awt.Color
|
||||
import java.awt.GridBagLayout
|
||||
import javax.swing.Icon
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JLabel
|
||||
|
||||
|
||||
object VcsCloneDialogExtensionListItem : JComponent() {
|
||||
|
||||
private val iconLabel: JLabel = JLabel()
|
||||
private val titleLabel: JLabel = JLabel()
|
||||
|
||||
init {
|
||||
layout = GridBagLayout()
|
||||
|
||||
var gbc = GridBag().next()
|
||||
.insetRight(UIUtil.DEFAULT_VGAP)
|
||||
.anchor(GridBag.LINE_START)
|
||||
.fillCellNone()
|
||||
add(iconLabel, gbc)
|
||||
|
||||
gbc = gbc.next()
|
||||
.insets(JBUI.emptyInsets())
|
||||
.anchor(GridBag.BELOW_BASELINE_LEADING)
|
||||
.fillCellHorizontally()
|
||||
titleLabel.font = JBUI.Fonts.label().asBold()
|
||||
add(titleLabel, gbc)
|
||||
}
|
||||
|
||||
fun setTitle(title: String) {
|
||||
titleLabel.text = title
|
||||
}
|
||||
|
||||
fun setIcon(icon: Icon) {
|
||||
iconLabel.icon = IconUtil.scale(icon, null, 22.0f/icon.iconHeight) // scale is chosen so that the size of icon corresponds the design
|
||||
}
|
||||
|
||||
fun setTitleForeground(foreground: Color) {
|
||||
titleLabel.foreground = foreground
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user