mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Extract color pipette interface
This commit is contained in:
committed by
Alexander Zolotov
parent
a2ccc2ef9d
commit
ed21a2e0b3
@@ -21,9 +21,13 @@ import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.ui.picker.ColorListener;
|
||||
import com.intellij.ui.picker.ColorPipette;
|
||||
import com.intellij.ui.picker.ColorPipetteBase;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
@@ -44,7 +48,6 @@ import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.MemoryImageSource;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
@@ -70,6 +73,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
private final List<ColorPickerListener> myExternalListeners;
|
||||
|
||||
private RecentColorsComponent myRecentColorsComponent;
|
||||
@Nullable
|
||||
private final ColorPipette myPicker;
|
||||
private final JLabel myR = new JLabel("R:");
|
||||
private final JLabel myG = new JLabel("G:");
|
||||
@@ -120,13 +124,12 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
}
|
||||
});
|
||||
|
||||
myPicker = new ColorPipette(this, getColor());
|
||||
myPicker.setListener(new ColorListener() {
|
||||
myPicker = createPipette(new ColorListener() {
|
||||
@Override
|
||||
public void colorChanged(Color color, Object source) {
|
||||
setColor(color, source);
|
||||
}
|
||||
});
|
||||
}, parent);
|
||||
try {
|
||||
add(buildTopPanel(true), BorderLayout.NORTH);
|
||||
add(myColorWheelPanel, BorderLayout.CENTER);
|
||||
@@ -155,6 +158,16 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private DefaultColorPipette createPipette(@NotNull ColorListener colorListener, @NotNull Disposable parentDisposable) {
|
||||
DefaultColorPipette defaultPipette = new DefaultColorPipette(this, colorListener);
|
||||
Disposer.register(parentDisposable, defaultPipette);
|
||||
if (defaultPipette.isAvailable()) {
|
||||
return defaultPipette;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isRGBMode() {
|
||||
return myFormat.getSelectedIndex() == 0;
|
||||
}
|
||||
@@ -345,7 +358,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
final JPanel result = new JPanel(new BorderLayout());
|
||||
|
||||
final JPanel previewPanel = new JPanel(new BorderLayout());
|
||||
if (enablePipette && ColorPipette.isAvailable()) {
|
||||
if (enablePipette && myPicker != null) {
|
||||
final JButton pipette = new JButton();
|
||||
pipette.setUI(new BasicButtonUI());
|
||||
pipette.setRolloverEnabled(true);
|
||||
@@ -356,12 +369,8 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
pipette.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
myPicker.myOldColor = getColor();
|
||||
myPicker.pick();
|
||||
//JBPopupFactory.getInstance().createBalloonBuilder(new JLabel("Press ESC button to close pipette"))
|
||||
// .setAnimationCycle(2000)
|
||||
// .setSmallVariant(true)
|
||||
// .createBalloon().show(new RelativePoint(pipette, new Point(pipette.getWidth() / 2, 0)), Balloon.Position.above);
|
||||
myPicker.setColor(getColor());
|
||||
myPicker.show();
|
||||
}
|
||||
});
|
||||
previewPanel.add(pipette, BorderLayout.WEST);
|
||||
@@ -1019,47 +1028,60 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
}
|
||||
}
|
||||
|
||||
private static class ColorPipette implements ImageObserver {
|
||||
private Dialog myPickerFrame;
|
||||
private static class DefaultColorPipette extends ColorPipetteBase {
|
||||
private static final int SIZE = 32;
|
||||
|
||||
private final JComponent myParent;
|
||||
private final Robot myRobot;
|
||||
private final ColorListener myColorListener;
|
||||
private final Timer myTimer;
|
||||
|
||||
@SuppressWarnings("UseJBColor")
|
||||
private final Color myTransparentColor = new Color(0, true);
|
||||
private final Rectangle myCaptureRect = new Rectangle(-4, -4, 8, 8);
|
||||
private final Rectangle myZoomRect = new Rectangle(0, 0, SIZE, SIZE);
|
||||
private final Point myHotSpot = new Point(SIZE / 2, SIZE / 2);
|
||||
private final Point myPreviousLocation = new Point();
|
||||
|
||||
private final Alarm myColorListenersNotifier = new Alarm(Alarm.ThreadToUse.SWING_THREAD, this);
|
||||
|
||||
private Color myOldColor;
|
||||
private Timer myTimer;
|
||||
|
||||
private Point myPoint = new Point();
|
||||
private Robot myRobot = null;
|
||||
private Color myPreviousColor;
|
||||
private Point myPreviousLocation;
|
||||
private Rectangle myCaptureRect;
|
||||
|
||||
private Dialog myPickerFrame;
|
||||
private Graphics2D myGraphics;
|
||||
private BufferedImage myImage;
|
||||
private Point myHotspot;
|
||||
private BufferedImage myPipetteImage;
|
||||
@SuppressWarnings("UseJBColor")
|
||||
private Color myTransparentColor = new Color(0, true);
|
||||
private Rectangle myZoomRect;
|
||||
private ColorListener myColorListener;
|
||||
private BufferedImage myMaskImage;
|
||||
private Alarm myColorListenersNotifier = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
|
||||
private static final int SIZE = 32;
|
||||
|
||||
private ColorPipette(JComponent parent, Color oldColor) {
|
||||
private DefaultColorPipette(@NotNull JComponent parent, @NotNull ColorListener colorListener) {
|
||||
myParent = parent;
|
||||
myOldColor = oldColor;
|
||||
|
||||
try {
|
||||
myRobot = new Robot();
|
||||
}
|
||||
catch (AWTException e) {
|
||||
// should not happen
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener(ColorListener colorListener) {
|
||||
myRobot = createRobot();
|
||||
myColorListener = colorListener;
|
||||
myTimer = new Timer(5, new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
updatePipette();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void pick() {
|
||||
@Override
|
||||
public void setColor(@Nullable Color color) {
|
||||
myOldColor = color;
|
||||
myPreviousColor = color;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Color getColor() {
|
||||
return myPreviousColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
Dialog picker = getPicker();
|
||||
updateLocation();
|
||||
picker.setVisible(true);
|
||||
myTimer.start();
|
||||
// it seems like it's the lowest value for opacity for mouse events to be processed correctly
|
||||
@@ -1067,7 +1089,23 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean imageUpdate(Image img, int flags, int x, int y, int width, int height) {
|
||||
public void close() {
|
||||
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||
Point location = pointerInfo.getLocation();
|
||||
Color pixelColor = myRobot.getPixelColor(location.x, location.y);
|
||||
cancelPipette();
|
||||
if (myColorListener != null) {
|
||||
myColorListener.colorChanged(pixelColor, this);
|
||||
myOldColor = pixelColor;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (myRobot != null) {
|
||||
myRobot.createScreenCapture(new Rectangle(0, 0, 1, 1));
|
||||
return WindowManager.getInstance().isAlphaModeSupported();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1089,7 +1127,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
e.consume();
|
||||
pickDone();
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1124,11 +1162,6 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
JRootPane rootPane = ((JDialog)myPickerFrame).getRootPane();
|
||||
rootPane.putClientProperty("Window.shadow", Boolean.FALSE);
|
||||
|
||||
myCaptureRect = new Rectangle(-4, -4, 8, 8);
|
||||
myHotspot = new Point(SIZE / 2, SIZE / 2);
|
||||
|
||||
myZoomRect = new Rectangle(0, 0, SIZE, SIZE);
|
||||
|
||||
myMaskImage = UIUtil.createImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D maskG = myMaskImage.createGraphics();
|
||||
maskG.setColor(Color.BLUE);
|
||||
@@ -1141,6 +1174,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
|
||||
myPipetteImage = UIUtil.createImage(AllIcons.Ide.Pipette.getIconWidth(), AllIcons.Ide.Pipette.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D graphics = myPipetteImage.createGraphics();
|
||||
//noinspection ConstantConditions
|
||||
AllIcons.Ide.Pipette.paintIcon(null, graphics, 0, 0);
|
||||
graphics.dispose();
|
||||
|
||||
@@ -1156,57 +1190,26 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
cancelPipette();
|
||||
break;
|
||||
case KeyEvent.VK_ENTER:
|
||||
pickDone();
|
||||
close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myTimer = new Timer(5, new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
updatePipette();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return myPickerFrame;
|
||||
}
|
||||
|
||||
private void cancelPipette() {
|
||||
myTimer.stop();
|
||||
myPickerFrame.setVisible(false);
|
||||
if (myColorListener != null && myOldColor != null) {
|
||||
myColorListener.colorChanged(myOldColor, this);
|
||||
}
|
||||
}
|
||||
|
||||
public void pickDone() {
|
||||
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||
Point location = pointerInfo.getLocation();
|
||||
Color pixelColor = myRobot.getPixelColor(location.x, location.y);
|
||||
cancelPipette();
|
||||
if (myColorListener != null) {
|
||||
myColorListener.colorChanged(pixelColor, this);
|
||||
myOldColor = pixelColor;
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePipette() {
|
||||
if (myPickerFrame != null && myPickerFrame.isShowing()) {
|
||||
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||
Point mouseLoc = pointerInfo.getLocation();
|
||||
myPickerFrame.setLocation(mouseLoc.x - myPickerFrame.getWidth() / 2, mouseLoc.y - myPickerFrame.getHeight() / 2);
|
||||
|
||||
myPoint.setLocation(mouseLoc);
|
||||
|
||||
final Color c = myRobot.getPixelColor(myPoint.x, myPoint.y);
|
||||
Point mouseLoc = updateLocation();
|
||||
final Color c = myRobot.getPixelColor(mouseLoc.x, mouseLoc.y);
|
||||
if (!c.equals(myPreviousColor) || !mouseLoc.equals(myPreviousLocation)) {
|
||||
myPreviousColor = c;
|
||||
myPreviousLocation = mouseLoc;
|
||||
myCaptureRect.setLocation(mouseLoc.x - 2/*+ myCaptureOffset.x*/, mouseLoc.y - 2/*+ myCaptureOffset.y*/);
|
||||
myCaptureRect.setBounds(mouseLoc.x -2, mouseLoc.y -2, 5, 5);
|
||||
|
||||
myPreviousLocation.setLocation(mouseLoc);
|
||||
myCaptureRect.setLocation(mouseLoc.x - 2, mouseLoc.y - 2);
|
||||
myCaptureRect.setBounds(mouseLoc.x - 2, mouseLoc.y - 2, 5, 5);
|
||||
|
||||
BufferedImage capture = myRobot.createScreenCapture(myCaptureRect);
|
||||
|
||||
// Clear the cursor graphics
|
||||
@@ -1225,13 +1228,13 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
|
||||
UIUtil.drawImage(myGraphics, myPipetteImage, SIZE - AllIcons.Ide.Pipette.getIconWidth(), 0, this);
|
||||
|
||||
myPickerFrame.setCursor(myParent.getToolkit().createCustomCursor(myImage, myHotspot, "ColorPicker"));
|
||||
if (myColorListener != null) {
|
||||
myPickerFrame.setCursor(myParent.getToolkit().createCustomCursor(myImage, myHotSpot, "ColorPicker"));
|
||||
if (myColorListener != null && !myColorListenersNotifier.isDisposed()) {
|
||||
myColorListenersNotifier.cancelAllRequests();
|
||||
myColorListenersNotifier.addRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myColorListener.colorChanged(c, ColorPipette.this);
|
||||
myColorListener.colorChanged(c, DefaultColorPipette.this);
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
@@ -1239,20 +1242,46 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isAvailable() {
|
||||
try {
|
||||
Robot robot = new Robot();
|
||||
robot.createScreenCapture(new Rectangle(0, 0, 1, 1));
|
||||
return WindowManager.getInstance().isAlphaModeSupported();
|
||||
@NotNull
|
||||
private Point updateLocation() {
|
||||
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||
Point mouseLoc = pointerInfo.getLocation();
|
||||
if (myPickerFrame != null) {
|
||||
myPickerFrame.setLocation(mouseLoc.x - myPickerFrame.getWidth() / 2, mouseLoc.y - myPickerFrame.getHeight() / 2);
|
||||
}
|
||||
catch (AWTException e) {
|
||||
return false;
|
||||
return mouseLoc;
|
||||
}
|
||||
|
||||
private void cancelPipette() {
|
||||
myTimer.stop();
|
||||
myPickerFrame.setVisible(false);
|
||||
if (myColorListener != null && myOldColor != null) {
|
||||
myColorListener.colorChanged(myOldColor, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Robot createRobot() {
|
||||
try {
|
||||
return new Robot();
|
||||
}
|
||||
catch (AWTException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
UIUtil.dispose(myPickerFrame);
|
||||
if (myGraphics != null) {
|
||||
myGraphics.dispose();
|
||||
}
|
||||
myOldColor = null;
|
||||
myPreviousColor = null;
|
||||
myImage = null;
|
||||
myPipetteImage = null;
|
||||
myMaskImage = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
interface ColorListener {
|
||||
void colorChanged(Color color, Object source);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.ui.picker;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public interface ColorListener {
|
||||
void colorChanged(Color color, Object source);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.ui.picker;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.ImageObserver;
|
||||
|
||||
public interface ColorPipette extends ImageObserver, Disposable {
|
||||
void setColor(@Nullable Color color);
|
||||
|
||||
@Nullable
|
||||
Color getColor();
|
||||
|
||||
void show();
|
||||
|
||||
void close();
|
||||
|
||||
boolean isAvailable();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.ui.picker;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public abstract class ColorPipetteBase implements ColorPipette {
|
||||
@Override
|
||||
public boolean imageUpdate(Image image, int i, int i1, int i2, int i3, int i4) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user