[IFT] split Learn IDE panel into platform and IFT; make Interactive Courses extendable

GitOrigin-RevId: 8bbee632ea187872b94b273ce815fd722bd940b0
This commit is contained in:
Sergey Karashevich
2020-10-20 23:15:39 +00:00
committed by intellij-monorepo-bot
parent 2643fa9d3b
commit 4940c62966
15 changed files with 650 additions and 0 deletions
@@ -6,6 +6,7 @@ import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Calendar;
@@ -68,6 +69,11 @@ public abstract class ApplicationInfo {
public abstract String getKeyConversionUrl();
@Nullable
public String getGettingStartedUrl() {
return null;
}
public abstract boolean hasHelp();
public abstract boolean hasContextHelp();
@@ -1916,6 +1916,12 @@ welcome.screen.action.docs.how.tos.action.text=Docs and How-Tos
welcome.screen.plugins.title=Plugins
welcome.screen.projects.title=Projects
welcome.screen.customize.title=Customize
welcome.screen.learnIde.title=Learn IDE
welcome.screen.learnIde.interactive.courses.text=Interactive Courses
welcome.screen.learnIde.help.and.resources.text=Help and Resources
welcome.screen.color.theme.header=Color theme
welcome.screen.ide.font.size.label=IDE font:
@@ -289,6 +289,7 @@ public interface IdeActions {
@NonNls String GROUP_WELCOME_SCREEN_DOC = "WelcomeScreen.Documentation";
@NonNls String GROUP_WELCOME_SCREEN_CONFIGURE = "WelcomeScreen.Configure";
@NonNls String GROUP_WELCOME_SCREEN_HELP = "WelcomeScreen.Help";
@NonNls String GROUP_WELCOME_SCREEN_LEARN_IDE = "WelcomeScreen.LearnIdeHelp";
@NonNls String ACTION_KEYMAP_REFERENCE="Help.KeymapReference";
@NonNls String ACTION_MOVE = "Move";
@NonNls String ACTION_RENAME = "RenameElement";
@@ -0,0 +1,22 @@
// Copyright 2000-2020 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
import javax.swing.Action
import javax.swing.Icon
import javax.swing.JComponent
interface InteractiveCourseData {
fun getName(): String
fun getDescription(): String
fun getIcon(): Icon
fun getActionButtonName(): String
fun getAction(): Action
fun getExpandContent(): JComponent
}
@@ -0,0 +1,13 @@
// Copyright 2000-2020 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
import com.intellij.openapi.extensions.ExtensionPointName
interface InteractiveCourseFactory {
companion object {
val INTERACTIVE_COURSE_FACTORY_EP = ExtensionPointName<InteractiveCourseFactory>("com.intellij.interactiveCourseFactory")
}
fun getInteractiveCourseData(): InteractiveCourseData
}
@@ -0,0 +1,31 @@
// Copyright 2000-2020 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.ide.actions;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.project.DumbAware;
import org.jetbrains.annotations.NotNull;
public class GettingStartedAction extends AnAction implements DumbAware {
private final String myUrl;
public GettingStartedAction() {
myUrl = ApplicationInfo.getInstance().getGettingStartedUrl();
}
@Override
public void update(@NotNull AnActionEvent e) {
//boolean enabled = myUrl != null;
//e.getPresentation().setEnabledAndVisible(enabled);
e.getPresentation().setEnabledAndVisible(true);
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
if (myUrl != null) {
BrowserUtil.browse(myUrl);
}
}
}
@@ -0,0 +1,19 @@
// Copyright 2000-2020 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.ide.IdeBundle
import com.intellij.openapi.Disposable
import com.intellij.openapi.wm.WelcomeScreenTab
import com.intellij.openapi.wm.WelcomeTabFactory
import com.intellij.openapi.wm.impl.welcomeScreen.learnIde.LearnIdeContentPanel
import javax.swing.JComponent
class LearnIdeTabFactory: WelcomeTabFactory {
override fun createWelcomeTab(parentDisposable: Disposable): WelcomeScreenTab {
return object : TabbedWelcomeScreen.DefaultWelcomeScreenTab(IdeBundle.message("welcome.screen.learnIde.title")) {
override fun buildComponent(): JComponent {
return LearnIdeContentPanel()
}
}
}
}
@@ -0,0 +1,75 @@
// Copyright 2000-2020 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.learnIde
import com.intellij.ui.scale.JBUIScale
import java.awt.Dimension
import java.awt.event.MouseEvent
import javax.swing.JTextPane
import javax.swing.plaf.ComponentUI
import javax.swing.plaf.FontUIResource
import javax.swing.plaf.TextUI
import javax.swing.text.DefaultCaret
import javax.swing.text.SimpleAttributeSet
import javax.swing.text.StyleConstants
class HeightLimitedPane(text: String, val relativeFontSize: Int, val style: SimpleAttributeSet, val _width: Int? = null) : JTextPane() {
init {
isEditable = false
document.insertString(0, text, style)
//ensure that style has been applied
StyleConstants.setFontSize(style, (font.size2D + JBUIScale.scale(relativeFontSize)).toInt())
styledDocument.setCharacterAttributes(0, text.length, style, true)
styledDocument.setParagraphAttributes(0, text.length, style, true)
isOpaque = false
isEditable = false
alignmentX = LEFT_ALIGNMENT
highlighter = null
//make JTextPane transparent for mouse actions
caret = object : DefaultCaret() {
override fun mousePressed(e: MouseEvent?) {
this@HeightLimitedPane.parent.mouseListeners.forEach { it.mousePressed(e) }
}
override fun mouseReleased(e: MouseEvent?) {
this@HeightLimitedPane.parent.mouseListeners.forEach { it.mouseReleased(e) }
}
override fun mouseEntered(e: MouseEvent?) {
this@HeightLimitedPane.parent.mouseListeners.forEach { it.mouseEntered(e) }
}
override fun mouseExited(e: MouseEvent?) {
this@HeightLimitedPane.parent.mouseListeners.forEach { it.mouseExited(e) }
}
}
}
override fun getMaximumSize(): Dimension {
if (_width == null) {
return this.preferredSize
}
else {
return Dimension(width, this.preferredSize.height)
}
}
override fun setUI(ui: TextUI?) {
super.setUI(ui)
if (font != null) {
font = FontUIResource(font.deriveFont(font.size2D + JBUIScale.scale(relativeFontSize)))
}
}
override fun setUI(newUI: ComponentUI?) {
super.setUI(newUI)
}
override fun updateUI() {
super.updateUI()
if (font != null && style != null) {
StyleConstants.setFontSize(style, font.size)
styledDocument.setCharacterAttributes(0, text.length, style, true)
styledDocument.setParagraphAttributes(0, text.length, style, true)
}
}
}
@@ -0,0 +1,226 @@
// Copyright 2000-2020 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.learnIde
import com.intellij.icons.AllIcons
import com.intellij.openapi.wm.InteractiveCourseData
import com.intellij.ui.RoundedLineBorder
import com.intellij.ui.components.JBLabel
import com.intellij.util.ui.JBUI
import java.awt.*
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.awt.event.MouseListener
import javax.swing.*
import javax.swing.border.CompoundBorder
import javax.swing.border.EmptyBorder
import javax.swing.plaf.FontUIResource
import javax.swing.plaf.LabelUI
class InteractiveCoursePanel(private val data: InteractiveCourseData) : JPanel() {
private enum class ContentState { COLLAPSED, EXPANDED }
private val pluginPanelWidth = 72
private val chevronPanelWidth = 55
val startLearningButton = JButton()
private val interactiveCourseDescription = HeightLimitedPane(data.getDescription(), -1, LearnIdeContentColorsAndFonts.REGULAR)
private val interactiveCourseContent = createInteractiveCourseContent()
private var contentState: ContentState = ContentState.COLLAPSED
private val expandCollapseListener: MouseListener = createExpandCollapseListener()
private val expandedCourseContent = data.getExpandContent()
private val chevronPanel = JPanel()
private val chevronLabel = JLabel(AllIcons.General.ChevronDown)
val pluginPanel = JPanel()
val pluginLabel = JLabel(data.getIcon())
private val roundBorder1px = CompoundBorder(RoundedLineBorder(LearnIdeContentColorsAndFonts.InteractiveCoursesBorder, 4, 1),
JBUI.Borders.emptyRight(5))
private val calculateInnerComponentHeight: () -> Int = { preferredSize.height }
init {
initPluginPanel()
initChevronPanel()
layout = BoxLayout(this, BoxLayout.LINE_AXIS)
isOpaque = false
border = roundBorder1px
alignmentX = LEFT_ALIGNMENT
add(pluginPanel)
add(interactiveCourseContent)
add(chevronPanel)
addMouseListener(expandCollapseListener)
interactiveCourseDescription.addMouseListener(expandCollapseListener)
}
private fun initChevronPanel() {
chevronPanel.apply {
layout = BorderLayout()
isOpaque = false
alignmentY = TOP_ALIGNMENT
add(chevronLabel, BorderLayout.CENTER)
add(JPanel()
.apply { preferredSize = Dimension(chevronPanelWidth, 1); minimumSize = Dimension(chevronPanelWidth, 1); isOpaque = false },
BorderLayout.NORTH)
}
}
private fun initPluginPanel() {
pluginPanel.apply {
layout = BorderLayout()
border = EmptyBorder(12, 0, 0, 0)
isOpaque = false
add(pluginLabel, BorderLayout.NORTH)
alignmentY = TOP_ALIGNMENT
add(JPanel()
.apply { preferredSize = Dimension(pluginPanelWidth, 1); minimumSize = Dimension(pluginPanelWidth, 1); isOpaque = false },
BorderLayout.CENTER)
}
}
override fun getMaximumSize(): Dimension {
return Dimension(this.preferredSize.width, calculateInnerComponentHeight())
}
private fun createInteractiveCourseContent(): JPanel {
val panel = JPanel()
panel.layout = BoxLayout(panel, BoxLayout.PAGE_AXIS)
panel.isOpaque = false
panel.alignmentY = TOP_ALIGNMENT
panel.add(rigid(12, 10))
val learnIdeFeaturesHeader = object : JBLabel(data.getName()) {
override fun setUI(ui: LabelUI?) {
super.setUI(ui)
if (font != null) {
font = FontUIResource(font.deriveFont(font.size2D).deriveFont(Font.BOLD))
}
}
}
learnIdeFeaturesHeader.alignmentX = LEFT_ALIGNMENT
panel.add(learnIdeFeaturesHeader)
panel.add(rigid(1, 4))
panel.add(interactiveCourseDescription)
panel.add(rigid(4, 9))
startLearningButton.action = data.getAction()
startLearningButton.margin = Insets(0, 0, 0, 0)
startLearningButton.isSelected = true
startLearningButton.isOpaque = false
startLearningButton.alignmentX = LEFT_ALIGNMENT
val buttonPlace = buttonPixelHunting(startLearningButton)
panel.add(buttonPlace)
panel.add(rigid(18, 21))
return panel
}
private fun createExpandCollapseListener(): MouseAdapter {
return object : MouseAdapter() {
override fun mouseEntered(e: MouseEvent?) {
if (contentState == ContentState.EXPANDED) return
activateLearnIdeFeaturesPanel()
}
override fun mouseExited(e: MouseEvent?) {
if (e == null) return
deactivateLearnIdeFeaturesPanel(e.locationOnScreen)
}
override fun mousePressed(e: MouseEvent?) {
onLearnIdeFeaturesPanelClick()
}
}
}
private fun buttonPixelHunting(button: JButton): JPanel {
val buttonSizeWithoutInsets = Dimension(button.preferredSize.width - button.insets.left - button.insets.right,
button.preferredSize.height - button.insets.top - button.insets.bottom)
val buttonPlace = JPanel().apply {
layout = null
maximumSize = buttonSizeWithoutInsets
preferredSize = buttonSizeWithoutInsets
minimumSize = buttonSizeWithoutInsets
isOpaque = false
alignmentX = LEFT_ALIGNMENT
}
buttonPlace.add(button)
button.bounds = Rectangle(-button.insets.left, -button.insets.top, button.preferredSize.width, button.preferredSize.height)
return buttonPlace
}
private fun activateLearnIdeFeaturesPanel() {
background = LearnIdeContentColorsAndFonts.HoveredColor
isOpaque = true
repaint()
cursor = Cursor(Cursor.HAND_CURSOR);
}
private fun deactivateLearnIdeFeaturesPanel(mouseLocationOnScreen: Point) {
if (pointerInLearnIdeFeaturesPanel(mouseLocationOnScreen)) return
isOpaque = false
repaint()
cursor = Cursor(Cursor.DEFAULT_CURSOR)
}
private fun onLearnIdeFeaturesPanelClick() {
if (contentState == ContentState.COLLAPSED) {
expandContent()
chevronLabel.icon = AllIcons.General.ChevronUp
contentState = ContentState.EXPANDED
}
else {
collapseContent()
chevronLabel.icon = AllIcons.General.ChevronDown
contentState = ContentState.COLLAPSED
}
chevronLabel.repaint()
}
private fun expandContent() {
this.isOpaque = false
interactiveCourseDescription.maximumSize = interactiveCourseDescription.preferredSize
interactiveCourseContent.add(expandedCourseContent)
chevronPanel.maximumSize = chevronPanel.size
interactiveCourseContent.revalidate()
interactiveCourseContent.repaint()
repaint()
}
private fun collapseContent() {
val pointerLocation = MouseInfo.getPointerInfo().location
if (pointerInLearnIdeFeaturesPanel(pointerLocation)) activateLearnIdeFeaturesPanel()
interactiveCourseContent.remove(expandedCourseContent)
interactiveCourseContent.revalidate()
interactiveCourseContent.repaint()
repaint()
}
private fun pointerInLearnIdeFeaturesPanel(mouseLocationOnScreen: Point) =
Rectangle(Point(locationOnScreen.x + 1, locationOnScreen.y + 1),
Dimension(bounds.size.width - 2, bounds.size.height - 2)).contains(
mouseLocationOnScreen)
private fun rigid(_width: Int, _height: Int): Component {
return Box.createRigidArea(
Dimension(JBUI.scale(_width), JBUI.scale(_height))).apply { (this as JComponent).alignmentX = LEFT_ALIGNMENT }
}
}
@@ -0,0 +1,83 @@
// Copyright 2000-2020 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.learnIde
import com.intellij.ide.ui.UISettings
import com.intellij.ui.JBColor
import com.intellij.util.ui.JBUI
import java.awt.Font
import java.awt.font.TextAttribute
import javax.swing.JLabel
import javax.swing.text.SimpleAttributeSet
import javax.swing.text.StyleConstants
object LearnIdeContentColorsAndFonts {
val InteractiveCoursesBorder = JBColor.namedColor("Button.startBorderColor", JBColor(0x87AFDA, 0x5E6060))
private val fontSize: Int by lazy { UISettings.instance.fontSize.ifZero(JBUI.scale(13)) }
private val fontFace: String by lazy { UISettings.instance.fontFace ?: JLabel().font.fontName }
val HeaderFont: Font by lazy { Font(fontFace, Font.BOLD, fontSize + 5) }
val HeaderColor = JBColor.namedColor("ParameterInfo.foreground", JBColor(0x1D1D1D, 0xBBBBBB))
val HoveredColor = JBColor.namedColor("Plugins.lightSelectionBackground", JBColor(0xEDF6FE, 0x464A4D))
val REGULAR = SimpleAttributeSet()
val ModuleHeaderColor = JBColor.namedColor("link", JBColor(0x2470B3, 0x589DF6))
val ModuleDescriptionColor = JBColor.namedColor("disabledText", JBColor(0x8C8C8C, 0x777777))
val MODULE_HEADER = SimpleAttributeSet()
val MODULE_DESCRIPTION = SimpleAttributeSet()
val PARAGRAPH_STYLE = SimpleAttributeSet()
val HEADER = SimpleAttributeSet()
init {
StyleConstants.setFontSize(REGULAR, UISettings.instance.fontSize - 1)
StyleConstants.setFontFamily(REGULAR, UISettings.instance.fontFace)
StyleConstants.setForeground(REGULAR, HeaderColor)
StyleConstants.setLeftIndent(REGULAR, 0.0f)
StyleConstants.setRightIndent(REGULAR, 0f)
StyleConstants.setSpaceAbove(REGULAR, 0.0f)
StyleConstants.setSpaceBelow(REGULAR, 0.0f)
StyleConstants.setLineSpacing(REGULAR, 0.0f)
StyleConstants.setFontSize(HEADER, HeaderFont.size)
StyleConstants.setFontFamily(HEADER, UISettings.instance.fontFace)
StyleConstants.setForeground(HEADER, HeaderColor)
StyleConstants.setBold(HEADER, true)
HEADER.addAttribute(TextAttribute.TRACKING, -0.1)
StyleConstants.setLeftIndent(PARAGRAPH_STYLE, 0.0f)
StyleConstants.setRightIndent(PARAGRAPH_STYLE, 0f)
StyleConstants.setSpaceAbove(PARAGRAPH_STYLE, 0.0f)
StyleConstants.setSpaceBelow(PARAGRAPH_STYLE, 0.0f)
StyleConstants.setLineSpacing(PARAGRAPH_STYLE, 0.0f)
StyleConstants.setFontFamily(MODULE_HEADER, UISettings.instance.fontFace)
StyleConstants.setFontSize(MODULE_HEADER, UISettings.instance.fontSize - 1)
StyleConstants.setForeground(MODULE_HEADER, ModuleHeaderColor)
StyleConstants.setLeftIndent(MODULE_HEADER, 0.0f)
StyleConstants.setRightIndent(MODULE_HEADER, 0f)
StyleConstants.setSpaceAbove(MODULE_HEADER, 0.0f)
StyleConstants.setSpaceBelow(MODULE_HEADER, 0.0f)
StyleConstants.setLineSpacing(MODULE_HEADER, 0.0f)
StyleConstants.setFontFamily(MODULE_DESCRIPTION, UISettings.instance.fontFace)
StyleConstants.setFontSize(MODULE_DESCRIPTION, UISettings.instance.fontSize - 2)
StyleConstants.setForeground(MODULE_DESCRIPTION, ModuleDescriptionColor)
StyleConstants.setLeftIndent(MODULE_DESCRIPTION, 0.0f)
StyleConstants.setRightIndent(MODULE_DESCRIPTION, 0f)
StyleConstants.setSpaceAbove(MODULE_DESCRIPTION, 0.0f)
StyleConstants.setSpaceBelow(MODULE_DESCRIPTION, 0.0f)
StyleConstants.setLineSpacing(MODULE_DESCRIPTION, 0.0f)
}
private fun Int.ifZero(nonZeroValue: Int): Int =
if (this == 0) nonZeroValue else this
}
@@ -0,0 +1,153 @@
// Copyright 2000-2020 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.learnIde
import com.intellij.icons.AllIcons.Ide.External_link_arrow
import com.intellij.ide.IdeBundle
import com.intellij.ide.actions.GettingStartedAction
import com.intellij.ide.actions.HelpTopicsAction
import com.intellij.ide.actions.JetBrainsTvAction
import com.intellij.ide.actions.WhatsNewAction
import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.actionSystem.ex.ActionUtil
import com.intellij.openapi.wm.InteractiveCourseFactory
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager
import com.intellij.openapi.wm.impl.welcomeScreen.learnIde.LearnIdeContentColorsAndFonts.HEADER
import com.intellij.ui.AncestorListenerAdapter
import com.intellij.ui.components.JBScrollPane
import com.intellij.ui.components.labels.LinkLabel
import com.intellij.util.ui.JBUI
import java.awt.*
import javax.swing.*
import javax.swing.border.EmptyBorder
import javax.swing.event.AncestorEvent
class LearnIdeContentPanel : JPanel() {
private val interactiveCoursesPanel: JPanel = JPanel()
private val helpAndResourcesPanel: JPanel = JPanel()
private val viewComponent: JPanel = JPanel().apply { layout = BorderLayout(); background = WelcomeScreenUIManager.getProjectsBackground() }
private val myScrollPane: JBScrollPane = JBScrollPane(viewComponent, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER).apply { border = JBUI.Borders.empty()}
private val interactiveCoursesHeader: JTextPane = HeightLimitedPane(IdeBundle.message("welcome.screen.learnIde.interactive.courses.text"),
5, HEADER)
private val helpAndResourcesHeader: JTextPane = HeightLimitedPane(IdeBundle.message("welcome.screen.learnIde.help.and.resources.text"), 5, HEADER)
init {
layout = BorderLayout()
isFocusable = false
isOpaque = true
background = WelcomeScreenUIManager.getProjectsBackground()
val contentPanel = JPanel()
contentPanel.layout = BoxLayout(contentPanel, BoxLayout.PAGE_AXIS)
//get all Interactive Courses
contentPanel.addInteractiveCoursesPanel()
contentPanel.addHelpAndResourcesPanel()
contentPanel.add(Box.createVerticalGlue())
//set LearnPanel UI
contentPanel.border = EmptyBorder(24, 24, 24, 24)
contentPanel.isOpaque = false
viewComponent.add(contentPanel, BorderLayout.CENTER)
add(myScrollPane, BorderLayout.CENTER)
contentPanel.bounds = Rectangle(contentPanel.location, contentPanel.preferredSize)
revalidate()
repaint()
}
private fun Container.addHelpAndResourcesPanel() {
helpAndResourcesPanel.apply {
layout = BoxLayout(this, BoxLayout.PAGE_AXIS)
isOpaque = false
add(helpAndResourcesHeader)
add(rigid(0, 1))
addHelpActions()
}
this.add(helpAndResourcesPanel)
}
private fun Container.addInteractiveCoursesPanel() {
val interactiveCourses = InteractiveCourseFactory.INTERACTIVE_COURSE_FACTORY_EP.extensions.map {it.getInteractiveCourseData()}
interactiveCoursesPanel.layout = BoxLayout(interactiveCoursesPanel, BoxLayout.PAGE_AXIS)
interactiveCoursesPanel.isOpaque = false
if (interactiveCourses.isNotEmpty()) {
interactiveCoursesPanel.add(interactiveCoursesHeader)
var actionButton: JButton? = null
for (interactiveCourse in interactiveCourses) {
interactiveCoursesPanel.add(rigid(0, 12))
val interactiveCoursePanel = InteractiveCoursePanel(interactiveCourse)
interactiveCoursesPanel.add(interactiveCoursePanel)
if (actionButton == null) actionButton = interactiveCoursePanel.startLearningButton
}
addAncestorListener(object : AncestorListenerAdapter() {
override fun ancestorAdded(event: AncestorEvent?) {
rootPane?.defaultButton = actionButton
}
})
this.add(interactiveCoursesPanel)
this.add(rigid(1, 32))
}
}
private fun addHelpActions() {
val whatsNewAction = WhatsNewAction()
if (emptyWelcomeScreenEventFromAction(whatsNewAction).presentation.isEnabled) {
helpAndResourcesPanel.add(linkLabelByAction(WhatsNewAction()))
helpAndResourcesPanel.add(rigid(1, 16))
}
val helpActions = ActionManager.getInstance().getAction(IdeActions.GROUP_WELCOME_SCREEN_LEARN_IDE) as ActionGroup
val anActionEvent = emptyWelcomeScreenEventFromAction(helpActions)
helpActions.getChildren(anActionEvent).forEach {
if (setOf<String>(HelpTopicsAction::class.java.simpleName, GettingStartedAction::class.java.simpleName,
JetBrainsTvAction::class.java.simpleName).any { simpleName -> simpleName == it.javaClass.simpleName }) {
helpAndResourcesPanel.add(linkLabelByAction(it).wrapWithUrlPanel())
}
else {
helpAndResourcesPanel.add(linkLabelByAction(it))
}
helpAndResourcesPanel.add(rigid(1, 6))
}
}
private fun LinkLabel<Any>.wrapWithUrlPanel(): JPanel {
val jPanel = JPanel()
jPanel.isOpaque = false
jPanel.layout = BoxLayout(jPanel, BoxLayout.LINE_AXIS)
jPanel.add(this, BorderLayout.CENTER)
jPanel.add(JLabel(External_link_arrow), BorderLayout.EAST)
jPanel.maximumSize = jPanel.preferredSize
jPanel.alignmentX = LEFT_ALIGNMENT
return jPanel
}
private fun emptyWelcomeScreenEventFromAction(action: AnAction) =
AnActionEvent.createFromAnAction(action, null, ActionPlaces.WELCOME_SCREEN, DataContext.EMPTY_CONTEXT)
private fun linkLabelByAction(it: AnAction): LinkLabel<Any> {
return LinkLabel<Any>(it.templateText, null).apply {
alignmentX = LEFT_ALIGNMENT
setListener({ _, _ -> performActionOnWelcomeScreen(it) }, null)
}
}
private fun rigid(_width: Int, _height: Int): Component {
return Box.createRigidArea(
Dimension(JBUI.scale(_width), JBUI.scale(_height))).apply { (this as JComponent).alignmentX = LEFT_ALIGNMENT }
}
private fun performActionOnWelcomeScreen(action: AnAction) {
val anActionEvent = AnActionEvent.createFromAnAction(action, null, ActionPlaces.WELCOME_SCREEN, DataContext.EMPTY_CONTEXT)
ActionUtil.performActionDumbAware(action, anActionEvent)
}
}
@@ -1136,6 +1136,8 @@ action.Help.KeymapReference.text=_Keymap Reference
action.Help.KeymapReference.description=Open PDF file with the default keymap reference card.
action.Help.JetBrainsTV.text=_Demos and Screencasts
action.Help.JetBrainsTV.description=View short live demos introducing features of JetBrains products.
action.Help.GettingStarted.text=Getting Started
action.Help.GettingStarted.description=Knowledge base and learning materials.
action.CheckForUpdate.text=_Check for Updates...
action.CheckForUpdate.description=Checks for available IDE and plugin updates
action.CheckForUpdate.WelcomeScreen.text=Check for Updates
@@ -177,6 +177,7 @@
<extensionPoint name="welcomeScreen" interface="com.intellij.openapi.wm.WelcomeScreenProvider"/>
<extensionPoint name="welcomeFrameProvider" interface="com.intellij.openapi.wm.WelcomeFrameProvider" dynamic="true"/>
<extensionPoint name="welcomeTabFactory" interface="com.intellij.openapi.wm.WelcomeTabFactory" dynamic="true"/>
<extensionPoint name="interactiveCourseFactory" interface="com.intellij.openapi.wm.InteractiveCourseFactory" dynamic="true"/>
<extensionPoint name="welcomeScreenCustomization" interface="com.intellij.openapi.wm.WelcomeScreenCustomization" dynamic="true"/>
<extensionPoint name="statistic.eventLog.eventLoggerProvider" interface="com.intellij.internal.statistic.eventLog.StatisticsEventLoggerProvider"/>
@@ -435,6 +435,8 @@
order="after ProjectsWelcomeTab"/>
<welcomeTabFactory id="PluginsWelcomeTab" implementation="com.intellij.openapi.wm.impl.welcomeScreen.PluginsTabFactory"
order="after CustomizeWelcomeTab"/>
<welcomeTabFactory id="LearnIdeWelcomeTab" implementation="com.intellij.openapi.wm.impl.welcomeScreen.LearnIdeTabFactory"
order="after PluginsWelcomeTab'"/>
<welcomeScreenCustomization id="defaultCustomization"
implementation="com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenDefaultCustomization"/>
@@ -771,6 +771,7 @@
<action id="OnlineDocAction" class="com.intellij.ide.actions.OnlineDocAction"/>
<action id="Help.KeymapReference" class="com.intellij.ide.actions.RefCardAction"/>
<action id="Help.JetBrainsTV" class="com.intellij.ide.actions.JetBrainsTvAction"/>
<action id="Help.GettingStarted" class="com.intellij.ide.actions.GettingStartedAction"/>
<action id="ShowTips" class="com.intellij.ide.actions.ShowTipsAction"/>
<separator/>
<action id="ProductivityGuide" class="com.intellij.featureStatistics.actions.ShowFeatureUsageStatisticsAction"/>
@@ -939,6 +940,15 @@
<reference ref="CheckForUpdate"/>
</group>
<group id="WelcomeScreen.LearnIdeHelp">
<reference ref="HelpTopics"/>
<reference ref="Help.GettingStarted"/>
<reference ref="Help.JetBrainsTV"/>
<reference ref="Help.KeymapReference"/>
<reference ref="ShowTips"/>
</group>
<group id="WelcomeScreenRecentProjectActionGroup">
<action id="WelcomeScreen.OpenSelected" class="com.intellij.openapi.wm.impl.welcomeScreen.OpenSelectedProjectsAction"/>
<action id="WelcomeScreen.NewGroup" class="com.intellij.openapi.wm.impl.welcomeScreen.CreateNewProjectGroupAction"/>