├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── libraries │ └── libs.xml ├── misc.xml ├── modules.xml ├── uiDesigner.xml ├── vcs.xml └── workspace.xml ├── AndroidSuperPlugin.iml ├── GsonFormat ├── ConvertBridge.java ├── EditDialog.form ├── EditDialog.java ├── ErrorDialog.form ├── ErrorDialog.java ├── FieldsDialog.form ├── FieldsDialog.java ├── JsonUtilsDialog.form ├── JsonUtilsDialog.java ├── MainAction.java ├── SettingDialog.form ├── SettingDialog.java ├── WriterUtil.java ├── config │ ├── Config.java │ └── Strings.java ├── entity │ ├── FieldEntity.java │ └── InnerClassEntity.java ├── org │ └── json │ │ ├── JSONArray.java │ │ ├── JSONException.java │ │ ├── JSONObject.java │ │ ├── JSONString.java │ │ └── JSONTokener.java ├── res │ └── icon.png ├── src │ ├── cn │ │ └── vearn │ │ │ └── checktreetable │ │ │ └── FiledTreeTableModel.java │ └── org │ │ └── jdesktop │ │ └── swingx │ │ └── ux │ │ ├── CheckTreeCellProvider.java │ │ ├── CheckTreeSelectionModel.java │ │ ├── CheckTreeTableManager.java │ │ └── TristateCheckBox.java └── utils │ ├── CheckUtil.java │ ├── PsiClassUtil.java │ └── Toast.java ├── README.md ├── android_code_generator └── com │ └── morcinek │ └── android │ └── codegenerator │ └── plugin │ ├── actions │ ├── ActivityAction.java │ ├── AdapterAction.java │ ├── FragmentAction.java │ ├── LayoutAction.java │ ├── MenuAction.java │ ├── butterknife │ │ ├── BActivityAction.java │ │ ├── BAdapterAction.java │ │ └── BFragmentAction.java │ └── visibility │ │ └── ActionVisibilityHelper.java │ ├── codegenerator │ ├── CodeGeneratorController.java │ └── CodeGeneratorFactory.java │ ├── error │ └── ErrorHandler.java │ ├── groups │ └── GenerateAndroidCodeGroup.java │ ├── persistence │ └── Settings.java │ ├── preferences │ ├── configurables │ │ ├── MainConfigurable.java │ │ └── templates │ │ │ └── TemplateConfigurable.java │ └── persistence │ │ └── TemplateSettings.java │ ├── ui │ ├── CodeDialogBuilder.java │ ├── DialogsFactory.java │ └── StringResources.java │ └── utils │ ├── ClipboardHelper.java │ ├── PackageHelper.java │ ├── PathHelper.java │ └── ProjectHelper.java ├── android_parcelable_intellij_plugin └── pl │ └── charmas │ └── parcelablegenerator │ ├── CodeGenerator.java │ ├── GenerateDialog.java │ ├── ParcelableAction.java │ ├── typeserializers │ ├── BundleSerializerFactory.java │ ├── ChainSerializerFactory.java │ ├── DateSerializerFactory.java │ ├── EnumerationSerializerFactory.java │ ├── ListSerializerFactory.java │ ├── ParcelableSerializerFactory.java │ ├── PrimitiveArraySerializerFactory.java │ ├── PrimitiveTypeSerializerFactory.java │ ├── SerializableSerializerFactory.java │ ├── TypeSerializer.java │ ├── TypeSerializerFactory.java │ └── serializers │ │ ├── BooleanPrimitiveSerializer.java │ │ ├── BooleanSparseArraySerializer.java │ │ ├── BundleSerializer.java │ │ ├── CharPrimitiveSerializer.java │ │ ├── DateSerializer.java │ │ ├── EnumerationSerializer.java │ │ ├── GenericListSerializer.java │ │ ├── NullablePrimitivesSerializer.java │ │ ├── ParcelableArraySerializer.java │ │ ├── ParcelableListSerializer.java │ │ ├── ParcelableObjectSerializer.java │ │ ├── PrimitiveArraySerializer.java │ │ ├── PrimitiveTypeSerializer.java │ │ ├── SerializableObjectSerializer.java │ │ └── UnknownTypeSerializer.java │ └── util │ └── PsiUtils.java ├── android_selector_chapek ├── Constants.java ├── SelectorChapekAction.java ├── SelectorDetector.java ├── SelectorGenerator.java └── utils │ ├── Log.java │ └── RunnableHelper.java ├── folding_plugin └── com │ └── dd │ ├── ComposeAction.java │ ├── DirectoryNode.java │ ├── FoldingNode.java │ ├── ProjectStructureProvider.java │ ├── SettingConfigurable.form │ ├── SettingConfigurable.java │ ├── Settings.java │ ├── SettingsManager.java │ └── Utils.java ├── libs ├── android-codegenerator-library-1.0.5.jar ├── commons-io-2.4-sources.jar ├── commons-io-2.4.jar ├── commons-lang3-3.3.2.jar ├── commons-math3-3.4.1-src.zip ├── commons-math3-3.4.1.jar ├── gson-2.3.1.jar ├── guava-18.0.jar ├── imgscalr-lib-4.2-sources.jar ├── imgscalr-lib-4.2.jar ├── thumbnailator-0.4.8-sources.jar ├── thumbnailator-0.4.8.jar └── xom-1.2.10.jar ├── lifecycle_sorter ├── Action │ ├── SortAction.java │ ├── SortEndAction.java │ └── SortStartAction.java ├── Lifecycle │ ├── ActivityLifecycle.java │ ├── FragmentLifecycle.java │ ├── Lifecycle.java │ └── LifecycleFactory.java ├── Sort │ └── Sorter.java └── Util │ └── LifecycleUtils.java ├── resources └── META-INF │ └── plugin.xml └── src └── de └── espend └── idea └── android ├── AndroidView.java ├── RelatedPopupGotoLineMarker.java ├── action ├── ExtractStringAction.java ├── generator │ ├── AbstractActivityViewAction.java │ ├── AbstractInflateViewAction.java │ ├── ActivityViewFieldVariable.java │ ├── ActivityViewMethodVariable.java │ ├── FieldViewInflateViewAction.java │ └── LocalViewAction.java └── write │ ├── InflateLocalVariableAction.java │ ├── InflateThisExpressionAction.java │ └── ReformatAndOptimizeImportsProcessor.java ├── annotator ├── InflateCastAnnotator.java └── InflateViewAnnotator.java ├── linemarker ├── FragmentRelatedFileLineMarker.java ├── InflateLayoutLineMarkerProvider.java └── ViewInflateLineMarker.java ├── symbol └── AndroidSymbolContributor.java └── utils ├── AndroidUtils.java ├── AndroidViewUtil.java └── JavaPsiUtil.java /.idea/.name: -------------------------------------------------------------------------------- 1 | AndroidSuperPlugin -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/libraries/libs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /AndroidSuperPlugin.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /GsonFormat/EditDialog.java: -------------------------------------------------------------------------------- 1 | import config.Config; 2 | import config.Strings; 3 | 4 | import javax.swing.*; 5 | import java.awt.event.*; 6 | 7 | public class EditDialog extends JFrame { 8 | private JPanel contentPane; 9 | private JButton okButton; 10 | private JButton cancelButton; 11 | private JTextPane editTP; 12 | private JButton resetButton; 13 | private JLabel titleLB; 14 | 15 | private String titleName; 16 | 17 | private String editStr; 18 | 19 | private Type type; 20 | 21 | 22 | public EditDialog(Type type ) { 23 | this.type=type; 24 | setContentPane(contentPane); 25 | // setModal(true); 26 | this.setAlwaysOnTop(true); 27 | getRootPane().setDefaultButton(okButton); 28 | 29 | okButton.addActionListener(new ActionListener() { 30 | public void actionPerformed(ActionEvent e) { 31 | onOK(); 32 | } 33 | }); 34 | 35 | cancelButton.addActionListener(new ActionListener() { 36 | public void actionPerformed(ActionEvent e) { 37 | onCancel(); 38 | } 39 | }); 40 | setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); 41 | 42 | addWindowListener(new WindowAdapter() { 43 | public void windowClosing(WindowEvent e) { 44 | onCancel(); 45 | } 46 | }); 47 | 48 | contentPane.registerKeyboardAction(new ActionListener() { 49 | public void actionPerformed(ActionEvent e) { 50 | onCancel(); 51 | } 52 | }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 53 | 54 | 55 | setTitle("Convert method"); 56 | switch (type){ 57 | case OBJECT_FROM_DATA: 58 | titleName="objectFromData(Object data)"; 59 | editStr=Config.getInstant().getObjectFromDataStr(); 60 | break; 61 | case OBJECT_FROM_DATA1: 62 | titleName="objectFromData(Object data,String key)"; 63 | editStr=Config.getInstant().getObjectFromDataStr1(); 64 | break; 65 | case ARRAY_FROM_DATA: 66 | titleName="arrayFromData(Object data)"; 67 | editStr=Config.getInstant().getArrayFromDataStr(); 68 | break; 69 | case ARRAY_FROM_DATA1: 70 | titleName="arrayFromData(Object data,String key)"; 71 | editStr=Config.getInstant().getArrayFromData1Str(); 72 | break; 73 | } 74 | titleLB.setText(titleName); 75 | 76 | editTP.setText(editStr); 77 | resetButton.addActionListener(new ActionListener() { 78 | @Override 79 | public void actionPerformed(ActionEvent actionEvent) { 80 | 81 | resetAction(); 82 | 83 | } 84 | }); 85 | 86 | 87 | } 88 | 89 | private void resetAction() { 90 | 91 | switch (type){ 92 | case OBJECT_FROM_DATA: 93 | editTP.setText(Strings.objectFromObject); 94 | break; 95 | case OBJECT_FROM_DATA1: 96 | 97 | System.out.println(Strings.objectFromObject1); 98 | editTP.setText(Strings.objectFromObject1); 99 | break; 100 | case ARRAY_FROM_DATA: 101 | editTP.setText(Strings.arrayFromData); 102 | break; 103 | case ARRAY_FROM_DATA1: 104 | editTP.setText(Strings.arrayFromData1); 105 | break; 106 | } 107 | } 108 | 109 | private void onOK() { 110 | switch (type){ 111 | case OBJECT_FROM_DATA: 112 | Config.getInstant().saveObjectFromDataStr(editTP.getText()); 113 | break; 114 | case OBJECT_FROM_DATA1: 115 | Config.getInstant().saveObjectFromDataStr1(editTP.getText()); 116 | break; 117 | case ARRAY_FROM_DATA: 118 | Config.getInstant().saveArrayFromDataStr(editTP.getText()); 119 | break; 120 | case ARRAY_FROM_DATA1: 121 | Config.getInstant().saveArrayFromData1Str(editTP.getText()); 122 | break; 123 | } 124 | dispose(); 125 | } 126 | 127 | private void onCancel() { 128 | dispose(); 129 | } 130 | 131 | 132 | 133 | 134 | public enum Type{ 135 | OBJECT_FROM_DATA,OBJECT_FROM_DATA1,ARRAY_FROM_DATA,ARRAY_FROM_DATA1; 136 | 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /GsonFormat/ErrorDialog.form: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
70 | -------------------------------------------------------------------------------- /GsonFormat/ErrorDialog.java: -------------------------------------------------------------------------------- 1 | import javax.swing.*; 2 | import java.awt.event.ActionEvent; 3 | import java.awt.event.ActionListener; 4 | 5 | public class ErrorDialog extends JFrame { 6 | private JPanel contentPane; 7 | private JTextPane editTP; 8 | private JButton okButton; 9 | private JScrollPane scrollPane; 10 | 11 | public ErrorDialog(String errorInfo) { 12 | setContentPane(contentPane); 13 | setTitle("error info"); 14 | getRootPane().setDefaultButton(okButton); 15 | this.setAlwaysOnTop(true); 16 | editTP.setText(errorInfo); 17 | 18 | 19 | okButton.addActionListener(new ActionListener() { 20 | public void actionPerformed(ActionEvent e) { 21 | dispose(); 22 | } 23 | }); 24 | editTP.setCaretPosition(0); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /GsonFormat/MainAction.java: -------------------------------------------------------------------------------- 1 | import com.intellij.codeInsight.CodeInsightActionHandler; 2 | import com.intellij.codeInsight.generation.actions.BaseGenerateAction; 3 | import com.intellij.openapi.actionSystem.AnActionEvent; 4 | import com.intellij.openapi.actionSystem.PlatformDataKeys; 5 | import com.intellij.openapi.editor.Editor; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.psi.*; 8 | import com.intellij.psi.util.PsiUtilBase; 9 | 10 | /** 11 | * Created with IntelliJ IDEA. 12 | * User: zzz40500 13 | * Date: 14-7-4 14 | * Time: 下午1:44 15 | * 16 | */ 17 | public class MainAction extends BaseGenerateAction { 18 | protected PsiClass mClass; 19 | private PsiElementFactory mFactory; 20 | private Project project; 21 | 22 | @SuppressWarnings("unused") 23 | public MainAction() { 24 | super(null); 25 | } 26 | 27 | @SuppressWarnings("unused") 28 | public MainAction(CodeInsightActionHandler handler) { 29 | super(handler); 30 | } 31 | 32 | @Override 33 | protected boolean isValidForClass(final PsiClass targetClass) { 34 | return super.isValidForClass(targetClass) ; 35 | } 36 | 37 | @Override 38 | public boolean isValidForFile(Project project, Editor editor, PsiFile file) { 39 | 40 | return super.isValidForFile(project, editor, file); 41 | } 42 | 43 | 44 | public void actionPerformed(AnActionEvent event) { 45 | 46 | project = event.getData(PlatformDataKeys.PROJECT); 47 | Editor editor = event.getData(PlatformDataKeys.EDITOR); 48 | PsiFile mFile = PsiUtilBase.getPsiFileInEditor(editor, project); 49 | mClass=getTargetClass(editor,mFile); 50 | JsonUtilsDialog jsonD=new JsonUtilsDialog(mClass,mFactory,mFile,project); 51 | jsonD.setmClass(mClass); 52 | jsonD.setmFactory(mFactory); 53 | jsonD.setmFile(mFile); 54 | jsonD.setmProject(project); 55 | jsonD.setSize(600, 400); 56 | jsonD.setLocationRelativeTo(null); 57 | jsonD.setVisible(true); 58 | 59 | } 60 | 61 | 62 | 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /GsonFormat/WriterUtil.java: -------------------------------------------------------------------------------- 1 | import com.intellij.openapi.command.WriteCommandAction; 2 | import com.intellij.openapi.project.Project; 3 | import com.intellij.psi.*; 4 | import com.intellij.psi.codeStyle.JavaCodeStyleManager; 5 | import entity.InnerClassEntity; 6 | 7 | import javax.swing.*; 8 | 9 | /** 10 | * Created with IntelliJ IDEA. 11 | * User: zzz40500 12 | * Date: 14-7-4 13 | * Time: 下午3:58 14 | * To change this template use File | Settings | File Templates. 15 | */ 16 | public class WriterUtil extends WriteCommandAction.Simple { 17 | 18 | protected PsiClass mClass; 19 | private PsiElementFactory mFactory; 20 | private Project project; 21 | private PsiFile mFile; 22 | 23 | public InnerClassEntity mInnerClassEntity; 24 | 25 | public WriterUtil(JsonUtilsDialog mJsonUtilsDialog, JLabel jLabel, 26 | PsiFile mFile, Project project, PsiClass mClass, PsiFile... files) { 27 | super(project, files); 28 | mFactory = JavaPsiFacade.getElementFactory(project); 29 | this.mFile = mFile; 30 | this.project = project; 31 | this.mClass = mClass; 32 | 33 | } 34 | 35 | @Override 36 | protected void run() { 37 | 38 | mInnerClassEntity.generateFiled(mFactory, mClass); 39 | JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project); 40 | styleManager.optimizeImports(mFile); 41 | styleManager.shortenClassReferences(mClass); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /GsonFormat/config/Strings.java: -------------------------------------------------------------------------------- 1 | package config; 2 | 3 | /** 4 | * Created by zzz40500 on 15/5/31. 5 | */ 6 | public class Strings { 7 | 8 | 9 | public static final String privateStr=" private String name;\n" + 10 | "\n" + 11 | " public void setName(String name){\n" + 12 | " this.name=name;\n" + 13 | " }\n" + 14 | "\n" + 15 | " public String getName(){\n" + 16 | " return name;\n" + 17 | " }"; 18 | public static final String publicStr=" public String name;"; 19 | public static final String privateUseSerializedNameStr=" @SerializedName(\"name\")\n" + 20 | " private String name;\n" + 21 | "\n" + 22 | " public void setName(String name){\n" + 23 | " this.name=name;\n" + 24 | " }\n" + 25 | "\n" + 26 | " public String getName(){\n" + 27 | " return name;\n" + 28 | " }"; 29 | public static final String publicUseSerializedNameStr=" @SerializedName(\"name\")\n" + 30 | " public String name;"; 31 | 32 | 33 | 34 | public static final String objectFromObject=" public static $ClassName$ objectFromData(String str){\n" + 35 | "\n" + 36 | " return new com.google.gson.Gson().fromJson(str,$ClassName$.class);\n" + 37 | " }"; 38 | public static final String objectFromObject1=" public static $ClassName$ objectFromData(String str, String key){\n" + 39 | "\n" + 40 | " try {\n" + 41 | " org.json.JSONObject jsonObject=new org.json.JSONObject(str);\n" + 42 | "\n" + 43 | " return new com.google.gson.Gson().fromJson(jsonObject.getString(str),$ClassName$.class);\n" + 44 | " } catch (org.json.JSONException e) {\n" + 45 | " e.printStackTrace();\n" + 46 | " }\n" + 47 | "\n" + 48 | " return null;\n" + 49 | " }"; 50 | public static final String arrayFromData=" public static java.util.List<$ClassName$> array$ClassName$FromData(String str){\n" + 51 | "\n" + 52 | " java.lang.reflect.Type listType=new com.google.gson.reflect.TypeToken>(){}.getType();\n" + 53 | "\n" + 54 | " return new com.google.gson.Gson().fromJson(str,listType);\n" + 55 | " }"; 56 | public static final String arrayFromData1=" public static java.util.List<$ClassName$> array$ClassName$FromData(String str,String key){\n" + 57 | "\n" + 58 | " try {\n" + 59 | " org.json.JSONObject jsonObject=new org.json.JSONObject(str);\n" + 60 | " java.lang.reflect.Type listType=new com.google.gson.reflect.TypeToken>(){}.getType();\n" + 61 | "\n" + 62 | " return new com.google.gson.Gson().fromJson(jsonObject.getString(str),listType);\n" + 63 | "\n" + 64 | " } catch (org.json.JSONException e) {\n" + 65 | " e.printStackTrace();\n" + 66 | " }\n" + 67 | "\n" + 68 | " return new java.util.ArrayList();\n" + 69 | "\n" + 70 | "\n" + 71 | " }"; 72 | 73 | public static final String gsonAnnotation="@com.google.gson.annotations.SerializedName\\s*\\(\\s*\"{filed}\"\\s*\\)"; 74 | public static final String gsonFullNameAnnotation="@com.google.gson.annotations.SerializedName(\"{filed}\")"; 75 | public static final String fastFullNameAnnotation="@com.alibaba.fastjson.annotation.JSONField(name=\"{filed}\")"; 76 | public static final String fastAnnotation="@com.alibaba.fastjson.annotation.JSONField\\s*\\(\\s*name\\s*=\\s*\"{filed}\"\\s*\\)"; 77 | public static final String jackAnnotation="@com.fasterxml.jackson.annotation.JsonProperty\\s*\\(\\s*\"{filed}\"\\s*\\)"; 78 | public static final String jackFullNameAnnotation="@com.fasterxml.jackson.annotation.JsonProperty(\"{filed}\")"; 79 | } 80 | -------------------------------------------------------------------------------- /GsonFormat/org/json/JSONException.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /** 4 | * The JSONException is thrown by the JSON.org classes when things are amiss. 5 | * 6 | * @author JSON.org 7 | * @version 2014-05-03 8 | */ 9 | public class JSONException extends RuntimeException { 10 | private static final long serialVersionUID = 0; 11 | private Throwable cause; 12 | 13 | /** 14 | * Constructs a JSONException with an explanatory message. 15 | * 16 | * @param message 17 | * Detail about the reason for the exception. 18 | */ 19 | public JSONException(String message) { 20 | super(message); 21 | } 22 | 23 | /** 24 | * Constructs a new JSONException with the specified cause. 25 | * @param cause The cause. 26 | */ 27 | public JSONException(Throwable cause) { 28 | super(cause.getMessage()); 29 | this.cause = cause; 30 | } 31 | 32 | /** 33 | * Returns the cause of this exception or null if the cause is nonexistent 34 | * or unknown. 35 | * 36 | * @return the cause of this exception or null if the cause is nonexistent 37 | * or unknown. 38 | */ 39 | @Override 40 | public Throwable getCause() { 41 | return this.cause; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /GsonFormat/org/json/JSONString.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | /** 3 | * The JSONString interface allows a toJSONString() 4 | * method so that a class can change the behavior of 5 | * JSONObject.toString(), JSONArray.toString(), 6 | * and JSONWriter.value(Object). The 7 | * toJSONString method will be used instead of the default behavior 8 | * of using the Object's toString() method and quoting the result. 9 | */ 10 | public interface JSONString { 11 | /** 12 | * The toJSONString method allows a class to produce its own JSON 13 | * serialization. 14 | * 15 | * @return A strictly syntactically correct JSON text. 16 | */ 17 | public String toJSONString(); 18 | } 19 | -------------------------------------------------------------------------------- /GsonFormat/res/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/GsonFormat/res/icon.png -------------------------------------------------------------------------------- /GsonFormat/src/cn/vearn/checktreetable/FiledTreeTableModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package src.cn.vearn.checktreetable; 6 | 7 | import entity.FieldEntity; 8 | import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode; 9 | import org.jdesktop.swingx.treetable.DefaultTreeTableModel; 10 | import org.jdesktop.swingx.treetable.TreeTableNode; 11 | 12 | /** 13 | * 14 | * @author vearn 15 | */ 16 | public class FiledTreeTableModel extends DefaultTreeTableModel { 17 | 18 | private String[] _names = {" Key ", "Value", "Data Types"," FiledName "}; 19 | private Class[] _types = {Object.class,Object.class, Object.class, Object.class}; 20 | 21 | 22 | public FiledTreeTableModel(TreeTableNode node) { 23 | super(node); 24 | } 25 | 26 | /** 27 | * 列的类型 28 | */ 29 | @Override 30 | public Class getColumnClass(int col) { 31 | return _types[col]; 32 | } 33 | 34 | /** 35 | * 列的数量 36 | */ 37 | @Override 38 | public int getColumnCount() { 39 | return _names.length; 40 | } 41 | 42 | /** 43 | * 表头显示的内容 44 | */ 45 | @Override 46 | public String getColumnName(int column) { 47 | return _names[column]; 48 | } 49 | 50 | /** 51 | * 返回在单元格中显示的Object 52 | */ 53 | @Override 54 | public Object getValueAt(Object node, int column) { 55 | Object value = null; 56 | if (node instanceof DefaultMutableTreeTableNode) { 57 | DefaultMutableTreeTableNode mutableNode = (DefaultMutableTreeTableNode) node; 58 | Object o = mutableNode.getUserObject(); 59 | if (o != null && o instanceof FieldEntity) { 60 | FieldEntity bean = (FieldEntity) o; 61 | switch (column) { 62 | case 0: 63 | value = bean.getKey(); 64 | break; 65 | case 1: 66 | value = bean.getValue(); 67 | break; 68 | case 2: 69 | value = bean.getRealType(); 70 | break; 71 | case 3: 72 | value = bean.getFieldName(); 73 | break; 74 | } 75 | } 76 | } 77 | return value; 78 | } 79 | 80 | @Override 81 | public void setValueAt(Object value, Object node, int column) { 82 | super.setValueAt(value, node, column); 83 | 84 | if (node instanceof DefaultMutableTreeTableNode) { 85 | DefaultMutableTreeTableNode mutableNode = (DefaultMutableTreeTableNode) node; 86 | Object o = mutableNode.getUserObject(); 87 | if (o != null && o instanceof FieldEntity) { 88 | FieldEntity bean = (FieldEntity) o; 89 | switch (column) { 90 | case 2: 91 | bean.checkAndSetType(value.toString()); 92 | break; 93 | case 3: 94 | bean.setFieldName(value.toString()); 95 | break; 96 | } 97 | } 98 | } 99 | } 100 | 101 | 102 | @Override 103 | public boolean isCellEditable(Object node, int column) { 104 | 105 | 106 | 107 | if(column == 2){ 108 | return true; 109 | } 110 | 111 | if(column == 3){ 112 | return true; 113 | } 114 | return false; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /GsonFormat/src/org/jdesktop/swingx/ux/CheckTreeCellProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package src.org.jdesktop.swingx.ux; 6 | 7 | import java.awt.BorderLayout; 8 | import javax.swing.JLabel; 9 | import javax.swing.JPanel; 10 | import javax.swing.JTree; 11 | import javax.swing.tree.TreePath; 12 | 13 | import entity.FieldEntity; 14 | import org.jdesktop.swingx.renderer.CellContext; 15 | import org.jdesktop.swingx.renderer.ComponentProvider; 16 | import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode; 17 | 18 | /** 19 | * 20 | * @author vearn 21 | */ 22 | public class CheckTreeCellProvider extends ComponentProvider { 23 | 24 | private CheckTreeSelectionModel selectionModel; 25 | private TristateCheckBox _checkBox = null; 26 | private JLabel _label = null; 27 | 28 | public CheckTreeCellProvider(CheckTreeSelectionModel selectionModel) { 29 | this.selectionModel = selectionModel; 30 | _checkBox = new TristateCheckBox(); // 创建一个TristateCheckBox实例 31 | _checkBox.setOpaque(false); // 设置TristateCheckBox不绘制背景 32 | _label = new JLabel(); // 创建一个JLabel实例 33 | } 34 | 35 | @Override 36 | protected void format(CellContext arg0) { 37 | // 从CellContext获取tree中的文字和图标 38 | JTree tree = (JTree) arg0.getComponent(); 39 | DefaultMutableTreeTableNode node = (DefaultMutableTreeTableNode) arg0.getValue(); 40 | Object obj = node.getUserObject(); 41 | if(obj instanceof FieldEntity){ 42 | _label.setText(((FieldEntity) obj).getKey()); 43 | _checkBox.setFieldEntity((FieldEntity) obj); 44 | } 45 | 46 | // _label.setIcon(arg0.getIcon()); 47 | 48 | // 根据selectionModel中的状态来绘制TristateCheckBox的外观 49 | TreePath path = tree.getPathForRow(arg0.getRow()); 50 | if (path != null) { 51 | if (selectionModel.isPathSelected(path, true)) { 52 | _checkBox.setState(Boolean.TRUE); 53 | } else if (selectionModel.isPartiallySelected(path)) { 54 | _checkBox.setState(null); // 注意“部分选中”状态的API 55 | } else { 56 | _checkBox.setState(Boolean.FALSE); 57 | } 58 | } 59 | 60 | // 使用BorderLayout布局,依次放置TristateCheckBox和JLabel 61 | rendererComponent.setLayout(new BorderLayout()); 62 | rendererComponent.add(_checkBox); 63 | rendererComponent.add(_label, BorderLayout.LINE_END); 64 | } 65 | 66 | @Override 67 | protected void configureState(CellContext arg0) { 68 | } 69 | 70 | /** 71 | * 初始化一个JPanel来放置TristateCheckBox和JLabel 72 | */ 73 | @Override 74 | protected JPanel createRendererComponent() { 75 | JPanel panel = new JPanel(); 76 | return panel; 77 | } 78 | } -------------------------------------------------------------------------------- /GsonFormat/src/org/jdesktop/swingx/ux/CheckTreeTableManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package src.org.jdesktop.swingx.ux; 6 | 7 | import java.awt.event.MouseAdapter; 8 | import java.awt.event.MouseEvent; 9 | import javax.swing.JCheckBox; 10 | import javax.swing.JTree; 11 | import javax.swing.event.TreeSelectionEvent; 12 | import javax.swing.event.TreeSelectionListener; 13 | import javax.swing.tree.TreePath; 14 | import org.jdesktop.swingx.JXTreeTable; 15 | import org.jdesktop.swingx.renderer.DefaultTreeRenderer; 16 | 17 | /** 18 | * 19 | * @author Santhosh Kumr T - santhosh@in.fiorano.com 20 | */ 21 | public class CheckTreeTableManager extends MouseAdapter implements TreeSelectionListener { 22 | 23 | private CheckTreeSelectionModel selectionModel; 24 | private JXTreeTable treetable; 25 | private JTree tree; 26 | int hotspot = new JCheckBox().getPreferredSize().width; 27 | 28 | public CheckTreeTableManager(JXTreeTable treeTable) { 29 | this.treetable = treeTable; 30 | this.tree = (JTree) treeTable.getCellRenderer(0, 0); 31 | selectionModel = new CheckTreeSelectionModel(tree.getModel()); 32 | tree.setCellRenderer(new DefaultTreeRenderer(new CheckTreeCellProvider(selectionModel))); 33 | treeTable.addMouseListener(this); 34 | 35 | selectionModel.addTreeSelectionListener(this); 36 | } 37 | 38 | @Override 39 | public void mouseClicked(MouseEvent me) { 40 | TreePath path = tree.getPathForLocation(me.getX(), me.getY()); 41 | if (path == null) { 42 | return; 43 | } 44 | if (me.getX() > tree.getPathBounds(path).x + hotspot) { 45 | return; 46 | } 47 | 48 | boolean selected = selectionModel.isPathSelected(path, true); 49 | selectionModel.removeTreeSelectionListener(this); 50 | 51 | try { 52 | if (selected) { 53 | selectionModel.removeSelectionPath(path); 54 | } else { 55 | selectionModel.addSelectionPath(path); 56 | } 57 | } finally { 58 | selectionModel.addTreeSelectionListener(this); 59 | treetable.repaint(); 60 | } 61 | } 62 | 63 | public CheckTreeSelectionModel getSelectionModel() { 64 | return selectionModel; 65 | } 66 | 67 | public void valueChanged(TreeSelectionEvent e) { 68 | } 69 | } -------------------------------------------------------------------------------- /GsonFormat/utils/CheckUtil.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by qingwei on 2015/8/21. 8 | */ 9 | public class CheckUtil { 10 | 11 | private static CheckUtil mCheckUtil; 12 | private List mKeyWordList=new ArrayList(); 13 | 14 | private CheckUtil(){ 15 | mKeyWordList.add("abstract"); 16 | mKeyWordList.add("assert"); 17 | mKeyWordList.add("boolean"); 18 | mKeyWordList.add("break"); 19 | mKeyWordList.add("byte"); 20 | mKeyWordList.add("case"); 21 | mKeyWordList.add("catch"); 22 | mKeyWordList.add("char"); 23 | mKeyWordList.add("class"); 24 | mKeyWordList.add("const"); 25 | mKeyWordList.add("continue"); 26 | mKeyWordList.add("default"); 27 | mKeyWordList.add("do"); 28 | mKeyWordList.add("double"); 29 | mKeyWordList.add("else"); 30 | mKeyWordList.add("enum"); 31 | mKeyWordList.add("extends"); 32 | mKeyWordList.add("final"); 33 | mKeyWordList.add("finally"); 34 | mKeyWordList.add("float"); 35 | mKeyWordList.add("for"); 36 | mKeyWordList.add("goto"); 37 | mKeyWordList.add("if"); 38 | mKeyWordList.add("implements"); 39 | mKeyWordList.add("import"); 40 | mKeyWordList.add("instanceof"); 41 | mKeyWordList.add("int"); 42 | mKeyWordList.add("interface"); 43 | mKeyWordList.add("long"); 44 | mKeyWordList.add("native"); 45 | mKeyWordList.add("new"); 46 | mKeyWordList.add("package"); 47 | mKeyWordList.add("private"); 48 | mKeyWordList.add("protected"); 49 | mKeyWordList.add("public"); 50 | mKeyWordList.add("return"); 51 | mKeyWordList.add("strictfp"); 52 | mKeyWordList.add("short"); 53 | mKeyWordList.add("static"); 54 | mKeyWordList.add("super"); 55 | mKeyWordList.add("switch"); 56 | mKeyWordList.add("synchronized"); 57 | mKeyWordList.add("this"); 58 | mKeyWordList.add("throw"); 59 | mKeyWordList.add("throws"); 60 | mKeyWordList.add("transient"); 61 | mKeyWordList.add("abstract"); 62 | mKeyWordList.add("void"); 63 | mKeyWordList.add("volatile"); 64 | mKeyWordList.add("while"); 65 | 66 | } 67 | 68 | public static CheckUtil getInstant(){ 69 | if(mCheckUtil == null){ 70 | mCheckUtil =new CheckUtil(); 71 | } 72 | return mCheckUtil; 73 | } 74 | 75 | 76 | public boolean checkKeyWord(String key) { 77 | 78 | return mKeyWordList.contains(key); 79 | } 80 | 81 | 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /GsonFormat/utils/Toast.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import com.intellij.openapi.ui.MessageType; 5 | import com.intellij.openapi.ui.popup.Balloon; 6 | import com.intellij.openapi.ui.popup.JBPopupFactory; 7 | import com.intellij.openapi.wm.StatusBar; 8 | import com.intellij.openapi.wm.WindowManager; 9 | import com.intellij.ui.awt.RelativePoint; 10 | 11 | import javax.swing.*; 12 | 13 | /** 14 | * Created by zzz40500 on 15/8/24. 15 | */ 16 | public class Toast { 17 | 18 | /** 19 | * Display simple notification of given type 20 | * 21 | * @param project 22 | * @param type 23 | * @param text 24 | */ 25 | public static void make(Project project,JComponent jComponent, MessageType type, String text) { 26 | 27 | StatusBar statusBar = WindowManager.getInstance().getStatusBar(project); 28 | 29 | JBPopupFactory.getInstance() 30 | .createHtmlTextBalloonBuilder(text, type, null) 31 | .setFadeoutTime(7500) 32 | .createBalloon() 33 | .show(RelativePoint.getCenterOf(jComponent), Balloon.Position.above); 34 | } /** 35 | * Display simple notification of given type 36 | * 37 | * @param project 38 | * @param type 39 | * @param text 40 | */ 41 | public static void make(Project project, MessageType type, String text) { 42 | 43 | StatusBar statusBar = WindowManager.getInstance().getStatusBar(project); 44 | 45 | JBPopupFactory.getInstance() 46 | .createHtmlTextBalloonBuilder(text, type, null) 47 | .setFadeoutTime(7500) 48 | .createBalloon() 49 | .show(RelativePoint.getCenterOf(statusBar.getComponent()), Balloon.Position.atRight); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndroidStudioSuperPlugin 2 | 3 | 4 | This project aims at integrating existing good-to-use android studio plugin so that we can use just one plugin and don't have to download plugins everywhere 5 | 6 | 7 | Version1.0.0 integrated following plugins: 8 | * Android Studio Prettify(https://github.com/Haehnchen/idea-android-studio-plugin) 9 | * GsonFormat(https://github.com/zzz40500/GsonFormat") 10 | * Android Code Generator(https://github.com/tmorcinek/android-codegenerator-plugin-intellij) 11 | * SelectorChapek(https://github.com/inmite/android-selector-chapek) 12 | * IntelliJ/Android Studio Plugin for Android Parcelable boilerplate code generation(https://github.com/mcharmas/android-parcelable-intellij-plugin) 13 | * folding-plugin(https://github.com/dmytrodanylyk/folding-plugin) 14 | * Lifecycle-Sorter(https://github.com/armandAkop/Lifecycle-Sorter) 15 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/actions/ActivityAction.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.actions; 2 | 3 | import com.morcinek.android.codegenerator.codegeneration.providers.ResourceProvidersFactory; 4 | import com.morcinek.android.codegenerator.codegeneration.providers.factories.ActivityResourceProvidersFactory; 5 | 6 | /** 7 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 8 | */ 9 | public class ActivityAction extends LayoutAction { 10 | 11 | @Override 12 | protected String getResourceName() { 13 | return "Activity"; 14 | } 15 | 16 | @Override 17 | protected String getTemplateName() { 18 | return "Activity_template"; 19 | } 20 | 21 | @Override 22 | protected ResourceProvidersFactory getResourceProvidersFactory() { 23 | return new ActivityResourceProvidersFactory(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/actions/AdapterAction.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.actions; 2 | 3 | import com.morcinek.android.codegenerator.codegeneration.providers.ResourceProvidersFactory; 4 | import com.morcinek.android.codegenerator.codegeneration.providers.factories.AdapterResourceProvidersFactory; 5 | 6 | /** 7 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 8 | */ 9 | public class AdapterAction extends LayoutAction { 10 | 11 | @Override 12 | protected String getResourceName() { 13 | return "Adapter"; 14 | } 15 | 16 | @Override 17 | protected String getTemplateName() { 18 | return "Adapter_template"; 19 | } 20 | 21 | @Override 22 | protected ResourceProvidersFactory getResourceProvidersFactory() { 23 | return new AdapterResourceProvidersFactory(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/actions/FragmentAction.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.actions; 2 | 3 | import com.morcinek.android.codegenerator.codegeneration.providers.ResourceProvidersFactory; 4 | import com.morcinek.android.codegenerator.codegeneration.providers.factories.FragmentResourceProvidersFactory; 5 | 6 | /** 7 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 8 | */ 9 | public class FragmentAction extends LayoutAction { 10 | 11 | @Override 12 | protected String getResourceName() { 13 | return "Fragment"; 14 | } 15 | 16 | @Override 17 | protected String getTemplateName() { 18 | return "Fragment_template"; 19 | } 20 | 21 | @Override 22 | protected ResourceProvidersFactory getResourceProvidersFactory() { 23 | return new FragmentResourceProvidersFactory(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/actions/MenuAction.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.actions; 2 | 3 | import com.intellij.openapi.actionSystem.AnAction; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.openapi.actionSystem.PlatformDataKeys; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.openapi.vfs.VirtualFile; 8 | import com.morcinek.android.codegenerator.codegeneration.providers.factories.MenuResourceProvidersFactory; 9 | import com.morcinek.android.codegenerator.plugin.actions.visibility.ActionVisibilityHelper; 10 | import com.morcinek.android.codegenerator.plugin.codegenerator.CodeGeneratorController; 11 | import com.morcinek.android.codegenerator.plugin.error.ErrorHandler; 12 | import com.morcinek.android.codegenerator.plugin.ui.CodeDialogBuilder; 13 | import com.morcinek.android.codegenerator.plugin.ui.StringResources; 14 | import com.morcinek.android.codegenerator.plugin.utils.ClipboardHelper; 15 | 16 | /** 17 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 18 | */ 19 | public class MenuAction extends AnAction { 20 | 21 | private final ActionVisibilityHelper actionVisibilityHelper = new ActionVisibilityHelper("menu", "xml"); 22 | 23 | private final ErrorHandler errorHandler = new ErrorHandler(); 24 | 25 | @Override 26 | public void actionPerformed(AnActionEvent event) { 27 | final Project project = event.getData(PlatformDataKeys.PROJECT); 28 | final VirtualFile selectedFile = event.getData(PlatformDataKeys.VIRTUAL_FILE); 29 | try { 30 | CodeGeneratorController codeGeneratorController = new CodeGeneratorController("Menu_template", new MenuResourceProvidersFactory()); 31 | String generatedCode = codeGeneratorController.generateCode(project, selectedFile, event.getData(PlatformDataKeys.EDITOR)); 32 | final CodeDialogBuilder codeDialogBuilder = new CodeDialogBuilder(project, 33 | String.format(StringResources.TITLE_FORMAT_TEXT, selectedFile.getName()), generatedCode); 34 | codeDialogBuilder.addAction(StringResources.COPY_ACTION_LABEL, new Runnable() { 35 | @Override 36 | public void run() { 37 | ClipboardHelper.copy(codeDialogBuilder.getModifiedCode()); 38 | codeDialogBuilder.closeDialog(); 39 | } 40 | }); 41 | codeDialogBuilder.showDialog(); 42 | } catch (Exception exception) { 43 | errorHandler.handleError(project, exception); 44 | } 45 | } 46 | 47 | @Override 48 | public void update(AnActionEvent event) { 49 | event.getPresentation().setVisible(actionVisibilityHelper.isVisible(event.getDataContext())); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/actions/butterknife/BActivityAction.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.actions.butterknife; 2 | 3 | import com.morcinek.android.codegenerator.codegeneration.providers.ResourceProvidersFactory; 4 | import com.morcinek.android.codegenerator.codegeneration.providers.factories.BActivityResourceProvidersFactory; 5 | import com.morcinek.android.codegenerator.plugin.actions.LayoutAction; 6 | 7 | /** 8 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 9 | */ 10 | public class BActivityAction extends LayoutAction { 11 | 12 | @Override 13 | protected String getResourceName() { 14 | return "Activity"; 15 | } 16 | 17 | @Override 18 | protected String getTemplateName() { 19 | return "BActivity_template"; 20 | } 21 | 22 | @Override 23 | protected ResourceProvidersFactory getResourceProvidersFactory() { 24 | return new BActivityResourceProvidersFactory(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/actions/butterknife/BAdapterAction.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.actions.butterknife; 2 | 3 | import com.morcinek.android.codegenerator.codegeneration.providers.ResourceProvidersFactory; 4 | import com.morcinek.android.codegenerator.codegeneration.providers.factories.BAdapterResourceProvidersFactory; 5 | import com.morcinek.android.codegenerator.plugin.actions.LayoutAction; 6 | 7 | /** 8 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 9 | */ 10 | public class BAdapterAction extends LayoutAction { 11 | 12 | @Override 13 | protected String getResourceName() { 14 | return "Adapter"; 15 | } 16 | 17 | @Override 18 | protected String getTemplateName() { 19 | return "BAdapter_template"; 20 | } 21 | 22 | @Override 23 | protected ResourceProvidersFactory getResourceProvidersFactory() { 24 | return new BAdapterResourceProvidersFactory(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/actions/butterknife/BFragmentAction.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.actions.butterknife; 2 | 3 | import com.morcinek.android.codegenerator.codegeneration.providers.ResourceProvidersFactory; 4 | import com.morcinek.android.codegenerator.codegeneration.providers.factories.BActivityResourceProvidersFactory; 5 | import com.morcinek.android.codegenerator.codegeneration.providers.factories.FragmentResourceProvidersFactory; 6 | import com.morcinek.android.codegenerator.plugin.actions.LayoutAction; 7 | 8 | /** 9 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 10 | */ 11 | public class BFragmentAction extends LayoutAction { 12 | 13 | @Override 14 | protected String getResourceName() { 15 | return "Fragment"; 16 | } 17 | 18 | @Override 19 | protected String getTemplateName() { 20 | return "BFragment_template"; 21 | } 22 | 23 | @Override 24 | protected ResourceProvidersFactory getResourceProvidersFactory() { 25 | return new BActivityResourceProvidersFactory(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/actions/visibility/ActionVisibilityHelper.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.actions.visibility; 2 | 3 | import com.intellij.openapi.actionSystem.CommonDataKeys; 4 | import com.intellij.openapi.actionSystem.DataContext; 5 | import com.intellij.openapi.vfs.VirtualFile; 6 | 7 | /** 8 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 9 | */ 10 | public class ActionVisibilityHelper { 11 | 12 | private String folder; 13 | 14 | private String extension; 15 | 16 | public ActionVisibilityHelper(String folder, String extension) { 17 | this.folder = folder; 18 | this.extension = extension; 19 | } 20 | 21 | public boolean isVisible(DataContext dataContext) { 22 | VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext); 23 | if (files != null && files.length == 1) { 24 | VirtualFile file = files[0]; 25 | return !file.isDirectory() && hasCorrectExtension(file) && hasCorrectFolder(file); 26 | } else { 27 | return false; 28 | } 29 | } 30 | 31 | private boolean hasCorrectExtension(VirtualFile data) { 32 | return data.getExtension() != null && data.getExtension().equals(extension); 33 | } 34 | 35 | private boolean hasCorrectFolder(VirtualFile data) { 36 | return data.getParent().getName().equals(folder); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/codegenerator/CodeGeneratorController.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.codegenerator; 2 | 3 | import com.intellij.openapi.editor.Editor; 4 | import com.intellij.openapi.fileEditor.FileEditor; 5 | import com.intellij.openapi.fileEditor.FileEditorManager; 6 | import com.intellij.openapi.fileEditor.TextEditor; 7 | import com.intellij.openapi.project.Project; 8 | import com.intellij.openapi.vfs.VirtualFile; 9 | import com.morcinek.android.codegenerator.CodeGenerator; 10 | import com.morcinek.android.codegenerator.codegeneration.providers.ResourceProvidersFactory; 11 | import org.xml.sax.SAXException; 12 | 13 | import javax.xml.parsers.ParserConfigurationException; 14 | import javax.xml.xpath.XPathExpressionException; 15 | import java.io.ByteArrayInputStream; 16 | import java.io.IOException; 17 | import java.io.InputStream; 18 | 19 | /** 20 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 21 | */ 22 | public class CodeGeneratorController { 23 | 24 | private CodeGenerator codeGenerator; 25 | 26 | public CodeGeneratorController(String templateName, ResourceProvidersFactory resourceProvidersFactory) { 27 | codeGenerator = CodeGeneratorFactory.createCodeGenerator(templateName, resourceProvidersFactory); 28 | } 29 | 30 | public String generateCode(Project project, VirtualFile file, Editor editor) throws ParserConfigurationException, SAXException, XPathExpressionException, IOException { 31 | return codeGenerator.produceCode(getContents(project, editor, file), file.getName()); 32 | } 33 | 34 | private InputStream getContents(Project project, Editor editor, VirtualFile file) throws IOException { 35 | editor = getEditor(project, editor, file); 36 | if (editor != null) { 37 | return new ByteArrayInputStream(getText(editor).getBytes()); 38 | } else { 39 | return file.getInputStream(); 40 | } 41 | } 42 | 43 | private Editor getEditor(Project project, Editor editor, VirtualFile file) { 44 | if (editor == null) { 45 | TextEditor textEditor = getTextEditor(project, file); 46 | if (textEditor != null) { 47 | return textEditor.getEditor(); 48 | } 49 | } 50 | return editor; 51 | } 52 | 53 | private TextEditor getTextEditor(Project project, VirtualFile file) { 54 | FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(file); 55 | if (fileEditor instanceof TextEditor) { 56 | return (TextEditor) fileEditor; 57 | } 58 | return null; 59 | } 60 | 61 | private String getText(Editor editor) { 62 | return editor.getDocument().getText(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/codegenerator/CodeGeneratorFactory.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.codegenerator; 2 | 3 | import com.google.common.io.Resources; 4 | import com.morcinek.android.codegenerator.CodeGenerator; 5 | import com.morcinek.android.codegenerator.codegeneration.TemplateCodeGenerator; 6 | import com.morcinek.android.codegenerator.codegeneration.providers.ResourceProvidersFactory; 7 | import com.morcinek.android.codegenerator.codegeneration.templates.TemplatesProvider; 8 | import com.morcinek.android.codegenerator.extractor.XMLResourceExtractor; 9 | import com.morcinek.android.codegenerator.extractor.string.FileNameExtractor; 10 | import com.morcinek.android.codegenerator.plugin.preferences.persistence.TemplateSettings; 11 | 12 | import java.io.IOException; 13 | import java.net.URL; 14 | import java.nio.charset.Charset; 15 | 16 | /** 17 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 18 | */ 19 | public class CodeGeneratorFactory { 20 | 21 | public static CodeGenerator createCodeGenerator(String templateName, ResourceProvidersFactory resourceProvidersFactory) { 22 | return new CodeGenerator(XMLResourceExtractor.createResourceExtractor(), 23 | new FileNameExtractor(), 24 | //FIXME change ResourceTemplateProvider for PreferencesTemplateProvider 25 | new TemplateCodeGenerator(templateName, resourceProvidersFactory, TemplateSettings.getInstance())); 26 | } 27 | 28 | public static class ResourceTemplateProvider implements TemplatesProvider { 29 | 30 | @Override 31 | public String provideTemplateForName(String templateName) { 32 | URL url = getClass().getClassLoader().getResource(templateName); 33 | try { 34 | return Resources.toString(url, Charset.defaultCharset()); 35 | } catch (IOException e) { 36 | e.printStackTrace(); 37 | } 38 | return null; 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/error/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.error; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import com.intellij.openapi.ui.Messages; 5 | 6 | /** 7 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 8 | */ 9 | public class ErrorHandler { 10 | 11 | public void handleError(Project project, Exception exception) { 12 | exception.printStackTrace(); 13 | showErrorMessage(project, exception); 14 | } 15 | 16 | private void showErrorMessage(Project project, Exception e) { 17 | showErrorMessage(project, e.getMessage()); 18 | } 19 | 20 | private void showErrorMessage(Project project, String message) { 21 | Messages.showErrorDialog(project, message, "Eclipse Maven Plugin"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/groups/GenerateAndroidCodeGroup.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.groups; 2 | 3 | import com.intellij.openapi.actionSystem.DefaultActionGroup; 4 | 5 | /** 6 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 7 | */ 8 | public class GenerateAndroidCodeGroup extends DefaultActionGroup { 9 | 10 | @Override 11 | public boolean hideIfNoVisibleChildren() { 12 | return true; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/persistence/Settings.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.persistence; 2 | 3 | import com.intellij.openapi.components.*; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.util.xmlb.XmlSerializerUtil; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | /** 9 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 10 | */ 11 | @State( 12 | name = "CodeGeneratorSettings", 13 | storages = { 14 | @Storage(file = StoragePathMacros.PROJECT_FILE), 15 | @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/code_generator_settings.xml", scheme = StorageScheme.DIRECTORY_BASED) 16 | } 17 | ) 18 | public class Settings implements PersistentStateComponent { 19 | 20 | private String sourcePath; 21 | 22 | public String getSourcePath() { 23 | return sourcePath; 24 | } 25 | 26 | public void setSourcePath(String sourcePath) { 27 | this.sourcePath = sourcePath; 28 | } 29 | 30 | public static Settings getInstance(Project project) { 31 | return ServiceManager.getService(project, Settings.class); 32 | } 33 | 34 | @Nullable 35 | @Override 36 | public Settings getState() { 37 | return this; 38 | } 39 | 40 | @Override 41 | public void loadState(Settings settings) { 42 | XmlSerializerUtil.copyBean(settings, this); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/preferences/configurables/MainConfigurable.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.preferences.configurables; 2 | 3 | import com.intellij.openapi.options.Configurable; 4 | import com.intellij.openapi.options.ConfigurationException; 5 | import com.morcinek.android.codegenerator.plugin.preferences.configurables.templates.TemplateConfigurable; 6 | import org.jetbrains.annotations.Nls; 7 | import org.jetbrains.annotations.NonNls; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import javax.swing.*; 11 | import java.awt.*; 12 | 13 | /** 14 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 15 | */ 16 | public class MainConfigurable implements Configurable.Composite, Configurable.NoScroll, Configurable { 17 | 18 | private Configurable[] configurables; 19 | 20 | public MainConfigurable() { 21 | super(); 22 | } 23 | 24 | @Nls 25 | @Override 26 | public String getDisplayName() { 27 | return "Android Code Generator"; 28 | } 29 | 30 | @Nullable 31 | @NonNls 32 | @Override 33 | public String getHelpTopic() { 34 | return null; 35 | } 36 | 37 | @Override 38 | public JComponent createComponent() { 39 | JPanel panel = new JPanel(new BorderLayout()); 40 | JLabel label = new JLabel("Here you can edit 'Android Code Generator' settings. In children pages you can edit template for each code generation method."); 41 | label.setVerticalAlignment(SwingConstants.TOP); 42 | panel.add(label, BorderLayout.PAGE_START); 43 | return panel; 44 | } 45 | 46 | public void disposeUIResources() { 47 | } 48 | 49 | @Override 50 | public boolean isModified() { 51 | return false; 52 | } 53 | 54 | @Override 55 | public void apply() throws ConfigurationException { 56 | } 57 | 58 | @Override 59 | public void reset() { 60 | } 61 | 62 | public Configurable[] getConfigurables() { 63 | if (configurables == null) { 64 | configurables = new Configurable[]{ 65 | new TemplateConfigurable("Activity Template", "Setup Template for Activity code generation:", "Activity_template"), 66 | new TemplateConfigurable("Adapter Template", "Setup Template for Adapter code generation:", "Adapter_template"), 67 | new TemplateConfigurable("Fragment Template", "Setup Template for Fragment code generation:", "Fragment_template"), 68 | new TemplateConfigurable("Menu Template", "Setup Template for Menu code generation:", "Menu_template") 69 | }; 70 | } 71 | return configurables; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/preferences/persistence/TemplateSettings.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.preferences.persistence; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.intellij.openapi.components.*; 5 | import com.intellij.util.xmlb.XmlSerializerUtil; 6 | import com.morcinek.android.codegenerator.codegeneration.templates.TemplatesProvider; 7 | import com.morcinek.android.codegenerator.plugin.codegenerator.CodeGeneratorFactory; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.util.Map; 11 | 12 | /** 13 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 14 | */ 15 | @State( 16 | name = "CodeGeneratorTemplateSettings", 17 | storages = { 18 | @Storage(file = StoragePathMacros.APP_CONFIG + "/code_generator_template_settings.xml") 19 | } 20 | ) 21 | public class TemplateSettings implements PersistentStateComponent, TemplatesProvider { 22 | 23 | private Map templateValues = Maps.newHashMap(); 24 | 25 | private TemplatesProvider templatesProvider = new CodeGeneratorFactory.ResourceTemplateProvider(); 26 | 27 | public static TemplateSettings getInstance() { 28 | return ServiceManager.getService(TemplateSettings.class); 29 | } 30 | 31 | public Map getTemplateValues() { 32 | return templateValues; 33 | } 34 | 35 | public void setTemplateValues(Map templateValues) { 36 | this.templateValues = templateValues; 37 | } 38 | 39 | @Nullable 40 | @Override 41 | public TemplateSettings getState() { 42 | return this; 43 | } 44 | 45 | @Override 46 | public void loadState(TemplateSettings templateSettings) { 47 | XmlSerializerUtil.copyBean(templateSettings, this); 48 | } 49 | 50 | @Override 51 | public String provideTemplateForName(String templateName) { 52 | if (isUsingCustomTemplateForName(templateName)) { 53 | return templateValues.get(templateName); 54 | } 55 | return templatesProvider.provideTemplateForName(templateName); 56 | } 57 | 58 | public void removeTemplateForName(String templateName) { 59 | templateValues.remove(templateName); 60 | } 61 | 62 | public boolean isUsingCustomTemplateForName(String templateName) { 63 | return templateValues.containsKey(templateName); 64 | } 65 | 66 | public void setTemplateForName(String templateName, String template) { 67 | templateValues.put(templateName, template); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/ui/CodeDialogBuilder.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.ui; 2 | 3 | import com.google.common.collect.Maps; 4 | import com.intellij.openapi.application.ApplicationManager; 5 | import com.intellij.openapi.project.Project; 6 | import com.intellij.openapi.ui.ComboBox; 7 | import com.intellij.openapi.ui.DialogBuilder; 8 | import com.intellij.openapi.ui.DialogWrapper; 9 | import com.intellij.ui.CollectionComboBoxModel; 10 | import com.intellij.ui.JBColor; 11 | import com.intellij.ui.components.JBScrollPane; 12 | import com.intellij.ui.components.JBTextField; 13 | 14 | import javax.swing.*; 15 | import javax.swing.border.LineBorder; 16 | import java.awt.*; 17 | import java.awt.event.ActionEvent; 18 | import java.util.Map; 19 | 20 | /** 21 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 22 | */ 23 | public class CodeDialogBuilder { 24 | 25 | private final DialogBuilder dialogBuilder; 26 | 27 | private final JPanel topPanel; 28 | 29 | private final JTextArea codeArea; 30 | private JBTextField packageText; 31 | private JComboBox sourcePathComboBox; 32 | 33 | public CodeDialogBuilder(Project project, String title, String producedCode) { 34 | dialogBuilder = new DialogBuilder(project); 35 | dialogBuilder.setTitle(title); 36 | 37 | JPanel centerPanel = new JPanel(new BorderLayout()); 38 | 39 | codeArea = prepareCodeArea(producedCode); 40 | centerPanel.add(new JBScrollPane(codeArea), BorderLayout.CENTER); 41 | dialogBuilder.setCenterPanel(centerPanel); 42 | 43 | topPanel = new JPanel(new GridLayout(0, 2)); 44 | centerPanel.add(topPanel, BorderLayout.PAGE_START); 45 | 46 | dialogBuilder.removeAllActions(); 47 | } 48 | 49 | public void addAction(String title, final Runnable action) { 50 | addAction(title, action, false); 51 | } 52 | 53 | public void addAction(String title, final Runnable action, final boolean runWriteAction) { 54 | dialogBuilder.addAction(new AbstractAction(title) { 55 | @Override 56 | public void actionPerformed(ActionEvent e) { 57 | if (runWriteAction) { 58 | ApplicationManager.getApplication().runWriteAction(action); 59 | } else { 60 | action.run(); 61 | } 62 | } 63 | }); 64 | } 65 | 66 | public void addPackageSection(String defaultText) { 67 | topPanel.add(new JLabel(StringResources.PACKAGE_LABEL)); 68 | packageText = new JBTextField(defaultText); 69 | topPanel.add(packageText); 70 | } 71 | 72 | public String getPackage() { 73 | return packageText.getText(); 74 | } 75 | 76 | public void addSourcePathSection(java.util.List string, String defaultValue) { 77 | topPanel.add(new JLabel(StringResources.SOURCE_PATH_LABEL)); 78 | sourcePathComboBox = new ComboBox(new CollectionComboBoxModel(string)); 79 | sourcePathComboBox.setSelectedItem(defaultValue); 80 | topPanel.add(sourcePathComboBox); 81 | } 82 | 83 | public String getSourcePath() { 84 | return (String) sourcePathComboBox.getSelectedItem(); 85 | } 86 | 87 | public int showDialog() { 88 | return dialogBuilder.show(); 89 | } 90 | 91 | public void closeDialog(){ 92 | dialogBuilder.getDialogWrapper().close(DialogWrapper.OK_EXIT_CODE); 93 | } 94 | 95 | public String getModifiedCode() { 96 | return codeArea.getText(); 97 | } 98 | 99 | private JTextArea prepareCodeArea(String producedCode) { 100 | JTextArea codeArea = new JTextArea(producedCode); 101 | codeArea.setBorder(new LineBorder(JBColor.gray)); 102 | return codeArea; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/ui/DialogsFactory.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.ui; 2 | 3 | import com.intellij.ide.IdeBundle; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.openapi.ui.Messages; 6 | import com.intellij.util.ui.UIUtil; 7 | 8 | /** 9 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 10 | */ 11 | public class DialogsFactory { 12 | 13 | public static boolean openOverrideFileDialog(Project project, String folderPath, String fileName) { 14 | return Messages.showYesNoDialog( 15 | project, 16 | String.format(StringResources.OVERRIDE_DIALOG_MESSAGE, folderPath, fileName), 17 | StringResources.OVERRIDE_DIALOG_TITLE, 18 | StringResources.OVERRIDE_DIALOG_YES_TEXT, 19 | StringResources.OVERRIDE_DIALOG_NO_TEXT, 20 | UIUtil.getWarningIcon() 21 | ) == Messages.OK; 22 | } 23 | 24 | public static void showMissingSourcePathDialog(Project project) { 25 | Messages.showErrorDialog( 26 | project, 27 | StringResources.MISSING_SOURCE_PATH_DIALOG_MESSAGE, 28 | StringResources.MISSING_SOURCE_PATH_DIALOG_TITLE 29 | ); 30 | } 31 | 32 | public static boolean openResetTemplateDialog() { 33 | return Messages.showOkCancelDialog(IdeBundle.message("prompt.reset.to.original.template"), 34 | IdeBundle.message("title.reset.template"), Messages.getQuestionIcon()) == 35 | Messages.OK; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/ui/StringResources.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.ui; 2 | 3 | /** 4 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 5 | */ 6 | public interface StringResources { 7 | 8 | String PACKAGE_LABEL = "Package"; 9 | String SOURCE_PATH_LABEL = "Source Path"; 10 | String TITLE_FORMAT_TEXT = "Code generated from: '%s'"; 11 | String COPY_ACTION_LABEL = "Copy Code To Clipboard"; 12 | String CREATE_ACTION_LABEL = "Create File"; 13 | 14 | String OVERRIDE_DIALOG_TITLE = "File Already Exists"; 15 | String OVERRIDE_DIALOG_MESSAGE = "File '%s/%s' already exists.\nDo you want to override file content with generated code."; 16 | String OVERRIDE_DIALOG_YES_TEXT = "Override"; 17 | String OVERRIDE_DIALOG_NO_TEXT = "Cancel"; 18 | 19 | String MISSING_SOURCE_PATH_DIALOG_MESSAGE = "You need to select 'Source Path' in which the file will be created.\nSelect one from the project's source roots."; 20 | String MISSING_SOURCE_PATH_DIALOG_TITLE = "Missing Source Path"; 21 | 22 | String RESET_TO_DEFAULT_ACTION_DESCRIPTION = "Reset templates to Defaults"; 23 | String RESET_TO_DEFAULT_ACTION_TITLE = "Reset to Defaults"; 24 | } 25 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/utils/ClipboardHelper.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.utils; 2 | 3 | import com.intellij.openapi.ide.CopyPasteManager; 4 | 5 | import java.awt.datatransfer.StringSelection; 6 | 7 | /** 8 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 9 | */ 10 | public class ClipboardHelper { 11 | 12 | public static void copy(String generatedCode) { 13 | CopyPasteManager.getInstance().setContents(new StringSelection(generatedCode)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/utils/PackageHelper.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.utils; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.openapi.project.Project; 6 | import com.intellij.openapi.vfs.VirtualFile; 7 | import com.morcinek.android.codegenerator.extractor.PackageExtractor; 8 | import com.morcinek.android.codegenerator.extractor.XMLPackageExtractor; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 15 | */ 16 | public class PackageHelper { 17 | 18 | private final PackageExtractor packageExtractor = new XMLPackageExtractor(); 19 | 20 | private final ProjectHelper projectHelper = new ProjectHelper(); 21 | 22 | public String getPackageName(Project project, AnActionEvent event) { 23 | try { 24 | for (String path : possibleManifestPaths()) { 25 | VirtualFile file = getManifestFileFromPath(project, path); 26 | if (file != null && file.exists()) { 27 | return packageExtractor.extractPackageFromManifestStream(file.getInputStream()); 28 | } 29 | } 30 | for (String path : sourceRootPaths(project, event)) { 31 | VirtualFile file = getManifestFileFromPath(project, path); 32 | if (file != null && file.exists()) { 33 | return packageExtractor.extractPackageFromManifestStream(file.getInputStream()); 34 | } 35 | } 36 | } catch (Exception ignored) { 37 | } 38 | return ""; 39 | } 40 | 41 | private ArrayList possibleManifestPaths() { 42 | return Lists.newArrayList("", "app/", "app/src/main/", "src/main/", "res/"); 43 | } 44 | 45 | private List sourceRootPaths(Project project, AnActionEvent event) { 46 | return projectHelper.getSourceRootPathList(project, event); 47 | } 48 | 49 | private VirtualFile getManifestFileFromPath(Project project, String path) { 50 | VirtualFile folder = project.getBaseDir().findFileByRelativePath(path); 51 | if (folder != null) { 52 | return folder.findChild("AndroidManifest.xml"); 53 | } 54 | return null; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/utils/PathHelper.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.utils; 2 | 3 | import com.morcinek.android.codegenerator.codegeneration.builders.file.ClassNameBuilder; 4 | import com.morcinek.android.codegenerator.codegeneration.builders.file.PackageBuilder; 5 | import com.morcinek.android.codegenerator.extractor.string.FileNameExtractor; 6 | import org.apache.velocity.util.StringUtils; 7 | 8 | /** 9 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 10 | */ 11 | public class PathHelper { 12 | 13 | public String getMergedCodeWithPackage(String packageName, String generateCode) { 14 | if (!packageName.isEmpty()) { 15 | return new PackageBuilder(packageName).builtString() + generateCode; 16 | } 17 | return generateCode; 18 | } 19 | 20 | public String getFileName(String filePath, String resourceName) { 21 | String fileName = new FileNameExtractor().extractFromString(filePath); 22 | return new ClassNameBuilder(fileName).builtString() + resourceName + ".java"; 23 | } 24 | 25 | public String getFolderPath(String sourcePath, String packageName) { 26 | String normalizePath = StringUtils.normalizePath(sourcePath + "/" + StringUtils.getPackageAsPath(packageName)); 27 | return org.apache.commons.lang3.StringUtils.strip(normalizePath, "/"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /android_code_generator/com/morcinek/android/codegenerator/plugin/utils/ProjectHelper.java: -------------------------------------------------------------------------------- 1 | package com.morcinek.android.codegenerator.plugin.utils; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.openapi.actionSystem.LangDataKeys; 6 | import com.intellij.openapi.fileEditor.FileEditorManager; 7 | import com.intellij.openapi.project.Project; 8 | import com.intellij.openapi.roots.ModuleRootManager; 9 | import com.intellij.openapi.vfs.VirtualFile; 10 | import org.apache.velocity.util.StringUtils; 11 | 12 | import java.io.IOException; 13 | import java.util.List; 14 | 15 | /** 16 | * Copyright 2014 Tomasz Morcinek. All rights reserved. 17 | */ 18 | public class ProjectHelper { 19 | 20 | public boolean fileExists(Project project, String fileName, String folderPath) throws IOException { 21 | try { 22 | return project.getBaseDir().findFileByRelativePath(folderPath).findFileByRelativePath(fileName).exists(); 23 | } catch (NullPointerException e) { 24 | return false; 25 | } 26 | } 27 | 28 | public VirtualFile createOrFindFile(Project project, String fileName, String folderPath) throws IOException { 29 | VirtualFile folder = createFolderIfNotExist(project, folderPath); 30 | return folder.findOrCreateChildData(project, fileName); 31 | } 32 | 33 | public VirtualFile setFileContent(Project project, VirtualFile createdFile, String code) throws IOException { 34 | createdFile.setBinaryContent(code.getBytes()); 35 | openFileInEditor(project, createdFile); 36 | return createdFile; 37 | } 38 | 39 | private void openFileInEditor(Project project, VirtualFile fileWithGeneratedCode) { 40 | FileEditorManager.getInstance(project).openFile(fileWithGeneratedCode, true); 41 | } 42 | 43 | private VirtualFile createFolderIfNotExist(Project project, String folder) throws IOException { 44 | VirtualFile directory = project.getBaseDir(); 45 | String[] folders = folder.split("/"); 46 | for (String childFolder : folders) { 47 | VirtualFile childDirectory = directory.findChild(childFolder); 48 | if (childDirectory != null && childDirectory.isDirectory()) { 49 | directory = childDirectory; 50 | } else { 51 | directory = directory.createChildDirectory(project, childFolder); 52 | } 53 | } 54 | return directory; 55 | } 56 | 57 | public List getSourceRootPathList(Project project, AnActionEvent event) { 58 | List sourceRoots = Lists.newArrayList(); 59 | String projectPath = StringUtils.normalizePath(project.getBasePath()); 60 | for (VirtualFile virtualFile : getModuleRootManager(event).getSourceRoots(false)) { 61 | sourceRoots.add(StringUtils.normalizePath(virtualFile.getPath()).replace(projectPath, "")); 62 | } 63 | return sourceRoots; 64 | } 65 | 66 | private ModuleRootManager getModuleRootManager(AnActionEvent event) { 67 | return ModuleRootManager.getInstance(event.getData(LangDataKeys.MODULE)); 68 | } 69 | } -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/GenerateDialog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator; 17 | 18 | import com.intellij.ide.util.DefaultPsiElementCellRenderer; 19 | import com.intellij.openapi.ui.DialogWrapper; 20 | import com.intellij.openapi.ui.LabeledComponent; 21 | import com.intellij.psi.PsiClass; 22 | import com.intellij.psi.PsiField; 23 | import com.intellij.psi.PsiModifier; 24 | import com.intellij.psi.search.SearchScope; 25 | import com.intellij.ui.CollectionListModel; 26 | import com.intellij.ui.ToolbarDecorator; 27 | import com.intellij.ui.components.JBList; 28 | import org.jetbrains.annotations.Nullable; 29 | 30 | import javax.lang.model.element.Modifier; 31 | import javax.swing.*; 32 | import java.util.Arrays; 33 | import java.util.List; 34 | 35 | public class GenerateDialog extends DialogWrapper { 36 | 37 | private final LabeledComponent myComponent; 38 | private CollectionListModel myFields; 39 | 40 | protected GenerateDialog(PsiClass psiClass) { 41 | super(psiClass.getProject()); 42 | setTitle("Select Fields for Parcelable Generation"); 43 | 44 | PsiField[] allFields = psiClass.getFields(); 45 | PsiField[] fields = new PsiField[allFields.length]; 46 | 47 | int i = 0; 48 | 49 | for (PsiField field : allFields) { 50 | // Exclude static fields 51 | if (!field.hasModifierProperty(PsiModifier.STATIC)) { 52 | fields[i++] = field; 53 | } 54 | } 55 | 56 | // i is post-incremented, so no need to add 1 for the count 57 | fields = Arrays.copyOfRange(fields, 0, i); 58 | 59 | myFields = new CollectionListModel(fields); 60 | 61 | JBList fieldList = new JBList(myFields); 62 | fieldList.setCellRenderer(new DefaultPsiElementCellRenderer()); 63 | ToolbarDecorator decorator = ToolbarDecorator.createDecorator(fieldList); 64 | decorator.disableAddAction(); 65 | JPanel panel = decorator.createPanel(); 66 | 67 | myComponent = LabeledComponent.create(panel, "Fields to include in Parcelable"); 68 | 69 | init(); 70 | } 71 | 72 | @Nullable 73 | @Override 74 | protected JComponent createCenterPanel() { 75 | return myComponent; 76 | } 77 | 78 | public List getSelectedFields() { 79 | return myFields.getItems(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/ParcelableAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator; 17 | 18 | import com.intellij.openapi.actionSystem.AnAction; 19 | import com.intellij.openapi.actionSystem.AnActionEvent; 20 | import com.intellij.openapi.actionSystem.LangDataKeys; 21 | import com.intellij.openapi.actionSystem.PlatformDataKeys; 22 | import com.intellij.openapi.command.WriteCommandAction; 23 | import com.intellij.openapi.editor.Editor; 24 | import com.intellij.psi.PsiClass; 25 | import com.intellij.psi.PsiElement; 26 | import com.intellij.psi.PsiField; 27 | import com.intellij.psi.PsiFile; 28 | import com.intellij.psi.util.PsiTreeUtil; 29 | 30 | import java.util.List; 31 | 32 | public class ParcelableAction extends AnAction { 33 | 34 | @Override 35 | public void actionPerformed(AnActionEvent e) { 36 | PsiClass psiClass = getPsiClassFromContext(e); 37 | 38 | GenerateDialog dlg = new GenerateDialog(psiClass); 39 | dlg.show(); 40 | 41 | if (dlg.isOK()) { 42 | generateParcelable(psiClass, dlg.getSelectedFields()); 43 | } 44 | } 45 | 46 | private void generateParcelable(final PsiClass psiClass, final List fields) { 47 | new WriteCommandAction.Simple(psiClass.getProject(), psiClass.getContainingFile()) { 48 | @Override 49 | protected void run() throws Throwable { 50 | new CodeGenerator(psiClass, fields).generate(); 51 | } 52 | }.execute(); 53 | } 54 | 55 | 56 | @Override 57 | public void update(AnActionEvent e) { 58 | PsiClass psiClass = getPsiClassFromContext(e); 59 | e.getPresentation().setEnabled(psiClass != null && !psiClass.isEnum() && !psiClass.isInterface()); 60 | } 61 | 62 | private PsiClass getPsiClassFromContext(AnActionEvent e) { 63 | PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE); 64 | Editor editor = e.getData(PlatformDataKeys.EDITOR); 65 | 66 | if (psiFile == null || editor == null) { 67 | return null; 68 | } 69 | 70 | int offset = editor.getCaretModel().getOffset(); 71 | PsiElement element = psiFile.findElementAt(offset); 72 | 73 | return PsiTreeUtil.getParentOfType(element, PsiClass.class); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/BundleSerializerFactory.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.typeserializers; 2 | 3 | import com.intellij.psi.PsiType; 4 | import pl.charmas.parcelablegenerator.typeserializers.serializers.BundleSerializer; 5 | 6 | /** 7 | * Custom serializer factory for Date objects 8 | * 9 | * @author Dallas Gutauckis [dallas@gutauckis.com] 10 | */ 11 | public class BundleSerializerFactory implements TypeSerializerFactory { 12 | private final BundleSerializer mSerializer; 13 | 14 | public BundleSerializerFactory() { 15 | mSerializer = new BundleSerializer(); 16 | } 17 | 18 | @Override 19 | public TypeSerializer getSerializer(PsiType psiType) { 20 | if ("android.os.Bundle".equals(psiType.getCanonicalText())) { 21 | return mSerializer; 22 | } 23 | 24 | return null; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/ChainSerializerFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers; 17 | 18 | import com.intellij.psi.PsiType; 19 | import pl.charmas.parcelablegenerator.typeserializers.serializers.UnknownTypeSerializer; 20 | 21 | import java.util.Arrays; 22 | import java.util.List; 23 | 24 | public class ChainSerializerFactory implements TypeSerializerFactory { 25 | 26 | private final List factories; 27 | 28 | public ChainSerializerFactory(TypeSerializerFactory... factories) { 29 | this.factories = Arrays.asList(factories); 30 | } 31 | 32 | @Override 33 | public TypeSerializer getSerializer(PsiType psiType) { 34 | for (TypeSerializerFactory factory : factories) { 35 | TypeSerializer serializer = factory.getSerializer(psiType); 36 | if (serializer != null) { 37 | return serializer; 38 | } 39 | } 40 | return new UnknownTypeSerializer(psiType.getCanonicalText()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/DateSerializerFactory.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.typeserializers; 2 | 3 | import com.intellij.psi.PsiType; 4 | import pl.charmas.parcelablegenerator.typeserializers.serializers.DateSerializer; 5 | 6 | /** 7 | * Custom serializer factory for Date objects 8 | * 9 | * @author Dallas Gutauckis [dallas@gutauckis.com] 10 | */ 11 | public class DateSerializerFactory implements TypeSerializerFactory { 12 | private final DateSerializer mSerializer; 13 | 14 | public DateSerializerFactory() { 15 | mSerializer = new DateSerializer(); 16 | } 17 | 18 | @Override 19 | public TypeSerializer getSerializer(PsiType psiType) { 20 | if ("java.util.Date".equals(psiType.getCanonicalText())) { 21 | return mSerializer; 22 | } 23 | 24 | return null; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/EnumerationSerializerFactory.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.typeserializers; 2 | 3 | import com.intellij.psi.PsiClassType; 4 | import com.intellij.psi.PsiEnumConstant; 5 | import com.intellij.psi.PsiField; 6 | import com.intellij.psi.PsiType; 7 | import com.intellij.psi.impl.source.PsiClassReferenceType; 8 | import com.intellij.psi.impl.source.PsiEnumConstantImpl; 9 | import pl.charmas.parcelablegenerator.typeserializers.serializers.EnumerationSerializer; 10 | import pl.charmas.parcelablegenerator.util.PsiUtils; 11 | 12 | /** 13 | * Modified by Dallas Gutauckis [dallas@gutauckis.com] 14 | */ 15 | public class EnumerationSerializerFactory implements TypeSerializerFactory { 16 | private TypeSerializer mSerializer = new EnumerationSerializer(); 17 | 18 | @Override 19 | public TypeSerializer getSerializer(PsiType psiType) { 20 | if (psiType instanceof PsiClassReferenceType && ((PsiClassReferenceType) psiType).resolve().isEnum()) { 21 | return mSerializer; 22 | } 23 | 24 | return null; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/ListSerializerFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers; 17 | 18 | import com.intellij.psi.PsiType; 19 | import pl.charmas.parcelablegenerator.typeserializers.serializers.GenericListSerializer; 20 | import pl.charmas.parcelablegenerator.util.PsiUtils; 21 | 22 | public class ListSerializerFactory implements TypeSerializerFactory { 23 | private TypeSerializer mSerializer = new GenericListSerializer(); 24 | 25 | @Override 26 | public TypeSerializer getSerializer(PsiType psiType) { 27 | if (PsiUtils.isOfType(psiType, "java.util.List")) { 28 | return mSerializer; 29 | } 30 | 31 | return null; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/ParcelableSerializerFactory.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.typeserializers; 2 | 3 | import com.intellij.psi.PsiType; 4 | import pl.charmas.parcelablegenerator.typeserializers.serializers.ParcelableArraySerializer; 5 | import pl.charmas.parcelablegenerator.typeserializers.serializers.ParcelableListSerializer; 6 | import pl.charmas.parcelablegenerator.typeserializers.serializers.ParcelableObjectSerializer; 7 | import pl.charmas.parcelablegenerator.util.PsiUtils; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Serializer factory for Parcelable objects 13 | * 14 | * @author Dallas Gutauckis [dallas@gutauckis.com] 15 | * @author Michał Charmas [micha@charmas.pl] 16 | */ 17 | public class ParcelableSerializerFactory implements TypeSerializerFactory { 18 | private TypeSerializer mSerializer = new ParcelableObjectSerializer(); 19 | private TypeSerializer listSerializer = new ParcelableListSerializer(); 20 | private TypeSerializer arraySerializer = new ParcelableArraySerializer(); 21 | 22 | @Override 23 | public TypeSerializer getSerializer(PsiType psiType) { 24 | if (PsiUtils.isOfType(psiType, "android.os.Parcelable[]")) { 25 | return arraySerializer; 26 | } 27 | 28 | if (PsiUtils.isOfType(psiType, "android.os.Parcelable")) { 29 | return mSerializer; 30 | } 31 | 32 | if (PsiUtils.isOfType(psiType, "java.util.List")) { 33 | List resolvedGenerics = PsiUtils.getResolvedGenerics(psiType); 34 | for (PsiType resolvedGeneric : resolvedGenerics) { 35 | if (PsiUtils.isOfType(resolvedGeneric, "android.os.Parcelable")) { 36 | return listSerializer; 37 | } 38 | } 39 | } 40 | 41 | return null; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/PrimitiveArraySerializerFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers; 17 | 18 | import com.intellij.psi.PsiType; 19 | import pl.charmas.parcelablegenerator.typeserializers.serializers.BooleanSparseArraySerializer; 20 | import pl.charmas.parcelablegenerator.typeserializers.serializers.PrimitiveArraySerializer; 21 | 22 | import java.util.HashMap; 23 | 24 | public class PrimitiveArraySerializerFactory implements TypeSerializerFactory { 25 | private final HashMap handledTypes; 26 | 27 | public PrimitiveArraySerializerFactory() { 28 | handledTypes = new HashMap(); 29 | handledTypes.put("boolean[]", new PrimitiveArraySerializer("Boolean")); 30 | handledTypes.put("byte[]", new PrimitiveArraySerializer("Byte")); 31 | handledTypes.put("char[]", new PrimitiveArraySerializer("Char")); 32 | handledTypes.put("double[]", new PrimitiveArraySerializer("Double")); 33 | handledTypes.put("float[]", new PrimitiveArraySerializer("Float")); 34 | handledTypes.put("int[]", new PrimitiveArraySerializer("Int")); 35 | handledTypes.put("long[]", new PrimitiveArraySerializer("Long")); 36 | handledTypes.put("java.lang.String[]", new PrimitiveArraySerializer("String")); 37 | handledTypes.put("android.util.SparseBooleanArray", new BooleanSparseArraySerializer()); 38 | } 39 | 40 | @Override 41 | public TypeSerializer getSerializer(PsiType psiType) { 42 | return handledTypes.get(psiType.getCanonicalText()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/PrimitiveTypeSerializerFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers; 17 | 18 | import com.intellij.psi.PsiType; 19 | import pl.charmas.parcelablegenerator.typeserializers.serializers.BooleanPrimitiveSerializer; 20 | import pl.charmas.parcelablegenerator.typeserializers.serializers.CharPrimitiveSerializer; 21 | import pl.charmas.parcelablegenerator.typeserializers.serializers.NullablePrimitivesSerializer; 22 | import pl.charmas.parcelablegenerator.typeserializers.serializers.PrimitiveTypeSerializer; 23 | 24 | import java.util.HashMap; 25 | import java.util.Map; 26 | 27 | public class PrimitiveTypeSerializerFactory implements TypeSerializerFactory { 28 | 29 | private final Map writeMethodsForTypes = new HashMap(); 30 | 31 | public PrimitiveTypeSerializerFactory() { 32 | initPrimitives(); 33 | initNullablePrimitives(); 34 | } 35 | 36 | private void initNullablePrimitives() { 37 | writeMethodsForTypes.put("byte", new PrimitiveTypeSerializer("Byte")); 38 | writeMethodsForTypes.put("double", new PrimitiveTypeSerializer("Double")); 39 | writeMethodsForTypes.put("float", new PrimitiveTypeSerializer("Float")); 40 | writeMethodsForTypes.put("int", new PrimitiveTypeSerializer("Int")); 41 | writeMethodsForTypes.put("long", new PrimitiveTypeSerializer("Long")); 42 | writeMethodsForTypes.put("java.lang.String", new PrimitiveTypeSerializer("String")); 43 | writeMethodsForTypes.put("boolean", new BooleanPrimitiveSerializer()); 44 | writeMethodsForTypes.put("char", new CharPrimitiveSerializer()); 45 | } 46 | 47 | private void initPrimitives() { 48 | writeMethodsForTypes.put("java.lang.Byte", new NullablePrimitivesSerializer("java.lang.Byte")); 49 | writeMethodsForTypes.put("java.lang.Double", new NullablePrimitivesSerializer("java.lang.Double")); 50 | writeMethodsForTypes.put("java.lang.Float", new NullablePrimitivesSerializer("java.lang.Float")); 51 | writeMethodsForTypes.put("java.lang.Integer", new NullablePrimitivesSerializer("java.lang.Integer")); 52 | writeMethodsForTypes.put("java.lang.Long", new NullablePrimitivesSerializer("java.lang.Long")); 53 | writeMethodsForTypes.put("java.lang.Boolean", new NullablePrimitivesSerializer("java.lang.Boolean")); 54 | writeMethodsForTypes.put("java.lang.Char", new NullablePrimitivesSerializer("java.lang.Char")); 55 | } 56 | 57 | @Override 58 | public TypeSerializer getSerializer(PsiType psiType) { 59 | return writeMethodsForTypes.get(psiType.getCanonicalText()); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/SerializableSerializerFactory.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.typeserializers; 2 | 3 | import com.intellij.psi.PsiType; 4 | import pl.charmas.parcelablegenerator.typeserializers.serializers.SerializableObjectSerializer; 5 | 6 | /** 7 | * Modified by Dallas Gutauckis [dallas@gutauckis.com] 8 | */ 9 | public class SerializableSerializerFactory implements TypeSerializerFactory { 10 | private TypeSerializer mSerializer; 11 | 12 | public SerializableSerializerFactory() { 13 | mSerializer = new SerializableObjectSerializer(); 14 | } 15 | 16 | @Override 17 | public TypeSerializer getSerializer(PsiType psiType) { 18 | PsiType[] superTypes = psiType.getSuperTypes(); 19 | 20 | for (PsiType superType : superTypes) { 21 | String canonicalText = superType.getCanonicalText(); 22 | 23 | if ("java.io.Serializable".equals(canonicalText)) { 24 | return mSerializer; 25 | } 26 | } 27 | 28 | return null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/TypeSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers; 17 | 18 | import com.intellij.psi.PsiField; 19 | 20 | public interface TypeSerializer { 21 | 22 | String writeValue(PsiField field, String parcel, String flags); 23 | 24 | String readValue(PsiField field, String parcel); 25 | } 26 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/TypeSerializerFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers; 17 | 18 | import com.intellij.psi.PsiType; 19 | 20 | public interface TypeSerializerFactory { 21 | public TypeSerializer getSerializer(PsiType psiType); 22 | } 23 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/BooleanPrimitiveSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 17 | 18 | import com.intellij.psi.PsiField; 19 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 20 | 21 | public class BooleanPrimitiveSerializer implements TypeSerializer { 22 | 23 | @Override 24 | public String writeValue(PsiField field, String parcel, String flags) { 25 | return parcel + ".writeByte(" + field.getName() + " ? (byte) 1 : (byte) 0);"; 26 | } 27 | 28 | @Override 29 | public String readValue(PsiField field, String parcel) { 30 | return "this." + field.getName() + " = " + parcel + ".readByte() != 0;"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/BooleanSparseArraySerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 17 | 18 | import com.intellij.psi.PsiField; 19 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 20 | 21 | public class BooleanSparseArraySerializer implements TypeSerializer { 22 | 23 | @Override 24 | public String writeValue(PsiField field, String parcel, String flags) { 25 | return parcel + ".writeSparseBooleanArray(this." + field.getName() + ");"; 26 | } 27 | 28 | @Override 29 | public String readValue(PsiField field, String parcel) { 30 | return "this." + field.getName() + " = " + parcel + ".readSparseBooleanArray();"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/BundleSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 17 | 18 | import com.intellij.psi.PsiField; 19 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 20 | 21 | /** 22 | * Custom serializer for Date objects to simplify parceling 23 | * 24 | * @author Dallas Gutauckis [dallas@gutauckis.com] 25 | */ 26 | public class BundleSerializer implements TypeSerializer { 27 | 28 | private static final String NULL_VALUE = "-1"; 29 | 30 | @Override 31 | public String writeValue(PsiField field, String parcel, String flags) { 32 | return parcel + ".writeBundle(" + field.getName() + ");"; 33 | } 34 | 35 | @Override 36 | public String readValue(PsiField field, String parcel) { 37 | return field.getName() + " = " + parcel + ".readBundle();"; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/CharPrimitiveSerializer.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 2 | 3 | import com.intellij.psi.PsiField; 4 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 5 | 6 | public class CharPrimitiveSerializer implements TypeSerializer { 7 | @Override 8 | public String writeValue(PsiField field, String parcel, String flags) { 9 | return parcel + ".writeInt(" + field.getName() + ");"; 10 | } 11 | 12 | @Override 13 | public String readValue(PsiField field, String parcel) { 14 | return "this." + field.getName() + " = (char) " + parcel + ".readInt();"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/DateSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 17 | 18 | import com.intellij.psi.PsiField; 19 | import org.apache.xmlbeans.impl.common.NameUtil; 20 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 21 | 22 | /** 23 | * Custom serializer for Date objects to simplify parceling 24 | * 25 | * @author Dallas Gutauckis [dallas@gutauckis.com] 26 | */ 27 | public class DateSerializer implements TypeSerializer { 28 | 29 | private static final String NULL_VALUE = "-1"; 30 | 31 | @Override 32 | public String writeValue(PsiField field, String parcel, String flags) { 33 | String fieldName = field.getName(); 34 | return String.format("%s.writeLong(%s != null ? %s.getTime() : %s);", parcel, fieldName, fieldName, NULL_VALUE); 35 | } 36 | 37 | @Override 38 | public String readValue(PsiField field, String parcel) { 39 | String fieldName = field.getName(); 40 | String tmpFieldName = NameUtil.upperCaseFirstLetter(fieldName); 41 | String formatted = String.format("long tmp%s = %s.readLong(); " + 42 | "this.%s = tmp%s == %s ? null : new java.util.Date(tmp%s);", tmpFieldName, parcel, fieldName, tmpFieldName, NULL_VALUE, tmpFieldName); 43 | return formatted; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/EnumerationSerializer.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 2 | 3 | import com.intellij.psi.PsiField; 4 | import org.apache.xmlbeans.impl.common.NameUtil; 5 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 6 | 7 | /** 8 | * Modified by Dallas Gutauckis [dallas@gutauckis.com] 9 | */ 10 | public class EnumerationSerializer implements TypeSerializer { 11 | @Override 12 | public String writeValue(PsiField field, String parcel, String flags) { 13 | String fieldName = field.getName(); 14 | return String.format("%s.writeInt(this.%s == null ? -1 : this.%s.ordinal());", parcel, fieldName, fieldName); 15 | } 16 | 17 | @Override 18 | public String readValue(PsiField field, String parcel) { 19 | String fieldName = field.getName(); 20 | String tmpFieldName = NameUtil.upperCaseFirstLetter(fieldName); 21 | String format = "int tmp%s = %s.readInt();" 22 | + "this.%s = tmp%s == -1 ? null : %s.values()[tmp%s];"; 23 | return String.format(format, tmpFieldName, parcel, fieldName, tmpFieldName, field.getType().getCanonicalText(), tmpFieldName); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/GenericListSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 17 | 18 | import com.intellij.psi.PsiField; 19 | import com.intellij.psi.PsiType; 20 | import com.intellij.psi.impl.source.PsiClassReferenceType; 21 | import org.jetbrains.annotations.NotNull; 22 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 23 | 24 | public class GenericListSerializer implements TypeSerializer { 25 | 26 | public static final String STRING_TYPE_NAME = "java.lang.String"; 27 | 28 | @Override 29 | public String writeValue(PsiField field, String parcel, String flags) { 30 | String method = "writeList"; 31 | if (getGenericType(field).equals(STRING_TYPE_NAME)) { 32 | method = "writeStringList"; 33 | } 34 | return parcel + "." + method + "(this." + field.getName() + ");"; 35 | } 36 | 37 | @Override 38 | public String readValue(PsiField field, String parcel) { 39 | String genericType = getGenericType(field); 40 | 41 | StringBuilder statement = new StringBuilder(); 42 | if (genericType.equals(STRING_TYPE_NAME)) { 43 | statement.append("this.").append(field.getName()).append("=").append(parcel).append(".createStringArrayList();"); 44 | } else { 45 | String listConstructor = !genericType.isEmpty() 46 | ? "new java.util.ArrayList<" + genericType + ">();" 47 | : "new java.util.ArrayList();"; 48 | 49 | statement.append("this.").append(field.getName()).append(" = ").append(listConstructor); 50 | statement.append(parcel).append(".readList(this.").append(field.getName()).append(", List.class.getClassLoader());"); 51 | } 52 | 53 | return statement.toString(); 54 | } 55 | 56 | @NotNull 57 | private String getGenericType(PsiField field) { 58 | String genericType = ""; 59 | try { 60 | PsiType[] parameters = ((PsiClassReferenceType) field.getType()).getParameters(); 61 | if (parameters.length > 0) { 62 | genericType = parameters[0].getCanonicalText(); 63 | } 64 | } catch (Exception ignored) { 65 | } 66 | return genericType; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/NullablePrimitivesSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 17 | 18 | import com.intellij.psi.PsiField; 19 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 20 | 21 | public class NullablePrimitivesSerializer implements TypeSerializer { 22 | 23 | private final String typeName; 24 | 25 | public NullablePrimitivesSerializer(String typeName) { 26 | this.typeName = typeName; 27 | } 28 | 29 | @Override 30 | public String writeValue(PsiField field, String parcel, String flags) { 31 | return parcel + ".writeValue(this." + field.getName() + ");"; 32 | } 33 | 34 | @Override 35 | public String readValue(PsiField field, String parcel) { 36 | return "this." + field.getName() + " = (" + typeName + ")" + parcel + ".readValue(" + typeName + ".class.getClassLoader());"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/ParcelableArraySerializer.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 2 | 3 | import com.intellij.psi.PsiField; 4 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 5 | 6 | public class ParcelableArraySerializer implements TypeSerializer { 7 | @Override 8 | public String writeValue(PsiField field, String parcel, String flags) { 9 | return parcel + ".writeParcelableArray(this." + field.getName() + ", 0);"; 10 | } 11 | 12 | @Override 13 | public String readValue(PsiField field, String parcel) { 14 | return "this." + field.getName() + " = (" + field.getType().getCanonicalText() + ")" + parcel + ".readParcelableArray(" + field.getType().getDeepComponentType().getCanonicalText() + ".class.getClassLoader());"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/ParcelableListSerializer.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 2 | 3 | import com.intellij.psi.PsiField; 4 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 5 | import pl.charmas.parcelablegenerator.util.PsiUtils; 6 | 7 | /** 8 | * @author Dallas Gutauckis [dallas@gutauckis.com] 9 | * @author Michał Charmas [michal@charmas.pl] 10 | */ 11 | public class ParcelableListSerializer implements TypeSerializer { 12 | @Override 13 | public String writeValue(PsiField field, String parcel, String flags) { 14 | return String.format("%s.writeTypedList(%s);", parcel, field.getName()); 15 | } 16 | 17 | @Override 18 | public String readValue(PsiField field, String parcel) { 19 | String paramType = PsiUtils.getResolvedGenerics(field.getType()).get(0).getCanonicalText(); 20 | return String.format("this.%s = %s.createTypedArrayList(%s.CREATOR);", field.getName(), parcel, paramType); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/ParcelableObjectSerializer.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 2 | 3 | import com.intellij.psi.PsiField; 4 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 5 | 6 | /** 7 | * Serializer for types implementing Parcelable 8 | * 9 | * @author Dallas Gutauckis [dallas@gutauckis.com] 10 | */ 11 | public class ParcelableObjectSerializer implements TypeSerializer { 12 | @Override 13 | public String writeValue(PsiField field, String parcel, String flags) { 14 | return parcel + ".writeParcelable(this." + field.getName() + ", 0);"; 15 | } 16 | 17 | @Override 18 | public String readValue(PsiField field, String parcel) { 19 | return "this." + field.getName() + " = " + parcel + ".readParcelable(" + field.getType().getCanonicalText() + ".class.getClassLoader());"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/PrimitiveArraySerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 17 | 18 | import com.intellij.psi.PsiField; 19 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 20 | 21 | public class PrimitiveArraySerializer implements TypeSerializer { 22 | 23 | private final String type; 24 | 25 | public PrimitiveArraySerializer(String type) { 26 | this.type = type; 27 | } 28 | 29 | @Override 30 | public String writeValue(PsiField field, String parcel, String flags) { 31 | return parcel + ".write" + type + "Array(this." + field.getName() + ");"; 32 | } 33 | 34 | @Override 35 | public String readValue(PsiField field, String parcel) { 36 | return "this." + field.getName() + " = " + parcel + ".create" + type + "Array();"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/PrimitiveTypeSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 17 | 18 | import com.intellij.psi.PsiField; 19 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 20 | 21 | public class PrimitiveTypeSerializer implements TypeSerializer { 22 | 23 | private final String typeName; 24 | 25 | public PrimitiveTypeSerializer(String typeName) { 26 | this.typeName = typeName; 27 | } 28 | 29 | @Override 30 | public String writeValue(PsiField field, String parcel, String flags) { 31 | return parcel + ".write" + typeName + "(this." + field.getName() + ");"; 32 | } 33 | 34 | @Override 35 | public String readValue(PsiField field, String parcel) { 36 | return "this." + field.getName() + " = " + parcel + ".read" + typeName + "();"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/SerializableObjectSerializer.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 2 | 3 | import com.intellij.psi.PsiField; 4 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 5 | 6 | /** 7 | * Modified by Dallas Gutauckis [dallas@gutauckis.com] 8 | */ 9 | public class SerializableObjectSerializer implements TypeSerializer { 10 | @Override 11 | public String writeValue(PsiField field, String parcel, String flags) { 12 | return parcel + ".writeSerializable(this." + field.getName() + ");"; 13 | } 14 | 15 | @Override 16 | public String readValue(PsiField field, String parcel) { 17 | return "this." + field.getName() + " = (" + field.getType().getCanonicalText() + ") " + parcel + ".readSerializable();"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/typeserializers/serializers/UnknownTypeSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Michał Charmas (http://blog.charmas.pl) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package pl.charmas.parcelablegenerator.typeserializers.serializers; 17 | 18 | import com.intellij.psi.PsiField; 19 | import pl.charmas.parcelablegenerator.typeserializers.TypeSerializer; 20 | 21 | public class UnknownTypeSerializer implements TypeSerializer { 22 | 23 | private final String typeName; 24 | 25 | public UnknownTypeSerializer(String typeName) { 26 | this.typeName = typeName; 27 | } 28 | 29 | @Override 30 | public String writeValue(PsiField field, String parcel, String flags) { 31 | return parcel + ".writeParcelable(this." + field.getName() + ", " + flags + ");"; 32 | } 33 | 34 | @Override 35 | public String readValue(PsiField field, String parcel) { 36 | return "this." + field.getName() + " = " + parcel + ".readParcelable(" + this.typeName + ".class.getClassLoader());"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /android_parcelable_intellij_plugin/pl/charmas/parcelablegenerator/util/PsiUtils.java: -------------------------------------------------------------------------------- 1 | package pl.charmas.parcelablegenerator.util; 2 | 3 | import com.intellij.psi.PsiClass; 4 | import com.intellij.psi.PsiClassType; 5 | import com.intellij.psi.PsiType; 6 | import com.intellij.psi.util.PsiTypesUtil; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * Utils for introspecting Psi* stuff 13 | * 14 | * @author Dallas Gutauckis [dallas@gutauckis.com] 15 | */ 16 | final public class PsiUtils { 17 | private PsiUtils() { 18 | } 19 | 20 | /** 21 | * Resolves generics on the given type and returns them (if any) or null if there are none 22 | * 23 | * @param type 24 | * @return 25 | */ 26 | public static List getResolvedGenerics(PsiType type) { 27 | List psiTypes = null; 28 | 29 | if (type instanceof PsiClassType) { 30 | PsiClassType pct = (PsiClassType) type; 31 | psiTypes = new ArrayList(pct.resolveGenerics().getSubstitutor().getSubstitutionMap().values()); 32 | } 33 | 34 | return psiTypes; 35 | } 36 | 37 | public static boolean isOfType(PsiType type, String canonicalName) { 38 | if (type.getCanonicalText().equals(canonicalName)) { 39 | return true; 40 | } 41 | 42 | if (getNonGenericType(type).equals(canonicalName)) { 43 | return true; 44 | } 45 | 46 | for (PsiType iterType : type.getSuperTypes()) { 47 | if (isOfType(iterType, canonicalName)) { 48 | return true; 49 | } 50 | } 51 | 52 | return false; 53 | } 54 | 55 | public static String getNonGenericType(PsiType type) { 56 | if (type instanceof PsiClassType) { 57 | PsiClassType pct = (PsiClassType) type; 58 | return pct.resolve().getQualifiedName(); 59 | } 60 | 61 | return type.getCanonicalText(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /android_selector_chapek/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Inmite s.r.o. (www.inmite.eu). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import java.util.HashMap; 18 | import java.util.regex.Pattern; 19 | 20 | /** 21 | * Constants for various stuff used in whole plugin. 22 | * @author David Vávra (david@inmite.eu) 23 | */ 24 | public class Constants { 25 | public static final String NORMAL = "_normal"; 26 | public static final String FOCUSED = "_focused"; 27 | public static final String PRESSED = "_pressed"; 28 | public static final String SELECTED = "_selected"; 29 | public static final String CHECKED = "_checked"; 30 | public static final String DISABLED = "_disabled"; 31 | public static final String HOVERED = "_hovered"; 32 | public static final String CHECKABLE = "_checkable"; 33 | public static final String ACTIVATED = "_activated"; 34 | public static final String WINDOW_FOCUSED = "_windowfocused"; 35 | public static String[] SUFFIXES = new String[]{NORMAL, PRESSED, FOCUSED, SELECTED, CHECKED, DISABLED, HOVERED, CHECKABLE, ACTIVATED, WINDOW_FOCUSED}; 36 | public static Pattern VALID_FOLDER_PATTERN = Pattern.compile("^drawable(-[a-zA-Z0-9]+)*$"); 37 | public static String EXPORT_FOLDER = "drawable"; 38 | public static HashMap sMapping; 39 | 40 | static { 41 | // mapping from file suffixes into android attributes and their default values 42 | sMapping = new HashMap(); 43 | sMapping.put(FOCUSED, new State("state_focused", false)); 44 | sMapping.put(PRESSED, new State("state_pressed", false)); 45 | sMapping.put(SELECTED, new State("state_selected", false)); 46 | sMapping.put(CHECKED, new State("state_checked", false)); 47 | sMapping.put(DISABLED, new State("state_enabled", true)); 48 | sMapping.put(HOVERED, new State("state_hovered", false)); 49 | sMapping.put(CHECKABLE, new State("state_checkable", false)); 50 | sMapping.put(ACTIVATED, new State("state_activated", false)); 51 | sMapping.put(WINDOW_FOCUSED, new State("state_window_focused", false)); 52 | } 53 | 54 | static class State { 55 | public String attributeName; 56 | public boolean defaultValue; 57 | 58 | State(String attributeName, boolean defaultValue) { 59 | this.attributeName = attributeName; 60 | this.defaultValue = defaultValue; 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /android_selector_chapek/SelectorChapekAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Inmite s.r.o. (www.inmite.eu). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import com.intellij.openapi.actionSystem.AnAction; 18 | import com.intellij.openapi.actionSystem.AnActionEvent; 19 | import com.intellij.openapi.actionSystem.DataKeys; 20 | import com.intellij.openapi.ui.MessageType; 21 | import com.intellij.openapi.ui.popup.Balloon; 22 | import com.intellij.openapi.ui.popup.JBPopupFactory; 23 | import com.intellij.openapi.vfs.VirtualFile; 24 | import com.intellij.openapi.wm.StatusBar; 25 | import com.intellij.openapi.wm.WindowManager; 26 | import com.intellij.ui.awt.RelativePoint; 27 | import utils.Log; 28 | 29 | import java.util.regex.Matcher; 30 | 31 | /** 32 | * Action which is launched when user clicks the menu item. It handles related UI-stuff. 33 | * 34 | * @author David Vávra (david@inmite.eu) 35 | */ 36 | public class SelectorChapekAction extends AnAction { 37 | 38 | @Override 39 | public void actionPerformed(AnActionEvent e) { 40 | Log.d("---- Start - menu item clicked ----"); 41 | VirtualFile selectedFile = DataKeys.VIRTUAL_FILE.getData(e.getDataContext()); 42 | if (isCorrectFolderSelected(selectedFile)) { 43 | new SelectorDetector(e.getProject()).detectAndCreateSelectors(selectedFile); 44 | showInfoDialog("Selectors were generated into 'drawable' folder", e); 45 | } else { 46 | if (selectedFile != null) { 47 | showErrorDialog("You need to select folder with image resources, for example 'drawables-xhdpi' " + 48 | "" + selectedFile.getName(), e); 49 | } 50 | } 51 | } 52 | 53 | @Override 54 | public void update(AnActionEvent e) { 55 | VirtualFile selectedFile = DataKeys.VIRTUAL_FILE.getData(e.getDataContext()); 56 | e.getPresentation().setEnabled(isCorrectFolderSelected(selectedFile)); 57 | } 58 | 59 | private boolean isCorrectFolderSelected(VirtualFile selectedFile) { 60 | if (selectedFile != null && selectedFile.isDirectory()) { 61 | Matcher matcher = Constants.VALID_FOLDER_PATTERN.matcher(selectedFile.getName()); 62 | if (matcher.matches()) { 63 | return true; 64 | } 65 | } 66 | return false; 67 | } 68 | 69 | private void showInfoDialog(String text, AnActionEvent e) { 70 | StatusBar statusBar = WindowManager.getInstance().getStatusBar(DataKeys.PROJECT.getData(e.getDataContext())); 71 | 72 | if (statusBar != null) { 73 | JBPopupFactory.getInstance() 74 | .createHtmlTextBalloonBuilder(text, MessageType.INFO, null) 75 | .setFadeoutTime(10000) 76 | .createBalloon() 77 | .show(RelativePoint.getCenterOf(statusBar.getComponent()), 78 | Balloon.Position.atRight); 79 | } 80 | } 81 | 82 | private void showErrorDialog(String text, AnActionEvent e) { 83 | StatusBar statusBar = WindowManager.getInstance().getStatusBar(DataKeys.PROJECT.getData(e.getDataContext() 84 | )); 85 | 86 | if (statusBar != null) { 87 | JBPopupFactory.getInstance() 88 | .createHtmlTextBalloonBuilder(text, MessageType.ERROR, null) 89 | .setFadeoutTime(10000) 90 | .createBalloon() 91 | .show(RelativePoint.getCenterOf(statusBar.getComponent()), 92 | Balloon.Position.atRight); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /android_selector_chapek/SelectorGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Inmite s.r.o. (www.inmite.eu). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import com.intellij.openapi.vfs.VirtualFile; 18 | import nu.xom.Attribute; 19 | import nu.xom.Document; 20 | import nu.xom.Element; 21 | import nu.xom.Serializer; 22 | import utils.Log; 23 | 24 | import java.io.IOException; 25 | import java.io.OutputStream; 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | /** 30 | * Generates selectors into XML. 31 | * 32 | * @author David Vávra (david@inmite.eu) 33 | */ 34 | public class SelectorGenerator { 35 | 36 | private static final String SCHEMA = "http://schemas.android.com/apk/res/android"; 37 | private static final String NS = "android"; 38 | 39 | public static void generate(VirtualFile newFile, List detectorResults) { 40 | Log.d("generating XML:"); 41 | Element root = new Element("selector"); 42 | root.addNamespaceDeclaration(NS, SCHEMA); 43 | List allStatesWithoutNormal = new ArrayList(); 44 | for (SelectorDetector.Result result : detectorResults) { 45 | for (String state : result.states) { 46 | if (!state.equals(Constants.NORMAL) && !allStatesWithoutNormal.contains(state)) { 47 | allStatesWithoutNormal.add(state); 48 | } 49 | } 50 | } 51 | for (SelectorDetector.Result result : detectorResults) { 52 | Log.d("fileName=" + result.drawableName + ", states:" + result.states); 53 | Element item = new Element("item"); 54 | Attribute attribute = new Attribute("drawable", "@drawable/" + result.drawableName); 55 | attribute.setNamespace(NS, SCHEMA); 56 | item.addAttribute(attribute); 57 | for (String state : allStatesWithoutNormal) { 58 | boolean defaultValue = Constants.sMapping.get(state).defaultValue; 59 | addState(item, Constants.sMapping.get(state).attributeName, result.states.contains(state) 60 | ? (!defaultValue) : defaultValue); 61 | } 62 | Log.d("row=" + item.toXML()); 63 | root.appendChild(item); 64 | } 65 | Document doc = new Document(root); 66 | OutputStream os = null; 67 | try { 68 | os = newFile.getOutputStream(null); 69 | Serializer serializer = new Serializer(os); 70 | serializer.setIndent(4); 71 | serializer.write(doc); 72 | } catch (IOException e) { 73 | Log.e(e); 74 | } finally { 75 | if (os != null) { 76 | try { 77 | os.close(); 78 | } catch (IOException e) { 79 | Log.e(e); 80 | } 81 | } 82 | } 83 | 84 | } 85 | 86 | private static void addState(Element item, String state, boolean value) { 87 | Attribute attribute = new Attribute(state, String.valueOf(value)); 88 | attribute.setNamespace(NS, SCHEMA); 89 | item.addAttribute(attribute); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /android_selector_chapek/utils/Log.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | /** 4 | * Copyright (c) 2013, Inmite s.r.o. (www.inmite.eu). All rights reserved. 5 | *

6 | * This source code can be used only for purposes specified by the given license contract 7 | * signed by the rightful deputy of Inmite s.r.o. This source code can be used only 8 | * by the owner of the license. 9 | *

10 | * Any disputes arising in respect of this agreement (license) shall be brought 11 | * before the Municipal Court of Prague. 12 | */ 13 | public class Log { 14 | public static final boolean DEBUG = false; 15 | 16 | public static void d(String output) { 17 | if (DEBUG) { 18 | System.out.println(output); 19 | } 20 | } 21 | 22 | public static void e(Exception e) { 23 | e.printStackTrace(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /android_selector_chapek/utils/RunnableHelper.java: -------------------------------------------------------------------------------- 1 | package utils;/* 2 | * Copyright 2013 Inmite s.r.o. (www.inmite.eu). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import com.intellij.openapi.application.ApplicationManager; 17 | import com.intellij.openapi.command.CommandProcessor; 18 | import com.intellij.openapi.project.Project; 19 | 20 | /** 21 | * Helper class for launching filesystem write operations on background. 22 | * @author David Vávra (david@inmite.eu) 23 | */ 24 | public class RunnableHelper 25 | { 26 | public static void runReadCommand(Project project, Runnable cmd) 27 | { 28 | CommandProcessor.getInstance().executeCommand(project, new ReadAction(cmd), "Foo", "Bar"); 29 | } 30 | 31 | public static void runWriteCommand(Project project, Runnable cmd) 32 | { 33 | CommandProcessor.getInstance().executeCommand(project, new WriteAction(cmd), "Foo", "Bar"); 34 | } 35 | 36 | static class ReadAction implements Runnable 37 | { 38 | ReadAction(Runnable cmd) 39 | { 40 | this.cmd = cmd; 41 | } 42 | 43 | public void run() 44 | { 45 | ApplicationManager.getApplication().runReadAction(cmd); 46 | } 47 | 48 | Runnable cmd; 49 | } 50 | 51 | static class WriteAction implements Runnable 52 | { 53 | WriteAction(Runnable cmd) 54 | { 55 | this.cmd = cmd; 56 | } 57 | 58 | public void run() 59 | { 60 | ApplicationManager.getApplication().runWriteAction(cmd); 61 | } 62 | 63 | Runnable cmd; 64 | } 65 | 66 | private RunnableHelper() {} 67 | } 68 | -------------------------------------------------------------------------------- /folding_plugin/com/dd/ComposeAction.java: -------------------------------------------------------------------------------- 1 | package com.dd; 2 | 3 | import com.intellij.ide.projectView.ProjectView; 4 | import com.intellij.openapi.actionSystem.AnAction; 5 | import com.intellij.openapi.actionSystem.AnActionEvent; 6 | import com.intellij.openapi.actionSystem.CommonDataKeys; 7 | import com.intellij.openapi.project.Project; 8 | import com.intellij.psi.PsiDirectory; 9 | 10 | public class ComposeAction extends AnAction { 11 | 12 | private static final String DECOMPOSE = "Ungroup"; 13 | private static final String COMPOSE = "Group"; 14 | 15 | @Override 16 | public void actionPerformed(AnActionEvent actionEvent) { 17 | Object nav = actionEvent.getData(CommonDataKeys.NAVIGATABLE); 18 | if (nav instanceof PsiDirectory) { 19 | PsiDirectory directory = (PsiDirectory) nav; 20 | 21 | String path = directory.getVirtualFile().getPath(); 22 | 23 | if (SettingsManager.isComposed(path)) { 24 | SettingsManager.removeComposedFolder(path); 25 | } else { 26 | SettingsManager.addComposedFolder(path); 27 | } 28 | 29 | Project project = actionEvent.getData(CommonDataKeys.PROJECT); 30 | if (project != null) { 31 | ProjectView.getInstance(project).refresh(); 32 | } 33 | } 34 | } 35 | 36 | @Override 37 | public void update(AnActionEvent actionEvent) { 38 | boolean enabledAndVisible = false; 39 | Project project = actionEvent.getData(CommonDataKeys.PROJECT); 40 | if (project != null) { 41 | Object nav = actionEvent.getData(CommonDataKeys.NAVIGATABLE); 42 | 43 | if (nav instanceof PsiDirectory) { 44 | PsiDirectory directory = (PsiDirectory) nav; 45 | 46 | String path = directory.getVirtualFile().getPath(); 47 | 48 | if (SettingsManager.isComposed(path)) { 49 | actionEvent.getPresentation().setText(DECOMPOSE); 50 | } else { 51 | actionEvent.getPresentation().setText(COMPOSE); 52 | } 53 | 54 | enabledAndVisible = true; 55 | } 56 | } 57 | actionEvent.getPresentation().setEnabledAndVisible(enabledAndVisible); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /folding_plugin/com/dd/DirectoryNode.java: -------------------------------------------------------------------------------- 1 | package com.dd; 2 | 3 | import com.intellij.icons.AllIcons; 4 | import com.intellij.ide.projectView.PresentationData; 5 | import com.intellij.ide.projectView.ProjectViewNode; 6 | import com.intellij.ide.projectView.ViewSettings; 7 | import com.intellij.ide.projectView.impl.nodes.PsiFileNode; 8 | import com.intellij.ide.util.PropertiesComponent; 9 | import com.intellij.ide.util.treeView.AbstractTreeNode; 10 | import com.intellij.openapi.project.Project; 11 | import com.intellij.openapi.vfs.VirtualFile; 12 | import com.intellij.psi.PsiFile; 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | public class DirectoryNode extends ProjectViewNode { 19 | 20 | private final String mName; 21 | private List mChildNodeList; 22 | 23 | protected DirectoryNode(Project project, ViewSettings viewSettings, PsiFile directory, String name) { 24 | super(project, directory, viewSettings); 25 | mName = name; 26 | mChildNodeList = new ArrayList(); 27 | } 28 | 29 | @Override 30 | public boolean contains(@NotNull VirtualFile file) { 31 | for (final AbstractTreeNode childNode : mChildNodeList) { 32 | ProjectViewNode treeNode = (ProjectViewNode) childNode; 33 | if (treeNode.contains(file)) { 34 | return true; 35 | } 36 | } 37 | return false; 38 | } 39 | 40 | public void addChildren(AbstractTreeNode treeNode) { 41 | mChildNodeList.add(treeNode); 42 | } 43 | 44 | public void addAllChildren(List treeNodeList) { 45 | mChildNodeList.addAll(treeNodeList); 46 | } 47 | 48 | @NotNull 49 | @Override 50 | public List getChildren() { 51 | if (PropertiesComponent.getInstance().getBoolean(SettingConfigurable.PREFIX_HIDE, false)) { 52 | final ArrayList abstractTreeNodes = new ArrayList<>(); 53 | for (AbstractTreeNode fileNode : mChildNodeList) { 54 | PsiFile psiFile = (PsiFile) fileNode.getValue(); 55 | final ViewSettings settings = ((PsiFileNode) fileNode).getSettings(); 56 | String shortName = psiFile.getName().substring(mName.length()); 57 | final int beginIndex = shortName.indexOf(ProjectStructureProvider.COMPOSE_BY_CHAR); 58 | if (beginIndex != -1) { 59 | shortName = shortName.substring(beginIndex + 1); 60 | } 61 | abstractTreeNodes.add(new FoldingNode(fileNode.getProject(), psiFile, settings, shortName)); 62 | } 63 | return abstractTreeNodes; 64 | } else { 65 | return mChildNodeList; 66 | } 67 | } 68 | 69 | 70 | @Override 71 | protected void update(PresentationData presentation) { 72 | presentation.setPresentableText(mName); 73 | presentation.setIcon(AllIcons.Nodes.Folder); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /folding_plugin/com/dd/FoldingNode.java: -------------------------------------------------------------------------------- 1 | package com.dd; 2 | 3 | import com.intellij.ide.projectView.PresentationData; 4 | import com.intellij.ide.projectView.ViewSettings; 5 | import com.intellij.ide.projectView.impl.nodes.PsiFileNode; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.psi.PsiFile; 8 | 9 | class FoldingNode extends PsiFileNode { 10 | private String mName; 11 | 12 | public FoldingNode(Project project, PsiFile value, ViewSettings viewSettings, String shortName) { 13 | super(project, value, viewSettings); 14 | mName = shortName; 15 | } 16 | 17 | @Override 18 | protected void updateImpl(PresentationData presentationData) { 19 | super.updateImpl(presentationData); 20 | 21 | presentationData.setPresentableText(mName); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /folding_plugin/com/dd/SettingConfigurable.form: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
49 | -------------------------------------------------------------------------------- /folding_plugin/com/dd/SettingConfigurable.java: -------------------------------------------------------------------------------- 1 | package com.dd; 2 | 3 | import com.intellij.ide.projectView.ProjectView; 4 | import com.intellij.ide.util.PropertiesComponent; 5 | import com.intellij.openapi.options.Configurable; 6 | import com.intellij.openapi.options.ConfigurationException; 7 | import com.intellij.openapi.project.Project; 8 | import org.jetbrains.annotations.Nls; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import javax.swing.*; 12 | import javax.swing.event.DocumentEvent; 13 | import javax.swing.event.DocumentListener; 14 | import java.awt.event.ActionEvent; 15 | import java.awt.event.ActionListener; 16 | 17 | /** 18 | * 19 | * Created by skyrylyuk on 10/15/15. 20 | */ 21 | public class SettingConfigurable implements Configurable { 22 | public static final String PREFIX_PATTERN = "folding_plugin_prefix_pattern"; 23 | public static final String PREFIX_CUSTOM_USE = "folding_plugin_prefix_custom_use"; 24 | public static final String PREFIX_HIDE = "folding_plugin_prefix_hide"; 25 | 26 | public static final String DEFAULT_PATTERN = "[^_]{1,}(?=_)"; 27 | public static final String DEFAULT_PATTERN_DOUBLE = "[^_]{1,}_[^_]{1,}(?=_)"; 28 | 29 | private JPanel mPanel; 30 | private JCheckBox useCustomPatternCheckBox; 31 | private JTextField customPattern; 32 | private JCheckBox hideFoldingPrefix; 33 | private boolean isModified = false; 34 | 35 | @Nls 36 | @Override 37 | public String getDisplayName() { 38 | return "Android Folding"; 39 | } 40 | 41 | @Nullable 42 | @Override 43 | public String getHelpTopic() { 44 | return "null:"; 45 | } 46 | 47 | @Nullable 48 | @Override 49 | public JComponent createComponent() { 50 | 51 | useCustomPatternCheckBox.addActionListener(new ActionListener() { 52 | public void actionPerformed(ActionEvent actionEvent) { 53 | boolean selected = getCheckBoxStatus(actionEvent); 54 | 55 | customPattern.setEnabled(selected); 56 | isModified = true; 57 | } 58 | }); 59 | 60 | customPattern.getDocument().addDocumentListener(new DocumentListener() { 61 | @Override 62 | public void insertUpdate(DocumentEvent e) { 63 | isModified = true; 64 | } 65 | 66 | @Override 67 | public void removeUpdate(DocumentEvent e) { 68 | isModified = true; 69 | } 70 | 71 | @Override 72 | public void changedUpdate(DocumentEvent e) { 73 | isModified = true; 74 | } 75 | }); 76 | 77 | hideFoldingPrefix.addActionListener(new ActionListener() { 78 | public void actionPerformed(ActionEvent actionEvent) { 79 | isModified = true; 80 | } 81 | }); 82 | 83 | reset(); 84 | 85 | return mPanel; 86 | } 87 | 88 | private boolean getCheckBoxStatus(ActionEvent actionEvent) { 89 | AbstractButton abstractButton = (AbstractButton) actionEvent.getSource(); 90 | return abstractButton.getModel().isSelected(); 91 | } 92 | 93 | 94 | @Override 95 | public boolean isModified() { 96 | 97 | return isModified; 98 | } 99 | 100 | @Override 101 | public void apply() throws ConfigurationException { 102 | PropertiesComponent.getInstance().setValue(PREFIX_CUSTOM_USE, Boolean.valueOf(useCustomPatternCheckBox.isSelected()).toString()); 103 | PropertiesComponent.getInstance().setValue(PREFIX_PATTERN, customPattern.getText()); 104 | PropertiesComponent.getInstance().setValue(PREFIX_HIDE, Boolean.valueOf(hideFoldingPrefix.isSelected()).toString()); 105 | 106 | if (isModified) { 107 | Project currentProject = Utils.getCurrentProject(); 108 | 109 | if (currentProject != null) { 110 | ProjectView.getInstance(currentProject).refresh(); 111 | } 112 | } 113 | 114 | isModified = false; 115 | } 116 | 117 | @Override 118 | public void reset() { 119 | final boolean customPrefix = PropertiesComponent.getInstance().getBoolean(PREFIX_CUSTOM_USE, false); 120 | useCustomPatternCheckBox.setSelected(customPrefix); 121 | customPattern.setEnabled(customPrefix); 122 | customPattern.setText(PropertiesComponent.getInstance().getValue(PREFIX_PATTERN, DEFAULT_PATTERN_DOUBLE)); 123 | hideFoldingPrefix.getModel().setSelected(PropertiesComponent.getInstance().getBoolean(PREFIX_HIDE, false)); 124 | } 125 | 126 | @Override 127 | public void disposeUIResources() { 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /folding_plugin/com/dd/Settings.java: -------------------------------------------------------------------------------- 1 | package com.dd; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class Settings { 10 | 11 | @SerializedName("DecomposedFolders") 12 | private List mComposedFolders; 13 | 14 | @NotNull 15 | public List getComposedFolders() { 16 | if(mComposedFolders == null) { 17 | mComposedFolders = new ArrayList(); 18 | } 19 | 20 | return mComposedFolders; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /folding_plugin/com/dd/SettingsManager.java: -------------------------------------------------------------------------------- 1 | package com.dd; 2 | 3 | import com.google.gson.Gson; 4 | import com.intellij.ide.util.PropertiesComponent; 5 | import com.intellij.openapi.project.Project; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | public class SettingsManager { 9 | 10 | private static final String KEY_SETTINGS = "KEY_COMPOSED_FOLDERS"; 11 | 12 | public static boolean isComposed(@NotNull String folder) { 13 | boolean isFoldingOn = false; 14 | Project currentProject = Utils.getCurrentProject(); 15 | if (currentProject != null) { 16 | Settings settings = getSettings(currentProject); 17 | isFoldingOn = settings.getComposedFolders().contains(folder); 18 | 19 | } 20 | 21 | return isFoldingOn; 22 | } 23 | 24 | public static void addComposedFolder(@NotNull String folder) { 25 | Project currentProject = Utils.getCurrentProject(); 26 | if (currentProject != null) { 27 | Gson gson = new Gson(); 28 | Settings settings = getSettings(currentProject); 29 | settings.getComposedFolders().add(folder); 30 | 31 | PropertiesComponent.getInstance(currentProject).setValue(KEY_SETTINGS, gson.toJson(settings)); 32 | } 33 | 34 | } 35 | 36 | public static void removeComposedFolder(@NotNull String folder) { 37 | Project currentProject = Utils.getCurrentProject(); 38 | if (currentProject != null) { 39 | Gson gson = new Gson(); 40 | Settings settings = getSettings(currentProject); 41 | settings.getComposedFolders().remove(folder); 42 | 43 | PropertiesComponent.getInstance(currentProject).setValue(KEY_SETTINGS, gson.toJson(settings)); 44 | } 45 | } 46 | 47 | @NotNull 48 | private static Settings getSettings(@NotNull Project currentProject) { 49 | Gson gson = new Gson(); 50 | String json = PropertiesComponent.getInstance(currentProject).getValue(KEY_SETTINGS); 51 | Settings settings; 52 | if (json == null) { 53 | settings = new Settings(); 54 | } else { 55 | settings = gson.fromJson(json, Settings.class); 56 | } 57 | 58 | return settings; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /folding_plugin/com/dd/Utils.java: -------------------------------------------------------------------------------- 1 | package com.dd; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import com.intellij.openapi.project.ProjectManager; 5 | import org.jetbrains.annotations.Nullable; 6 | 7 | public final class Utils { 8 | 9 | @Nullable 10 | public static Project getCurrentProject() { 11 | Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); 12 | return openProjects.length > 0 ? openProjects[0] : null; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /libs/android-codegenerator-library-1.0.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/android-codegenerator-library-1.0.5.jar -------------------------------------------------------------------------------- /libs/commons-io-2.4-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/commons-io-2.4-sources.jar -------------------------------------------------------------------------------- /libs/commons-io-2.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/commons-io-2.4.jar -------------------------------------------------------------------------------- /libs/commons-lang3-3.3.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/commons-lang3-3.3.2.jar -------------------------------------------------------------------------------- /libs/commons-math3-3.4.1-src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/commons-math3-3.4.1-src.zip -------------------------------------------------------------------------------- /libs/commons-math3-3.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/commons-math3-3.4.1.jar -------------------------------------------------------------------------------- /libs/gson-2.3.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/gson-2.3.1.jar -------------------------------------------------------------------------------- /libs/guava-18.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/guava-18.0.jar -------------------------------------------------------------------------------- /libs/imgscalr-lib-4.2-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/imgscalr-lib-4.2-sources.jar -------------------------------------------------------------------------------- /libs/imgscalr-lib-4.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/imgscalr-lib-4.2.jar -------------------------------------------------------------------------------- /libs/thumbnailator-0.4.8-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/thumbnailator-0.4.8-sources.jar -------------------------------------------------------------------------------- /libs/thumbnailator-0.4.8.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/thumbnailator-0.4.8.jar -------------------------------------------------------------------------------- /libs/xom-1.2.10.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b2b2244424/AndroidStudioSuperPlugin/68ed824ad99b22deb7b0133b7e6702329109585f/libs/xom-1.2.10.jar -------------------------------------------------------------------------------- /lifecycle_sorter/Action/SortAction.java: -------------------------------------------------------------------------------- 1 | package Action; 2 | 3 | import com.intellij.openapi.actionSystem.*; 4 | import com.intellij.openapi.command.WriteCommandAction; 5 | import com.intellij.openapi.editor.Editor; 6 | import com.intellij.psi.*; 7 | import com.intellij.psi.util.PsiTreeUtil; 8 | import Sort.Sorter; 9 | /** 10 | * Created by armand on 3/1/15. 11 | */ 12 | public class SortAction extends AnAction { 13 | 14 | protected Sorter.SortPosition mSortPosition; 15 | 16 | @Override 17 | public void actionPerformed(AnActionEvent e) { 18 | 19 | PsiClass psiClass = getPsiClassFromContext(e); 20 | 21 | if (psiClass != null) { 22 | sortLifecycleMethods(psiClass); 23 | } 24 | 25 | } 26 | 27 | private void sortLifecycleMethods(final PsiClass psiClass) { 28 | new WriteCommandAction.Simple(psiClass.getProject(), psiClass.getContainingFile()) { 29 | @Override 30 | protected void run() throws Throwable { 31 | new Sorter(psiClass, mSortPosition).sort(); 32 | } 33 | }.execute(); 34 | 35 | 36 | } 37 | 38 | 39 | /** 40 | * @param e the action event that occurred 41 | * @return The PSIClass object based on which class your mouse cursor was in 42 | */ 43 | protected PsiClass getPsiClassFromContext(AnActionEvent e) { 44 | PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE); 45 | Editor editor = e.getData(PlatformDataKeys.EDITOR); 46 | 47 | if (psiFile == null || editor == null) { 48 | return null; 49 | } 50 | 51 | int offSet = editor.getCaretModel().getOffset(); 52 | PsiElement elementAt = psiFile.findElementAt(offSet); 53 | PsiClass psiClass = PsiTreeUtil.getParentOfType(elementAt, PsiClass.class); 54 | 55 | return psiClass; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lifecycle_sorter/Action/SortEndAction.java: -------------------------------------------------------------------------------- 1 | package Action; 2 | 3 | import Sort.Sorter; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | 6 | /** 7 | * Created by akopian on 5/24/15. 8 | */ 9 | public class SortEndAction extends SortAction { 10 | 11 | @Override 12 | public void actionPerformed(AnActionEvent e) { 13 | mSortPosition = Sorter.SortPosition.END; 14 | super.actionPerformed(e); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lifecycle_sorter/Action/SortStartAction.java: -------------------------------------------------------------------------------- 1 | package Action; 2 | 3 | import Sort.Sorter; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | 6 | /** 7 | * Created by akopian on 5/24/15. 8 | */ 9 | public class SortStartAction extends SortAction { 10 | 11 | @Override 12 | public void actionPerformed(AnActionEvent e) { 13 | mSortPosition = Sorter.SortPosition.START; 14 | super.actionPerformed(e); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lifecycle_sorter/Lifecycle/ActivityLifecycle.java: -------------------------------------------------------------------------------- 1 | package Lifecycle; 2 | 3 | import com.intellij.psi.PsiMethod; 4 | 5 | import java.util.*; 6 | 7 | /** 8 | * Created by armand on 3/1/15. 9 | */ 10 | public class ActivityLifecycle extends Lifecycle { 11 | 12 | /** 13 | * Activity Lifecycle method names 14 | */ 15 | private static final String ON_CREATE = "onCreate"; 16 | private static final String ON_RESTART = "onRestart"; 17 | private static final String ON_START = "onStart"; 18 | private static final String ON_RESUME = "onResume"; 19 | private static final String ON_PAUSE = "onPause"; 20 | private static final String ON_STOP = "onStop"; 21 | private static final String ON_DESTROY = "onDestroy"; 22 | 23 | 24 | /** 25 | * The ordering of the Activity Lifecycle methods 26 | */ 27 | private static final List ACTIVITY_LIFECYCLE_METHODS = new ArrayList(); 28 | 29 | static { 30 | ACTIVITY_LIFECYCLE_METHODS.add(ON_CREATE); 31 | ACTIVITY_LIFECYCLE_METHODS.add(ON_RESTART); 32 | ACTIVITY_LIFECYCLE_METHODS.add(ON_START); 33 | ACTIVITY_LIFECYCLE_METHODS.add(ON_RESUME); 34 | ACTIVITY_LIFECYCLE_METHODS.add(ON_PAUSE); 35 | ACTIVITY_LIFECYCLE_METHODS.add(ON_STOP); 36 | ACTIVITY_LIFECYCLE_METHODS.add(ON_DESTROY); 37 | } 38 | 39 | 40 | public ActivityLifecycle(Map methods) { 41 | super(methods); 42 | mLifecycleOrdering = ACTIVITY_LIFECYCLE_METHODS; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /lifecycle_sorter/Lifecycle/FragmentLifecycle.java: -------------------------------------------------------------------------------- 1 | package Lifecycle; 2 | 3 | import com.intellij.psi.PsiMethod; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * Created by armand on 3/29/15. 11 | */ 12 | public class FragmentLifecycle extends Lifecycle { 13 | 14 | /** 15 | * Fragment Lifecycle method names 16 | */ 17 | private static final String ON_ATTACH = "onAttach"; 18 | private static final String ON_CREATE = "onCreate"; 19 | private static final String ON_CREATE_VIEW = "onCreateView"; 20 | private static final String ON_VIEW_CREATED = "onViewCreated"; 21 | private static final String ON_ACTIVITY_CREATED = "onActivityCreated"; 22 | private static final String ON_VIEW_STATE_RESTORED = "onViewStateRestored"; 23 | private static final String ON_START = "onStart"; 24 | private static final String ON_RESUME = "onResume"; 25 | private static final String ON_PAUSE = "onPause"; 26 | private static final String ON_STOP = "onStop"; 27 | private static final String ON_DESTROY_VIEW = "onDestroyView"; 28 | private static final String ON_DESTROY = "onDestroy"; 29 | private static final String ON_DETACH = "onDetach"; 30 | 31 | 32 | /** 33 | * The ordering of the Fragment Lifecycle methods 34 | */ 35 | private static final List FRAGMENT_LIFECYCLE_METHODS = new ArrayList(); 36 | 37 | static { 38 | FRAGMENT_LIFECYCLE_METHODS.add(ON_ATTACH); 39 | FRAGMENT_LIFECYCLE_METHODS.add(ON_CREATE); 40 | FRAGMENT_LIFECYCLE_METHODS.add(ON_CREATE_VIEW); 41 | FRAGMENT_LIFECYCLE_METHODS.add(ON_VIEW_CREATED); 42 | FRAGMENT_LIFECYCLE_METHODS.add(ON_ACTIVITY_CREATED); 43 | FRAGMENT_LIFECYCLE_METHODS.add(ON_VIEW_STATE_RESTORED); 44 | FRAGMENT_LIFECYCLE_METHODS.add(ON_START); 45 | FRAGMENT_LIFECYCLE_METHODS.add(ON_RESUME); 46 | FRAGMENT_LIFECYCLE_METHODS.add(ON_PAUSE); 47 | FRAGMENT_LIFECYCLE_METHODS.add(ON_STOP); 48 | FRAGMENT_LIFECYCLE_METHODS.add(ON_DESTROY_VIEW); 49 | FRAGMENT_LIFECYCLE_METHODS.add(ON_DESTROY); 50 | FRAGMENT_LIFECYCLE_METHODS.add(ON_DETACH); 51 | } 52 | 53 | public FragmentLifecycle(Map methods) { 54 | super(methods); 55 | mLifecycleOrdering = FRAGMENT_LIFECYCLE_METHODS; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /lifecycle_sorter/Lifecycle/Lifecycle.java: -------------------------------------------------------------------------------- 1 | package Lifecycle; 2 | 3 | import com.intellij.psi.PsiMethod; 4 | 5 | import java.util.LinkedHashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * Created by armand on 3/15/15. 11 | * 12 | * Abstract class that represents a Lifecycle (could be an Activity/Fragment/etc). 13 | */ 14 | public abstract class Lifecycle { 15 | 16 | /** 17 | * A Map representing all methods in a PsiClass. This Map will be filtered down to create 18 | * a new Map with the lifecycle methods of an Activity or Fragment in the proper ordering. 19 | * The key is the method name, and the value is the entire method represented as a String, 20 | * such as any Annotations, signature, accessors, method body, etc. 21 | */ 22 | private Map mAllMethods; 23 | 24 | /** 25 | * A List containing the proper ordering of the lifecycle methods, whether it's 26 | * the activity lifecycle or fragment lifecycle 27 | */ 28 | protected List mLifecycleOrdering; 29 | 30 | 31 | public Lifecycle(Map methods) { 32 | this.mAllMethods = methods; 33 | } 34 | 35 | 36 | /** 37 | * Sorts the lifecycle methods provided 38 | * @return A Map of the method names and entire method definitions, respecting the 39 | * sort order of mLifecycleOrdering 40 | */ 41 | public Map sort() { 42 | 43 | // LinkedHashMap because we must respect the ordering in which we insert 44 | Map sortedMethods = new LinkedHashMap(); 45 | 46 | for (int i = 0; i < mLifecycleOrdering.size(); i++) { 47 | String methodName = mLifecycleOrdering.get(i); 48 | PsiMethod method = mAllMethods.get(methodName); 49 | 50 | if (method != null) { 51 | sortedMethods.put(methodName, method); 52 | } 53 | } 54 | 55 | return sortedMethods; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lifecycle_sorter/Lifecycle/LifecycleFactory.java: -------------------------------------------------------------------------------- 1 | package Lifecycle; 2 | 3 | import Util.LifecycleUtils; 4 | import com.intellij.psi.PsiClass; 5 | import com.intellij.psi.PsiMethod; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * Created by armand on 4/4/15. 11 | */ 12 | public class LifecycleFactory { 13 | 14 | public Lifecycle createLifecycle(PsiClass psiClass, Map methods) { 15 | switch (LifecycleUtils.getLifeCycleType(psiClass)) { 16 | 17 | case LifecycleUtils.ACTIVITY: 18 | return new ActivityLifecycle(methods); 19 | 20 | case LifecycleUtils.FRAGMENT: 21 | return new FragmentLifecycle(methods); 22 | 23 | default: return null; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lifecycle_sorter/Sort/Sorter.java: -------------------------------------------------------------------------------- 1 | package Sort; 2 | 3 | import Lifecycle.Lifecycle; 4 | import Lifecycle.LifecycleFactory; 5 | import com.intellij.psi.*; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.util.Collection; 9 | import java.util.LinkedHashMap; 10 | import java.util.Map; 11 | 12 | /** 13 | * Created by armand on 3/1/15. 14 | */ 15 | 16 | /** 17 | * This class determines if the current class is an Activity or a Fragment 18 | * and sorts the lifecycle methods based off that criteria. 19 | */ 20 | public class Sorter { 21 | 22 | private PsiClass mPsiClass; 23 | 24 | /** 25 | * Enum for specifying the offset in the file where the lifecycle methods will be placed. 26 | * START - Places the methods at the start of the class, after the variable declarations. 27 | * END - Places the methods at the end of the class 28 | */ 29 | public enum SortPosition { 30 | START, END 31 | } 32 | 33 | private SortPosition mSortPosition; 34 | 35 | /** 36 | * @param psiClass The class whose methods to sort 37 | * @param sortPosition The offset position in the class in which to place the sorted methods 38 | */ 39 | public Sorter(PsiClass psiClass, SortPosition sortPosition) { 40 | mPsiClass = psiClass; 41 | mSortPosition = sortPosition; 42 | } 43 | 44 | /** 45 | * Formats the activity/fragment lifecycle methods 46 | */ 47 | public void sort() { 48 | Map methods = getMethodsMap(); 49 | 50 | Map sortedMethods = null; 51 | 52 | LifecycleFactory lifecycleFactory = new LifecycleFactory(); 53 | Lifecycle lifecycle = lifecycleFactory.createLifecycle(mPsiClass, methods); 54 | 55 | if (lifecycle != null && !methods.isEmpty()) { 56 | sortedMethods = lifecycle.sort(); 57 | appendSortedMethods(sortedMethods); 58 | 59 | // After obtaining and appending the new sorted list of PsiMethods, 60 | // we must remove the old, unsorted list 61 | deleteUnsortedLifecycleMethods(sortedMethods.values()); 62 | } 63 | 64 | } 65 | 66 | /** 67 | * Generates a Map of all the methods in the current class 68 | * @return a Map of all the methods in the current class 69 | */ 70 | @NotNull 71 | private Map getMethodsMap() { 72 | PsiMethod[] psiClassMethods = mPsiClass.getMethods(); 73 | 74 | Map methods = new LinkedHashMap(); 75 | 76 | for (PsiMethod method : psiClassMethods) { 77 | if (method != null) { 78 | methods.put(method.getName(), method); 79 | } 80 | } 81 | return methods; 82 | } 83 | 84 | 85 | /** 86 | * Removes the collection of PsiMethods from the PsiClass 87 | * 88 | * @param methods the methods to remove from the PsiClass 89 | */ 90 | private void deleteUnsortedLifecycleMethods(Collection methods) { 91 | for (PsiMethod method : methods) method.delete(); 92 | } 93 | 94 | 95 | /** 96 | * Appends the sorted methods to the file 97 | * 98 | * @param sortedMethods The sorted methods to append 99 | */ 100 | private void appendSortedMethods(Map sortedMethods) { 101 | 102 | switch (mSortPosition) { 103 | case START: 104 | appendToStart(sortedMethods); break; 105 | case END: 106 | appendToEnd(sortedMethods); break; 107 | default: 108 | appendToStart(sortedMethods); break; 109 | } 110 | 111 | } 112 | 113 | /** 114 | * Appends the sorted lifecycle methods to the end of the class. 115 | * @param sortedMethods The sorted lifecycle methods 116 | */ 117 | private void appendToEnd(Map sortedMethods) { 118 | for (PsiMethod method : sortedMethods.values()) { 119 | mPsiClass.add(method); 120 | } 121 | } 122 | 123 | /** 124 | * Appends the sorted lifecycle methods to the start of the class. 125 | * @param sortedMethods The sorted lifecycle methods 126 | */ 127 | private void appendToStart(Map sortedMethods) { 128 | // We want the lifecycle methods to be the first methods in the class 129 | // so we grab the current first method and append the lifecycle 130 | // methods before it. 131 | PsiElement anchorToAddBefore = mPsiClass.getMethods()[0]; 132 | 133 | for (PsiMethod method : sortedMethods.values()) { 134 | mPsiClass.addBefore(method, anchorToAddBefore); 135 | } 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /lifecycle_sorter/Util/LifecycleUtils.java: -------------------------------------------------------------------------------- 1 | package Util; 2 | 3 | import com.intellij.psi.PsiClass; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by armand on 3/22/15. 10 | */ 11 | public class LifecycleUtils { 12 | 13 | public static final int ACTIVITY = 1; 14 | public static final int FRAGMENT = 2; 15 | 16 | 17 | private static final List ACTIVITY_PACKAGE_NAMES = new ArrayList(); 18 | 19 | static { 20 | ACTIVITY_PACKAGE_NAMES.add("android.app.Activity"); 21 | } 22 | 23 | 24 | /** 25 | * The fragment package names and the support libraries that come with it. 26 | */ 27 | private static final List FRAGMENT_PACKAGE_NAMES = new ArrayList(); 28 | 29 | static { 30 | FRAGMENT_PACKAGE_NAMES.add("android.app.Fragment"); 31 | FRAGMENT_PACKAGE_NAMES.add("android.support.v4.app.Fragment"); 32 | } 33 | 34 | /** 35 | * To Prevent instantiation 36 | */ 37 | private LifecycleUtils() { 38 | } 39 | 40 | 41 | /** 42 | * Checks a list of superclasses of a PsiClass against the Activity/Fragment classes and support classes. 43 | * @param psiClass 44 | * @return true if a match is found, false otherwise 45 | */ 46 | public static int getLifeCycleType(PsiClass psiClass) { 47 | List packages = buildSuperClassList(psiClass, new ArrayList()); 48 | return resolvePackageToCompare(packages); 49 | 50 | } 51 | 52 | /** 53 | * Cross checks the list of package names we've built up against the list of 54 | * Activity package names and list of Fragment package names. 55 | * @param superClassList The hierarchy of classes found from the current PsiClass 56 | * @return {@value #ACTIVITY} if the superClassList contains the appropriate package 57 | * name identifying that Activity has been inherited, {@value #FRAGMENT} if the superClassList 58 | * contains the appropriate package name identifying that Fragment has been inherited. 59 | * -1 if no inheritance matches are found. 60 | */ 61 | private static int resolvePackageToCompare(List superClassList) { 62 | for (int i = 0; i < ACTIVITY_PACKAGE_NAMES.size(); i++) { 63 | if (superClassList.contains(ACTIVITY_PACKAGE_NAMES.get(i))) return ACTIVITY; 64 | } 65 | 66 | for (int i = 0; i < FRAGMENT_PACKAGE_NAMES.size(); i++) { 67 | if (superClassList.contains(FRAGMENT_PACKAGE_NAMES.get(i))) return FRAGMENT; 68 | } 69 | 70 | return -1; 71 | } 72 | 73 | 74 | /** 75 | * Recurses up the superclass chain of the PsiClass provided to determine 76 | * if the chain contains Activity or Fragment as one of the base classes. 77 | * This will then be used to determine which lifecycle methods to sort by. 78 | * 79 | * @param psiClass the psiClass used to traverse up the superclass chain 80 | * @param packages the list of packages that will be built up from traversal 81 | * @return the list of packages collected after traversal 82 | */ 83 | private static List buildSuperClassList(PsiClass psiClass, List packages) { 84 | 85 | // After traversing up the hierarchy, either the JDK is not 86 | // configured or they're simply not using the Android SDK 87 | // which would obviously contain the required packages 88 | if (psiClass == null || psiClass.getQualifiedName().equals("java.lang.Object")) { 89 | return packages; 90 | } else { 91 | packages.add(psiClass.getQualifiedName()); 92 | return buildSuperClassList(psiClass.getSuperClass(), packages); 93 | } 94 | } 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/AndroidView.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android; 2 | 3 | import com.intellij.psi.PsiElement; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public class AndroidView { 7 | 8 | private String id; 9 | private String name; 10 | private PsiElement xmlTarget; 11 | 12 | public AndroidView(@NotNull String id, @NotNull String className, PsiElement xmlTarget) { 13 | this.xmlTarget = xmlTarget; 14 | 15 | if (id.startsWith("@+id/")) { 16 | this.id = ("R.id." + id.split("@\\+id/")[1]); 17 | } else if (id.contains(":")) { 18 | String[] s = id.split(":id/"); 19 | String packageStr = s[0].substring(1, s[0].length()); 20 | this.id = (packageStr + ".R.id." + s[1]); 21 | } 22 | if (className.contains(".")) 23 | this.name = className; 24 | else if ((className.equals("View")) || (className.equals("ViewGroup"))) 25 | this.name = String.format("android.view.%s", className); 26 | else 27 | this.name = String.format("android.widget.%s", className); 28 | } 29 | 30 | public PsiElement getXmlTarget() { 31 | return xmlTarget; 32 | } 33 | 34 | public String getId() { 35 | return this.id; 36 | } 37 | 38 | public String getName() { 39 | return this.name; 40 | } 41 | 42 | public String getFieldName() { 43 | String[] words = getId().split("_"); 44 | StringBuilder fieldName = new StringBuilder(); 45 | for (String word : words) { 46 | String[] idTokens = word.split("\\."); 47 | char[] chars = idTokens[(idTokens.length - 1)].toCharArray(); 48 | fieldName.append(chars); 49 | } 50 | return fieldName.toString(); 51 | } 52 | } -------------------------------------------------------------------------------- /src/de/espend/idea/android/RelatedPopupGotoLineMarker.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android; 2 | 3 | import com.intellij.codeInsight.daemon.GutterIconNavigationHandler; 4 | import com.intellij.ide.actions.GotoRelatedFileAction; 5 | import com.intellij.navigation.GotoRelatedItem; 6 | import com.intellij.psi.PsiElement; 7 | import com.intellij.ui.awt.RelativePoint; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import javax.swing.*; 12 | import java.awt.event.MouseEvent; 13 | import java.util.List; 14 | 15 | public class RelatedPopupGotoLineMarker { 16 | 17 | public static class NavigationHandler implements GutterIconNavigationHandler { 18 | 19 | private List items; 20 | 21 | public NavigationHandler(List items){ 22 | this.items = items; 23 | } 24 | 25 | public void navigate(MouseEvent e, PsiElement elt) { 26 | List items = this.items; 27 | if (items.size() == 1) { 28 | items.get(0).navigate(); 29 | } else { 30 | GotoRelatedFileAction.createPopup(items, "Go to Related Files").show(new RelativePoint(e)); 31 | } 32 | 33 | } 34 | 35 | } 36 | 37 | public static class PopupGotoRelatedItem extends GotoRelatedItem { 38 | 39 | private String customName; 40 | private Icon icon; 41 | private Icon smallIcon; 42 | 43 | public PopupGotoRelatedItem(@NotNull PsiElement element) { 44 | super(element); 45 | } 46 | 47 | public PopupGotoRelatedItem(@NotNull PsiElement element, String customName) { 48 | super(element); 49 | this.customName = customName; 50 | } 51 | 52 | @Nullable 53 | @Override 54 | public String getCustomName() { 55 | return customName; 56 | } 57 | 58 | @Nullable 59 | @Override 60 | public Icon getCustomIcon() { 61 | if(this.icon != null) { 62 | return this.icon; 63 | } 64 | 65 | return super.getCustomIcon(); 66 | } 67 | 68 | public PopupGotoRelatedItem withIcon(Icon icon, Icon smallIcon) { 69 | this.icon = icon; 70 | this.smallIcon = smallIcon; 71 | return this; 72 | } 73 | 74 | public Icon getSmallIcon() { 75 | return smallIcon; 76 | } 77 | 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/action/ExtractStringAction.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.action; 2 | 3 | import com.intellij.openapi.actionSystem.AnActionEvent; 4 | import com.intellij.openapi.actionSystem.PlatformDataKeys; 5 | import com.intellij.openapi.application.ApplicationManager; 6 | import com.intellij.openapi.command.CommandProcessor; 7 | import com.intellij.openapi.editor.Editor; 8 | import com.intellij.openapi.project.DumbAwareAction; 9 | import com.intellij.openapi.project.Project; 10 | import com.intellij.psi.PsiElement; 11 | import com.intellij.psi.PsiFile; 12 | import com.intellij.psi.PsiLiteralExpression; 13 | import icons.AndroidIcons; 14 | import org.jetbrains.android.intentions.AndroidAddStringResourceAction; 15 | import org.jetbrains.annotations.Nullable; 16 | 17 | public class ExtractStringAction extends DumbAwareAction { 18 | 19 | public ExtractStringAction() { 20 | super("Extract String resource", "Extract string resource (string.xml)", AndroidIcons.Android); 21 | } 22 | 23 | @Override 24 | public void update(AnActionEvent event) { 25 | PsiElement psiElement = getPsiElement(event.getData(PlatformDataKeys.PSI_FILE), event.getData(PlatformDataKeys.EDITOR)); 26 | event.getPresentation().setVisible(psiElement instanceof PsiLiteralExpression); 27 | } 28 | 29 | @Override 30 | public void actionPerformed(AnActionEvent event) { 31 | 32 | final PsiFile psiFile = event.getData(PlatformDataKeys.PSI_FILE); 33 | final Editor editor = event.getData(PlatformDataKeys.EDITOR); 34 | final Project project = event.getData(PlatformDataKeys.PROJECT); 35 | 36 | if(project == null) { 37 | return; 38 | } 39 | 40 | CommandProcessor.getInstance().executeCommand(project, new Runnable() { 41 | @Override 42 | public void run() { 43 | ApplicationManager.getApplication().runWriteAction(new Runnable() { 44 | @Override 45 | public void run() { 46 | new AndroidAddStringResourceAction().invoke(project, editor, psiFile); 47 | } 48 | }); 49 | 50 | } 51 | }, "Extract string resource", "Android Studio Plugin"); 52 | 53 | } 54 | 55 | @Nullable 56 | protected static PsiElement getPsiElement(@Nullable PsiFile file, @Nullable Editor editor) { 57 | 58 | if(file == null || editor == null) { 59 | return null; 60 | } 61 | 62 | int offset = editor.getCaretModel().getOffset(); 63 | PsiElement element = file.findElementAt(offset); 64 | return element != null ? element.getParent() : null; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/action/generator/AbstractActivityViewAction.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.action.generator; 2 | 3 | import com.intellij.codeInsight.generation.actions.BaseGenerateAction; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.openapi.editor.Editor; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.patterns.PlatformPatterns; 8 | import com.intellij.psi.*; 9 | import com.intellij.psi.impl.source.PsiClassReferenceType; 10 | import com.intellij.psi.util.PsiTreeUtil; 11 | import com.intellij.psi.util.PsiUtilBase; 12 | import de.espend.idea.android.annotator.InflateViewAnnotator; 13 | import de.espend.idea.android.utils.AndroidUtils; 14 | import icons.AndroidIcons; 15 | import org.jetbrains.annotations.NotNull; 16 | import org.jetbrains.annotations.Nullable; 17 | 18 | abstract public class AbstractActivityViewAction extends BaseGenerateAction { 19 | 20 | public AbstractActivityViewAction() { 21 | super(null); 22 | } 23 | 24 | @Override 25 | protected boolean isValidForFile(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { 26 | int offset = editor.getCaretModel().getOffset(); 27 | PsiElement psiElement = file.findElementAt(offset); 28 | 29 | if(!PlatformPatterns.psiElement().inside(PsiMethodCallExpression.class).accepts(psiElement)) { 30 | return false; 31 | } 32 | 33 | PsiMethodCallExpression psiMethodCallExpression = PsiTreeUtil.getParentOfType(psiElement, PsiMethodCallExpression.class); 34 | if(psiMethodCallExpression == null) { 35 | return false; 36 | } 37 | 38 | PsiMethod psiMethod = psiMethodCallExpression.resolveMethod(); 39 | if(psiMethod == null) { 40 | return false; 41 | } 42 | 43 | return "setContentView".equals(psiMethod.getName()); 44 | } 45 | 46 | @Override 47 | public void actionPerformedImpl(@NotNull final Project project, final Editor editor) { 48 | PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, project); 49 | if(file == null) { 50 | return; 51 | } 52 | 53 | int offset = editor.getCaretModel().getOffset(); 54 | PsiElement psiElement = file.findElementAt(offset); 55 | if(psiElement == null) { 56 | return; 57 | } 58 | 59 | PsiMethodCallExpression psiMethodCallExpression = PsiTreeUtil.getParentOfType(psiElement, PsiMethodCallExpression.class); 60 | if(psiMethodCallExpression == null) { 61 | return; 62 | } 63 | 64 | PsiFile xmlFile = matchInflate(psiMethodCallExpression); 65 | generate(psiMethodCallExpression, xmlFile, editor, file); 66 | } 67 | 68 | @Nullable 69 | public static PsiFile matchInflate(PsiMethodCallExpression psiMethodCallExpression) { 70 | 71 | PsiExpression[] psiExpressions = psiMethodCallExpression.getArgumentList().getExpressions(); 72 | if(psiExpressions.length == 0) { 73 | return null; 74 | } 75 | 76 | return AndroidUtils.findXmlResource((PsiReferenceExpression) psiExpressions[0]); 77 | } 78 | 79 | @Override 80 | public void update(AnActionEvent event) { 81 | super.update(event); 82 | event.getPresentation().setIcon(AndroidIcons.AndroidToolWindow); 83 | } 84 | 85 | abstract public void generate(PsiMethodCallExpression psiMethodCallExpression, PsiFile xmlFile, Editor editor, @NotNull PsiFile file); 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/action/generator/AbstractInflateViewAction.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.action.generator; 2 | 3 | import com.intellij.codeInsight.generation.actions.BaseGenerateAction; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.openapi.editor.Editor; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.patterns.PlatformPatterns; 8 | import com.intellij.psi.PsiElement; 9 | import com.intellij.psi.PsiFile; 10 | import com.intellij.psi.PsiLocalVariable; 11 | import com.intellij.psi.util.PsiTreeUtil; 12 | import com.intellij.psi.util.PsiUtilBase; 13 | import de.espend.idea.android.annotator.InflateViewAnnotator; 14 | import icons.AndroidIcons; 15 | import org.jetbrains.annotations.NotNull; 16 | 17 | abstract public class AbstractInflateViewAction extends BaseGenerateAction { 18 | 19 | public AbstractInflateViewAction() { 20 | super(null); 21 | } 22 | 23 | @Override 24 | protected boolean isValidForFile(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { 25 | int offset = editor.getCaretModel().getOffset(); 26 | PsiElement psiElement = file.findElementAt(offset); 27 | 28 | if(!PlatformPatterns.psiElement().inside(PsiLocalVariable.class).accepts(psiElement)) { 29 | return false; 30 | } 31 | 32 | PsiLocalVariable psiLocalVariable = PsiTreeUtil.getParentOfType(psiElement, PsiLocalVariable.class); 33 | return InflateViewAnnotator.matchInflate(psiLocalVariable) != null; 34 | } 35 | 36 | @Override 37 | public void actionPerformedImpl(@NotNull final Project project, final Editor editor) { 38 | PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, project); 39 | if(file == null) { 40 | return; 41 | } 42 | 43 | int offset = editor.getCaretModel().getOffset(); 44 | PsiElement psiElement = file.findElementAt(offset); 45 | if(psiElement == null) { 46 | return; 47 | } 48 | 49 | PsiLocalVariable psiLocalVariable = PsiTreeUtil.getParentOfType(psiElement, PsiLocalVariable.class); 50 | InflateViewAnnotator.InflateContainer inflateContainer = InflateViewAnnotator.matchInflate(psiLocalVariable); 51 | if(inflateContainer == null) { 52 | return; 53 | } 54 | 55 | generate(inflateContainer, editor, file); 56 | } 57 | 58 | @Override 59 | public void update(AnActionEvent event) { 60 | super.update(event); 61 | event.getPresentation().setIcon(AndroidIcons.AndroidToolWindow); 62 | } 63 | 64 | abstract public void generate(InflateViewAnnotator.InflateContainer inflateContainer, Editor editor, @NotNull PsiFile file); 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/action/generator/ActivityViewFieldVariable.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.action.generator; 2 | 3 | import com.intellij.openapi.editor.Editor; 4 | import com.intellij.psi.PsiFile; 5 | import com.intellij.psi.PsiMethodCallExpression; 6 | import de.espend.idea.android.action.write.InflateLocalVariableAction; 7 | import de.espend.idea.android.action.write.InflateThisExpressionAction; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | public class ActivityViewFieldVariable extends AbstractActivityViewAction { 11 | 12 | @Override 13 | public void generate(PsiMethodCallExpression psiMethodCallExpression, PsiFile xmlFile, Editor editor, @NotNull PsiFile file) { 14 | new InflateThisExpressionAction(psiMethodCallExpression, xmlFile).invoke(file.getProject(), editor, file); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/action/generator/ActivityViewMethodVariable.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.action.generator; 2 | 3 | import com.intellij.openapi.editor.Editor; 4 | import com.intellij.psi.PsiFile; 5 | import com.intellij.psi.PsiMethodCallExpression; 6 | import de.espend.idea.android.action.write.InflateLocalVariableAction; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public class ActivityViewMethodVariable extends AbstractActivityViewAction { 10 | 11 | @Override 12 | public void generate(PsiMethodCallExpression psiMethodCallExpression, PsiFile xmlFile, Editor editor, @NotNull PsiFile file) { 13 | new InflateLocalVariableAction(psiMethodCallExpression, xmlFile).invoke(file.getProject(), editor, file); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/action/generator/FieldViewInflateViewAction.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.action.generator; 2 | 3 | import com.intellij.openapi.editor.Editor; 4 | import com.intellij.psi.PsiFile; 5 | import de.espend.idea.android.action.write.InflateThisExpressionAction; 6 | import de.espend.idea.android.annotator.InflateViewAnnotator; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public class FieldViewInflateViewAction extends AbstractInflateViewAction { 10 | 11 | @Override 12 | public void generate(InflateViewAnnotator.InflateContainer inflateContainer, Editor editor, @NotNull PsiFile file) { 13 | new InflateThisExpressionAction(inflateContainer.getPsiLocalVariable(), inflateContainer.getXmlFile()).invoke(file.getProject(), editor, file); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/action/generator/LocalViewAction.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.action.generator; 2 | 3 | import com.intellij.openapi.editor.Editor; 4 | import com.intellij.psi.PsiFile; 5 | import de.espend.idea.android.action.write.InflateLocalVariableAction; 6 | import de.espend.idea.android.annotator.InflateViewAnnotator; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public class LocalViewAction extends AbstractInflateViewAction { 10 | 11 | @Override 12 | public void generate(InflateViewAnnotator.InflateContainer inflateContainer, Editor editor, @NotNull PsiFile file) { 13 | new InflateLocalVariableAction(inflateContainer.getPsiLocalVariable(), inflateContainer.getXmlFile()).invoke(file.getProject(), editor, file); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/action/write/InflateLocalVariableAction.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.action.write; 2 | 3 | import com.intellij.codeInsight.intention.impl.BaseIntentionAction; 4 | import com.intellij.openapi.application.ApplicationManager; 5 | import com.intellij.openapi.editor.Editor; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.psi.*; 8 | import com.intellij.psi.codeStyle.JavaCodeStyleManager; 9 | import com.intellij.psi.util.PsiElementFilter; 10 | import com.intellij.psi.util.PsiTreeUtil; 11 | import com.intellij.util.DocumentUtil; 12 | import com.intellij.util.IncorrectOperationException; 13 | import de.espend.idea.android.AndroidView; 14 | import de.espend.idea.android.utils.AndroidUtils; 15 | import org.jetbrains.annotations.NotNull; 16 | import org.jetbrains.annotations.Nullable; 17 | 18 | import java.util.HashSet; 19 | import java.util.List; 20 | import java.util.Set; 21 | 22 | public class InflateLocalVariableAction extends BaseIntentionAction { 23 | 24 | final private PsiFile xmlFile; 25 | final private PsiElement psiElement; 26 | 27 | @Nullable 28 | private String variableName = null; 29 | 30 | public InflateLocalVariableAction(PsiLocalVariable psiLocalVariable, PsiFile xmlFile) { 31 | this.xmlFile = xmlFile; 32 | this.psiElement = psiLocalVariable; 33 | this.variableName = psiLocalVariable.getName(); 34 | } 35 | 36 | public InflateLocalVariableAction(PsiElement psiElement, PsiFile xmlFile) { 37 | this.xmlFile = xmlFile; 38 | this.psiElement = psiElement; 39 | } 40 | 41 | @NotNull 42 | @Override 43 | public String getFamilyName() { 44 | return "Android Studio Prettify"; 45 | } 46 | 47 | @Override 48 | public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile psiFile) { 49 | return true; 50 | } 51 | 52 | @Override 53 | public void invoke(@NotNull Project project, Editor editor, PsiFile psiFile) throws IncorrectOperationException { 54 | DocumentUtil.writeInRunUndoTransparentAction(new Runnable() { 55 | @Override 56 | public void run() { 57 | List androidViews = AndroidUtils.getIDsFromXML(xmlFile); 58 | 59 | PsiStatement psiStatement = PsiTreeUtil.getParentOfType(psiElement, PsiStatement.class); 60 | if (psiStatement == null) { 61 | return; 62 | } 63 | 64 | PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(psiStatement.getProject()); 65 | 66 | PsiElement[] localVariables = PsiTreeUtil.collectElements(psiStatement.getParent(), new PsiElementFilter() { 67 | @Override 68 | public boolean isAccepted(PsiElement element) { 69 | return element instanceof PsiLocalVariable; 70 | } 71 | }); 72 | 73 | Set variables = new HashSet(); 74 | for (PsiElement localVariable : localVariables) { 75 | variables.add(((PsiLocalVariable) localVariable).getName()); 76 | } 77 | 78 | for (AndroidView v : androidViews) { 79 | if (!variables.contains(v.getFieldName())) { 80 | String sb1; 81 | 82 | if (variableName != null) { 83 | sb1 = String.format("%s %s = (%s) %s.findViewById(%s);", v.getName(), v.getFieldName(), v.getName(), variableName, v.getId()); 84 | } else { 85 | sb1 = String.format("%s %s = (%s) findViewById(%s);", v.getName(), v.getFieldName(), v.getName(), v.getId()); 86 | } 87 | 88 | PsiStatement statementFromText = elementFactory.createStatementFromText(sb1, null); 89 | psiStatement.getParent().addAfter(statementFromText, psiStatement); 90 | } 91 | } 92 | 93 | JavaCodeStyleManager.getInstance(psiStatement.getProject()).shortenClassReferences(psiStatement.getParent()); 94 | new ReformatAndOptimizeImportsProcessor(psiStatement.getProject(), psiStatement.getContainingFile(), true).run(); 95 | 96 | } 97 | }); 98 | 99 | } 100 | 101 | @NotNull 102 | @Override 103 | public String getText() { 104 | return "Local View Variables"; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/action/write/ReformatAndOptimizeImportsProcessor.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.action.write; 2 | 3 | import com.intellij.codeInsight.CodeInsightBundle; 4 | import com.intellij.codeInsight.actions.AbstractLayoutCodeProcessor; 5 | import com.intellij.codeInsight.actions.OptimizeImportsProcessor; 6 | import com.intellij.codeInsight.actions.ReformatCodeProcessor; 7 | import com.intellij.openapi.module.Module; 8 | import com.intellij.openapi.project.Project; 9 | import com.intellij.psi.PsiDirectory; 10 | import com.intellij.psi.PsiFile; 11 | import com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl; 12 | import com.intellij.util.IncorrectOperationException; 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | import java.util.concurrent.Callable; 16 | import java.util.concurrent.FutureTask; 17 | 18 | /** 19 | * @author max 20 | */ 21 | public class ReformatAndOptimizeImportsProcessor extends AbstractLayoutCodeProcessor { 22 | public static final String COMMAND_NAME = CodeInsightBundle.message("progress.reformat.and.optimize.common.command.text"); 23 | private static final String PROGRESS_TEXT = CodeInsightBundle.message("reformat.and.optimize.progress.common.text"); 24 | 25 | private final OptimizeImportsProcessor myOptimizeImportsProcessor; 26 | private final ReformatCodeProcessor myReformatCodeProcessor; 27 | 28 | public ReformatAndOptimizeImportsProcessor(Project project, PsiFile file, boolean processChangedTextOnly) { 29 | super(project, file, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly); 30 | myOptimizeImportsProcessor = new OptimizeImportsProcessor(project, file); 31 | myReformatCodeProcessor = new ReformatCodeProcessor(project, file, null, processChangedTextOnly); 32 | } 33 | 34 | @NotNull 35 | @Override 36 | protected FutureTask prepareTask(@NotNull PsiFile psiFile, boolean b) throws IncorrectOperationException { 37 | return new FutureTask(new Callable() { 38 | @Override 39 | public Boolean call() throws Exception { 40 | return true; 41 | } 42 | }); 43 | } 44 | 45 | @Override 46 | @NotNull 47 | public FutureTask preprocessFile(@NotNull PsiFile file, boolean processChangedTextOnly) throws IncorrectOperationException { 48 | final FutureTask reformatTask = myReformatCodeProcessor.preprocessFile(file, processChangedTextOnly); 49 | final FutureTask optimizeImportsTask = myOptimizeImportsProcessor.preprocessFile(file, false); 50 | return new FutureTask(new Callable() { 51 | @Override 52 | public Boolean call() throws Exception { 53 | reformatTask.run(); 54 | if (!reformatTask.get() || reformatTask.isCancelled()) { 55 | return false; 56 | } 57 | 58 | CodeStyleManagerImpl.setSequentialProcessingAllowed(false); 59 | try { 60 | optimizeImportsTask.run(); 61 | return optimizeImportsTask.get() && !optimizeImportsTask.isCancelled(); 62 | } 63 | finally { 64 | CodeStyleManagerImpl.setSequentialProcessingAllowed(true); 65 | } 66 | } 67 | }); 68 | } 69 | } -------------------------------------------------------------------------------- /src/de/espend/idea/android/annotator/InflateViewAnnotator.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.annotator; 2 | 3 | import com.intellij.lang.annotation.Annotation; 4 | import com.intellij.lang.annotation.AnnotationHolder; 5 | import com.intellij.lang.annotation.Annotator; 6 | import com.intellij.psi.*; 7 | import com.intellij.psi.impl.source.PsiClassReferenceType; 8 | import com.intellij.psi.impl.source.tree.java.PsiIdentifierImpl; 9 | import com.intellij.psi.util.PsiTreeUtil; 10 | import de.espend.idea.android.action.write.InflateLocalVariableAction; 11 | import de.espend.idea.android.action.write.InflateThisExpressionAction; 12 | import de.espend.idea.android.utils.AndroidUtils; 13 | import de.espend.idea.android.utils.JavaPsiUtil; 14 | import org.jetbrains.annotations.NotNull; 15 | import org.jetbrains.annotations.Nullable; 16 | 17 | public class InflateViewAnnotator implements Annotator { 18 | 19 | @Override 20 | public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder annotationHolder) { 21 | 22 | InflateContainer inflateContainer = matchInflate(psiElement); 23 | if(inflateContainer == null) { 24 | return; 25 | } 26 | 27 | Annotation inflateLocal = annotationHolder.createWeakWarningAnnotation(psiElement, null); 28 | inflateLocal.setHighlightType(null); 29 | inflateLocal.registerFix(new InflateLocalVariableAction(inflateContainer.getPsiLocalVariable(), inflateContainer.getXmlFile())); 30 | 31 | Annotation inflateThis = annotationHolder.createWeakWarningAnnotation(psiElement, null); 32 | inflateThis.setHighlightType(null); 33 | inflateThis.registerFix(new InflateThisExpressionAction(inflateContainer.getPsiLocalVariable(), inflateContainer.getXmlFile())); 34 | 35 | } 36 | 37 | @Nullable 38 | public static InflateContainer matchInflate(@Nullable PsiElement psiElement) { 39 | if(!(psiElement instanceof PsiIdentifierImpl)) { 40 | return null; 41 | } 42 | 43 | // View "rootView" = inflater.inflate(R.layout.fragment_main, container, false); 44 | PsiElement psiLocalVariable = psiElement.getParent(); 45 | if(psiLocalVariable instanceof PsiLocalVariable) { 46 | return matchInflate((PsiLocalVariable) psiLocalVariable); 47 | } 48 | 49 | return null; 50 | 51 | } 52 | 53 | @Nullable 54 | public static InflateContainer matchInflate(PsiLocalVariable psiLocalVariable) { 55 | PsiType psiType = psiLocalVariable.getType(); 56 | if(psiType instanceof PsiClassReferenceType) { 57 | PsiMethodCallExpression psiMethodCallExpression = PsiTreeUtil.findChildOfType(psiLocalVariable, PsiMethodCallExpression.class); 58 | if(psiMethodCallExpression != null) { 59 | PsiMethod psiMethod = psiMethodCallExpression.resolveMethod(); 60 | 61 | // @TODO: replace "inflate"; resolve method and check nethod calls 62 | if(psiMethod != null && psiMethod.getName().equals("inflate")) { 63 | PsiExpression[] expressions = psiMethodCallExpression.getArgumentList().getExpressions(); 64 | if(expressions.length > 0 && expressions[0] instanceof PsiReferenceExpression) { 65 | PsiFile xmlFile = AndroidUtils.findXmlResource((PsiReferenceExpression) expressions[0]); 66 | if(xmlFile != null) { 67 | return new InflateContainer(xmlFile, ((PsiLocalVariable) psiLocalVariable)); 68 | } 69 | } 70 | } 71 | } 72 | } 73 | 74 | return null; 75 | } 76 | 77 | public static class InflateContainer { 78 | 79 | final private PsiFile xmlFile; 80 | final private PsiLocalVariable psiLocalVariable; 81 | 82 | public InflateContainer(PsiFile xmlFile, PsiLocalVariable psiLocalVariable) { 83 | this.xmlFile = xmlFile; 84 | this.psiLocalVariable = psiLocalVariable; 85 | } 86 | 87 | public PsiLocalVariable getPsiLocalVariable() { 88 | return psiLocalVariable; 89 | } 90 | 91 | public PsiFile getXmlFile() { 92 | return xmlFile; 93 | } 94 | 95 | } 96 | 97 | 98 | 99 | 100 | } 101 | 102 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/linemarker/FragmentRelatedFileLineMarker.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.linemarker; 2 | 3 | import com.intellij.codeInsight.daemon.LineMarkerInfo; 4 | import com.intellij.codeInsight.daemon.LineMarkerProvider; 5 | import com.intellij.navigation.GotoRelatedItem; 6 | import com.intellij.psi.*; 7 | import com.intellij.psi.util.PsiTreeUtil; 8 | import com.intellij.util.ConstantFunction; 9 | import de.espend.idea.android.RelatedPopupGotoLineMarker; 10 | import de.espend.idea.android.utils.AndroidUtils; 11 | import icons.AndroidIcons; 12 | import org.jetbrains.android.AndroidLineMarkerProvider; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | import java.util.ArrayList; 17 | import java.util.Collection; 18 | import java.util.List; 19 | 20 | public class FragmentRelatedFileLineMarker implements LineMarkerProvider { 21 | 22 | @Nullable 23 | @Override 24 | public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) { 25 | return null; 26 | } 27 | 28 | @Override 29 | public void collectSlowLineMarkers(@NotNull List elements, @NotNull Collection result) { 30 | 31 | for(PsiElement psiElement : elements) { 32 | 33 | List gotoRelatedItems = new ArrayList(); 34 | List psiFiles = new ArrayList(); 35 | 36 | // android studio provide line marker with xml targets only on root classes not on class inside classes like fragments 37 | // we support all of them :) 38 | if(psiElement instanceof PsiIdentifier && psiElement.getParent() instanceof PsiClass && !(psiElement.getParent().getParent() instanceof PsiFile)) { 39 | 40 | // simple hack activity provide this on core 41 | if(isFragmentClass((PsiClass) psiElement.getParent())) { 42 | Collection PsiMethodCallExpressions = PsiTreeUtil.collectElementsOfType(psiElement.getParent(), PsiMethodCallExpression.class); 43 | for(PsiMethodCallExpression methodCallExpression: PsiMethodCallExpressions) { 44 | PsiMethod psiMethod = methodCallExpression.resolveMethod(); 45 | if(psiMethod != null && psiMethod.getName().equals("inflate")) { 46 | PsiExpression[] expressions = methodCallExpression.getArgumentList().getExpressions(); 47 | if(expressions.length > 0 && expressions[0] instanceof PsiReferenceExpression) { 48 | PsiFile xmlFile = AndroidUtils.findXmlResource((PsiReferenceExpression) expressions[0]); 49 | if(xmlFile != null && !psiFiles.contains(xmlFile)) { 50 | psiFiles.add(xmlFile); 51 | gotoRelatedItems.add(new GotoRelatedItem(xmlFile)); 52 | } 53 | } 54 | } 55 | } 56 | } 57 | 58 | } 59 | 60 | if(gotoRelatedItems.size() > 0) { 61 | result.add(new LineMarkerInfo(psiElement, psiElement.getTextOffset(), AndroidIcons.AndroidToolWindow, 6, new ConstantFunction("Related Files"), new RelatedPopupGotoLineMarker.NavigationHandler(gotoRelatedItems))); 62 | } 63 | 64 | } 65 | 66 | } 67 | 68 | private boolean isFragmentClass(PsiClass psiClass) { 69 | 70 | PsiReferenceList extendsList = psiClass.getExtendsList(); 71 | if(extendsList == null) { 72 | return false; 73 | } 74 | 75 | // @TODO: replace this one with instance check 76 | PsiClassType[] tests = extendsList.getReferencedTypes(); 77 | for(PsiClassType psiClassType: tests) { 78 | if(psiClassType.getClassName().contains("Activity")) { 79 | return false; 80 | } 81 | if(psiClassType.getClassName().contains("Fragment")) { 82 | return true; 83 | } 84 | } 85 | 86 | return false; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/linemarker/InflateLayoutLineMarkerProvider.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.linemarker; 2 | 3 | import com.intellij.codeInsight.daemon.LineMarkerInfo; 4 | import com.intellij.codeInsight.daemon.LineMarkerProvider; 5 | import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder; 6 | import com.intellij.psi.*; 7 | import de.espend.idea.android.utils.AndroidUtils; 8 | import icons.AndroidIcons; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | import java.util.Collection; 13 | import java.util.List; 14 | 15 | public class InflateLayoutLineMarkerProvider implements LineMarkerProvider { 16 | 17 | @Nullable 18 | @Override 19 | public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) { 20 | return null; 21 | } 22 | 23 | @Override 24 | public void collectSlowLineMarkers(@NotNull List elements, @NotNull Collection result) { 25 | for(PsiElement psiElement : elements) { 26 | 27 | if(psiElement instanceof PsiMethodCallExpression) { 28 | PsiMethod psiMethod = ((PsiCallExpression) psiElement).resolveMethod(); 29 | if(psiMethod != null && ("inflate".equals(psiMethod.getName()) || "setContentView".equals(psiMethod.getName()))) { 30 | PsiExpressionList psiExpressionList = ((PsiCallExpression) psiElement).getArgumentList(); 31 | if(psiExpressionList != null) { 32 | PsiExpression[] psiExpressions = psiExpressionList.getExpressions(); 33 | if(psiExpressions.length > 0 && psiExpressions[0].getText().startsWith("R.layout")) { 34 | String layoutText = psiExpressions[0].getText(); 35 | 36 | PsiFile xmlFile = AndroidUtils.findXmlResource(psiElement.getProject(), layoutText); 37 | if(xmlFile != null) { 38 | 39 | NavigationGutterIconBuilder builder = NavigationGutterIconBuilder.create(AndroidIcons.Views.Fragment). 40 | setTooltipText(xmlFile.getName()). 41 | setTargets(xmlFile); 42 | 43 | result.add(builder.createLineMarkerInfo(psiElement)); 44 | } 45 | 46 | } 47 | } 48 | } 49 | } 50 | 51 | } 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/linemarker/ViewInflateLineMarker.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.linemarker; 2 | 3 | import com.intellij.codeInsight.daemon.LineMarkerInfo; 4 | import com.intellij.codeInsight.daemon.LineMarkerProvider; 5 | import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder; 6 | import com.intellij.psi.*; 7 | import com.intellij.psi.search.GlobalSearchScope; 8 | import com.intellij.psi.util.PsiTreeUtil; 9 | import de.espend.idea.android.AndroidView; 10 | import de.espend.idea.android.utils.AndroidUtils; 11 | import de.espend.idea.android.utils.AndroidViewUtil; 12 | import icons.AndroidIcons; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | import javax.swing.*; 17 | import java.util.Collection; 18 | import java.util.List; 19 | 20 | public class ViewInflateLineMarker implements LineMarkerProvider { 21 | 22 | @Nullable 23 | @Override 24 | public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) { 25 | return null; 26 | } 27 | 28 | @Override 29 | public void collectSlowLineMarkers(@NotNull List elements, @NotNull Collection result) { 30 | 31 | for(PsiElement psiElement : elements) { 32 | if(psiElement instanceof PsiMethodCallExpression) { 33 | attachFindViewByIdInflate((PsiMethodCallExpression) psiElement, result); 34 | attachFindViewByIdSetContentViews((PsiMethodCallExpression) psiElement, result); 35 | } 36 | } 37 | 38 | } 39 | private void attachFindViewByIdInflate(PsiMethodCallExpression psiMethodCallExpression, @NotNull Collection result) { 40 | AndroidView androidView = AndroidViewUtil.getAndroidView(psiMethodCallExpression); 41 | if(androidView != null) { 42 | attachLineIcon(androidView, psiMethodCallExpression, result); 43 | } 44 | } 45 | 46 | private void attachFindViewByIdSetContentViews(PsiMethodCallExpression psiMethodCallExpression, @NotNull Collection result) { 47 | 48 | PsiExpression[] psiExpressions = psiMethodCallExpression.getArgumentList().getExpressions(); 49 | if(psiExpressions.length == 0) { 50 | return; 51 | } 52 | 53 | PsiMethod psiMethodResolved = psiMethodCallExpression.resolveMethod(); 54 | if(psiMethodResolved == null) { 55 | return; 56 | } 57 | 58 | if("findViewById".equals(psiMethodResolved.getName())) { 59 | String viewId = psiExpressions[0].getText(); 60 | 61 | PsiMethod psiMethod = PsiTreeUtil.getParentOfType(psiMethodCallExpression, PsiMethod.class); 62 | if(psiMethod != null) { 63 | for(PsiFile psiFile : AndroidViewUtil.findLayoutFilesInsideMethod(psiMethod)) { 64 | AndroidView androidView = AndroidUtils.getViewType(psiFile, viewId); 65 | if(androidView != null) { 66 | attachLineIcon(androidView, psiMethodCallExpression, result); 67 | } 68 | } 69 | } 70 | } 71 | 72 | } 73 | 74 | private void attachLineIcon(@NotNull AndroidView view, @NotNull PsiElement psiElement, @NotNull Collection result) { 75 | 76 | JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(psiElement.getProject()); 77 | PsiClass psiClass = psiFacade.findClass(view.getName(), GlobalSearchScope.allScope(psiElement.getProject())); 78 | if(psiClass == null) { 79 | return; 80 | } 81 | 82 | Icon icon = AndroidViewUtil.getCoreIconWithExtends(view, psiClass); 83 | if(icon == null) { 84 | icon = AndroidIcons.Views.View; 85 | } 86 | 87 | NavigationGutterIconBuilder builder = NavigationGutterIconBuilder.create(icon). 88 | setTooltipText(view.getName()). 89 | setTargets(view.getXmlTarget()); 90 | 91 | result.add(builder.createLineMarkerInfo(psiElement)); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/utils/AndroidUtils.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.utils; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import com.intellij.openapi.vfs.VfsUtil; 5 | import com.intellij.openapi.vfs.VirtualFile; 6 | import com.intellij.psi.*; 7 | import com.intellij.psi.search.FilenameIndex; 8 | import com.intellij.psi.search.GlobalSearchScope; 9 | import com.intellij.psi.xml.XmlAttribute; 10 | import com.intellij.psi.xml.XmlTag; 11 | import de.espend.idea.android.AndroidView; 12 | import org.jetbrains.annotations.NotNull; 13 | import org.jetbrains.annotations.Nullable; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | 19 | public class AndroidUtils { 20 | 21 | @Nullable 22 | public static PsiFile findXmlResource(@Nullable PsiReferenceExpression referenceExpression) { 23 | if (referenceExpression == null) return null; 24 | 25 | PsiElement firstChild = referenceExpression.getFirstChild(); 26 | if (firstChild == null || !"R.layout".equals(firstChild.getText())) { 27 | return null; 28 | } 29 | 30 | PsiElement lastChild = referenceExpression.getLastChild(); 31 | if(lastChild == null) { 32 | return null; 33 | } 34 | 35 | String name = String.format("%s.xml", lastChild.getText()); 36 | PsiFile[] foundFiles = FilenameIndex.getFilesByName(referenceExpression.getProject(), name, GlobalSearchScope.allScope(referenceExpression.getProject())); 37 | if (foundFiles.length <= 0) { 38 | return null; 39 | } 40 | 41 | return foundFiles[0]; 42 | } 43 | 44 | public static List getProjectViews(Project project) { 45 | 46 | List androidViews = new ArrayList(); 47 | for(PsiFile psiFile: getLayoutFiles(project)) { 48 | androidViews.addAll(getIDsFromXML(psiFile)); 49 | } 50 | 51 | return androidViews; 52 | } 53 | 54 | public static List getLayoutFiles(Project project) { 55 | 56 | List psiFileList = new ArrayList(); 57 | 58 | for (VirtualFile virtualFile : FilenameIndex.getAllFilesByExt(project, "xml")) { 59 | VirtualFile parent = virtualFile.getParent(); 60 | if (parent != null && "layout".equals(parent.getName())) { 61 | String relative = VfsUtil.getRelativePath(virtualFile, project.getBaseDir(), '/'); 62 | if (relative != null) { 63 | PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); 64 | if (psiFile != null) { 65 | psiFileList.add(psiFile); 66 | } 67 | } 68 | } 69 | } 70 | 71 | return psiFileList; 72 | } 73 | 74 | @Nullable 75 | public static PsiFile findXmlResource(Project project, String layoutName) { 76 | 77 | if (!layoutName.startsWith("R.layout.")) { 78 | return null; 79 | } 80 | 81 | layoutName = layoutName.substring("R.layout.".length()); 82 | 83 | String name = String.format("%s.xml", layoutName); 84 | PsiFile[] foundFiles = FilenameIndex.getFilesByName(project, name, GlobalSearchScope.allScope(project)); 85 | if (foundFiles.length <= 0) { 86 | return null; 87 | } 88 | 89 | return foundFiles[0]; 90 | } 91 | 92 | @NotNull 93 | public static List getIDsFromXML(@NotNull PsiFile f) { 94 | final ArrayList ret = new ArrayList(); 95 | f.accept(new XmlRecursiveElementVisitor() { 96 | @Override 97 | public void visitElement(final PsiElement element) { 98 | super.visitElement(element); 99 | if (element instanceof XmlTag) { 100 | XmlTag t = (XmlTag) element; 101 | XmlAttribute id = t.getAttribute("android:id", null); 102 | if (id == null) { 103 | return; 104 | } 105 | final String val = id.getValue(); 106 | if (val == null) { 107 | return; 108 | } 109 | ret.add(new AndroidView(val, t.getName(), id)); 110 | 111 | } 112 | 113 | } 114 | }); 115 | 116 | return ret; 117 | } 118 | 119 | @Nullable 120 | public static AndroidView getViewType(@NotNull PsiFile f, String findId) { 121 | 122 | // @TODO: replace dup for 123 | List views = getIDsFromXML(f); 124 | 125 | for(AndroidView view: views) { 126 | if(findId.equals(view.getId())) { 127 | return view; 128 | } 129 | } 130 | 131 | return null; 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /src/de/espend/idea/android/utils/JavaPsiUtil.java: -------------------------------------------------------------------------------- 1 | package de.espend.idea.android.utils; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import com.intellij.psi.JavaPsiFacade; 5 | import com.intellij.psi.PsiClass; 6 | import com.intellij.psi.PsiClassType; 7 | import com.intellij.psi.impl.PsiClassImplUtil; 8 | import com.intellij.psi.search.GlobalSearchScope; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | public class JavaPsiUtil { 12 | 13 | @Nullable 14 | public static PsiClass getClass(Project project, String qualifiedClassName) { 15 | JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); 16 | return psiFacade.findClass(qualifiedClassName, GlobalSearchScope.allScope(project)); 17 | } 18 | 19 | public static boolean isInstanceOf(PsiClass instance, PsiClass interfaceExtendsClass) { 20 | 21 | String className = interfaceExtendsClass.getQualifiedName(); 22 | if(className == null) { 23 | return true; 24 | } 25 | 26 | if(className.equals(instance.getQualifiedName())) { 27 | return true; 28 | } 29 | 30 | for(PsiClassType psiClassType: PsiClassImplUtil.getExtendsListTypes(instance)) { 31 | PsiClass resolve = psiClassType.resolve(); 32 | if(resolve != null) { 33 | if(className.equals(resolve.getQualifiedName())) { 34 | return true; 35 | } 36 | } 37 | } 38 | 39 | for(PsiClass psiInterface: PsiClassImplUtil.getInterfaces(instance)) { 40 | if(className.equals(psiInterface.getQualifiedName())) { 41 | return true; 42 | } 43 | } 44 | 45 | return false; 46 | } 47 | } 48 | --------------------------------------------------------------------------------