Repository: importre/android-selector-intellij-plugin
Branch: master
Commit: 16569b022508
Files: 9
Total size: 28.9 KB
Directory structure:
gitextract_0tlwig1c/
├── .gitignore
├── META-INF/
│ └── plugin.xml
├── license
├── readme.md
└── src/
└── importre/
└── intellij/
└── android/
└── selector/
├── action/
│ └── AndroidSelector.java
├── color/
│ ├── ColorIcon.java
│ └── ColorItemRenderer.java
└── form/
├── AndroidSelectorDialog.form
└── AndroidSelectorDialog.java
================================================
FILE CONTENTS
================================================
================================================
FILE: META-INF/plugin.xml
================================================
<idea-plugin version="2">
<id>importre.intellij.android.selector</id>
<name>Android Selector</name>
<version>0.2.0</version>
<vendor email="jaeweheo@gmail.com" url="http://import.re">
importre
</vendor>
<description><![CDATA[
<h1>Generate selectors for background drawable</h1>
<br/>
You can use `colorButtonNormal` simply,
<br/>
but make easily touch feedback of normal `View`s as well as `Button`s with this plugin.
<br/><br/>
1. Set your colors(in `res/values/colors.xml`).
<br/>
2. Select `New -> Android Selector(or Ctrl/Cmd + N)` on your `res` directory.
<br/>
3. Select filename, color, pressed and pressed-v21 respectively.
<br/><br/>
- ripple drawable is generated in drawable-v21 directory.<br/>
- normal drawable is generated in drawable directory.<br/><br/>
<h2>Dependency</h2>
<br/>
- com.android.support:appcompat-v7:22.+
]]></description>
<change-notes><![CDATA[
- Implementation of color selection based on `res/values/colors.xml`
<br/>
- Changing icon
]]>
</change-notes>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="141"/>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
on how to target different products -->
<depends>com.intellij.modules.lang</depends>
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
</extensions>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
<!-- Add your actions here -->
<action id="importre.intellij.android.selector.AndroidSelector"
class="importre.intellij.android.selector.action.AndroidSelector"
text="Android Selector"
icon="/icons/icon.png"
description="Generate android selector xml files">
<add-to-group group-id="NewGroup" anchor="after"
relative-to-action="NewAndroidAssetImage"/>
</action>
</actions>
</idea-plugin>
================================================
FILE: license
================================================
The MIT License (MIT)
Copyright (c) 2015 Jaewe Heo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: readme.md
================================================
[](https://android-arsenal.com/details/1/2342)
# android-selector-intellij-plugin 
:art: Generate selectors for background drawable.
You can use `colorButtonNormal` simply,
but make easily touch feedback of normal `View`s as well as `Button`s with this plugin.
## Installation
1. open Android Studio(or IntelliJ)
2. Preferences :arrow_right: Plugins :arrow_right: Browse Repositories
3. Search "Android Selector"
4. Click "Install Plugin" button
## Usage
- Set your colors(in `res/values/colors.xml`).
```xml
<color name="colorPrimary">#519FE5</color>
<color name="colorPrimaryDark">#388AC6</color>
<color name="colorAccent">#FFFFFF</color>
```
- Select `New -> Android Selector(or Ctrl/Cmd + N)` on your `res` directory.

- Select filename, color, pressed and pressed-v21 respectively.

> ripple drawable is generated in drawable-v21 directory.
> normal drawable is generated in drawable directory.
- Use the drawable.
```xml
<android.support.v7.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="@drawable/<GENERATED_DRAWABLE>"
android:gravity="center"
android:minWidth="100dp"
android:text="pressed" />
```
## Demo
| Lollipop > | Lollipop <= |
|---------------|----------------|
| ![demo1][d1] | ![demo2][d2] |
## Dependency
- com.android.support:appcompat-v7:22.+
## License
MIT © [Jaewe Heo][importre]
[importre]: http://import.re
[d1]: images/demo1.png
[d2]: images/demo2.png
================================================
FILE: src/importre/intellij/android/selector/action/AndroidSelector.java
================================================
package importre.intellij.android.selector.action;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import importre.intellij.android.selector.form.AndroidSelectorDialog;
public class AndroidSelector extends AnAction {
@Override
public void update(AnActionEvent e) {
super.update(e);
VirtualFile dir = e.getData(LangDataKeys.VIRTUAL_FILE);
if (dir != null && dir.isDirectory()) {
String text = dir.getName();
e.getPresentation().setVisible("res".equals(text));
}
}
@Override
public void actionPerformed(AnActionEvent e) {
final VirtualFile dir = e.getData(LangDataKeys.VIRTUAL_FILE);
if (dir == null) {
return;
}
Project project = e.getProject();
AndroidSelectorDialog dialog = new AndroidSelectorDialog(project, dir);
dialog.show();
}
}
================================================
FILE: src/importre/intellij/android/selector/color/ColorIcon.java
================================================
package importre.intellij.android.selector.color;
import com.intellij.ui.JBColor;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ColorIcon implements Icon {
private final String color;
public ColorIcon(String color) {
if (color == null) {
this.color = null;
} else {
this.color = color.startsWith("#") ? color.substring(1) : null;
}
}
public int getIconHeight() {
return 16;
}
public int getIconWidth() {
return 16;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
JBColor color = getColor();
if (color == null) {
g.setColor(JBColor.WHITE);
g.fillRect(1, 1, getIconWidth(), getIconHeight());
g.setColor(JBColor.DARK_GRAY);
if (g instanceof Graphics2D) {
RenderingHints.Key key = RenderingHints.KEY_TEXT_ANTIALIASING;
Object value = RenderingHints.VALUE_TEXT_ANTIALIAS_ON;
((Graphics2D) g).setRenderingHint(key, value);
}
String q = "?";
FontMetrics fm = g.getFontMetrics();
Rectangle2D r = fm.getStringBounds(q, g);
x = (int) ((getIconWidth() - (int) r.getWidth()) * 0.7f);
y = (getIconHeight() - (int) r.getHeight()) / 2 + fm.getAscent();
g.drawString(q, x, y);
} else {
g.setColor(color);
g.fillRect(1, 1, getIconWidth(), getIconHeight());
}
g.setColor(JBColor.DARK_GRAY);
g.drawRect(1, 1, getIconWidth(), getIconHeight());
}
@Nullable
private JBColor getColor() {
String regex = "((?:[0-9a-fA-F]{2})?)" +
"([0-9a-fA-F]{2})" +
"([0-9a-fA-F]{2})" +
"([0-9a-fA-F]{2})";
Pattern p = Pattern.compile(regex);
try {
if (color == null) {
return null;
}
Matcher m = p.matcher(color);
if (m.find()) {
int r = Integer.parseInt(m.group(2), 16);
int g = Integer.parseInt(m.group(3), 16);
int b = Integer.parseInt(m.group(4), 16);
if (m.group(1).isEmpty()) {
return new JBColor(
new Color(r, g, b),
new Color(r, g, b));
} else {
int a = Integer.parseInt(m.group(1), 16);
return new JBColor(
new Color(r, g, b, a),
new Color(r, g, b, a));
}
}
} catch (Exception ignore) {
}
return null;
}
}
================================================
FILE: src/importre/intellij/android/selector/color/ColorItemRenderer.java
================================================
package importre.intellij.android.selector.color;
import javax.swing.*;
import java.awt.*;
public class ColorItemRenderer implements ListCellRenderer {
DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
@Override
public Component getListCellRendererComponent(
JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Icon icon;
String name;
JLabel renderer = (JLabel) defaultRenderer
.getListCellRendererComponent(
list, value, index, isSelected, cellHasFocus);
String values[] = (String[]) value;
name = values[1];
icon = new ColorIcon(values[0]);
renderer.setIcon(icon);
renderer.setText(name);
return renderer;
}
}
================================================
FILE: src/importre/intellij/android/selector/form/AndroidSelectorDialog.form
================================================
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="importre.intellij.android.selector.form.AndroidSelectorDialog">
<grid id="cbd77" binding="contentPane" layout-manager="GridLayoutManager" row-count="1" column-count="1" 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="541" height="297"/>
</constraints>
<properties>
<minimumSize width="400" height="150"/>
</properties>
<border type="none"/>
<children>
<grid id="e3588" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="d712" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="color"/>
</properties>
</component>
<component id="6d3ec" class="javax.swing.JLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="pressed"/>
</properties>
</component>
<component id="f2b95" class="javax.swing.JLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="pressed-v21"/>
</properties>
</component>
<component id="13295" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="filename"/>
</properties>
</component>
<component id="9546b" class="javax.swing.JTextField" binding="filenameText">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<text value="selectable_background"/>
<toolTipText value="filename of drawable xml"/>
</properties>
</component>
<component id="6223d" class="javax.swing.JComboBox" binding="colorCombo">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<model/>
</properties>
</component>
<component id="67df7" class="javax.swing.JComboBox" binding="pressedCombo">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="acac4" class="javax.swing.JComboBox" binding="pressedV21Combo">
<constraints>
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
</children>
</grid>
</form>
================================================
FILE: src/importre/intellij/android/selector/form/AndroidSelectorDialog.java
================================================
package importre.intellij.android.selector.form;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import importre.intellij.android.selector.color.ColorItemRenderer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import javax.swing.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import java.io.*;
import java.util.*;
public class AndroidSelectorDialog extends DialogWrapper {
private static final String INDENT_SPACE = "{http://xml.apache.org/xslt}indent-amount";
private static final String drawableDir = "drawable";
private static final String drawableV21Dir = "drawable-v21";
private static final String valuesColorsXml = "values/colors.xml";
private static final String localProps = "local.properties";
private static final String platformsRes = "%s/platforms/%s/data/res/values";
private static final String nsUri = "http://www.w3.org/2000/xmlns/";
private static final String androidUri = "http://schemas.android.com/apk/res/android";
private final VirtualFile dir;
private final Project project;
private JPanel contentPane;
private JTextField filenameText;
private JComboBox colorCombo;
private JComboBox pressedCombo;
private JComboBox pressedV21Combo;
public AndroidSelectorDialog(@Nullable Project project, VirtualFile dir) {
super(project);
this.project = project;
this.dir = dir;
setTitle("Android Selector");
setResizable(false);
init();
}
@Override
public void show() {
try {
if (initColors(dir)) {
super.show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean initColors(VirtualFile dir) {
VirtualFile colorsXml = dir.findFileByRelativePath(valuesColorsXml);
if (colorsXml != null && colorsXml.exists()) {
HashMap<String, String> cmap = parseColorsXml(colorsXml);
HashMap<String, String> andCmap = parseAndroidColorsXml();
if (cmap.isEmpty()) {
String title = "Error";
String msg = "Cannot find colors in colors.xml";
showMessageDialog(title, msg);
return false;
}
String regex = "^@(android:)?color/(.+$)";
ArrayList<String[]> elements = new ArrayList<String[]>();
for (String name : cmap.keySet()) {
String color = cmap.get(name);
while (color != null && color.matches(regex)) {
if (color.startsWith("@color/")) {
String key = color.replace("@color/", "");
color = cmap.get(key);
} else if (color.startsWith("@android:color/")) {
String key = color.replace("@android:color/", "");
color = andCmap.get(key);
} else {
// not reachable...
}
}
if (color != null) {
elements.add(new String[]{color, name});
}
}
ColorItemRenderer renderer = new ColorItemRenderer();
colorCombo.setRenderer(renderer);
pressedCombo.setRenderer(renderer);
pressedV21Combo.setRenderer(renderer);
for (Object element : elements) {
colorCombo.addItem(element);
pressedCombo.addItem(element);
pressedV21Combo.addItem(element);
}
return !elements.isEmpty();
}
String title = "Error";
String msg = String.format("Cannot find %s", valuesColorsXml);
showMessageDialog(title, msg);
return false;
}
@NotNull
private HashMap<String, String> parseColorsXml(VirtualFile colorsXml) {
HashMap<String, String> map = new LinkedHashMap<String, String>();
try {
NodeList colors = getColorNodes(colorsXml.getInputStream());
makeColorMap(colors, map);
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
private void makeColorMap(NodeList colors, HashMap<String, String> map) {
for (int i = 0; i < colors.getLength(); i++) {
Element node = (Element) colors.item(i);
String nodeName = node.getNodeName();
if ("color".equals(nodeName) || "item".equals(nodeName)) {
String name = node.getAttribute("name");
String color = node.getTextContent();
if (name != null && color != null && !map.containsKey(name)) {
map.put(name, color);
}
}
}
}
private NodeList getColorNodes(InputStream stream) throws Exception {
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "//item[@type=\"color\"]|//color";
XPathExpression compile = xPath.compile(expression);
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = f.newDocumentBuilder();
Document doc = builder.parse(stream);
return (NodeList) compile.evaluate(doc, XPathConstants.NODESET);
}
@NotNull
private HashMap<String, String> parseAndroidColorsXml() {
HashMap<String, String> map = new HashMap<String, String>();
if (project == null) return map;
VirtualFile baseDir = project.getBaseDir();
VirtualFile prop = baseDir.findFileByRelativePath(localProps);
if (prop == null) return map;
Properties properties = new Properties();
try {
properties.load(prop.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
String sdkDir = properties.getProperty("sdk.dir");
File file = new File(sdkDir + File.separator + "platforms");
if (!file.isDirectory()) return map;
ArrayList<String> platforms = new ArrayList<String>();
Collections.addAll(platforms, file.list());
Collections.reverse(platforms);
for (int i = 0, size = platforms.size(); i < size; i++) {
String platform = platforms.get(i);
if (platform.matches("^android-\\d+$")) continue;
if (i > 3) break;
String path = String.format(platformsRes, sdkDir, platform);
File[] files = new File(path).listFiles();
if (files == null) continue;
for (File f : files) {
if (f.getName().matches("colors.*\\.xml")) {
try {
FileInputStream stream = new FileInputStream(f);
NodeList colors = getColorNodes(stream);
makeColorMap(colors, map);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return map;
}
@Nullable
@Override
protected JComponent createCenterPanel() {
return contentPane;
}
private String getColorName(JComboBox combo) {
Object colorItem = combo.getSelectedItem();
try {
if (colorItem instanceof Object[]) {
return "@color/" + ((Object[]) (colorItem))[1];
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
@Override
protected void doOKAction() {
String f = filenameText.getText();
final String filename = (f.endsWith(".xml") ? f : f + ".xml").trim();
final String color = getColorName(colorCombo);
final String pressed = getColorName(pressedCombo);
final String pressedV21 = getColorName(pressedV21Combo);
if (!valid(filename, color, pressed, pressedV21)) {
String title = "Invalidation";
String msg = "color, pressed, pressedV21 must start with `@color/`";
showMessageDialog(title, msg);
return;
}
if (exists(filename)) {
String title = "Cannot create files";
String msg = String.format(Locale.US,
"`%s` already exists", filename);
showMessageDialog(title, msg);
return;
}
Application app = ApplicationManager.getApplication();
app.runWriteAction(new Runnable() {
@Override
public void run() {
try {
createDrawable(filename, color, pressed);
createDrawableV21(filename, color, pressedV21);
} catch (Exception e) {
e.printStackTrace();
}
}
});
super.doOKAction();
}
private boolean valid(String filename, String color,
String pressed, String pressedV21) {
if (filename.isEmpty() || ".xml".equals(filename))
return false;
String regex = "^@color/.+";
return color.matches(regex) ||
pressed.matches(regex) ||
pressedV21.matches(regex);
}
private boolean exists(String filename) {
String[] dirs = new String[]{drawableDir, drawableV21Dir};
for (String d : dirs) {
VirtualFile f = dir.findChild(d);
if (f != null && f.isDirectory()) {
VirtualFile dest = f.findChild(filename);
if (dest != null && dest.exists()) {
return true;
}
}
}
return false;
}
private void createDrawable(String filename,
String color,
String pressed) throws Exception {
VirtualFile child = dir.findChild(drawableDir);
if (child == null) {
child = dir.createChildDirectory(null, drawableDir);
}
VirtualFile newXmlFile = child.findChild(filename);
if (newXmlFile != null && newXmlFile.exists()) {
newXmlFile.delete(null);
}
newXmlFile = child.createChildData(null, filename);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element root = doc.createElement("selector");
root.setAttributeNS(nsUri, "xmlns:android", androidUri);
doc.appendChild(root);
Element item = doc.createElement("item");
item.setAttribute("android:drawable",
"@drawable/abc_list_selector_disabled_holo_light");
item.setAttribute("android:state_enabled", "false");
item.setAttribute("android:state_focused", "true");
item.setAttribute("android:state_pressed", "true");
root.appendChild(item);
item = doc.createElement("item");
item.setAttribute("android:drawable",
"@drawable/abc_list_selector_disabled_holo_light");
item.setAttribute("android:state_enabled", "false");
item.setAttribute("android:state_focused", "true");
root.appendChild(item);
item = doc.createElement("item");
item.setAttribute("android:drawable", pressed);
item.setAttribute("android:state_focused", "true");
item.setAttribute("android:state_pressed", "true");
root.appendChild(item);
item = doc.createElement("item");
item.setAttribute("android:drawable", pressed);
item.setAttribute("android:state_focused", "false");
item.setAttribute("android:state_pressed", "true");
root.appendChild(item);
item = doc.createElement("item");
item.setAttribute("android:drawable", color);
root.appendChild(item);
OutputStream os = newXmlFile.getOutputStream(null);
PrintWriter out = new PrintWriter(os);
StringWriter writer = new StringWriter();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(INDENT_SPACE, "4");
transformer.transform(new DOMSource(doc), new StreamResult(writer));
out.println(writer.getBuffer().toString());
out.close();
}
private void createDrawableV21(String filename,
String color,
String pressed) throws Exception {
VirtualFile child = dir.findChild(drawableV21Dir);
if (child == null) {
child = dir.createChildDirectory(null, drawableV21Dir);
}
VirtualFile newXmlFile = child.findChild(filename);
if (newXmlFile != null && newXmlFile.exists()) {
newXmlFile.delete(null);
}
newXmlFile = child.createChildData(null, filename);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element root = doc.createElement("ripple");
root.setAttributeNS(nsUri, "xmlns:android", androidUri);
root.setAttribute("android:color", pressed);
doc.appendChild(root);
Element item = doc.createElement("item");
item.setAttribute("android:drawable", color);
root.appendChild(item);
OutputStream os = newXmlFile.getOutputStream(null);
PrintWriter out = new PrintWriter(os);
StringWriter writer = new StringWriter();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(INDENT_SPACE, "4");
transformer.transform(new DOMSource(doc), new StreamResult(writer));
out.println(writer.getBuffer().toString());
out.close();
}
private void showMessageDialog(String title, String message) {
Messages.showMessageDialog(
project, message, title, Messages.getErrorIcon());
}
}
gitextract_0tlwig1c/
├── .gitignore
├── META-INF/
│ └── plugin.xml
├── license
├── readme.md
└── src/
└── importre/
└── intellij/
└── android/
└── selector/
├── action/
│ └── AndroidSelector.java
├── color/
│ ├── ColorIcon.java
│ └── ColorItemRenderer.java
└── form/
├── AndroidSelectorDialog.form
└── AndroidSelectorDialog.java
SYMBOL INDEX (27 symbols across 4 files)
FILE: src/importre/intellij/android/selector/action/AndroidSelector.java
class AndroidSelector (line 10) | public class AndroidSelector extends AnAction {
method update (line 12) | @Override
method actionPerformed (line 23) | @Override
FILE: src/importre/intellij/android/selector/color/ColorIcon.java
class ColorIcon (line 12) | public class ColorIcon implements Icon {
method ColorIcon (line 16) | public ColorIcon(String color) {
method getIconHeight (line 24) | public int getIconHeight() {
method getIconWidth (line 28) | public int getIconWidth() {
method paintIcon (line 32) | public void paintIcon(Component c, Graphics g, int x, int y) {
method getColor (line 59) | @Nullable
FILE: src/importre/intellij/android/selector/color/ColorItemRenderer.java
class ColorItemRenderer (line 6) | public class ColorItemRenderer implements ListCellRenderer {
method getListCellRendererComponent (line 9) | @Override
FILE: src/importre/intellij/android/selector/form/AndroidSelectorDialog.java
class AndroidSelectorDialog (line 31) | public class AndroidSelectorDialog extends DialogWrapper {
method AndroidSelectorDialog (line 52) | public AndroidSelectorDialog(@Nullable Project project, VirtualFile di...
method show (line 62) | @Override
method initColors (line 73) | private boolean initColors(VirtualFile dir) {
method parseColorsXml (line 125) | @NotNull
method makeColorMap (line 137) | private void makeColorMap(NodeList colors, HashMap<String, String> map) {
method getColorNodes (line 151) | private NodeList getColorNodes(InputStream stream) throws Exception {
method parseAndroidColorsXml (line 161) | @NotNull
method createCenterPanel (line 206) | @Nullable
method getColorName (line 212) | private String getColorName(JComboBox combo) {
method doOKAction (line 224) | @Override
method valid (line 262) | private boolean valid(String filename, String color,
method exists (line 273) | private boolean exists(String filename) {
method createDrawable (line 288) | private void createDrawable(String filename,
method createDrawableV21 (line 356) | private void createDrawableV21(String filename,
method showMessageDialog (line 398) | private void showMessageDialog(String title, String message) {
Condensed preview — 9 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (32K chars).
[
{
"path": "META-INF/plugin.xml",
"chars": 2394,
"preview": "<idea-plugin version=\"2\">\n <id>importre.intellij.android.selector</id>\n <name>Android Selector</name>\n <version"
},
{
"path": "license",
"chars": 1075,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2015 Jaewe Heo\n\nPermission is hereby granted, free of charge, to any person obtaini"
},
{
"path": "readme.md",
"chars": 1813,
"preview": "[
About this extraction
This page contains the full source code of the importre/android-selector-intellij-plugin GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 9 files (28.9 KB), approximately 6.7k tokens, and a symbol index with 27 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.