IDEA-117223 Custom background image/colour for each project

This commit is contained in:
Gregory.Shrago
2016-06-08 22:12:46 +03:00
parent 3d149f44ff
commit 257b8d2910
6 changed files with 78 additions and 31 deletions
+1 -1
View File
@@ -19,7 +19,7 @@
<fileLookupInfoProvider implementation="org.intellij.images.completion.ImageLookupInfoProvider"/>
<documentationProvider implementation="org.intellij.images.fileTypes.ImageDocumentationProvider"/>
<statistics.usagesCollector implementation="org.intellij.images.statistics.BackgroundUsageCollector"/>
<statistics.usagesCollector implementation="org.intellij.images.statistics.BackgroundImagesUsageCollector"/>
</extensions>
<actions>
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.images.editor.actions.SetBackgroundImageDialog">
<grid id="cbd77" binding="myRoot" layout-manager="GridLayoutManager" row-count="4" column-count="6" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="cbd77" binding="myRoot" layout-manager="GridLayoutManager" row-count="4" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="10" bottom="10" right="10"/>
<constraints>
<xy x="48" y="54" width="652" height="535"/>
<xy x="48" y="54" width="721" height="535"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="4ca83" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="4ca83" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
</constraints>
<properties/>
<border type="none"/>
@@ -21,7 +21,7 @@
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Frame background"/>
<text value="Frame"/>
</properties>
</component>
<component id="c72f5" class="com.intellij.ui.components.JBRadioButton" binding="myEditorRb">
@@ -29,14 +29,28 @@
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Editor background"/>
<actionCommand value=""/>
<text value="Editor and tools"/>
</properties>
</component>
<component id="ec878" class="com.intellij.ui.components.JBCheckBox" binding="myThisProjectOnlyCb">
<constraints>
<grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="This project only"/>
</properties>
</component>
<hspacer id="d9d4b">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
</children>
</grid>
<grid id="73c41" binding="myPreviewPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="2" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -44,19 +58,19 @@
</grid>
<component id="94212" class="com.intellij.ui.ComboboxWithBrowseButton" binding="myPathField" custom-create="true">
<constraints>
<grid row="0" column="1" row-span="1" col-span="5" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="0" column="1" row-span="1" col-span="4" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<vspacer id="abb42">
<constraints>
<grid row="2" column="3" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="1d970" layout-manager="GridLayoutManager" row-count="13" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="4" row-span="1" col-span="2" vsize-policy="3" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="2" column="3" row-span="1" col-span="2" vsize-policy="3" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -166,7 +180,7 @@
</grid>
<component id="fe56c" class="javax.swing.JSlider" binding="myOpacitySlider">
<constraints>
<grid row="1" column="1" row-span="1" col-span="4" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
<grid row="1" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<paintTicks value="false"/>
@@ -174,7 +188,7 @@
</component>
<component id="a265f" class="javax.swing.JSpinner" binding="myOpacitySpinner">
<constraints>
<grid row="1" column="5" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
<grid row="1" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
@@ -196,11 +210,6 @@
<text value="Opacity:"/>
</properties>
</component>
<hspacer id="909f7">
<constraints>
<grid row="3" column="2" row-span="1" col-span="4" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
</children>
</grid>
<buttonGroups>
@@ -30,10 +30,12 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.TextComponentAccessor;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.CollectionComboBoxModel;
import com.intellij.ui.ComboboxWithBrowseButton;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBRadioButton;
import com.intellij.util.containers.ContainerUtil;
@@ -59,6 +61,7 @@ import static com.intellij.openapi.wm.impl.IdeBackgroundUtil.*;
public class SetBackgroundImageDialog extends DialogWrapper {
private final String myPropertyTmp;
private final Project myProject;
private JPanel myRoot;
private JBRadioButton myEditorRb;
private JBRadioButton myScaleRb;
@@ -67,6 +70,7 @@ public class SetBackgroundImageDialog extends DialogWrapper {
private JSpinner myOpacitySpinner;
private JPanel myPreviewPanel;
private ComboboxWithBrowseButton myPathField;
private JBCheckBox myThisProjectOnlyCb;
boolean myAdjusting;
private String mySelectedPath;
@@ -77,6 +81,7 @@ public class SetBackgroundImageDialog extends DialogWrapper {
public SetBackgroundImageDialog(@NotNull Project project, @Nullable String selectedPath) {
super(project, true);
myProject = project;
setTitle("Background Image");
mySelectedPath = selectedPath;
myEditorPreview = createEditorPreview();
@@ -221,6 +226,8 @@ public class SetBackgroundImageDialog extends DialogWrapper {
myScaleRb.setSelected(true);
myCenterRb.setSelected(true);
myEditorRb.setSelected(true);
boolean perProject = !Comparing.equal(getBackgroundSpec(myProject, getSystemProp()), getBackgroundSpec(null, getSystemProp()));
myThisProjectOnlyCb.setSelected(perProject);
myAdjusting = false;
}
@@ -265,7 +272,7 @@ public class SetBackgroundImageDialog extends DialogWrapper {
private void retrieveExistingValue() {
myAdjusting = true;
String prop = getSystemProp();
String value = StringUtil.notNullize(myResults.get(prop), getBackgroundSpec(prop));
String value = StringUtil.notNullize(myResults.get(prop), getBackgroundSpec(myProject, prop));
String[] split = value.split(",");
int opacity = split.length > 1 ? StringUtil.parseInt(split[1], 15) : 15;
String fill = split.length > 2 ? split[2] : "scale";
@@ -295,7 +302,11 @@ public class SetBackgroundImageDialog extends DialogWrapper {
myResults.put(prop, value);
if (value.startsWith(",")) value = null;
PropertiesComponent.getInstance().setValue(prop, value);
PropertiesComponent propertiesComponent =
myThisProjectOnlyCb.isSelected() ?
PropertiesComponent.getInstance(myProject) : PropertiesComponent.getInstance();
propertiesComponent.setValue(prop, value);
repaintAllWindows();
}
@@ -15,14 +15,16 @@
*/
package org.intellij.images.statistics;
import com.intellij.internal.statistic.AbstractApplicationUsagesCollector;
import com.intellij.internal.statistic.CollectUsagesException;
import com.intellij.internal.statistic.UsagesCollector;
import com.intellij.internal.statistic.beans.GroupDescriptor;
import com.intellij.internal.statistic.beans.UsageDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Set;
import static com.intellij.openapi.wm.impl.IdeBackgroundUtil.*;
@@ -30,7 +32,7 @@ import static com.intellij.openapi.wm.impl.IdeBackgroundUtil.*;
/**
* @author gregsh
*/
public class BackgroundUsageCollector extends UsagesCollector {
public class BackgroundImagesUsageCollector extends AbstractApplicationUsagesCollector {
@NotNull
@Override
public GroupDescriptor getGroupId() {
@@ -40,9 +42,25 @@ public class BackgroundUsageCollector extends UsagesCollector {
@NotNull
@Override
public Set<UsageDescriptor> getUsages() throws CollectUsagesException {
boolean editor = StringUtil.isNotEmpty(getBackgroundSpec(EDITOR_PROP));
boolean ide = StringUtil.isNotEmpty(getBackgroundSpec(FRAME_PROP));
return ContainerUtil.newHashSet(new UsageDescriptor("editor", editor ? 1 : 0), new UsageDescriptor("frame", ide ? 1 : 0));
// join usages from all projects
HashMap<String, UsageDescriptor> map = ContainerUtil.newHashMap();
for (UsageDescriptor descriptor : super.getUsages()) {
String key = descriptor.getKey();
int idx = key.indexOf(' ');
key = idx > 0 ? key.substring(0, idx) : key;
UsageDescriptor existing = map.get(key);
if (existing == null || existing.getValue() == 0) {
map.put(key, new UsageDescriptor(key, descriptor.getValue()));
}
}
return ContainerUtil.newHashSet(map.values());
}
@NotNull
@Override
public Set<UsageDescriptor> getProjectUsages(@NotNull Project project) throws CollectUsagesException {
boolean editor = StringUtil.isNotEmpty(getBackgroundSpec(project, EDITOR_PROP));
boolean frame = StringUtil.isNotEmpty(getBackgroundSpec(project, FRAME_PROP));
return ContainerUtil.newHashSet(new UsageDescriptor("editor", editor ? 1 : 0), new UsageDescriptor("frame", frame ? 1 : 0));
}
}
@@ -27,6 +27,7 @@ import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
import com.intellij.openapi.editor.impl.EditorComponentImpl;
import com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter;
import com.intellij.openapi.fileEditor.impl.EditorsSplitters;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.AbstractPainter;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
@@ -163,8 +164,10 @@ public class IdeBackgroundUtil {
}
@NotNull
public static String getBackgroundSpec(@NotNull String propertyName) {
return StringUtil.notNullize(PropertiesComponent.getInstance().getValue(propertyName), System.getProperty(propertyName, ""));
public static String getBackgroundSpec(@Nullable Project project, @NotNull String propertyName) {
String spec = project == null ? null : PropertiesComponent.getInstance(project).getValue(propertyName);
if (spec == null) spec = PropertiesComponent.getInstance().getValue(propertyName);
return StringUtil.notNullize(spec, System.getProperty(propertyName, ""));
}
public static void repaintAllWindows() {
@@ -19,12 +19,14 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.AbstractPainter;
import com.intellij.openapi.ui.GraphicsConfig;
import com.intellij.openapi.ui.Painter;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ImageLoader;
import com.intellij.util.containers.ContainerUtil;
@@ -163,12 +165,12 @@ final class PaintersHelper implements Painter.Listener {
}
public static void initWallpaperPainter(@NotNull String propertyName, @NotNull PaintersHelper painters) {
ModalityState modalityState = ModalityState.stateForComponent(painters.myRootComponent);
ImagePainter painter = (ImagePainter)newWallpaperPainter(propertyName, modalityState);
ImagePainter painter = (ImagePainter)newWallpaperPainter(propertyName, painters.myRootComponent);
painters.addPainter(painter, null);
}
private static AbstractPainter newWallpaperPainter(@NotNull final String propertyName, @NotNull final ModalityState modalityState) {
private static AbstractPainter newWallpaperPainter(@NotNull final String propertyName,
@NotNull final JComponent rootComponent) {
return new ImagePainter() {
Image image;
float alpha;
@@ -190,7 +192,9 @@ final class PaintersHelper implements Painter.Listener {
}
boolean ensureImageLoaded() {
String value = getBackgroundSpec(propertyName);
IdeFrame frame = UIUtil.getParentOfType(IdeFrame.class, rootComponent);
Project project = frame == null ? null : frame.getProject();
String value = getBackgroundSpec(project, propertyName);
if (!Comparing.equal(value, current)) {
current = value;
loadImageAsync(value);
@@ -210,6 +214,7 @@ final class PaintersHelper implements Painter.Listener {
place = newPlace;
boolean newOk = newImage != null;
if (prevOk || newOk) {
ModalityState modalityState = ModalityState.stateForComponent(rootComponent);
if (modalityState.dominates(ModalityState.NON_MODAL)) {
UIUtil.getActiveWindow().repaint();
}
@@ -236,6 +241,7 @@ final class PaintersHelper implements Painter.Listener {
: new File(PathManager.getConfigPath(), filePath)).toURI().toURL();
ApplicationManager.getApplication().executeOnPooledThread(() -> {
final Image m = ImageLoader.loadFromUrl(url);
ModalityState modalityState = ModalityState.stateForComponent(rootComponent);
ApplicationManager.getApplication().invokeLater(() -> resetImage(propertyValue, m, newAlpha, newFillType, newPlace), modalityState);
});
}