private void updateDirectories(boolean updateFileCombo) { final Module module = getModule(); List<VirtualFile> valuesDirs = Collections.emptyList(); if (module != null) { final AndroidFacet facet = AndroidFacet.getInstance(module); if (facet != null) { myResourceDir = AndroidRootUtil.getResourceDir(facet); if (myResourceDir != null) { valuesDirs = AndroidResourceUtil.getResourceSubdirs( ResourceFolderType.VALUES.getName(), new VirtualFile[] {myResourceDir}); } } } Collections.sort( valuesDirs, new Comparator<VirtualFile>() { @Override public int compare(VirtualFile f1, VirtualFile f2) { return f1.getName().compareTo(f2.getName()); } }); final Map<String, JCheckBox> oldCheckBoxes = myCheckBoxes; final int selectedIndex = myDirectoriesList.getSelectedIndex(); final String selectedDirName = selectedIndex >= 0 ? myDirNames[selectedIndex] : null; final List<JCheckBox> checkBoxList = new ArrayList<JCheckBox>(); myCheckBoxes = new HashMap<String, JCheckBox>(); myDirNames = new String[valuesDirs.size()]; int newSelectedIndex = -1; int i = 0; for (VirtualFile dir : valuesDirs) { final String dirName = dir.getName(); final JCheckBox oldCheckBox = oldCheckBoxes.get(dirName); final boolean selected = oldCheckBox != null && oldCheckBox.isSelected(); final JCheckBox checkBox = new JCheckBox(dirName, selected); checkBoxList.add(checkBox); myCheckBoxes.put(dirName, checkBox); myDirNames[i] = dirName; if (dirName.equals(selectedDirName)) { newSelectedIndex = i; } i++; } myDirectoriesList.setModel(new CollectionListModel<JCheckBox>(checkBoxList)); if (newSelectedIndex >= 0) { myDirectoriesList.setSelectedIndex(newSelectedIndex); } if (checkBoxList.size() == 1) { checkBoxList.get(0).setSelected(true); } if (updateFileCombo) { final Object oldItem = myFileNameCombo.getEditor().getItem(); final Set<String> fileNameSet = new HashSet<String>(); for (VirtualFile valuesDir : valuesDirs) { for (VirtualFile file : valuesDir.getChildren()) { fileNameSet.add(file.getName()); } } final List<String> fileNames = new ArrayList<String>(fileNameSet); Collections.sort(fileNames); myFileNameCombo.setModel(new DefaultComboBoxModel(fileNames.toArray())); myFileNameCombo.getEditor().setItem(oldItem); } }
@Override protected void postWriteAction() throws ConsumerException { // now write the values files. for (String key : mValuesResMap.keySet()) { // the key is the qualifier. // check if we have to write the file due to deleted values. // also remove it from that list anyway (to detect empty qualifiers later). boolean mustWriteFile = mQualifierWithDeletedValues.remove(key); // get the list of items to write List<ResourceItem> items = mValuesResMap.get(key); // now check if we really have to write it if (!mustWriteFile) { for (ResourceItem item : items) { if (item.isTouched()) { mustWriteFile = true; break; } } } if (mustWriteFile) { String folderName = key.isEmpty() ? ResourceFolderType.VALUES.getName() : ResourceFolderType.VALUES.getName() + RES_QUALIFIER_SEP + key; try { File valuesFolder = new File(getRootFolder(), folderName); createDir(valuesFolder); File outFile = new File(valuesFolder, FN_VALUES_XML); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setValidating(false); factory.setIgnoringComments(true); DocumentBuilder builder; builder = factory.newDocumentBuilder(); Document document = builder.newDocument(); Node rootNode = document.createElement(TAG_RESOURCES); document.appendChild(rootNode); Collections.sort(items); ResourceFile currentFile = null; for (ResourceItem item : items) { ResourceFile source = item.getSource(); if (source != currentFile) { currentFile = source; rootNode.appendChild(document.createTextNode("\n")); File file = source.getFile(); rootNode.appendChild(document.createComment(createPathComment(file))); rootNode.appendChild(document.createTextNode("\n")); } Node adoptedNode = NodeUtils.adoptNode(document, item.getValue()); rootNode.appendChild(adoptedNode); } String content; try { content = XmlPrettyPrinter.prettyPrint(document, true); } catch (Throwable t) { content = XmlUtils.toXml(document, false); } Files.write(content, outFile, Charsets.UTF_8); } catch (Throwable t) { throw new ConsumerException(t); } } } // now remove empty values files. for (String key : mQualifierWithDeletedValues) { String folderName = key != null && !key.isEmpty() ? ResourceFolderType.VALUES.getName() + RES_QUALIFIER_SEP + key : ResourceFolderType.VALUES.getName(); removeOutFile(folderName, FN_VALUES_XML); } }
@Nullable public static String doExtractStyle( @NotNull Module module, @NotNull final XmlTag viewTag, final boolean addStyleAttributeToTag, @Nullable MyTestConfig testConfig) { final PsiFile file = viewTag.getContainingFile(); if (file == null) { return null; } final String dialogTitle = AndroidBundle.message("android.extract.style.title"); final String fileName = AndroidResourceUtil.getDefaultResourceFileName(ResourceType.STYLE); assert fileName != null; final List<String> dirNames = Arrays.asList(ResourceFolderType.VALUES.getName()); final List<XmlAttribute> extractableAttributes = getExtractableAttributes(viewTag); final Project project = module.getProject(); if (extractableAttributes.size() == 0) { AndroidUtils.reportError( project, "The tag doesn't contain any attributes that can be extracted", dialogTitle); return null; } final LayoutViewElement viewElement = getLayoutViewElement(viewTag); assert viewElement != null; final ResourceValue parentStyleVlaue = viewElement.getStyle().getValue(); final String parentStyle; boolean supportImplicitParent = false; if (parentStyleVlaue != null) { parentStyle = parentStyleVlaue.getResourceName(); if (!ResourceType.STYLE.getName().equals(parentStyleVlaue.getResourceType()) || parentStyle == null || parentStyle.length() == 0) { AndroidUtils.reportError( project, "Invalid parent style reference " + parentStyleVlaue.toString(), dialogTitle); return null; } supportImplicitParent = parentStyleVlaue.getPackage() == null; } else { parentStyle = null; } final String styleName; final List<XmlAttribute> styledAttributes; final Module chosenModule; if (testConfig == null) { final ExtractStyleDialog dialog = new ExtractStyleDialog( module, fileName, supportImplicitParent ? parentStyle : null, dirNames, extractableAttributes); dialog.setTitle(dialogTitle); dialog.show(); if (!dialog.isOK()) { return null; } chosenModule = dialog.getChosenModule(); assert chosenModule != null; styledAttributes = dialog.getStyledAttributes(); styleName = dialog.getStyleName(); } else { testConfig.validate(extractableAttributes); chosenModule = testConfig.getModule(); styleName = testConfig.getStyleName(); final Set<String> attrsToExtract = new HashSet<String>(Arrays.asList(testConfig.getAttributesToExtract())); styledAttributes = new ArrayList<XmlAttribute>(); for (XmlAttribute attribute : extractableAttributes) { if (attrsToExtract.contains(attribute.getName())) { styledAttributes.add(attribute); } } } final boolean[] success = {false}; final boolean finalSupportImplicitParent = supportImplicitParent; new WriteCommandAction(project, "Extract Android Style '" + styleName + "'", file) { @Override protected void run(final Result result) throws Throwable { final List<XmlAttribute> attributesToDelete = new ArrayList<XmlAttribute>(); if (!AndroidResourceUtil.createValueResource( chosenModule, styleName, ResourceType.STYLE, fileName, dirNames, new Processor<ResourceElement>() { @Override public boolean process(ResourceElement element) { assert element instanceof Style; final Style style = (Style) element; for (XmlAttribute attribute : styledAttributes) { if (SdkConstants.NS_RESOURCES.equals(attribute.getNamespace())) { final StyleItem item = style.addItem(); item.getName().setStringValue("android:" + attribute.getLocalName()); item.setStringValue(attribute.getValue()); attributesToDelete.add(attribute); } } if (parentStyleVlaue != null && (!finalSupportImplicitParent || !styleName.startsWith(parentStyle + "."))) { final String aPackage = parentStyleVlaue.getPackage(); style .getParentStyle() .setStringValue((aPackage != null ? aPackage + ":" : "") + parentStyle); } return true; } })) { return; } ApplicationManager.getApplication() .runWriteAction( new Runnable() { @Override public void run() { for (XmlAttribute attribute : attributesToDelete) { attribute.delete(); } if (addStyleAttributeToTag) { final LayoutViewElement viewElement = getLayoutViewElement(viewTag); assert viewElement != null; viewElement.getStyle().setStringValue("@style/" + styleName); } } }); success[0] = true; } @Override protected UndoConfirmationPolicy getUndoConfirmationPolicy() { return UndoConfirmationPolicy.REQUEST_CONFIRMATION; } }.execute(); return success[0] ? styleName : null; }