From 938003f4324cd43440d0b2d97f53d72f1e751e68 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Thu, 13 Dec 2018 19:29:12 +0300 Subject: [PATCH] IDEA-196053 Plugins: counter on Updates page appears only on opening the tab --- .../options/ConfigurableTreeRenderer.java | 11 ++- ...PluginManagerConfigurableTreeRenderer.java | 87 ++++++++++++++++--- .../options/newEditor/SettingsTreeView.java | 67 +++++++------- .../completion/UiDefaultsHardcodedKeys.java | 2 + 4 files changed, 124 insertions(+), 43 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableTreeRenderer.java b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableTreeRenderer.java index 8d56b78ac827..2a58be256536 100644 --- a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableTreeRenderer.java +++ b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableTreeRenderer.java @@ -1,6 +1,7 @@ // Copyright 2000-2018 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.options; +import com.intellij.openapi.util.Pair; import com.intellij.ui.treeStructure.SimpleTree; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -12,5 +13,13 @@ import java.awt.*; */ public interface ConfigurableTreeRenderer { @Nullable - Component getRightDecorator(@NotNull SimpleTree tree, @Nullable UnnamedConfigurable configurable, boolean selected); + Pair getDecorator(@NotNull SimpleTree tree, @Nullable UnnamedConfigurable configurable, boolean selected); + + interface Layout { + void layoutBeforePaint(@NotNull Component renderer, + @NotNull Rectangle bounds, + @NotNull Rectangle text, + @NotNull Rectangle right, + int textBaseline); + } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableTreeRenderer.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableTreeRenderer.java index 34d712c2518c..9a59278d9afc 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableTreeRenderer.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurableTreeRenderer.java @@ -4,14 +4,21 @@ package com.intellij.ide.plugins; import com.intellij.ide.plugins.newui.PluginUpdatesService; import com.intellij.openapi.options.ConfigurableTreeRenderer; import com.intellij.openapi.options.UnnamedConfigurable; -import com.intellij.openapi.roots.ui.configuration.SidePanelCountLabel; +import com.intellij.openapi.ui.GraphicsConfig; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.AncestorListenerAdapter; +import com.intellij.ui.JBColor; import com.intellij.ui.treeStructure.SimpleTree; +import com.intellij.util.ui.GraphicsUtil; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import javax.swing.event.AncestorEvent; import java.awt.*; import java.util.function.Consumer; @@ -20,21 +27,14 @@ import java.util.function.Consumer; * @author Alexander Lobas */ public class PluginManagerConfigurableTreeRenderer extends AncestorListenerAdapter implements ConfigurableTreeRenderer, Consumer { - private final SidePanelCountLabel myCountLabel = new SidePanelCountLabel() { - @Override - public void paint(Graphics g) { - g.translate(7, 0); - super.paint(g); - } - }; - + private final CountComponent myCountLabel = new CountComponent(); private PluginUpdatesService myService; private SimpleTree myTree; private String myCountValue; @Nullable @Override - public Component getRightDecorator(@NotNull SimpleTree tree, @Nullable UnnamedConfigurable configurable, boolean selected) { + public Pair getDecorator(@NotNull SimpleTree tree, @Nullable UnnamedConfigurable configurable, boolean selected) { if (!Registry.is("show.new.plugin.page", false)) { return null; } @@ -46,7 +46,13 @@ public class PluginManagerConfigurableTreeRenderer extends AncestorListenerAdapt if (myCountValue != null) { myCountLabel.setText(myCountValue); myCountLabel.setSelected(selected); - return myCountLabel; + + return Pair.create(myCountLabel, (renderer, bounds, text, right, textBaseline) -> { + Dimension size = renderer.getPreferredSize(); + int x = right.x + (right.width - size.width) / 2; + int y = bounds.y + textBaseline - renderer.getBaseline(size.width, size.height); + renderer.setBounds(x, y, size.width, size.height); + }); } return null; } @@ -64,4 +70,63 @@ public class PluginManagerConfigurableTreeRenderer extends AncestorListenerAdapt myTree.repaint(); } } + + private static class CountComponent extends JLabel { + @SuppressWarnings("UseJBColor") + private final Color myOvalColor = JBColor.namedColor("Counter.background", new Color(0xCC9AA7B0, true)); + + private CountComponent() { + setBorder(null); + setFont(UIUtil.getLabelFont(SystemInfo.isMac || (SystemInfo.isLinux && (UIUtil.isUnderIntelliJLaF() || UIUtil.isUnderDarcula())) + ? UIUtil.FontSize.SMALL + : UIUtil.FontSize.NORMAL)); + setForeground(JBColor.namedColor("Counter.foreground", new JBColor(0xFFFFFF, 0x3E434D))); + setHorizontalAlignment(CENTER); + setHorizontalTextPosition(CENTER); + } + + public void setSelected(boolean selected) { + setBackground(selected ? UIUtil.getTreeSelectionBackground(true) : UIUtil.SIDE_PANEL_BACKGROUND); + } + + @Override + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + return new Dimension(Math.max(size.width, getTextOffset() + getOvalWidth()), Math.max(size.height, getOvalHeight())); + } + + @Override + protected void paintComponent(Graphics g) { + int corner = JBUI.scale(14); + int ovalWidth = getOvalWidth(); + int ovalHeight = getOvalHeight(); + int width = getWidth(); + int height = getHeight(); + + GraphicsConfig config = GraphicsUtil.setupAAPainting(g); + + g.setColor(getBackground()); + g.fillRect(0, 0, width, height); + + g.setColor(myOvalColor); + g.fillRoundRect(getTextOffset() + (width - ovalWidth) / 2, (height - ovalHeight) / 2, ovalWidth, ovalHeight, corner, corner); + + config.restore(); + + super.paintComponent(g); + } + + private int getOvalWidth() { + return JBUI.scale(getText().length() == 1 ? 16 : 20); + } + + private int getTextOffset() { + String text = getText(); + return text.equals("1") || text.equals("4") ? 1 : 0; + } + + private static int getOvalHeight() { + return JBUI.scale(14); + } + } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java index 4541358d2203..c8bc49a92672 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java @@ -15,6 +15,7 @@ import com.intellij.openapi.options.ex.SortedConfigurableGroup; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.*; import com.intellij.ui.components.GradientViewport; @@ -22,6 +23,7 @@ import com.intellij.ui.treeStructure.*; import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder; import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure; import com.intellij.util.ui.GraphicsUtil; +import com.intellij.util.ui.JBInsets; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; @@ -509,41 +511,16 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab private final class MyRenderer extends CellRendererPanel implements TreeCellRenderer { final SimpleColoredComponent myTextLabel = new SimpleColoredComponent(); final JLabel myNodeIcon = new JLabel(); - Component myRightRenderer; - final CellRendererPanel myRightPanel = new CellRendererPanel() { - @Override - public Dimension getPreferredSize() { - if (myRightRenderer != null) { - return myRightRenderer.getPreferredSize(); - } - return super.getPreferredSize(); - } - - @Override - protected void paintChildren(Graphics g) { - super.paintChildren(g); - if (myRightRenderer != null) { - int width = getWidth(); - int height = getHeight(); - Graphics2D g2 = (Graphics2D)g.create(0, 0, width, height); - - myRightRenderer.setBounds(0, 0, width, height); - myRightRenderer.paint(g2); - g2.dispose(); - myRightRenderer = null; - } - } - }; final JLabel myProjectIcon = new JLabel(); + Pair myRenderInfo; MyRenderer() { setLayout(new BorderLayout(ICON_GAP, 0)); myNodeIcon.setName(NODE_ICON); myTextLabel.setOpaque(false); - myRightPanel.add(myProjectIcon); add(BorderLayout.CENTER, myTextLabel); add(BorderLayout.WEST, myNodeIcon); - add(BorderLayout.EAST, myRightPanel); + add(BorderLayout.EAST, myProjectIcon); setBorder(BorderFactory.createEmptyBorder(1, 10, 3, 10)); } @@ -604,7 +581,7 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab configurable = node.myConfigurable; } setProjectIcon(myProjectIcon, configurable, project, selected); - setRightRenderer(node != null && project == null, node, configurable, selected); + prepareRenderer(node != null, node, configurable, selected); // configure node icon Icon nodeIcon = null; if (value instanceof DefaultMutableTreeNode) { @@ -657,18 +634,46 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab return this; } - private void setRightRenderer(boolean visible, MyNode node, @Nullable UnnamedConfigurable configurable, boolean selected) { - myRightRenderer = null; + private void prepareRenderer(boolean visible, MyNode node, @Nullable UnnamedConfigurable configurable, boolean selected) { + myRenderInfo = null; if (visible) { ConfigurableTreeRenderer renderer = node.getRenderer(); if (renderer != null) { if (configurable instanceof ConfigurableWrapper) { configurable = ((ConfigurableWrapper)configurable).getRawConfigurable(); } - myRightRenderer = renderer.getRightDecorator(myTree, configurable, selected); + myRenderInfo = renderer.getDecorator(myTree, configurable, selected); } } } + + @Override + protected void paintChildren(Graphics g) { + super.paintChildren(g); + + if (myRenderInfo != null) { + Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight()); + JBInsets.removeFrom(bounds, getInsets()); + + Rectangle text = myTextLabel.getBounds(); + int baseline = myTextLabel.getBaseline(text.width, text.height); + + if (myProjectIcon.getIcon() == null) { + myProjectIcon.setIcon(AllIcons.General.ProjectConfigurable); + } + Dimension icon = myProjectIcon.getPreferredSize(); + Rectangle right = new Rectangle(bounds.x + bounds.width - icon.width, bounds.y, icon.width, icon.height); + + myRenderInfo.second.layoutBeforePaint(myRenderInfo.first, bounds, text, right, baseline); + + Rectangle paintBounds = myRenderInfo.first.getBounds(); + Graphics2D g2 = (Graphics2D)g.create(paintBounds.x, paintBounds.y, paintBounds.width, paintBounds.height); + myRenderInfo.first.paint(g2); + g2.dispose(); + + myRenderInfo = null; + } + } } @SuppressWarnings("unused") diff --git a/plugins/devkit/devkit-core/src/completion/UiDefaultsHardcodedKeys.java b/plugins/devkit/devkit-core/src/completion/UiDefaultsHardcodedKeys.java index f9bbba276472..fc62f95c4054 100644 --- a/plugins/devkit/devkit-core/src/completion/UiDefaultsHardcodedKeys.java +++ b/plugins/devkit/devkit-core/src/completion/UiDefaultsHardcodedKeys.java @@ -1283,6 +1283,8 @@ public final class UiDefaultsHardcodedKeys { "Component.inactiveErrorFocusColor", "Component.inactiveWarningFocusColor", "Component.warningFocusColor", + "Counter.background", + "Counter.foreground", "DragAndDrop.areaBackground", "DragAndDrop.areaBorderColor", "DragAndDrop.areaForeground",