diff --git a/images/src/META-INF/ImagesPlugin.xml b/images/src/META-INF/ImagesPlugin.xml index ecfe40b8103c..74132aed56fe 100644 --- a/images/src/META-INF/ImagesPlugin.xml +++ b/images/src/META-INF/ImagesPlugin.xml @@ -41,9 +41,10 @@ description="Show a chessboard on transparent image parts"> + @@ -81,7 +82,7 @@ - + diff --git a/images/src/org/intellij/images/editor/actions/SetBackgroundImageDialog.form b/images/src/org/intellij/images/editor/actions/SetBackgroundImageDialog.form index 1224d45a0d47..009961d89eb6 100644 --- a/images/src/org/intellij/images/editor/actions/SetBackgroundImageDialog.form +++ b/images/src/org/intellij/images/editor/actions/SetBackgroundImageDialog.form @@ -3,7 +3,7 @@ - + @@ -53,7 +53,7 @@ - + @@ -66,7 +66,7 @@ - + @@ -85,9 +85,9 @@ - + - + @@ -95,7 +95,7 @@ - + @@ -103,7 +103,7 @@ - + @@ -111,7 +111,7 @@ - + @@ -119,7 +119,7 @@ - + @@ -127,7 +127,7 @@ - + @@ -135,7 +135,7 @@ - + @@ -143,9 +143,25 @@ - + + + + + + + + + + + + + + + + + @@ -195,15 +211,22 @@ + + + + - - - - - + + + + + + + + diff --git a/images/src/org/intellij/images/editor/actions/SetBackgroundImageDialog.java b/images/src/org/intellij/images/editor/actions/SetBackgroundImageDialog.java index 05f0a46f6113..a46a8cecb910 100644 --- a/images/src/org/intellij/images/editor/actions/SetBackgroundImageDialog.java +++ b/images/src/org/intellij/images/editor/actions/SetBackgroundImageDialog.java @@ -15,6 +15,7 @@ */ package org.intellij.images.editor.actions; +import com.intellij.CommonBundle; import com.intellij.application.options.colors.ColorAndFontOptions; import com.intellij.application.options.colors.SimpleEditorPreview; import com.intellij.ide.util.PropertiesComponent; @@ -60,11 +61,12 @@ public class SetBackgroundImageDialog extends DialogWrapper { private final String myPropertyTmp; private JPanel myRoot; private JBRadioButton myEditorRb; + private JBRadioButton myScaleRb; + private JBRadioButton myCenterRb; private JSlider myOpacitySlider; private JSpinner myOpacitySpinner; private JPanel myPreviewPanel; private ComboboxWithBrowseButton myPathField; - private JBRadioButton myScaleRb; boolean myAdjusting; private String mySelectedPath; @@ -191,10 +193,15 @@ public class SetBackgroundImageDialog extends DialogWrapper { button.setActionCommand(button.getText()); button.addChangeListener(this::targetChanged); } - for (Enumeration e = getTypeRbGroup().getElements(); e.hasMoreElements();) { + for (Enumeration e = getFillRbGroup().getElements(); e.hasMoreElements();) { AbstractButton button = e.nextElement(); button.setActionCommand(button.getText()); - button.addChangeListener(this::fillTypeChanged); + button.addChangeListener(this::fillOrPlaceChanged); + } + for (Enumeration e = getPlaceRbGroup().getElements(); e.hasMoreElements();) { + AbstractButton button = e.nextElement(); + button.setActionCommand(button.getText()); + button.addChangeListener(this::fillOrPlaceChanged); } ChangeListener opacitySync = new ChangeListener() { @@ -220,6 +227,7 @@ public class SetBackgroundImageDialog extends DialogWrapper { myOpacitySlider.setValue(15); myOpacitySpinner.setValue(15); myScaleRb.setSelected(true); + myCenterRb.setSelected(true); myEditorRb.setSelected(true); myAdjusting = false; } @@ -232,7 +240,7 @@ public class SetBackgroundImageDialog extends DialogWrapper { updatePreview(); } - private void fillTypeChanged(ChangeEvent event) { + private void fillOrPlaceChanged(ChangeEvent event) { updatePreview(); } @@ -252,7 +260,7 @@ public class SetBackgroundImageDialog extends DialogWrapper { mySelectedPath = path; if (StringUtil.isEmptyOrSpaces(path)) return; CollectionComboBoxModel comboModel = getComboModel(); - if (!comboModel.getItems().contains(path)) { + if (!comboModel.contains(path)) { comboModel.add(path); } comboModel.setSelectedItem(path); @@ -264,20 +272,15 @@ public class SetBackgroundImageDialog extends DialogWrapper { String prop = getSystemProp(); String value = StringUtil.notNullize(myResults.get(prop), getProperty(prop)); String[] split = value.split(","); + int opacity = split.length > 1 ? StringUtil.parseInt(split[1], 15) : 15; + String fill = split.length > 2 ? split[2] : "scale"; + String place = split.length > 3 ? split[3] : "center"; setSelectedPath(split[0]); mySelectedPath = null; - int opacity = split.length > 1 ? StringUtil.parseInt(split[1], 15) : 15; myOpacitySlider.setValue(opacity); myOpacitySpinner.setValue(opacity); - String type = split.length > 2 ? split[2] : "scale"; - for (Enumeration e = getTypeRbGroup().getElements(); e.hasMoreElements(); ) { - AbstractButton button = e.nextElement(); - String s = button.getActionCommand().replace('-', '_'); - if (s.equalsIgnoreCase(type)) { - button.setSelected(true); - break; - } - } + setSelected(getFillRbGroup(), fill); + setSelected(getPlaceRbGroup(), place); myAdjusting = false; } @@ -294,7 +297,7 @@ public class SetBackgroundImageDialog extends DialogWrapper { String prop = getSystemProp(); myResults.put(prop, value); - if (value.startsWith(",")) return; + if (value.startsWith(",")) value = null; PropertiesComponent.getInstance().setValue(prop, value); super.doOKAction(); @@ -319,9 +322,10 @@ public class SetBackgroundImageDialog extends DialogWrapper { private void restoreRecentImages() { String value = PropertiesComponent.getInstance().getValue(getRecentItemsKey()); if (value == null) return; + CollectionComboBoxModel model = getComboModel(); for (String s : value.split("\n")) { - //noinspection unchecked - getComboModel().add(s); + if (StringUtil.isEmptyOrSpaces(s) || model.contains(s)) continue; + model.add(s); } } @@ -335,27 +339,44 @@ public class SetBackgroundImageDialog extends DialogWrapper { } private void updatePreview() { + if (myAdjusting) return; String prop = getSystemProp(); String value = calcNewValue(); System.setProperty(myPropertyTmp, value); myResults.put(prop, value); myPreviewPanel.validate(); myPreviewPanel.repaint(); + boolean clear = value.startsWith(","); + getOKAction().putValue(Action.NAME, clear ? "Clear" : CommonBundle.getOkButtonText()); } @NotNull private String calcNewValue() { String path = (String)myPathField.getComboBox().getEditor().getItem(); - String type = getTypeRbGroup().getSelection().getActionCommand() - .replace('-', '_').toLowerCase(Locale.ENGLISH); - - return path.trim() + "," + myOpacitySpinner.getValue() + "," + type; + String type = getFillRbGroup().getSelection().getActionCommand().replace('-', '_'); + String place = getPlaceRbGroup().getSelection().getActionCommand().replace('-', '_'); + return path.trim() + "," + myOpacitySpinner.getValue() + "," + (type + "," + place).toLowerCase(Locale.ENGLISH); } - private ButtonGroup getTypeRbGroup() { + private static void setSelected(ButtonGroup group, String fill) { + for (Enumeration e = group.getElements(); e.hasMoreElements(); ) { + AbstractButton button = e.nextElement(); + String s = button.getActionCommand().replace('-', '_'); + if (s.equalsIgnoreCase(fill)) { + button.setSelected(true); + break; + } + } + } + + private ButtonGroup getFillRbGroup() { return ((DefaultButtonModel)myScaleRb.getModel()).getGroup(); } + private ButtonGroup getPlaceRbGroup() { + return ((DefaultButtonModel)myCenterRb.getModel()).getGroup(); + } + private ButtonGroup getTargetRbGroup() { return ((DefaultButtonModel)myEditorRb.getModel()).getGroup(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeBackgroundUtil.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeBackgroundUtil.java index 49e952afb692..79abf2d64467 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeBackgroundUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeBackgroundUtil.java @@ -120,7 +120,7 @@ public class IdeBackgroundUtil { Image centerImage = url == null ? null : ImageLoader.loadFromUrl(url); if (centerImage != null) { - painters.addPainter(PaintersHelper.newImagePainter(centerImage, PaintersHelper.FillType.TOP_CENTER, 1.0f, JBUI.insets(10, 0, 0, 0)), null); + painters.addPainter(PaintersHelper.newImagePainter(centerImage, PaintersHelper.Fill.PLAIN, PaintersHelper.Place.TOP_CENTER, 1.0f, JBUI.insets(10, 0, 0, 0)), null); } painters.addPainter(new AbstractPainter() { EditorEmptyTextPainter p = ServiceManager.getService(EditorEmptyTextPainter.class); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/PaintersHelper.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/PaintersHelper.java index 2530a16ab8ef..c3323edf90c4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/PaintersHelper.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/PaintersHelper.java @@ -152,8 +152,11 @@ final class PaintersHelper implements Painter.Listener { } } - public enum FillType { - BG_CENTER, TILE, SCALE, + public enum Fill { + PLAIN, SCALE, TILE + } + + public enum Place { CENTER, TOP_CENTER, BOTTOM_CENTER, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT } @@ -169,7 +172,8 @@ final class PaintersHelper implements Painter.Listener { Image image; float alpha; Insets insets; - FillType fillType; + Fill fillType; + Place place; String current; @@ -181,7 +185,7 @@ final class PaintersHelper implements Painter.Listener { @Override public void executePaint(Component component, Graphics2D g) { if (image == null) return; // covered by needsRepaint() - executePaint(g, component, image, fillType, alpha, insets); + executePaint(g, component, image, fillType, place, alpha, insets); } boolean ensureImageLoaded() { @@ -195,14 +199,15 @@ final class PaintersHelper implements Painter.Listener { return image != null; } - private void resetImage(String value, Image newImage, float newAlpha, FillType newFillType) { + private void resetImage(String value, Image newImage, float newAlpha, Fill newFill, Place newPlace) { if (!Comparing.equal(current, value)) return; boolean prevOk = image != null; clearImages(-1); image = newImage; insets = JBUI.emptyInsets(); alpha = newAlpha; - fillType = newFillType; + fillType = newFill; + place = newPlace; boolean newOk = newImage != null; if (prevOk || newOk) { repaintAllWindows(); @@ -212,9 +217,14 @@ final class PaintersHelper implements Painter.Listener { private void loadImageAsync(final String propertyValue) { String[] parts = (propertyValue != null ? propertyValue : propertyName + ".png").split(","); final float newAlpha = Math.abs(Math.min(StringUtil.parseInt(parts.length > 1 ? parts[1] : "", 10) / 100f, 1f)); - final FillType newFillType = StringUtil.parseEnum(parts.length > 2 ? parts[2].toUpperCase(Locale.ENGLISH) : "", FillType.SCALE, FillType.class); + final Fill newFillType = StringUtil.parseEnum(parts.length > 2 ? parts[2].toUpperCase(Locale.ENGLISH) : "", Fill.SCALE, Fill.class); + final Place newPlace = StringUtil.parseEnum(parts.length > 3 ? parts[3].toUpperCase(Locale.ENGLISH) : "", Place.CENTER, Place.class); + String filePath = parts[0]; + if (StringUtil.isEmpty(filePath)) { + resetImage(propertyValue, null, newAlpha, newFillType, newPlace); + return; + } try { - String filePath = parts[0]; URL url = filePath.contains("://") ? new URL(filePath) : (FileUtil.isAbsolutePlatformIndependent(filePath) ? new File(filePath) @@ -226,14 +236,14 @@ final class PaintersHelper implements Painter.Listener { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { - resetImage(propertyValue, m, newAlpha, newFillType); + resetImage(propertyValue, m, newAlpha, newFillType, newPlace); } }, modalityState); } }); } catch (Exception e) { - resetImage(propertyValue, null, newAlpha, newFillType); + resetImage(propertyValue, null, newAlpha, newFillType, newPlace); } } }; @@ -245,7 +255,7 @@ final class PaintersHelper implements Painter.Listener { } } - public static AbstractPainter newImagePainter(@NotNull final Image image, final FillType fillType, final float alpha, final Insets insets) { + public static AbstractPainter newImagePainter(@NotNull final Image image, final Fill fillType, final Place place, final float alpha, final Insets insets) { return new ImagePainter() { @Override public boolean needsRepaint() { @@ -254,7 +264,7 @@ final class PaintersHelper implements Painter.Listener { @Override public void executePaint(Component component, Graphics2D g) { - executePaint(g, component, image, fillType, alpha, insets); + executePaint(g, component, image, fillType, place, alpha, insets); } }; } @@ -274,7 +284,7 @@ final class PaintersHelper implements Painter.Listener { final Map cachedMap = ContainerUtil.newHashMap(); - public void executePaint(Graphics2D g, Component component, Image image, FillType fillType, float alpha, Insets insets) { + public void executePaint(Graphics2D g, Component component, Image image, Fill fillType, Place place, float alpha, Insets insets) { int cw0 = component.getWidth(); int ch0 = component.getHeight(); Insets i = JBUI.insets(insets.top * ch0 / 100, insets.left * cw0 / 100, insets.bottom * ch0 / 100, insets.right * cw0 / 100); @@ -288,9 +298,9 @@ final class PaintersHelper implements Painter.Listener { GraphicsConfiguration cfg = g.getDeviceConfiguration(); Cached cached = cachedMap.get(cfg); VolatileImage scaled = cached == null ? null : cached.image; - if (fillType == FillType.SCALE || fillType == FillType.TILE) { + if (fillType == Fill.SCALE || fillType == Fill.TILE) { int sw, sh; - if (fillType == FillType.SCALE) { + if (fillType == Fill.SCALE) { boolean useWidth = cw * h > ch * w; sw = useWidth ? cw : w * ch / h; sh = useWidth ? h * cw / w : ch; @@ -312,7 +322,7 @@ final class PaintersHelper implements Painter.Listener { } Graphics2D gg = scaled.createGraphics(); gg.setComposite(AlphaComposite.Src); - if (fillType == FillType.SCALE) { + if (fillType == Fill.SCALE) { gg.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); gg.drawImage(image, 0, 0, sw, sh, null); @@ -347,18 +357,17 @@ final class PaintersHelper implements Painter.Listener { } int x, y; - if (fillType == FillType.CENTER || fillType == FillType.BG_CENTER || - fillType == FillType.SCALE || fillType == FillType.TILE || - fillType == FillType.TOP_CENTER || fillType == FillType.BOTTOM_CENTER) { + if (place == Place.CENTER || + place == Place.TOP_CENTER || place == Place.BOTTOM_CENTER) { x = i.left + (cw - w) / 2; - y = fillType == FillType.TOP_CENTER ? i.top : - fillType == FillType.BOTTOM_CENTER ? ch0 - i.bottom - h : + y = place == Place.TOP_CENTER ? i.top : + place == Place.BOTTOM_CENTER ? ch0 - i.bottom - h : i.top + (ch - h) / 2; } - else if (fillType == FillType.TOP_LEFT || fillType == FillType.TOP_RIGHT || - fillType == FillType.BOTTOM_LEFT || fillType == FillType.BOTTOM_RIGHT) { - x = fillType == FillType.TOP_LEFT || fillType == FillType.BOTTOM_LEFT ? i.left : cw0 - i.right - w; - y = fillType == FillType.TOP_LEFT || fillType == FillType.TOP_RIGHT ? i.top : ch0 - i.bottom - h; + else if (place == Place.TOP_LEFT || place == Place.TOP_RIGHT || + place == Place.BOTTOM_LEFT || place == Place.BOTTOM_RIGHT) { + x = place == Place.TOP_LEFT || place == Place.BOTTOM_LEFT ? i.left : cw0 - i.right - w; + y = place == Place.TOP_LEFT || place == Place.TOP_RIGHT ? i.top : ch0 - i.bottom - h; } else { return; @@ -366,13 +375,6 @@ final class PaintersHelper implements Painter.Listener { GraphicsConfig gc = new GraphicsConfig(g).setAlpha(alpha); UIUtil.drawImage(g, scaled, x, y, w, h, null); - if (fillType == FillType.BG_CENTER) { - g.setColor(component.getBackground()); - g.fillRect(0, 0, x, ch0); - g.fillRect(x, 0, w, h); - g.fillRect(x + w, 0, x, ch0); - g.fillRect(x, y + h, w, y); - } gc.restore(); }