mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-89461 Open in browser: popup buttons are drawn with artifacts
This commit is contained in:
@@ -23,4 +23,6 @@ import com.intellij.openapi.options.UnnamedConfigurable;
|
||||
public abstract class BrowserSettingsProvider implements UnnamedConfigurable {
|
||||
public void disposeUIResources() {
|
||||
}
|
||||
|
||||
public void applySettingsFromWindowsRegistry() {}
|
||||
}
|
||||
|
||||
@@ -17,43 +17,60 @@
|
||||
package com.intellij.openapi.actionSystem;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ActionGroupUtil {
|
||||
private static Presentation getPresentation(AnAction action, Map<AnAction, Presentation> action2presentation) {
|
||||
Presentation presentation = action2presentation.get(action);
|
||||
if (presentation == null) {
|
||||
presentation = (Presentation)action.getTemplatePresentation().clone();
|
||||
presentation = action.getTemplatePresentation().clone();
|
||||
action2presentation.put(action, presentation);
|
||||
}
|
||||
return presentation;
|
||||
}
|
||||
|
||||
public static boolean isGroupEmpty(ActionGroup actionGroup, AnActionEvent e) {
|
||||
return isGroupEmpty(actionGroup, e, new HashMap<AnAction, Presentation>());
|
||||
public static boolean isGroupEmpty(@NotNull ActionGroup actionGroup, @NotNull AnActionEvent e) {
|
||||
return getEnabledChildren(actionGroup, e, new HashMap<AnAction, Presentation>()).isEmpty();
|
||||
}
|
||||
|
||||
private static boolean isGroupEmpty(ActionGroup actionGroup, AnActionEvent e, Map<AnAction, Presentation> action2presentation) {
|
||||
@Nullable
|
||||
public static AnAction getSingleActiveAction(@NotNull ActionGroup actionGroup, @NotNull AnActionEvent e) {
|
||||
List<AnAction> children = getEnabledChildren(actionGroup, e, new HashMap<AnAction, Presentation>());
|
||||
if (children.size() == 1) {
|
||||
return children.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<AnAction> getEnabledChildren(@NotNull ActionGroup actionGroup,
|
||||
@NotNull AnActionEvent e,
|
||||
@NotNull Map<AnAction, Presentation> action2presentation) {
|
||||
List<AnAction> result = new ArrayList<AnAction>();
|
||||
AnAction[] actions = actionGroup.getChildren(e);
|
||||
for (AnAction action : actions) {
|
||||
if (action instanceof Separator) {
|
||||
continue;
|
||||
if (action instanceof ActionGroup) {
|
||||
if (isActionEnabledAndVisible(e, action2presentation, action)) {
|
||||
result.addAll(getEnabledChildren((ActionGroup)action, e, action2presentation));
|
||||
}
|
||||
}
|
||||
else if (action instanceof ActionGroup) {
|
||||
if (isActionEnabledAndVisible(e, action2presentation, action) && !isGroupEmpty((ActionGroup)action, e, action2presentation)) {
|
||||
return false;
|
||||
else if (!(action instanceof Separator)) {
|
||||
if (isActionEnabledAndVisible(e, action2presentation, action)) {
|
||||
result.add(action);
|
||||
}
|
||||
} else {
|
||||
if(isActionEnabledAndVisible(e, action2presentation, action)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isActionEnabledAndVisible(final AnActionEvent e, final Map<AnAction, Presentation> action2presentation,
|
||||
final AnAction action) {
|
||||
private static boolean isActionEnabledAndVisible(@NotNull final AnActionEvent e,
|
||||
@NotNull final Map<AnAction, Presentation> action2presentation,
|
||||
@NotNull final AnAction action) {
|
||||
Presentation presentation = getPresentation(action, action2presentation);
|
||||
AnActionEvent event = new AnActionEvent(e.getInputEvent(),
|
||||
e.getDataContext(),
|
||||
|
||||
@@ -111,6 +111,21 @@ public class BrowserSettingsPanel extends JPanel {
|
||||
for (BrowserSettingsProvider settingsProvider : mySettingsProviders) {
|
||||
outerPanel.add(settingsProvider.createComponent());
|
||||
}
|
||||
if (SystemInfo.isWindows) {
|
||||
JPanel wrapperPanel = new JPanel(new BorderLayout());
|
||||
JButton registryButton = new JButton("Retrieve settings from Windows registry");
|
||||
registryButton.setMnemonic('W');
|
||||
registryButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
for (BrowserSettingsProvider settingsProvider : mySettingsProviders) {
|
||||
settingsProvider.applySettingsFromWindowsRegistry();
|
||||
}
|
||||
}
|
||||
});
|
||||
wrapperPanel.add(registryButton, BorderLayout.EAST);
|
||||
outerPanel.add(wrapperPanel);
|
||||
}
|
||||
|
||||
add(outerPanel, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
+13
-10
@@ -339,13 +339,18 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
}
|
||||
}
|
||||
|
||||
private Dimension getChildPreferredSize(int index) {
|
||||
Component component = getComponent(index);
|
||||
return component.isVisible() ? component.getPreferredSize() : new Dimension();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return maximum button width
|
||||
*/
|
||||
private int getMaxButtonWidth() {
|
||||
int width = 0;
|
||||
for (int i = 0; i < getComponentCount(); i++) {
|
||||
final Dimension dimension = getComponent(i).getPreferredSize();
|
||||
final Dimension dimension = getChildPreferredSize(i);
|
||||
width = Math.max(width, dimension.width);
|
||||
}
|
||||
return width;
|
||||
@@ -357,7 +362,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
public int getMaxButtonHeight() {
|
||||
int height = 0;
|
||||
for (int i = 0; i < getComponentCount(); i++) {
|
||||
final Dimension dimension = getComponent(i).getPreferredSize();
|
||||
final Dimension dimension = getChildPreferredSize(i);
|
||||
height = Math.max(height, dimension.height);
|
||||
}
|
||||
return height;
|
||||
@@ -400,8 +405,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
int xOffset = insets.left;
|
||||
final int yOffset = insets.top;
|
||||
for (int i = 0; i < componentCount; i++) {
|
||||
final Component component = getComponent(i);
|
||||
final Dimension d = component.getPreferredSize();
|
||||
final Dimension d = getChildPreferredSize(i);
|
||||
final Rectangle r = bounds.get(i);
|
||||
r.setBounds(xOffset, yOffset + (maxHeight - d.height) / 2, d.width, d.height);
|
||||
xOffset += d.width;
|
||||
@@ -412,8 +416,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
final int xOffset = insets.left;
|
||||
int yOffset = insets.top;
|
||||
for (int i = 0; i < componentCount; i++) {
|
||||
final Component component = getComponent(i);
|
||||
final Dimension d = component.getPreferredSize();
|
||||
final Dimension d = getChildPreferredSize(i);
|
||||
final Rectangle r = bounds.get(i);
|
||||
r.setBounds(xOffset + (maxWidth - d.width) / 2, yOffset, d.width, d.height);
|
||||
yOffset += d.height;
|
||||
@@ -445,7 +448,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
final Component eachComp = getComponent(i);
|
||||
final boolean isLast = i == componentCount - 1;
|
||||
|
||||
final Rectangle eachBound = new Rectangle(eachComp.getPreferredSize());
|
||||
final Rectangle eachBound = new Rectangle(getChildPreferredSize(i));
|
||||
maxHeight = Math.max(eachBound.height, maxHeight);
|
||||
|
||||
if (!full) {
|
||||
@@ -500,7 +503,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
int eachX = insets.left;
|
||||
int eachY = insets.top;
|
||||
for (int i = 0; i < componentCount; i++) {
|
||||
final Rectangle eachBound = new Rectangle(getComponent(i).getPreferredSize());
|
||||
final Rectangle eachBound = new Rectangle(getChildPreferredSize(i));
|
||||
if (!full) {
|
||||
boolean outside;
|
||||
if (i < componentCount - 1) {
|
||||
@@ -604,7 +607,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
int rowHeight = 0;
|
||||
final Dimension[] dims = new Dimension[componentCount]; // we will use this dimesions later
|
||||
for (int i = 0; i < componentCount; i++) {
|
||||
dims[i] = getComponent(i).getPreferredSize();
|
||||
dims[i] = getChildPreferredSize(i);
|
||||
final int height = dims[i].height;
|
||||
rowHeight = Math.max(rowHeight, height);
|
||||
}
|
||||
@@ -632,7 +635,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
int rowWidth = 0;
|
||||
final Dimension[] dims = new Dimension[componentCount]; // we will use this dimesions later
|
||||
for (int i = 0; i < componentCount; i++) {
|
||||
dims[i] = getComponent(i).getPreferredSize();
|
||||
dims[i] = getChildPreferredSize(i);
|
||||
final int width = dims[i].width;
|
||||
rowWidth = Math.max(rowWidth, width);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* @author spleaner
|
||||
@@ -56,9 +55,9 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
private int myCurrentOpacity;
|
||||
private Timer myTimer;
|
||||
private EditorImpl myEditor;
|
||||
private ContextMenuPanel myContextMenuPanel;
|
||||
private boolean myDisposed;
|
||||
private final JLayeredPane myLayeredPane;
|
||||
private ActionToolbar myActionToolbar;
|
||||
|
||||
public ContextMenuImpl(JLayeredPane layeredPane, @NotNull final JScrollPane container, @NotNull final EditorImpl editor) {
|
||||
setLayout(new BorderLayout(0, 0));
|
||||
@@ -118,6 +117,9 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
|
||||
if (myShow != show) {
|
||||
myShow = show;
|
||||
if (myShow && myActionToolbar != null) {
|
||||
myActionToolbar.updateActionsImmediately();
|
||||
}
|
||||
restartTimer();
|
||||
}
|
||||
}
|
||||
@@ -134,7 +136,7 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
|
||||
if (myTimer != null && myTimer.isRunning()) myTimer.stop();
|
||||
|
||||
myTimer = UIUtil.createNamedTimer("Restart context menu now",50, new ActionListener() {
|
||||
myTimer = UIUtil.createNamedTimer("Restart context menu now", 50, new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (myShow) {
|
||||
@@ -151,7 +153,7 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
}
|
||||
|
||||
myCurrentOpacity += 20;
|
||||
if (myCurrentOpacity > 100) {
|
||||
if (myCurrentOpacity >= 100) {
|
||||
myCurrentOpacity = 100;
|
||||
myVisible = true;
|
||||
myTimer.stop();
|
||||
@@ -160,18 +162,19 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
}
|
||||
|
||||
repaint();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (!myVisible) {
|
||||
if (myTimer != null && myTimer.isRunning()) myTimer.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
myCurrentOpacity -= 20;
|
||||
if (myCurrentOpacity < 0) {
|
||||
if (myCurrentOpacity <= 0) {
|
||||
myCurrentOpacity = 0;
|
||||
myVisible = false;
|
||||
myLayeredPane.remove(ContextMenuImpl.this);
|
||||
myLayeredPane.revalidate();
|
||||
myLayeredPane.repaint();
|
||||
}
|
||||
|
||||
repaint();
|
||||
@@ -197,7 +200,6 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
myTimer.stop();
|
||||
myTimer = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static boolean mayShowToolbar(@Nullable final Document document) {
|
||||
@@ -214,7 +216,7 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
myTimer.stop();
|
||||
}
|
||||
|
||||
myTimer = UIUtil.createNamedTimer("Hide context menu",1500, new ActionListener() {
|
||||
myTimer = UIUtil.createNamedTimer("Hide context menu", 1500, new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(final ActionEvent e) {
|
||||
if (myDisposed) return;
|
||||
@@ -226,7 +228,8 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
SwingUtilities.convertPointFromScreen(location, myComponent);
|
||||
if (!myComponent.getBounds().contains(location)) {
|
||||
toggleContextToolbar(false);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
scheduleHide();
|
||||
}
|
||||
}
|
||||
@@ -243,25 +246,6 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
new ActionToolbarImpl(ActionPlaces.CONTEXT_TOOLBAR, group, true, DataManager.getInstance(), ActionManagerEx.getInstanceEx(),
|
||||
KeymapManagerEx.getInstanceEx()) {
|
||||
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
if (myContextMenuPanel.isPaintChildren()) {
|
||||
paintChildren(g);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintChildren(final Graphics g) {
|
||||
if (myContextMenuPanel.isPaintChildren()) {
|
||||
super.paintChildren(g);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaque() {
|
||||
return myContextMenuPanel.isPaintChildren();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionButton createToolbarButton(final AnAction action,
|
||||
final ActionButtonLook look,
|
||||
@@ -271,27 +255,9 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
final ActionButton result = new ActionButton(action, presentation, place, minimumSize) {
|
||||
@Override
|
||||
public void paintComponent(final Graphics g) {
|
||||
if (myContextMenuPanel.isPaintChildren()) {
|
||||
final ActionButtonLook look = getButtonLook();
|
||||
look.paintIcon(g, this, getIcon());
|
||||
}
|
||||
|
||||
if (myContextMenuPanel.isShown() && getPopState() == ActionButton.POPPED) {
|
||||
final ActionButtonLook look = getButtonLook();
|
||||
look.paintBackground(g, this);
|
||||
look.paintIcon(g, this, getIcon());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaque() {
|
||||
return myContextMenuPanel.isPaintChildren() || getPopState() == ActionButton.POPPED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
final Graphics2D g2 = (Graphics2D)g;
|
||||
paintComponent(g2);
|
||||
final ActionButtonLook look = getButtonLook();
|
||||
look.paintBackground(g, this);
|
||||
look.paintIcon(g, this, getIcon());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -301,26 +267,25 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
};
|
||||
|
||||
actionToolbar.setTargetComponent(myEditor.getContentComponent());
|
||||
|
||||
return actionToolbar;
|
||||
}
|
||||
|
||||
private JComponent createComponent() {
|
||||
final ActionToolbar toolbar = createToolbar(myActionGroup);
|
||||
toolbar.setMinimumButtonSize(new Dimension(20, 20));
|
||||
toolbar.setReservePlaceAutoPopupIcon(false);
|
||||
myActionToolbar = createToolbar(myActionGroup);
|
||||
myActionToolbar.setMinimumButtonSize(new Dimension(20, 20));
|
||||
myActionToolbar.setReservePlaceAutoPopupIcon(false);
|
||||
|
||||
myContextMenuPanel = new ContextMenuPanel(this);
|
||||
myContextMenuPanel.setLayout(new BorderLayout(0, 0));
|
||||
myContextMenuPanel.add(toolbar.getComponent());
|
||||
ContextMenuPanel contextMenuPanel = new ContextMenuPanel(this);
|
||||
contextMenuPanel.setLayout(new BorderLayout(0, 0));
|
||||
JComponent toolbarComponent = myActionToolbar.getComponent();
|
||||
toolbarComponent.setOpaque(false);
|
||||
contextMenuPanel.add(toolbarComponent);
|
||||
|
||||
return myContextMenuPanel;
|
||||
return contextMenuPanel;
|
||||
}
|
||||
|
||||
private static class ContextMenuPanel extends JPanel {
|
||||
private final ContextMenuImpl myContextMenu;
|
||||
private BufferedImage myBufferedImage;
|
||||
private boolean myPaintChildren = false;
|
||||
|
||||
private ContextMenuPanel(final ContextMenuImpl contextMenu) {
|
||||
myContextMenu = contextMenu;
|
||||
@@ -328,64 +293,37 @@ public class ContextMenuImpl extends JPanel implements Disposable {
|
||||
setOpaque(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
super.invalidate();
|
||||
|
||||
myBufferedImage = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revalidate() {
|
||||
super.revalidate();
|
||||
|
||||
myBufferedImage = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintChildren(final Graphics g) {
|
||||
if (myPaintChildren) {
|
||||
super.paintChildren(g);
|
||||
Graphics2D graphics = (Graphics2D)g.create();
|
||||
try {
|
||||
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, myContextMenu.myCurrentOpacity / 100.0f));
|
||||
super.paintChildren(graphics);
|
||||
}
|
||||
finally {
|
||||
graphics.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPaintChildren() {
|
||||
return myPaintChildren;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
final Rectangle r = getBounds();
|
||||
if (myBufferedImage == null) {
|
||||
myBufferedImage = new BufferedImage(r.width, r.height, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
final Graphics graphics = myBufferedImage.getGraphics();
|
||||
final Graphics2D g2d2 = (Graphics2D)graphics;
|
||||
final Composite old = g2d2.getComposite();
|
||||
|
||||
g2d2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f));
|
||||
|
||||
g2d2.setColor(Color.GRAY);
|
||||
g2d2.fillRoundRect(0, 0, r.width - 1, r.height - 1, 6, 6);
|
||||
|
||||
g2d2.setComposite(old);
|
||||
|
||||
myPaintChildren = true;
|
||||
paintChildren(g2d2);
|
||||
myPaintChildren = false;
|
||||
}
|
||||
|
||||
final Graphics2D g2 = (Graphics2D)g;
|
||||
final Composite old = g2.getComposite();
|
||||
|
||||
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, myContextMenu.myCurrentOpacity / 100.0f));
|
||||
g2.drawImage(myBufferedImage, 0, 0, myBufferedImage.getWidth(null), myBufferedImage.getHeight(null), null);
|
||||
|
||||
g2.setComposite(old);
|
||||
public void paint(Graphics g) {
|
||||
paintComponent(g);
|
||||
super.paint(g);
|
||||
}
|
||||
|
||||
public boolean isShown() {
|
||||
return myContextMenu.myCurrentOpacity == 100;
|
||||
@Override
|
||||
public void paintComponent(final Graphics g) {
|
||||
Rectangle r = getBounds();
|
||||
Graphics2D graphics = (Graphics2D)g.create();
|
||||
try {
|
||||
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, myContextMenu.myCurrentOpacity / 500.0f));
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
graphics.setColor(Color.GRAY);
|
||||
graphics.fillRoundRect(0, 0, r.width - 1, r.height - 1, 6, 6);
|
||||
}
|
||||
finally {
|
||||
graphics.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +175,7 @@ xml.split.tag.intention.action=Split current tag
|
||||
tag.name.completion.hint=Press {0} to view tags from other namespaces
|
||||
tag.name.completion.display.name=Tag Name Completion
|
||||
open_in.list.popup.title=Preview file in...
|
||||
open_in.list.prefix=Preview file in
|
||||
xml.inspections.unbound.prefix=Unbound XML namespace prefix
|
||||
|
||||
html.add.table.column.after.action=Add a new column to the table after the current one
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.util.io;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: Vassiliy.Kudryashov
|
||||
*/
|
||||
public class WindowsRegistryUtil {
|
||||
private WindowsRegistryUtil() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String trimToValue(@Nullable StringBuilder output) {
|
||||
if (output == null) {
|
||||
return null;
|
||||
}
|
||||
int pos = output.lastIndexOf(" ");
|
||||
int pos2 = output.lastIndexOf("\t");
|
||||
pos = Math.max(pos, pos2);
|
||||
if (pos == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
output.delete(0, pos + 1);
|
||||
String blackList = "\r\n \"";
|
||||
int startPos = 0;
|
||||
int endPos = output.length() - 1;
|
||||
while (true) {
|
||||
if (startPos >= endPos) {
|
||||
return null;
|
||||
}
|
||||
if (blackList.indexOf(output.charAt(startPos)) != -1) {
|
||||
startPos++;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
if (blackList.indexOf(output.charAt(endPos)) != -1) {
|
||||
endPos--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return output.subSequence(startPos, endPos + 1).toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<String> readRegistryBranch(@NotNull String location) {
|
||||
List<String> result = new ArrayList<String>();
|
||||
StringBuilder output = readRegistry("reg query \"" + location + "\" /s");
|
||||
if (output != null) {
|
||||
for (int pos = output.indexOf(location); pos != -1; pos = output.indexOf(location, pos + location.length())) {
|
||||
int pos2 = output.indexOf("\r\n", pos + location.length());
|
||||
if (pos2 <= pos + location.length()) {
|
||||
continue;
|
||||
}
|
||||
String section = output.substring(pos + location.length() + 1, pos2);
|
||||
if (!section.contains("\\")) {
|
||||
result.add(section);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String readRegistryDefault(@NotNull String location) {
|
||||
return trimToValue(readRegistry("reg query \"" + location + "\" /ve"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String readRegistryValue(@NotNull String location, @NotNull String key) {
|
||||
return trimToValue(readRegistry("reg query \"" + location + "\" /v " + key));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static StringBuilder readRegistry(String command) {
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(command);
|
||||
StringBuilder output = null;
|
||||
InputStream is = null;
|
||||
ByteArrayOutputStream os = null;
|
||||
try {
|
||||
byte[] buffer = new byte[128];
|
||||
is = process.getInputStream();
|
||||
os = new ByteArrayOutputStream();
|
||||
for (int length = is.read(buffer); length > 0; length = is.read(buffer)) {
|
||||
os.write(buffer, 0, length);
|
||||
}
|
||||
output = new StringBuilder(new String(os.toByteArray()));
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
|
||||
}
|
||||
finally {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
if (os != null) {
|
||||
os.close();
|
||||
}
|
||||
process.waitFor();
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,12 @@ public class BrowserSettingsProviderImpl extends BrowserSettingsProvider {
|
||||
myConfiguration = configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySettingsFromWindowsRegistry() {
|
||||
if (mySettingsPanel != null)
|
||||
mySettingsPanel.applySettingsFromWindowsRegistry();
|
||||
}
|
||||
|
||||
public JComponent createComponent() {
|
||||
if (mySettingsPanel == null) {
|
||||
mySettingsPanel = new WebBrowsersPanel(myConfiguration);
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Conditions;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.WindowsRegistryUtil;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
|
||||
@@ -37,13 +38,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author spleaner
|
||||
*/
|
||||
@State(name = "WebBrowsersConfiguration", storages = {@Storage( file = StoragePathMacros.APP_CONFIG + "/browsers.xml")})
|
||||
@State(name = "WebBrowsersConfiguration", storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/browsers.xml")})
|
||||
public class BrowsersConfiguration implements PersistentStateComponent<Element> {
|
||||
public enum BrowserFamily {
|
||||
EXPLORER(XmlBundle.message("browsers.explorer"), "iexplore", null, null, AllIcons.Xml.Browsers.Explorer16),
|
||||
@@ -68,7 +70,11 @@ public class BrowsersConfiguration implements PersistentStateComponent<Element>
|
||||
private final String myMacPath;
|
||||
private final Icon myIcon;
|
||||
|
||||
BrowserFamily(final String name, @NonNls final String windowsPath, @NonNls final String linuxPath, @NonNls final String macPath, final Icon icon) {
|
||||
BrowserFamily(final String name,
|
||||
@NonNls final String windowsPath,
|
||||
@NonNls final String linuxPath,
|
||||
@NonNls final String macPath,
|
||||
final Icon icon) {
|
||||
myName = name;
|
||||
myWindowsPath = windowsPath;
|
||||
myLinuxPath = linuxPath;
|
||||
@@ -237,4 +243,50 @@ public class BrowsersConfiguration implements PersistentStateComponent<Element>
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data from Windows registry, may take some time to run (up to ~300ms)
|
||||
*
|
||||
* @return Map[BrowserFamily -> "path to .exe"]
|
||||
*/
|
||||
@NotNull
|
||||
public static EnumMap<BrowserFamily, String> getWindowsBrowsersEXE() {
|
||||
EnumMap<BrowserFamily, String> map = new EnumMap<BrowserFamily, String>(BrowserFamily.class);
|
||||
if (SystemInfo.isWindows) {
|
||||
List<String> sections = WindowsRegistryUtil.readRegistryBranch("HKEY_LOCAL_MACHINE\\SOFTWARE\\Clients\\StartMenuInternet");
|
||||
for (String section : sections) {
|
||||
BrowserFamily family = getFamily(section);
|
||||
if (family == null) {
|
||||
continue; //We ignore "unknown" browsers like Maxthon, RockMelt, SeaMonkey, Deepnet Explorer, Avant Browser etc.
|
||||
}
|
||||
String pathToExe = WindowsRegistryUtil.readRegistryDefault(
|
||||
"HKLM\\SOFTWARE\\Clients\\StartMenuInternet\\" + section + "\\shell\\open\\command");
|
||||
if (pathToExe != null) {
|
||||
map.put(family, pathToExe);
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static BrowserFamily getFamily(String registryName) {
|
||||
registryName = registryName.toLowerCase();
|
||||
if (registryName.contains("firefox")) {
|
||||
return BrowserFamily.FIREFOX;
|
||||
}
|
||||
if (registryName.contains("iexplore")) {
|
||||
return BrowserFamily.EXPLORER;
|
||||
}
|
||||
if (registryName.contains("opera")) {
|
||||
return BrowserFamily.OPERA;
|
||||
}
|
||||
if (registryName.contains("safari")) {
|
||||
return BrowserFamily.SAFARI;
|
||||
}
|
||||
if (registryName.contains("google")) {
|
||||
return BrowserFamily.CHROME;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.ide.browsers;
|
||||
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
@@ -31,14 +32,17 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
/**
|
||||
* @author spleaner
|
||||
*/
|
||||
public class WebBrowsersPanel extends JPanel {
|
||||
private final JPanel mySettingsPanel;
|
||||
private Map<BrowsersConfiguration.BrowserFamily, Pair<JCheckBox, TextFieldWithBrowseButton>> myBrowserSettingsMap = new HashMap<BrowsersConfiguration.BrowserFamily, Pair<JCheckBox, TextFieldWithBrowseButton>>();
|
||||
private Map<BrowsersConfiguration.BrowserFamily, Pair<JCheckBox, TextFieldWithBrowseButton>> myBrowserSettingsMap =
|
||||
new HashMap<BrowsersConfiguration.BrowserFamily, Pair<JCheckBox, TextFieldWithBrowseButton>>();
|
||||
private final BrowsersConfiguration myConfiguration;
|
||||
|
||||
public WebBrowsersPanel(final BrowsersConfiguration configuration) {
|
||||
@@ -127,6 +131,48 @@ public class WebBrowsersPanel extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
public void applySettingsFromWindowsRegistry() {
|
||||
if (!SystemInfo.isWindows) {
|
||||
return;
|
||||
}
|
||||
ApplicationManager.getApplication()
|
||||
.executeOnPooledThread(new SwingWorker<EnumMap<BrowsersConfiguration.BrowserFamily, String>, Void>() {
|
||||
@Override
|
||||
protected EnumMap<BrowsersConfiguration.BrowserFamily, String> doInBackground() throws Exception {
|
||||
return BrowsersConfiguration.getWindowsBrowsersEXE();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
EnumMap<BrowsersConfiguration.BrowserFamily, String> map = null;
|
||||
try {
|
||||
map = get();
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
catch (ExecutionException ignored) {
|
||||
}
|
||||
if (myBrowserSettingsMap == null) {
|
||||
return;//we are disposed
|
||||
}
|
||||
if (map != null && !map.isEmpty()) {
|
||||
for (BrowsersConfiguration.BrowserFamily family : BrowsersConfiguration.BrowserFamily.values()) {
|
||||
Pair<JCheckBox, TextFieldWithBrowseButton> pair = myBrowserSettingsMap.get(family);
|
||||
String pathToExe = map.get(family);
|
||||
if (pathToExe != null) {
|
||||
pair.first.setSelected(true);
|
||||
pair.second.setText(pathToExe);
|
||||
}
|
||||
else {
|
||||
pair.first.setSelected(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void dispose() {
|
||||
myBrowserSettingsMap = null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user