Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Bas Leijdekkers
2012-03-19 10:15:09 +01:00
42 changed files with 1400 additions and 392 deletions
@@ -79,14 +79,13 @@ import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
@NotNull public static final Icon ICON = IconLoader.getIcon("/modules/annotation.png");
private static final Logger LOG = Logger.getInstance("#" + ExternalAnnotationsManagerImpl.class.getName());
@NotNull private final ConcurrentMap<String, List<XmlFile>> myExternalAnnotations = new ConcurrentWeakValueHashMap<String, List<XmlFile>>();
@NotNull private final AtomicReference<ThreeState> myHasAnyAnnotationsRoots = new AtomicReference<ThreeState>(ThreeState.UNSURE);
@NotNull private volatile ThreeState myHasAnyAnnotationsRoots = ThreeState.UNSURE;
@NotNull private static final List<XmlFile> NULL = new ArrayList<XmlFile>();
private final PsiManager myPsiManager;
@@ -94,38 +93,42 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
myPsiManager = psiManager;
final MessageBusConnection connection = project.getMessageBus().connect(project);
connection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() {
@Override
public void beforeRootsChange(ModuleRootEvent event) {
}
@Override
public void rootsChanged(ModuleRootEvent event) {
myExternalAnnotations.clear();
myHasAnyAnnotationsRoots.set(ThreeState.UNSURE);
myHasAnyAnnotationsRoots = ThreeState.UNSURE;
}
});
}
private ThreeState hasAnyAnnotationsRoots() {
if (myHasAnyAnnotationsRoots.get() == ThreeState.UNSURE) {
if (myHasAnyAnnotationsRoots == ThreeState.UNSURE) {
final Module[] modules = ModuleManager.getInstance(myPsiManager.getProject()).getModules();
for (Module module : modules) {
for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
final String[] urls = AnnotationOrderRootType.getUrls(entry);
if (urls.length > 0) {
myHasAnyAnnotationsRoots.set(ThreeState.YES);
myHasAnyAnnotationsRoots = ThreeState.YES;
return ThreeState.YES;
}
}
}
myHasAnyAnnotationsRoots.set(ThreeState.NO);
myHasAnyAnnotationsRoots = ThreeState.NO;
}
return myHasAnyAnnotationsRoots.get();
return myHasAnyAnnotationsRoots;
}
@Override
@Nullable
public PsiAnnotation findExternalAnnotation(@NotNull final PsiModifierListOwner listOwner, @NotNull final String annotationFQN) {
return collectExternalAnnotations(listOwner).get(annotationFQN);
}
@Override
@Nullable
public PsiAnnotation[] findExternalAnnotations(@NotNull final PsiModifierListOwner listOwner) {
final Map<String, PsiAnnotation> result = collectExternalAnnotations(listOwner);
@@ -135,11 +138,11 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
@NotNull
private Map<String, PsiAnnotation> collectExternalAnnotations(@NotNull final PsiModifierListOwner listOwner) {
if (hasAnyAnnotationsRoots() == ThreeState.NO) return Collections.emptyMap();
final Map<String, PsiAnnotation> result = new HashMap<String, PsiAnnotation>();
final List<XmlFile> files = findExternalAnnotationsFile(listOwner);
final List<XmlFile> files = findExternalAnnotationsFiles(listOwner);
if (files == null) {
return Collections.emptyMap();
}
final Map<String, PsiAnnotation> result = new HashMap<String, PsiAnnotation>();
for (XmlFile file : files) {
if (!file.isValid()) continue;
final XmlDocument document = file.getDocument();
@@ -168,7 +171,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
"@" + annotationFQN + (buf.length() > 0 ? "(" + StringUtil.trimStart(buf.toString(), ",") + ")" : "");
try {
result.put(annotationFQN,
JavaPsiFacade.getInstance(listOwner.getProject()).getElementFactory().createAnnotationFromText(
JavaPsiFacade.getInstance(myPsiManager.getProject()).getElementFactory().createAnnotationFromText(
annotationText, null));
}
catch (IncorrectOperationException e) {
@@ -186,11 +189,12 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
}
@Override
public void annotateExternally(@NotNull final PsiModifierListOwner listOwner,
@NotNull final String annotationFQName,
@NotNull final PsiFile fromFile,
final PsiNameValuePair[] value) {
final Project project = listOwner.getProject();
final Project project = myPsiManager.getProject();
final PsiFile containingFile = listOwner.getContainingFile();
if (!(containingFile instanceof PsiJavaFile)) {
return;
@@ -215,6 +219,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
return;
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
setupRootAndAnnotateExternally(entry, project, listOwner, annotationFQName, fromFile, packageName, virtualFile, value);
}
@@ -240,9 +245,10 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
return;
}
new WriteCommandAction(project) {
@Override
protected void run(final Result result) throws Throwable {
appendChosenAnnotationsRoot(entry, file);
final List<XmlFile> xmlFiles = findExternalAnnotationsFile(listOwner);
final List<XmlFile> xmlFiles = findExternalAnnotationsFiles(listOwner);
if (xmlFiles != null) { //file already exists under appeared content root
if (!CodeInsightUtilBase.preparePsiElementForWrite(xmlFiles.get(0))) return;
annotateExternally(listOwner, annotationFQName, xmlFiles.get(0), fromFile, value);
@@ -314,7 +320,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
@NotNull final PsiFile fromFile,
final PsiNameValuePair[] value) {
final XmlFile[] annotationsXml = new XmlFile[1];
List<XmlFile> xmlFiles = findExternalAnnotationsFile(listOwner);
List<XmlFile> xmlFiles = findExternalAnnotationsFiles(listOwner);
if (xmlFiles != null) {
for (XmlFile xmlFile : xmlFiles) {
final VirtualFile vXmlFile = xmlFile.getVirtualFile();
@@ -330,6 +336,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
final List<XmlFile> annotationFiles = new ArrayList<XmlFile>(xmlFiles);
new WriteCommandAction(project) {
@Override
protected void run(final Result result) throws Throwable {
if (annotationsXml[0] == null) {
annotationsXml[0] = createAnnotationsXml(file, packageName);
@@ -343,8 +350,9 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
}.execute();
}
@Override
public boolean deannotate(@NotNull final PsiModifierListOwner listOwner, @NotNull final String annotationFQN) {
final List<XmlFile> files = findExternalAnnotationsFile(listOwner);
final List<XmlFile> files = findExternalAnnotationsFiles(listOwner);
if (files != null) {
for (XmlFile file : files) {
if (file.isValid()) {
@@ -359,7 +367,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
if (Comparing.strEqual(className, externalName) || Comparing.strEqual(className, oldExternalName)) {
for (XmlTag annotationTag : tag.getSubTags()) {
if (Comparing.strEqual(annotationTag.getAttributeValue("name"), annotationFQN)) {
if (ReadonlyStatusHandler.getInstance(file.getProject())
if (ReadonlyStatusHandler.getInstance(myPsiManager.getProject())
.ensureFilesWritable(file.getVirtualFile()).hasReadonlyFiles()) {
return false;
}
@@ -386,11 +394,12 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
return false;
}
@Override
@NotNull
public AnnotationPlace chooseAnnotationsPlace(@NotNull final PsiElement element) {
if (!element.isPhysical()) return AnnotationPlace.IN_CODE; //element just created
if (!element.getManager().isInProject(element)) return AnnotationPlace.EXTERNAL;
final Project project = element.getProject();
final Project project = myPsiManager.getProject();
final PsiFile containingFile = element.getContainingFile();
final VirtualFile virtualFile = containingFile.getVirtualFile();
LOG.assertTrue(virtualFile != null);
@@ -472,7 +481,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
myExternalAnnotations.clear();
}
private static void annotateExternally(final PsiModifierListOwner listOwner,
private void annotateExternally(final PsiModifierListOwner listOwner,
final String annotationFQName,
@Nullable final XmlFile xmlFile,
@NotNull PsiFile codeUsageFile,
@@ -492,7 +501,8 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
break;
}
}
tag.add(XmlElementFactory.getInstance(xmlFile.getProject()).createTagFromText(createAnnotationTag(annotationFQName, values)));
tag.add(XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText(
createAnnotationTag(annotationFQName, values)));
return;
}
}
@@ -500,7 +510,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
"<item name=\'" + externalName + "\'>\n";
text += createAnnotationTag(annotationFQName, values);
text += "</item>";
rootTag.add(XmlElementFactory.getInstance(xmlFile.getProject()).createTagFromText(text));
rootTag.add(XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText(text));
}
}
}
@@ -520,13 +530,13 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
if (values != null) {
text = " <annotation name=\'" + annotationFQName + "\'>\n";
text += StringUtil.join(values, new Function<PsiNameValuePair, String>() {
@NonNls
@NotNull
@Override
public String fun(@NotNull PsiNameValuePair pair) {
if (pair.getName() != null) {
return "<val name=\"" + pair.getName() + "\" val=\"" + StringUtil.escapeXml(pair.getValue().getText()) + "\"/>";
}
return "<val val=\"" + StringUtil.escapeXml(pair.getValue().getText()) + "\"/>";
return "<val" +
(pair.getName() != null ? " name=\"" + pair.getName() + "\"" : "") +
" val=\"" + StringUtil.escapeXml(pair.getValue().getText()) + "\"/>";
}
}, " \n");
text += " </annotation>";
@@ -572,8 +582,8 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
}
@Nullable
private List<XmlFile> findExternalAnnotationsFile(@NotNull PsiModifierListOwner listOwner) {
final Project project = listOwner.getProject();
private List<XmlFile> findExternalAnnotationsFiles(@NotNull PsiModifierListOwner listOwner) {
final Project project = myPsiManager.getProject();
final PsiFile containingFile = listOwner.getContainingFile();
if (!(containingFile instanceof PsiJavaFile)) {
return null;
@@ -672,15 +682,18 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
init();
}
@Override
protected String getOkActionName() {
return ADD_IN_CODE;
}
@Override
@NotNull
protected String getCancelActionName() {
return CommonBundle.getCancelButtonText();
}
@Override
@NotNull
@SuppressWarnings({"NonStaticInitializer"})
protected Action[] createActions() {
@@ -692,6 +705,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
assignMnemonic(externalName, this);
}
@Override
public void actionPerformed(final ActionEvent e) {
if (canBeHidden()) {
setToBeShown(toBeShown(), true);
@@ -701,20 +715,24 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
}, getCancelAction()};
}
@Override
protected boolean isToBeShown() {
return CodeStyleSettingsManager.getSettings(myProject).USE_EXTERNAL_ANNOTATIONS;
}
@Override
protected void setToBeShown(boolean value, boolean onOk) {
CodeStyleSettingsManager.getSettings(myProject).USE_EXTERNAL_ANNOTATIONS = value;
}
@Override
protected JComponent createNorthPanel() {
final JPanel northPanel = (JPanel)super.createNorthPanel();
northPanel.add(new JLabel(MESSAGE), BorderLayout.CENTER);
return northPanel;
}
@Override
protected boolean shouldSaveOptionsOnCancel() {
return true;
}
@@ -33,8 +33,6 @@ public class UnscrambleListener implements ApplicationActivationListener {
@Override
public void applicationActivated(final IdeFrame ideFrame) {
if (SystemInfo.isMac) return;
final Runnable processClipboard = new Runnable() {
@Override
public void run() {
@@ -44,7 +44,7 @@ public abstract class JavaCodeInsightFixtureTestCase extends UsefulTestCase{
protected void setUp() throws Exception {
super.setUp();
final TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder();
final TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName());
myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture());
final JavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(JavaModuleFixtureBuilder.class);
moduleFixtureBuilder.addSourceContentRoot(myFixture.getTempDirPath());
@@ -15,6 +15,8 @@
*/
package com.intellij.testFramework.fixtures;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
@@ -41,8 +43,15 @@ public abstract class JavaTestFixtureFactory {
public abstract JavaCodeInsightTestFixture createCodeInsightFixture(IdeaProjectTestFixture projectFixture, TempDirTestFixture tempDirFixture);
/**
*
* @deprecated use {@link JavaTestFixtureFactory#createFixtureBuilder(String)}
*/
//also implicitly initializes ourInstance and registers java module fixture builder
public static TestFixtureBuilder<IdeaProjectTestFixture> createFixtureBuilder() {
return IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder();
}
public static TestFixtureBuilder<IdeaProjectTestFixture> createFixtureBuilder(@NotNull String name) {
return IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(name);
}
}
@@ -2,17 +2,16 @@ package org.jetbrains.jps.incremental;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import org.jetbrains.ether.dependencyView.Mappings;
import org.jetbrains.jps.Module;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.ProjectPaths;
import org.jetbrains.jps.incremental.messages.ProgressMessage;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.*;
/**
* Use {@link BuilderService} to register implementations of this class
@@ -103,6 +102,18 @@ public abstract class ModuleLevelBuilder extends Builder {
context.processMessage(new ProgressMessage("Found " + newlyAffectedFiles.size() + " affected files"));
if (!newlyAffectedFiles.isEmpty()) {
if (LOG.isDebugEnabled()) {
final List<Pair<File, Module>> wrongFiles = checkAffectedFilesInCorrectModules(context, chunk, newlyAffectedFiles);
if (!wrongFiles.isEmpty()) {
LOG.debug("Wrong affected files for module chunk " + chunk.getName() + ": ");
for (Pair<File, Module> pair : wrongFiles) {
LOG.debug("\t[" + pair.second.getName() + "] " + pair.first.getPath());
}
}
}
for (File file : newlyAffectedFiles) {
context.markDirtyIfNotDeleted(file);
}
@@ -135,6 +146,45 @@ public abstract class ModuleLevelBuilder extends Builder {
}
}
private static List<Pair<File, Module>> checkAffectedFilesInCorrectModules(CompileContext context, ModuleChunk currentChunk, Collection<File> affected) {
if (affected.isEmpty()) {
return Collections.emptyList();
}
final Set<Module> chunkModules = currentChunk.getModules();
final Map<Module, Set<Module>> cache = new HashMap<Module, Set<Module>>();
final List<Pair<File, Module>> result = new ArrayList<Pair<File, Module>>();
for (File file : affected) {
final RootDescriptor moduleAndRoot = context.getModuleAndRoot(file);
if (moduleAndRoot == null) {
continue;
}
final Module moduleOfFile = moduleAndRoot.module;
if (chunkModules.contains(moduleOfFile)) {
continue;
}
Set<Module> moduleOfFileWithDependencies = cache.get(moduleOfFile);
if (moduleOfFileWithDependencies == null) {
moduleOfFileWithDependencies = ProjectPaths.getModulesWithDependentsRecursively(moduleOfFile, true);
cache.put(moduleOfFile, moduleOfFileWithDependencies);
}
if (intersects(moduleOfFileWithDependencies, chunkModules)) {
continue;
}
result.add(Pair.create(file, moduleOfFile));
}
return result;
}
private static boolean intersects(Set<Module> set1, Set<Module> set2) {
if (set1.size() < set2.size()) {
return new HashSet<Module>(set1).removeAll(set2);
}
return new HashSet<Module>(set2).removeAll(set1);
}
private static boolean chunkContainsAffectedFiles(CompileContext context, ModuleChunk chunk, final Set<File> affected) throws IOException {
final Set<Module> chunkModules = new HashSet<Module>(chunk.getModules());
if (!chunkModules.isEmpty()) {
@@ -181,6 +181,16 @@ public class ProjectPaths {
return sourcePaths;
}
public static Set<Module> getModulesWithDependentsRecursively(final Module module, final boolean includeTests) {
final Set<Module> result = new HashSet<Module>();
collectPathsRecursively(module, ClasspathKind.compile(includeTests), new HashSet<Module>(), new PathsGetter() {
public void apply(Module module, ClasspathKind kind) {
result.add(module);
}
});
return result;
}
private interface PathsGetter {
void apply(Module module, ClasspathKind kind);
}
@@ -22,6 +22,7 @@ import java.util.List;
public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements DumbAware {
private CustomFoldingProvider myDefaultProvider;
private static final int MAX_LOOKUP_DEPTH = 10;
@NotNull
@Override
@@ -29,7 +30,7 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements D
List<FoldingDescriptor> descriptors = new ArrayList<FoldingDescriptor>();
if (CustomFoldingProvider.getAllProviders().length > 0) {
myDefaultProvider = null;
addCustomFoldingRegionsRecursively(null, root.getNode(), descriptors);
addCustomFoldingRegionsRecursively(null, root.getNode(), descriptors, 0);
}
buildLanguageFoldRegions(descriptors, root, document, quick);
return descriptors.toArray(new FoldingDescriptor[descriptors.size()]);
@@ -57,7 +58,8 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements D
private void addCustomFoldingRegionsRecursively(@Nullable FoldingStack foldingStack,
@NotNull ASTNode node,
List<FoldingDescriptor> descriptors) {
List<FoldingDescriptor> descriptors,
int currDepth) {
FoldingStack localFoldingStack = isCustomFoldingRoot(node) || foldingStack == null ? new FoldingStack(node) : foldingStack;
for (ASTNode child = node.getFirstChildNode(); child != null; child = child.getTreeNext()) {
if (isCustomRegionStart(child)) {
@@ -72,7 +74,9 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements D
}
}
else {
addCustomFoldingRegionsRecursively(localFoldingStack, child, descriptors);
if (currDepth < MAX_LOOKUP_DEPTH) {
addCustomFoldingRegionsRecursively(localFoldingStack, child, descriptors, currDepth + 1);
}
}
}
}
@@ -0,0 +1,73 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.project;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.Disposer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* User: ksafonov
*/
public abstract class ModuleNameTracker extends ModuleAdapter {
private final Map<Module, String> myModulesNames = new HashMap<Module, String>();
private final Project myProject;
public ModuleNameTracker(Project project) {
myProject = project;
Disposer.register(project, new Disposable() {
@Override
public void dispose() {
myModulesNames.clear();
}
});
}
@Override
public void moduleAdded(final Project project, final Module module) {
if (myProject == project) {
myModulesNames.put(module, module.getName());
}
}
@Override
public void moduleRemoved(final Project project, final Module module) {
if (myProject == project) {
myModulesNames.remove(module);
}
}
@Override
public void modulesRenamed(final Project project, final List<Module> modules) {
if (myProject != project) {
return;
}
Map<String, String> old2newNames = new HashMap<String, String>(modules.size());
for (Module module : modules) {
String newName = module.getName();
String oldName = myModulesNames.put(module, newName);
old2newNames.put(oldName, newName);
}
modulesRenamed(project, old2newNames);
}
protected abstract void modulesRenamed(final Project project, final Map<String, String> old2newNames);
}
@@ -61,6 +61,7 @@ import com.intellij.psi.impl.PsiDocumentManagerImpl;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Alarm;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
@@ -94,7 +95,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
private final Alarm myAlarm = new Alarm();
private boolean myUpdateByTimerEnabled = true;
private final Collection<VirtualFile> myDisabledHintsFiles = new THashSet<VirtualFile>();
private final Collection<PsiFile> myDisabledHighlightingFiles = new THashSet<PsiFile>();
private final Collection<VirtualFile> myDisabledHighlightingFiles = new THashSet<VirtualFile>();
private final FileStatusMap myFileStatusMap;
private DaemonCodeAnalyzerSettings myLastSettings;
@@ -122,6 +123,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myFileStatusMap = new FileStatusMap(myProject);
myPassExecutorService = new PassExecutorService(myProject) {
@Override
protected void afterApplyInformationToEditor(final TextEditorHighlightingPass pass,
final FileEditor fileEditor,
final ProgressIndicator updateProgress) {
@@ -132,6 +134,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
}
@Override
protected boolean isDisposed() {
return myDisposed || super.isDisposed();
}
@@ -283,14 +286,17 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myPassExecutorService.cancelAll(true);
}
@Override
@NotNull
public String getComponentName() {
return "DaemonCodeAnalyzer";
}
@Override
public void initComponent() {
}
@Override
public void disposeComponent() {
}
@@ -309,6 +315,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myFileStatusMap.markAllFilesDirty();
}
@Override
public void projectClosed() {
assert myInitialized : "Disposing not initialized component";
assert !myDisposed : "Double dispose";
@@ -354,6 +361,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return myScopes;
}
@Override
public void settingsChanged() {
DaemonCodeAnalyzerSettings settings = DaemonCodeAnalyzerSettings.getInstance();
if (settings.isCodeHighlightingChanged(myLastSettings)) {
@@ -362,11 +370,13 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myLastSettings = (DaemonCodeAnalyzerSettings)settings.clone();
}
@Override
public void updateVisibleHighlighters(@NotNull Editor editor) {
ApplicationManager.getApplication().assertIsDispatchThread();
// no need, will not work anyway
}
@Override
public void setUpdateByTimerEnabled(boolean value) {
myUpdateByTimerEnabled = value;
stopProcess(value);
@@ -376,6 +386,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return myUpdateByTimerEnabled;
}
@Override
public void setImportHintsEnabled(@NotNull PsiFile file, boolean value) {
VirtualFile vFile = file.getVirtualFile();
if (value) {
@@ -388,23 +399,27 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
}
@Override
public void resetImportHintsEnabledForProject() {
myDisabledHintsFiles.clear();
}
@Override
public void setHighlightingEnabled(@NotNull PsiFile file, boolean value) {
VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file);
if (value) {
myDisabledHighlightingFiles.remove(file);
myDisabledHighlightingFiles.remove(virtualFile);
}
else {
myDisabledHighlightingFiles.add(file);
myDisabledHighlightingFiles.add(virtualFile);
}
}
@Override
public boolean isHighlightingAvailable(PsiFile file) {
if (myDisabledHighlightingFiles.contains(file)) return false;
if (file == null || !file.isPhysical()) return false;
if (myDisabledHighlightingFiles.contains(PsiUtilCore.getVirtualFile(file))) return false;
if (file instanceof PsiCompiledElement) return false;
final FileType fileType = file.getFileType();
if (fileType == StdFileTypes.GUI_DESIGNER_FORM){
@@ -414,14 +429,17 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return !fileType.isBinary();
}
@Override
public boolean isImportHintsEnabled(@NotNull PsiFile file) {
return isAutohintsAvailable(file) && !myDisabledHintsFiles.contains(file.getVirtualFile());
}
@Override
public boolean isAutohintsAvailable(PsiFile file) {
return isHighlightingAvailable(file) && !(file instanceof PsiCompiledElement);
}
@Override
public void restart() {
myFileStatusMap.markAllFilesDirty();
stopProcess(true);
@@ -507,6 +525,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(project);
MarkupModelEx model = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, true);
return model.processRangeHighlightersOverlappingWith(startOffset, endOffset, new Processor<RangeHighlighterEx>() {
@Override
public boolean process(RangeHighlighterEx marker) {
Object tt = marker.getErrorStripeTooltip();
if (!(tt instanceof HighlightInfo)) return true;
@@ -529,6 +548,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(project);
MarkupModelEx model = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, true);
return model.processRangeHighlightersOutside(startOffset, endOffset, new Processor<RangeHighlighterEx>() {
@Override
public boolean process(RangeHighlighterEx marker) {
Object tt = marker.getErrorStripeTooltip();
if (!(tt instanceof HighlightInfo)) return true;
@@ -548,6 +568,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
final boolean includeFixRange,
@NotNull final Processor<HighlightInfo> processor) {
return processHighlights(document, project, null, 0, document.getTextLength(), new Processor<HighlightInfo>() {
@Override
public boolean process(HighlightInfo info) {
if (!isOffsetInsideHighlightInfo(offset, info, includeFixRange)) return true;
@@ -561,6 +582,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
public HighlightInfo findHighlightByOffset(Document document, final int offset, final boolean includeFixRange) {
final List<HighlightInfo> foundInfoList = new SmartList<HighlightInfo>();
processHighlightsNearOffset(document, myProject, HighlightSeverity.INFORMATION, offset, includeFixRange, new Processor<HighlightInfo>() {
@Override
public boolean process(HighlightInfo info) {
if (!foundInfoList.isEmpty()) {
HighlightInfo foundInfo = foundInfoList.get(0);
@@ -635,6 +657,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return myLastIntentionHint;
}
@Override
public void writeExternal(Element parentNode) throws WriteExternalException {
Element disableHintsElement = new Element(DISABLE_HINTS_TAG);
parentNode.addContent(disableHintsElement);
@@ -654,6 +677,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
}
@Override
public void readExternal(Element parentNode) throws InvalidDataException {
myDisabledHintsFiles.clear();
@@ -675,12 +699,14 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
private Runnable createUpdateRunnable() {
return new Runnable() {
@Override
public void run() {
if (myDisposed || !myProject.isInitialized()) return;
if (PowerSaveMode.isEnabled()) return;
Editor activeEditor = FileEditorManager.getInstance(myProject).getSelectedTextEditor();
Runnable runnable = new Runnable() {
@Override
public void run() {
PassExecutorService.log(myUpdateProgress, null, "Update Runnable. myUpdateByTimerEnabled:",myUpdateByTimerEnabled," something disposed:",PowerSaveMode.isEnabled() || myDisposed || !myProject.isInitialized()," activeEditors:",myProject.isDisposed() ? null : myDaemonListeners.getSelectedEditors());
if (!myUpdateByTimerEnabled) return;
@@ -745,6 +771,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return myDaemonListeners.canChangeFileSilently(file);
}
@Override
public void autoImportReferenceAtCursor(@NotNull Editor editor, @NotNull PsiFile file) {
for(ReferenceImporter importer: Extensions.getExtensions(ReferenceImporter.EP_NAME)) {
if (importer.autoImportReferenceAtCursor(editor, file)) break;
@@ -616,7 +616,7 @@ class RunConfigurable extends BaseConfigurable {
final String nameText = configurable != null ? configurable.getNameText() : configurationBean.getSettings().getName();
if (!names.add(nameText)) {
TreeUtil.selectNode(myTree, node);
throw new ConfigurationException("Configuration with name \'" + nameText + "\' already exist");
throw new ConfigurationException("Configuration with name \'" + nameText + "\' already exists");
}
stableConfigurations.add(configurationBean);
}
@@ -73,7 +73,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
private final NewVirtualFileSystem myFS;
// guarded by this
protected Object myChildren; // Either HashMap<String, VFile> or VFile[]
private Object myChildren; // Either HashMap<String, VFile> or VFile[]
public VirtualDirectoryImpl(@NotNull String name, final VirtualDirectoryImpl parent, @NotNull NewVirtualFileSystem fs, final int id) {
super(name, parent, id);
@@ -379,8 +379,9 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
@NotNull
private synchronized Collection<VirtualFile> getInDbChildren() {
if (myChildren instanceof VirtualFileSystemEntry[]) {
return Arrays.asList((VirtualFile[])myChildren);
VirtualFileSystemEntry[] children = asArray();
if (children != null) {
return Arrays.asList((VirtualFile[])children);
}
if (!ourPersistence.wereChildrenAccessed(this)) {
@@ -404,13 +405,13 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
@Override
@NotNull
public synchronized VirtualFile[] getChildren() {
if (myChildren instanceof VirtualFileSystemEntry[]) {
return (VirtualFileSystemEntry[])myChildren;
VirtualFileSystemEntry[] children = asArray();
if (children != null) {
return children;
}
Pair<String[], int[]> pair = PersistentFS.listAll(this);
final int[] childrenIds = pair.second;
VirtualFileSystemEntry[] children;
if (childrenIds.length == 0) {
children = EMPTY_ARRAY;
}
@@ -454,7 +455,10 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
@Override
public NewVirtualFile findChildByIdIfCached(int id) {
final VirtualFile[] a = asArray();
final VirtualFile[] a;
synchronized (this) {
a = asArray();
}
if (a != null) {
for (VirtualFile file : a) {
NewVirtualFile withId = (NewVirtualFile)file;
@@ -477,12 +481,15 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
return null;
}
// MUST BE CALLED UNDER this LOCK
@Nullable
private VirtualFileSystemEntry[] asArray() {
if (myChildren instanceof VirtualFileSystemEntry[]) return (VirtualFileSystemEntry[])myChildren;
Object children = myChildren;
if (children instanceof VirtualFileSystemEntry[]) return (VirtualFileSystemEntry[])children;
return null;
}
// MUST BE CALLED UNDER this LOCK
@Nullable
private Map<String, VirtualFileSystemEntry> asMap() {
if (myChildren instanceof Map) {
@@ -530,7 +537,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
}
public synchronized boolean allChildrenLoaded() {
return myChildren instanceof VirtualFileSystemEntry[];
return asArray() != null;
}
@NotNull
@@ -33,6 +33,7 @@ import com.intellij.designer.designSurface.OperationContext;
import com.intellij.designer.designSurface.selection.NonResizeSelectionDecorator;
import com.intellij.designer.designSurface.tools.ComponentCreationFactory;
import com.intellij.designer.designSurface.tools.ComponentPasteFactory;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.palette.Item;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
@@ -45,7 +46,10 @@ import com.intellij.psi.xml.XmlFile;
import com.intellij.util.ThrowableRunnable;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.uipreview.*;
import org.jetbrains.android.uipreview.LayoutDeviceConfiguration;
import org.jetbrains.android.uipreview.LocaleData;
import org.jetbrains.android.uipreview.RenderUtil;
import org.jetbrains.android.uipreview.RenderingException;
import org.jetbrains.android.util.AndroidSdkNotConfiguredException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -127,19 +131,22 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
createRenderer(parser.getLayoutXmlText(), new ThrowableRunnable<Throwable>() {
@Override
public void run() throws Throwable {
checkRenderer(false);
checkRenderer();
RootView rootView = new RootView(mySession.getImage(), 30, 20);
parser.updateRootComponent(mySession, rootView);
RadViewComponent newRootComponent = parser.getRootComponent();
new PropertyParser(myModule, myProfileAction.getProfileManager().getSelectedTarget()).loadRecursive(parser.getRootComponent());
PropertyParser propertyParser = new PropertyParser(myModule, myProfileAction.getProfileManager().getSelectedTarget());
newRootComponent.setClientProperty(PropertyParser.KEY, propertyParser);
propertyParser.loadRecursive(newRootComponent);
JPanel rootPanel = new JPanel(null);
rootPanel.setBackground(Color.WHITE);
rootPanel.add(rootView);
removeNativeRoot();
myRootComponent = parser.getRootComponent();
myRootComponent = newRootComponent;
myLayeredPane.add(rootPanel, LAYER_COMPONENT);
runnable.run();
@@ -157,24 +164,20 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
createRenderer(layoutXmlText, new ThrowableRunnable<Throwable>() {
@Override
public void run() throws Throwable {
updateRenderer(false);
checkRenderer();
RadViewComponent rootComponent = (RadViewComponent)myRootComponent;
RootView rootView = (RootView)rootComponent.getNativeComponent();
rootView.setImage(mySession.getImage());
ModelParser.updateRootComponent(rootComponent, mySession, rootView);
myLayeredPane.repaint();
}
});
}
private void updateRenderer(boolean render) throws Throwable {
checkRenderer(render);
RadViewComponent rootComponent = (RadViewComponent)myRootComponent;
RootView rootView = (RootView)rootComponent.getNativeComponent();
rootView.setImage(mySession.getImage());
ModelParser.updateRootComponent(rootComponent, mySession, rootView);
myLayeredPane.repaint();
}
private void checkRenderer(boolean render) throws Throwable {
Result result = render ? mySession.render() : mySession.getResult();
private void checkRenderer() throws Throwable {
Result result = mySession.getResult();
if (!result.isSuccess()) {
System.out.println(
"No session: " + result.getErrorMessage() + " : " + result.getStatus() + " : " + result.getData() + " : " + result.getException());
@@ -251,7 +254,6 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
mySession = RenderUtil
.createRenderSession(getProject(), layoutXmlText, myFile, manager.getSelectedTarget(), facet, config, xdpi, ydpi,
manager.getSelectedTheme());
System.out.println(mySession + " | " + mySession.getClass());
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
@@ -337,8 +339,14 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
@Override
@NotNull
protected ComponentCreationFactory createCreationFactory(Item paletteItem) {
return null; // TODO: Auto-generated method stub
protected ComponentCreationFactory createCreationFactory(final Item paletteItem) {
return new ComponentCreationFactory() {
@NotNull
@Override
public RadComponent create() throws Exception {
return ModelParser.createComponent(null, paletteItem.getMetaModel());
}
};
}
@Override
@@ -351,7 +359,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
try {
myPSIChangeListener.stop();
operation.run();
updateRenderer(true);
updateRenderer();
return true;
}
catch (Throwable e) {
@@ -370,7 +378,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
for (EditOperation operation : operations) {
operation.execute();
}
updateRenderer(true);
updateRenderer();
}
catch (Throwable e) {
showError("Execute command", e);
@@ -1,144 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.android.designer.model;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.intellij.designer.propertyTable.Property;
import com.intellij.designer.propertyTable.PropertyEditor;
import com.intellij.designer.propertyTable.PropertyRenderer;
import com.intellij.designer.propertyTable.editors.AbstractTextFieldEditor;
import com.intellij.designer.propertyTable.renderers.LabelPropertyRenderer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.xml.XmlAttribute;
import org.jetbrains.android.dom.attrs.AttributeDefinition;
import org.jetbrains.annotations.NotNull;
/**
* @author Alexander Lobas
*/
public class AttributeProperty extends Property<RadViewComponent> {
private final LabelPropertyRenderer myRenderer = new LabelPropertyRenderer(null);
private final AttributeDefinition myDefinition;
private final PropertyEditor myEditor = new AbstractTextFieldEditor() {
@Override
public Object getValue() throws Exception {
return myTextField.getText();
}
};
public AttributeProperty(Property parent, @NotNull AttributeDefinition definition) {
super(parent, definition.getName());
myDefinition = definition;
}
@Override
public Object getValue(RadViewComponent component) throws Exception {
Object value = null;
XmlAttribute attribute = getAttribute(component);
if (attribute != null) {
value = attribute.getValue();
}
if (value == null) {
Object viewObject = component.getViewInfo().getViewObject();
RenderSession session = component.getRoot().getClientProperty(ModelParser.SESSION);
Result result = session.getProperty(viewObject, myDefinition.getName());
if (result.isSuccess()) {
value = result.getData();
}
}
return value;
}
@Override
public void setValue(final RadViewComponent component, final Object value) throws Exception {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
component.getTag().setAttribute("android:" + myDefinition.getName(), (String)value);
}
});
Object viewObject = component.getViewInfo().getViewObject();
viewObject.getClass().getMethod("setBackgroundColor", int.class).invoke(viewObject, 0xEE09AA);
/*RenderSession session = component.getRoot().getClientProperty(ModelParser.SESSION);
Result result = session.setProperty(viewObject, myDefinition.getName(), (String)value);
if (!result.isSuccess()) {
System.out.println(
"No set property value(" +
myDefinition +
"): " +
result.getErrorMessage() +
" : " +
result.getStatus() +
" : " +
result.getData() +
" : " +
result.getException());
}*/
}
@Override
public boolean isDefaultValue(RadViewComponent component) throws Exception {
return getAttribute(component) == null;
}
@Override
public void setDefaultValue(RadViewComponent component) throws Exception {
final XmlAttribute attribute = getAttribute(component);
if (attribute != null) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
attribute.delete();
}
});
Object viewObject = component.getViewInfo().getViewObject();
RenderSession session = component.getRoot().getClientProperty(ModelParser.SESSION);
Result result = session.setProperty(viewObject, myDefinition.getName(), null);
if (!result.isSuccess()) {
System.out.println(
"No set default property value(" +
myDefinition +
"): " +
result.getErrorMessage() +
" : " +
result.getStatus() +
" : " +
result.getData() +
" : " +
result.getException());
}
}
}
private XmlAttribute getAttribute(RadViewComponent component) {
return component.getTag().getAttribute("android:" + myDefinition.getName());
}
@NotNull
@Override
public PropertyRenderer getRenderer() {
return myRenderer;
}
@Override
public PropertyEditor getEditor() {
return myEditor;
}
}
@@ -21,9 +21,12 @@ import com.intellij.designer.model.MetaManager;
import com.intellij.designer.model.MetaModel;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.model.RadLayout;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.XmlElementFactory;
import com.intellij.psi.XmlRecursiveElementVisitor;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
@@ -35,8 +38,6 @@ import java.util.List;
* @author Alexander Lobas
*/
public class ModelParser extends XmlRecursiveElementVisitor {
public static final String SESSION = "RENDER_LIB_SESSION";
private final MetaManager myMetaManager;
private final XmlFile myXmlFile;
private RadViewComponent myRootComponent;
@@ -97,7 +98,7 @@ public class ModelParser extends XmlRecursiveElementVisitor {
}
}
private static RadViewComponent createComponent(XmlTag tag, MetaModel metaModel) throws Exception {
public static RadViewComponent createComponent(XmlTag tag, MetaModel metaModel) throws Exception {
RadViewComponent component = (RadViewComponent)metaModel.getModel().newInstance();
component.setMetaModel(metaModel);
component.setTag(tag);
@@ -110,6 +111,26 @@ public class ModelParser extends XmlRecursiveElementVisitor {
return component;
}
public static void setComponentTag(final XmlTag parentTag, final RadViewComponent component, final XmlTag nextTag) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
Language language = StdFileTypes.XML.getLanguage();
XmlTag xmlTag =
XmlElementFactory.getInstance(parentTag.getProject()).createTagFromText(component.getMetaModel().getCreation(), language);
if (nextTag == null) {
xmlTag = parentTag.addSubTag(xmlTag, false);
}
else {
xmlTag = (XmlTag)parentTag.addBefore(xmlTag, nextTag);
}
component.setTag(xmlTag);
}
});
}
//////////////////////////////////////////////////////////////////////////////////////////
//
//
@@ -151,7 +172,6 @@ public class ModelParser extends XmlRecursiveElementVisitor {
rootComponent.setNativeComponent(nativeComponent);
rootComponent.setBounds(0, 0, nativeComponent.getWidth(), nativeComponent.getHeight());
rootComponent.setClientProperty(SESSION, session);
}
private static void updateComponent(RadViewComponent component,
@@ -17,12 +17,17 @@ package com.intellij.android.designer.model;
import com.android.ide.common.rendering.api.ViewInfo;
import com.android.sdklib.IAndroidTarget;
import com.intellij.android.designer.propertyTable.AttributeProperty;
import com.intellij.android.designer.propertyTable.FlagProperty;
import com.intellij.designer.model.MetaManager;
import com.intellij.designer.model.MetaModel;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.propertyTable.Property;
import com.intellij.designer.propertyTable.PropertyTable;
import com.intellij.openapi.module.Module;
import org.jetbrains.android.dom.attrs.AttributeDefinition;
import org.jetbrains.android.dom.attrs.AttributeDefinitions;
import org.jetbrains.android.dom.attrs.AttributeFormat;
import org.jetbrains.android.dom.attrs.StyleableDefinition;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.sdk.AndroidTargetData;
@@ -36,15 +41,18 @@ import java.util.*;
*/
@SuppressWarnings("unchecked")
public class PropertyParser {
public static final String KEY = "PROPERTY_PARSER";
private MetaManager myMetaManager;
private AttributeDefinitions myDefinitions;
private ProjectClassLoader myClassLoader;
private Map<String, List<Property>> myCachedProperties;
public PropertyParser(Module module, IAndroidTarget target) throws Exception {
MetaManager metaManager = ViewsMetaManager.getInstance(module.getProject());
myCachedProperties = metaManager.getCache(target.hashString());
myMetaManager = ViewsMetaManager.getInstance(module.getProject());
myCachedProperties = myMetaManager.getCache(target.hashString());
if (myCachedProperties == null) {
metaManager.setCache(target.hashString(), myCachedProperties = new HashMap<String, List<Property>>());
myMetaManager.setCache(target.hashString(), myCachedProperties = new HashMap<String, List<Property>>());
}
AndroidPlatform androidPlatform = AndroidPlatform.getInstance(module);
@@ -65,32 +73,87 @@ public class PropertyParser {
public void load(RadViewComponent component) throws Exception {
ViewInfo info = component.getViewInfo();
MetaModel model = component.getMetaModel();
if (info == null) {
component.setProperties(Collections.<Property>emptyList());
String target = model.getTarget();
if (target == null) {
component.setProperties(Collections.<Property>emptyList());
}
else {
component.setProperties(load(myClassLoader.loadClass(target), model));
}
}
else {
component.setProperties(load(myClassLoader.loadClass(info.getClassName())));
component.setProperties(load(myClassLoader.loadClass(info.getClassName()), model));
}
}
private List<Property> load(Class<?> componentClass) {
private List<Property> load(Class<?> componentClass, MetaModel model) {
String component = componentClass.getSimpleName();
List<Property> properties = myCachedProperties.get(component);
if (properties == null) {
properties = new ArrayList<Property>();
System.out.println("--- " + componentClass + " -----------------");
StyleableDefinition definitions = myDefinitions.getStyleableByName(component);
if (definitions != null) {
for (AttributeDefinition definition : definitions.getAttributes()) {
properties.add(new AttributeProperty(null, definition));
// TODO
String name = definition.getName();
Set<AttributeFormat> formats = definition.getFormats();
Property property;
if (formats.contains(AttributeFormat.Flag)) {
property = new FlagProperty(name, definition);
}
else {
property = new AttributeProperty(name, definition);
}
if (model != null) {
property.setImportant(model.isImportantProperty(name));
property.setExpert(model.isExpertProperty(name));
property.setDeprecated(model.isDeprecatedProperty(name));
}
properties.add(property);
System.out.println(definition + " = " + Arrays.toString(definition.getValues()));
}
}
Class<?> superComponentClass = componentClass.getSuperclass();
if (superComponentClass != null) {
properties.addAll(load(superComponentClass));
List<Property> superProperties = load(superComponentClass, myMetaManager.getModelByTarget(superComponentClass.getName()));
for (Property superProperty : superProperties) {
if (PropertyTable.findProperty(properties, superProperty) == -1) {
if (model == null) {
properties.add(superProperty);
}
else {
String name = superProperty.getName();
boolean normal = model.isNormalProperty(name);
boolean important = model.isImportantProperty(name);
boolean expert = model.isExpertProperty(name);
boolean deprecated = model.isDeprecatedProperty(name);
if ((normal && (superProperty.isImportant() || superProperty.isExpert())) ||
(important && !superProperty.isImportant()) ||
(expert && !superProperty.isExpert()) ||
(deprecated && !superProperty.isDeprecated())) {
Property property = superProperty.createForNewPresentation();
property.setImportant(important);
property.setExpert(expert);
property.setDeprecated(deprecated);
properties.add(property);
}
else {
properties.add(superProperty);
}
}
}
}
}
if (!properties.isEmpty()) {
@@ -15,8 +15,108 @@
*/
package com.intellij.android.designer.model;
import com.intellij.designer.componentTree.TreeEditOperation;
import com.intellij.designer.designSurface.EditOperation;
import com.intellij.designer.designSurface.FeedbackLayer;
import com.intellij.designer.designSurface.OperationContext;
import com.intellij.designer.designSurface.feedbacks.AlphaComponent;
import com.intellij.designer.model.RadComponent;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.List;
/**
* @author Alexander Lobas
*/
public class RadLinearLayout extends RadViewLayout {
@Override
public EditOperation processChildOperation(OperationContext context) {
if (context.isCreate()) {
return context.isTree() ? new TreeCreateOperation(myContainer, context) : new CreateOperation(context);
}
return null;
}
private void addNewComponent(RadViewComponent newComponent, @Nullable RadViewComponent insertBefore) throws Exception {
RadViewComponent container = (RadViewComponent)myContainer;
newComponent.setParent(container);
List<RadComponent> children = container.getChildren();
if (insertBefore == null) {
children.add(newComponent);
}
else {
children.add(children.indexOf(insertBefore), newComponent);
}
ModelParser
.setComponentTag(container.getTag(), newComponent, insertBefore == null ? null : insertBefore.getTag());
PropertyParser propertyParser = container.getRoot().getClientProperty(PropertyParser.KEY);
propertyParser.load(newComponent);
}
private class TreeCreateOperation extends TreeEditOperation {
public TreeCreateOperation(RadComponent host, OperationContext context) {
super(host, context);
}
@Override
protected void execute(RadComponent insertBefore) throws Exception {
addNewComponent((RadViewComponent)myComponents.get(0), (RadViewComponent)insertBefore);
}
}
private class CreateOperation implements EditOperation {
private final OperationContext myContext;
private RadComponent myComponent;
private JComponent myFeedback;
private CreateOperation(OperationContext context) {
myContext = context;
}
@Override
public void setComponent(RadComponent component) {
myComponent = component;
}
@Override
public void setComponents(List<RadComponent> components) {
}
@Override
public void showFeedback() {
FeedbackLayer layer = myContext.getArea().getFeedbackLayer();
if (myFeedback == null) {
myFeedback = new AlphaComponent(Color.green);
layer.add(myFeedback);
myFeedback.setBounds(myContainer.getBounds(layer));
layer.repaint();
}
}
@Override
public void eraseFeedback() {
if (myFeedback != null) {
FeedbackLayer layer = myContext.getArea().getFeedbackLayer();
layer.remove(myFeedback);
layer.repaint();
myFeedback = null;
}
}
@Override
public boolean canExecute() {
return true;
}
@Override
public void execute() throws Exception {
addNewComponent((RadViewComponent)myComponent, null);
}
}
}
@@ -18,6 +18,7 @@ package com.intellij.android.designer.model;
import com.android.ide.common.rendering.api.ViewInfo;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.propertyTable.Property;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.xml.XmlTag;
import javax.swing.*;
@@ -84,6 +85,18 @@ public class RadViewComponent extends RadComponent {
return SwingUtilities.convertPoint(component, x, y, myNativeComponent);
}
@Override
public void delete() throws Exception {
getParent().getChildren().remove(this);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
myTag.delete();
}
});
}
@Override
public List<Property> getProperties() {
return myProperties;
@@ -21,6 +21,19 @@
<palette title="Unknown (%tag%)" icon="/com/intellij/android/designer/icons/unknown.png"/>
</meta>
<meta class="android.view.View">
<properties
important="id background"
expert="tag scrollX scrollY fitsSystemWindows scrollbars scrollbarStyle isScrollContainer fadeScrollbars scrollbarFadeDuration scrollbarDefaultDelayBeforeFade scrollbarSize scrollbarThumbHorizontal scrollbarThumbVertical scrollbarTrackHorizontal scrollbarTrackVertical scrollbarAlwaysDrawHorizontalTrack scrollbarAlwaysDrawVerticalTrack fadingEdge requiresFadingEdge fadingEdgeLength nextFocusLeft nextFocusRight nextFocusUp nextFocusDown nextFocusForward saveEnabled filterTouchesWhenObscured drawingCacheQuality keepScreenOn duplicateParentState soundEffectsEnabled hapticFeedbackEnabled contentDescription overScrollMode translationX translationY transformPivotX transformPivotY rotation rotationX rotationY scaleX scaleY verticalScrollbarPosition layerType layoutDirection textDirection"
/>
</meta>
<meta class="class android.view.ViewGroup">
<properties
expert="animateLayoutChanges clipChildren clipToPadding layoutAnimation animationCache persistentDrawingCache alwaysDrawnWithCache addStatesFromChildren descendantFocusability splitMotionEvents"
/>
</meta>
<meta model="com.intellij.android.designer.model.RadViewComponent"
class="android.widget.Button"
tag="Button">
@@ -29,6 +42,11 @@
<palette title="Button" icon="/com/intellij/android/designer/icons/Button.png"
tooltip="Represents a push-button widget."/>
<properties
important="onClick"
expert="editable password autoLink linksClickable numeric digits phoneNumber inputMethod autoText inputType textIsSelectable"
/>
<creation>
<![CDATA[
<Button
@@ -48,6 +66,11 @@
<palette title="TextView" icon="/com/intellij/android/designer/icons/TextView.png"
tooltip="Displays text to the user and optionally allows them to edit it."/>
<properties
important="text hint textColor typeface textStyle gravity editable enabled"
expert="bufferType textScaleX cursorVisible scrollHorizontally includeFontPadding shadowDx shadowDy shadowRadius freezesText drawableTop drawableLeft drawableStart drawablePadding lineSpacingExtra lineSpacingMultiplier imeOptions privateImeOptions imeActionLabel imeActionId editorExtras textSelectHandleLeft textSelectHandleRight textSelectHandle textEditPasteWindowLayout textEditNoPasteWindowLayout textEditSideNoPasteWindowLayout textEditSuggestionItemLayout textCursorDrawable textAllCaps maxEms ems minEms"
/>
<creation>
<![CDATA[
<TextView
@@ -67,6 +90,10 @@
<palette title="LinearLayout" icon="/com/intellij/android/designer/icons/LinearLayout.png"
tooltip="A Layout that arranges its children in a single column or a single row."/>
<properties
important="orientation gravity"
/>
<creation>
<![CDATA[
<LinearLayout
@@ -79,6 +106,13 @@
</meta>
<palette>
<group name="Widgets">
<item tag="Button"/>
<item tag="TextView"/>
</group>
<group name="Containers">
<item tag="LinearLayout"/>
</group>
</palette>
</meta-model>
@@ -0,0 +1,134 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.android.designer.propertyTable;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.android.designer.propertyTable.editors.BooleanEditor;
import com.intellij.android.designer.propertyTable.renderers.BooleanRenderer;
import com.intellij.designer.propertyTable.Property;
import com.intellij.designer.propertyTable.PropertyEditor;
import com.intellij.designer.propertyTable.PropertyRenderer;
import com.intellij.designer.propertyTable.editors.AbstractTextFieldEditor;
import com.intellij.designer.propertyTable.renderers.LabelPropertyRenderer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.xml.XmlAttribute;
import org.jetbrains.android.dom.attrs.AttributeDefinition;
import org.jetbrains.android.dom.attrs.AttributeFormat;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
/**
* @author Alexander Lobas
*/
public class AttributeProperty extends Property<RadViewComponent> {
private final AttributeDefinition myDefinition;
private final PropertyRenderer myRenderer;
private final PropertyEditor myEditor;
public AttributeProperty(@NotNull String name, @NotNull AttributeDefinition definition) {
super(null, name);
myDefinition = definition;
Set<AttributeFormat> formats = definition.getFormats();
if (formats.contains(AttributeFormat.Boolean)) {
myRenderer = new BooleanRenderer();
myEditor = new BooleanEditor();
}
else {
myRenderer = new LabelPropertyRenderer(null);
if (formats.contains(AttributeFormat.Enum)) {
}
else {
}
myEditor = new AbstractTextFieldEditor() {
@Override
public Object getValue() throws Exception {
return myTextField.getText();
}
};
}
}
@Override
public Property createForNewPresentation() {
return new AttributeProperty(getName(), myDefinition);
}
@Override
public Object getValue(RadViewComponent component) throws Exception {
Object value = null;
XmlAttribute attribute = getAttribute(component);
if (attribute != null) {
value = attribute.getValue();
}
return value == null ? "" : value;
}
@Override
public void setValue(final RadViewComponent component, final Object value) throws Exception {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
if (StringUtil.isEmpty((String)value)) {
XmlAttribute attribute = getAttribute(component);
if (attribute != null) {
attribute.delete();
}
}
else {
component.getTag().setAttribute("android:" + myDefinition.getName(), (String)value);
}
}
});
}
@Override
public boolean isDefaultValue(RadViewComponent component) throws Exception {
return getAttribute(component) == null;
}
@Override
public void setDefaultValue(RadViewComponent component) throws Exception {
if (getAttribute(component) != null) {
setValue(component, null);
}
}
@Nullable
private XmlAttribute getAttribute(RadViewComponent component) {
return component.getTag().getAttribute("android:" + myDefinition.getName());
}
@NotNull
@Override
public PropertyRenderer getRenderer() {
return myRenderer;
}
@Override
public PropertyEditor getEditor() {
return myEditor;
}
}
@@ -0,0 +1,81 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.android.designer.propertyTable;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.designer.propertyTable.Property;
import com.intellij.designer.propertyTable.PropertyEditor;
import com.intellij.designer.propertyTable.PropertyRenderer;
import com.intellij.designer.propertyTable.renderers.LabelPropertyRenderer;
import org.jetbrains.android.dom.attrs.AttributeDefinition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author Alexander Lobas
*/
public class FlagProperty extends Property<RadViewComponent> {
private final PropertyRenderer myRenderer = new LabelPropertyRenderer(null);
private final AttributeDefinition myDefinition;
public FlagProperty(@NotNull String name, @NotNull AttributeDefinition definition) {
super(null, name);
myDefinition = definition;
}
@Override
public Property createForNewPresentation() {
return new FlagProperty(getName(), myDefinition);
}
@Override
public List<Property> getChildren(@Nullable RadViewComponent component) {
return super.getChildren(component); // TODO: Auto-generated method stub
}
@Override
public Object getValue(RadViewComponent component) throws Exception {
return "[]";
}
@Override
public void setValue(RadViewComponent component, Object value) throws Exception {
super.setValue(component, value); // TODO: Auto-generated method stub
}
@Override
public boolean isDefaultValue(RadViewComponent component) throws Exception {
return super.isDefaultValue(component); // TODO: Auto-generated method stub
}
@Override
public void setDefaultValue(RadViewComponent component) throws Exception {
super.setDefaultValue(component); // TODO: Auto-generated method stub
}
@NotNull
@Override
public PropertyRenderer getRenderer() {
return myRenderer;
}
@Override
public PropertyEditor getEditor() {
return null;
}
}
@@ -0,0 +1,33 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.android.designer.propertyTable.editors;
import com.intellij.openapi.util.text.StringUtil;
/**
* @author Alexander Lobas
*/
public class BooleanEditor extends com.intellij.designer.propertyTable.editors.BooleanEditor {
@Override
public Object getValue() throws Exception {
return Boolean.toString(myCheckBox.isSelected());
}
@Override
protected boolean getValue(Object value) {
return Boolean.parseBoolean((String)value);
}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.android.designer.propertyTable.renderers;
/**
* @author Alexander Lobas
*/
public class BooleanRenderer extends com.intellij.designer.propertyTable.renderers.BooleanRenderer {
@Override
protected boolean getValue(Object value) {
return Boolean.parseBoolean((String)value);
}
}
@@ -1,5 +1,6 @@
package org.jetbrains.android.actions;
import com.android.resources.ResourceFolderType;
import com.intellij.CommonBundle;
import com.intellij.ide.actions.CreateElementActionBase;
import com.intellij.openapi.actionSystem.DataContext;
@@ -22,15 +23,23 @@ import java.io.File;
* @author Eugene.Kudelevsky
*/
public class CreateResourceDirectoryAction extends CreateElementActionBase {
private final ResourceFolderType myResourceFolderType;
@SuppressWarnings("UnusedDeclaration")
public CreateResourceDirectoryAction() {
this(null);
}
public CreateResourceDirectoryAction(@Nullable ResourceFolderType resourceFolderType) {
super(AndroidBundle.message("new.resource.dir.action.title"), AndroidBundle.message("new.resource.action.description"),
PlatformIcons.DIRECTORY_CLOSED_ICON);
myResourceFolderType = resourceFolderType;
}
@NotNull
@Override
protected PsiElement[] invokeDialog(final Project project, final PsiDirectory directory) {
final CreateResourceDirectoryDialog dialog = new CreateResourceDirectoryDialog(project) {
public PsiElement[] invokeDialog(final Project project, final PsiDirectory directory) {
final CreateResourceDirectoryDialog dialog = new CreateResourceDirectoryDialog(project, myResourceFolderType) {
@Override
protected InputValidator createValidator() {
return CreateResourceDirectoryAction.this.createValidator(project, directory);
@@ -47,7 +47,7 @@
</grid>
</constraints>
<properties>
<enabled value="false"/>
<enabled value="true"/>
</properties>
</component>
<component id="71b17" class="com.intellij.ui.components.JBLabel" binding="myErrorLabel">
@@ -26,6 +26,7 @@ import com.intellij.ui.components.JBLabel;
import org.jetbrains.android.uipreview.DeviceConfiguratorPanel;
import org.jetbrains.android.uipreview.InvalidOptionValueException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -45,7 +46,7 @@ public abstract class CreateResourceDirectoryDialog extends DialogWrapper {
private final DeviceConfiguratorPanel myDeviceConfiguratorPanel;
private InputValidator myValidator;
public CreateResourceDirectoryDialog(@NotNull Project project) {
public CreateResourceDirectoryDialog(@NotNull Project project, @Nullable ResourceFolderType resType) {
super(project);
myResourceTypeComboBox.setModel(new EnumComboBoxModel<ResourceFolderType>(ResourceFolderType.class));
@@ -84,6 +85,11 @@ public abstract class CreateResourceDirectoryDialog extends DialogWrapper {
}
});
if (resType != null) {
myResourceTypeComboBox.setSelectedItem(resType);
myResourceTypeComboBox.setEnabled(false);
}
myDeviceConfiguratorPanel.updateAll();
setOKActionEnabled(myDirectoryNameTextField.getText().length() > 0);
init();
@@ -1,21 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.android.actions.CreateXmlResourceDialog">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="5" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
<xy x="20" y="20" width="288" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="82472" binding="myDeviceConfigurationWrapper" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<component id="43fab" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
@@ -48,29 +40,6 @@
<text value="&amp;Module:"/>
</properties>
</component>
<component id="d6c07" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="832da"/>
<text value="&amp;Directory name:"/>
</properties>
</component>
<component id="832da" class="javax.swing.JTextField" binding="myDirectoryNameField">
<constraints>
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="da401" class="com.intellij.ui.components.JBLabel" binding="myErrorLabel">
<constraints>
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="21872" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
@@ -88,6 +57,22 @@
</constraints>
<properties/>
</component>
<grid id="8a4e8" binding="myDirectoriesPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<component id="d6c07" class="com.intellij.ui.components.JBLabel" binding="myDirectoriesLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Directories:"/>
</properties>
</component>
</children>
</grid>
</form>
@@ -1,57 +1,68 @@
package org.jetbrains.android.actions;
import com.android.AndroidConstants;
import com.android.ide.common.resources.configuration.FolderConfiguration;
import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
import com.intellij.CommonBundle;
import com.intellij.ide.ui.ListCellRendererWrapper;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.fileChooser.actions.VirtualFileDeleteProvider;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.ui.*;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.hash.HashMap;
import org.jetbrains.android.dom.resources.ResourceElement;
import org.jetbrains.android.dom.resources.Resources;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.uipreview.DeviceConfiguratorPanel;
import org.jetbrains.android.uipreview.InvalidOptionValueException;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidResourceUtil;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Set;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
/**
* @author Eugene.Kudelevsky
*/
public class CreateXmlResourceDialog extends DialogWrapper {
private JPanel myPanel;
private JPanel myDeviceConfigurationWrapper;
private JTextField myNameField;
private JComboBox myModuleCombo;
private JBLabel myModuleLabel;
private JTextField myDirectoryNameField;
private JBLabel myErrorLabel;
private JTextField myFileNameField;
private JPanel myDirectoriesPanel;
private JBLabel myDirectoriesLabel;
private final DeviceConfiguratorPanel myDeviceConfiguratorPanel;
private final Module myModule;
private final ResourceType myResourceType;
private Map<String, JCheckBox> myCheckBoxes = Collections.emptyMap();
private String[] myDirNames = ArrayUtil.EMPTY_STRING_ARRAY;
private final CheckBoxList myDirectoriesList;
private VirtualFile myResourceDir;
public CreateXmlResourceDialog(@NotNull Module module, @NotNull ResourceType resourceType) {
super(module.getProject());
@@ -94,39 +105,189 @@ public class CreateXmlResourceDialog extends DialogWrapper {
});
}
myDeviceConfiguratorPanel = new DeviceConfiguratorPanel(null) {
@Override
public void applyEditors() {
try {
doApplyEditors();
final FolderConfiguration config = myDeviceConfiguratorPanel.getConfiguration();
myErrorLabel.setText("");
myDirectoryNameField.setText(config.getFolderName(ResourceFolderType.VALUES));
}
catch (InvalidOptionValueException e) {
myErrorLabel.setText("<html><body><font color=\"red\">" + e.getMessage() + "</font></body></html>");
myDirectoryNameField.setText(AndroidConstants.FD_RES_VALUES);
}
}
};
myDeviceConfigurationWrapper.add(myDeviceConfiguratorPanel, BorderLayout.CENTER);
final String defaultResFileName = AndroidResourceUtil.getDefaultResourceFileName(resourceType.getName());
if (defaultResFileName != null) {
myFileNameField.setText(defaultResFileName);
}
myDirectoryNameField.setText(AndroidConstants.FD_RES_VALUES);
myDeviceConfiguratorPanel.updateAll();
myDirectoriesList = new CheckBoxList();
myDirectoriesLabel.setLabelFor(myDirectoriesList);
final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myDirectoriesList);
decorator.setEditAction(null);
decorator.disableUpDownActions();
decorator.setAddAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
doAddNewDirectory();
}
});
decorator.setRemoveAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
doDeleteDirectory();
}
});
final AnActionButton selectAll = new AnActionButton("Select All", null, PlatformIcons.SELECT_ALL_ICON) {
@Override
public void actionPerformed(AnActionEvent e) {
doSelectAllDirs();
}
};
decorator.addExtraAction(selectAll);
final AnActionButton unselectAll = new AnActionButton("Unselect All", null, PlatformIcons.UNSELECT_ALL_ICON) {
@Override
public void actionPerformed(AnActionEvent e) {
doUnselectAllDirs();
}
};
decorator.addExtraAction(unselectAll);
myDirectoriesPanel.add(decorator.createPanel());
updateDirectories();
myModuleCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateDirectories();
}
});
init();
}
private void doDeleteDirectory() {
if (myResourceDir == null) {
return;
}
final int selectedIndex = myDirectoriesList.getSelectedIndex();
if (selectedIndex < 0) {
return;
}
final String selectedDirName = myDirNames[selectedIndex];
final VirtualFile selectedDir = myResourceDir.findChild(selectedDirName);
if (selectedDir == null) {
return;
}
final VirtualFileDeleteProvider provider = new VirtualFileDeleteProvider();
provider.deleteElement(new DataContext() {
@Override
public Object getData(@NonNls String dataId) {
if (PlatformDataKeys.VIRTUAL_FILE_ARRAY.getName().equals(dataId)) {
return new VirtualFile[] {selectedDir};
}
else {
return null;
}
}
});
updateDirectories();
}
private void doSelectAllDirs() {
for (JCheckBox checkBox : myCheckBoxes.values()) {
checkBox.setSelected(true);
}
myDirectoriesList.repaint();
}
private void doUnselectAllDirs() {
for (JCheckBox checkBox : myCheckBoxes.values()) {
checkBox.setSelected(false);
}
myDirectoriesList.repaint();
}
private void doAddNewDirectory() {
if (myResourceDir == null) {
return;
}
final Module module = getModule();
if (module == null) {
return;
}
final Project project = module.getProject();
final PsiDirectory psiResDir = PsiManager.getInstance(project).findDirectory(myResourceDir);
if (psiResDir != null) {
final PsiElement[] createdElements = new CreateResourceDirectoryAction(ResourceFolderType.VALUES).invokeDialog(project, psiResDir);
if (createdElements.length > 0) {
updateDirectories();
}
}
}
private void updateDirectories() {
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);
}
}
@Override
protected ValidationInfo doValidate() {
final String resourceName = getResourceName();
final Module selectedModule = getModule();
final String directoryName = getDirectoryName();
final List<String> directoryNames = getDirNames();
final String fileName = getFileName();
if (resourceName.length() == 0) {
@@ -141,23 +302,14 @@ public class CreateXmlResourceDialog extends DialogWrapper {
else if (selectedModule == null) {
return new ValidationInfo("specify module", myModuleCombo);
}
else if (!ResourceFolderType.VALUES.getName().equals(
AndroidCommonUtils.getResourceTypeByDirName(directoryName))) {
return new ValidationInfo("directory name is not appropriate for value resources");
else if (directoryNames.size() == 0) {
return new ValidationInfo("choose directories", myDirectoriesList);
}
final ValidationInfo info = checkIfResourceAlreadyExists(selectedModule, resourceName, myResourceType, directoryName, fileName);
final ValidationInfo info = checkIfResourceAlreadyExists(selectedModule, resourceName, myResourceType, directoryNames, fileName);
if (info != null) {
return info;
}
try {
myDeviceConfiguratorPanel.doApplyEditors();
}
catch (InvalidOptionValueException e) {
return new ValidationInfo("fix errors in configuration editor");
}
return null;
}
@@ -165,10 +317,10 @@ public class CreateXmlResourceDialog extends DialogWrapper {
private static ValidationInfo checkIfResourceAlreadyExists(@NotNull Module selectedModule,
@NotNull String resourceName,
@NotNull ResourceType resourceType,
@NotNull String directoryName,
@NotNull List<String> dirNames,
@NotNull String fileName) {
if (resourceName.length() == 0 ||
directoryName.length() == 0 ||
dirNames.size() == 0 ||
fileName.length() == 0) {
return null;
}
@@ -179,29 +331,31 @@ public class CreateXmlResourceDialog extends DialogWrapper {
return null;
}
final VirtualFile resourceSubdir = resourceDir.findChild(directoryName);
if (resourceSubdir == null) {
return null;
}
for (String directoryName : dirNames) {
final VirtualFile resourceSubdir = resourceDir.findChild(directoryName);
if (resourceSubdir == null) {
continue;
}
final VirtualFile resFile = resourceSubdir.findChild(fileName);
if (resFile == null) {
return null;
}
final VirtualFile resFile = resourceSubdir.findChild(fileName);
if (resFile == null) {
continue;
}
if (resFile.getFileType() != StdFileTypes.XML) {
return new ValidationInfo("File " + FileUtil.toSystemDependentName(resFile.getPath()) + " is not XML file");
}
if (resFile.getFileType() != StdFileTypes.XML) {
return new ValidationInfo("File " + FileUtil.toSystemDependentName(resFile.getPath()) + " is not XML file");
}
final Resources resources = AndroidUtils.loadDomElement(selectedModule, resFile, Resources.class);
if (resources == null) {
return new ValidationInfo(AndroidBundle.message("not.resource.file.error", FileUtil.toSystemDependentName(resFile.getPath())));
}
final Resources resources = AndroidUtils.loadDomElement(selectedModule, resFile, Resources.class);
if (resources == null) {
return new ValidationInfo(AndroidBundle.message("not.resource.file.error", FileUtil.toSystemDependentName(resFile.getPath())));
}
for (ResourceElement element : AndroidResourceUtil.getValueResourcesFromElement(resourceType.getName(), resources)) {
if (resourceName.equals(element.getName().getValue())) {
return new ValidationInfo("resource '" + resourceName + "' already exists in " + FileUtil.toSystemDependentName(
resFile.getPath()));
for (ResourceElement element : AndroidResourceUtil.getValueResourcesFromElement(resourceType.getName(), resources)) {
if (resourceName.equals(element.getName().getValue())) {
return new ValidationInfo("resource '" + resourceName + "' already exists in " + FileUtil.toSystemDependentName(
resFile.getPath()));
}
}
}
return null;
@@ -216,7 +370,7 @@ public class CreateXmlResourceDialog extends DialogWrapper {
protected void doOKAction() {
final String resourceName = getResourceName();
final String fileName = getFileName();
final String dirName = getDirectoryName();
final List<String> dirNames = getDirNames();
final Module module = getModule();
if (resourceName.length() == 0) {
@@ -228,8 +382,8 @@ public class CreateXmlResourceDialog extends DialogWrapper {
else if (fileName.length() == 0) {
Messages.showErrorDialog(myPanel, "File name is not specified", CommonBundle.getErrorTitle());
}
else if (dirName.length() == 0) {
Messages.showErrorDialog(myPanel, "Directory name is not specified", CommonBundle.getErrorTitle());
else if (dirNames.size() == 0) {
Messages.showErrorDialog(myPanel, "Directories are not selected", CommonBundle.getErrorTitle());
}
else if (module == null) {
Messages.showErrorDialog(myPanel, "Module is not specified", CommonBundle.getErrorTitle());
@@ -245,8 +399,15 @@ public class CreateXmlResourceDialog extends DialogWrapper {
}
@NotNull
public String getDirectoryName() {
return myDirectoryNameField.getText().trim();
public List<String> getDirNames() {
final List<String> selectedDirs = new ArrayList<String>();
for (Map.Entry<String, JCheckBox> entry : myCheckBoxes.entrySet()) {
if (entry.getValue().isSelected()) {
selectedDirs.add(entry.getKey());
}
}
return selectedDirs;
}
@NotNull
@@ -67,7 +67,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import static org.jetbrains.android.util.AndroidUtils.VIEW_CLASS_NAME;
@@ -204,20 +206,14 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl
return;
}
final ResourceElement createdElement =
doCreate(module, dialog.getResourceName(), ResourceType.STRING, dialog.getFileName(), dialog.getDirectoryName(), value);
if (createdElement != null) {
resName = createdElement.getName().getValue();
resName = dialog.getResourceName();
if (!doCreate(module, resName, ResourceType.STRING, dialog.getFileName(), dialog.getDirNames(), value)) {
return;
}
}
else {
assert ApplicationManager.getApplication().isUnitTestMode();
doCreate(facet.getModule(), resName, ResourceType.STRING, "strings.xml", "values", value);
}
if (resName == null) {
return;
doCreate(facet.getModule(), resName, ResourceType.STRING, "strings.xml", Collections.singletonList("values"), value);
}
if (file instanceof PsiJavaFile) {
@@ -358,19 +354,18 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl
return true;
}
@Nullable
private static ResourceElement doCreate(@NotNull Module module,
@NotNull String resourceName,
@NotNull ResourceType resourceType,
@NotNull String fileName,
@NotNull String dirName,
@NotNull String value) {
private static boolean doCreate(@NotNull Module module,
@NotNull String resourceName,
@NotNull ResourceType resourceType,
@NotNull String fileName,
@NotNull List<String> dirNames,
@NotNull String value) {
final Project project = module.getProject();
final AndroidFacet facet = AndroidFacet.getInstance(module);
assert facet != null;
try {
return addValueResource(facet, resourceName, resourceType, fileName, dirName, value);
return addValueResource(facet, resourceName, resourceType, fileName, dirNames, value);
}
catch (Exception e) {
final String message = CreateElementActionBase.filterMessage(e.getMessage());
@@ -382,36 +377,52 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl
LOG.info(e);
reportError(project, message);
}
return null;
return false;
}
}
@Nullable
public static ResourceElement addValueResource(@NotNull AndroidFacet facet,
@NotNull String resourceName,
@NotNull ResourceType resourceType,
@NotNull String fileName,
@NotNull String dirName,
@NotNull String value) throws Exception {
final VirtualFile resFile = findOrCreateResourceFile(facet, fileName, dirName);
if (resFile == null ||
!ReadonlyStatusHandler.ensureFilesWritable(facet.getModule().getProject(), resFile)) {
return null;
private static boolean addValueResource(@NotNull AndroidFacet facet,
@NotNull String resourceName,
@NotNull ResourceType resourceType,
@NotNull String fileName,
@NotNull List<String> dirNames,
@NotNull String value) throws Exception {
if (dirNames.size() == 0) {
return false;
}
final VirtualFile[] resFiles = new VirtualFile[dirNames.size()];
for (int i = 0, n = dirNames.size(); i < n; i++) {
final VirtualFile resFile = findOrCreateResourceFile(facet, fileName, dirNames.get(i));
if (resFile == null) {
return false;
}
resFiles[i] = resFile;
}
if (!ReadonlyStatusHandler.ensureFilesWritable(facet.getModule().getProject(), resFiles)) {
return false;
}
final Resources[] resourcesElements = new Resources[resFiles.length];
for (int i = 0; i < resFiles.length; i++) {
final Resources resources = AndroidUtils.loadDomElement(facet.getModule(), resFiles[i], Resources.class);
if (resources == null) {
reportError(facet.getModule().getProject(), AndroidBundle.message("not.resource.file.error", fileName));
return false;
}
resourcesElements[i] = resources;
}
final Resources resources = AndroidUtils.loadDomElement(facet.getModule(), resFile, Resources.class);
if (resources == null) {
reportError(facet.getModule().getProject(), AndroidBundle.message("not.resource.file.error", fileName));
return null;
}
for (Resources resources : resourcesElements) {
final ResourceElement element = AndroidResourceUtil.addValueResource(resourceType.getName(), resources);
element.getName().setValue(resourceName);
final ResourceElement element = AndroidResourceUtil.addValueResource(resourceType.getName(), resources);
element.getName().setValue(resourceName);
if (value.length() > 0) {
element.setStringValue(value);
if (value.length() > 0) {
element.setStringValue(value);
}
}
return element;
return true;
}
@Nullable
+1
View File
@@ -224,6 +224,7 @@
<readWriteAccessDetector implementation="org.jetbrains.plugins.groovy.findUsages.GroovyReadWriteAccessDetector" order="before java"/>
<findUsagesHandlerFactory implementation="org.jetbrains.plugins.groovy.findUsages.GroovyFindUsagesHandlerFactory"/>
<highlightUsagesHandlerFactory implementation="org.jetbrains.plugins.groovy.findUsages.GrHighlightOverridingMethodsHandlerFactory"/>
<lang.braceMatcher language="Groovy" implementationClass="org.jetbrains.plugins.groovy.highlighter.GroovyBraceMatcher"/>
<lang.importOptimizer language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.editor.GroovyImportOptimizer"/>
<lang.documentationProvider language="Groovy"
@@ -0,0 +1,57 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.findUsages;
import com.intellij.codeInsight.highlighting.ChooseClassAndDoHighlightRunnable;
import com.intellij.codeInsight.highlighting.HighlightOverridingMethodsHandler;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrReferenceList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import java.util.Collections;
import java.util.List;
/**
* @author Max Medvedev
*/
public class GrHighlightOverridingMethodsHandler extends HighlightOverridingMethodsHandler {
private final PsiElement myTarget;
private final GrTypeDefinition myClass;
public GrHighlightOverridingMethodsHandler(final Editor editor,
final PsiFile file,
final PsiElement target,
final GrTypeDefinition psiClass) {
super(editor, file, target, psiClass);
myTarget = target;
myClass = psiClass;
}
@Override
public List<PsiClass> getTargets() {
GrReferenceList list =
GroovyTokenTypes.kEXTENDS == myTarget.getNode().getElementType() ? myClass.getExtendsClause() : myClass.getImplementsClause();
if (list == null) return Collections.emptyList();
final PsiClassType[] classTypes = list.getReferenceTypes();
return ChooseClassAndDoHighlightRunnable.resolveClasses(classTypes);
}
}
@@ -0,0 +1,53 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.findUsages;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerBase;
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerFactory;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrReferenceList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
/**
* @author Max Medvedev
*/
public class GrHighlightOverridingMethodsHandlerFactory implements HighlightUsagesHandlerFactory {
@Override
public HighlightUsagesHandlerBase createHighlightUsagesHandler(Editor editor, PsiFile file) {
int offset = TargetElementUtilBase.adjustOffset(editor.getDocument(), editor.getCaretModel().getOffset());
final PsiElement target = file.findElementAt(offset);
if (target == null) return null;
ASTNode node = target.getNode();
if (node == null) return null;
IElementType type = node.getElementType();
if (type == GroovyTokenTypes.kIMPLEMENTS || type == GroovyTokenTypes.kEXTENDS) {
PsiElement parent = target.getParent();
if (!(parent instanceof GrReferenceList)) return null;
PsiElement grand = parent.getParent();
if (!(grand instanceof GrTypeDefinition)) return null;
return new GrHighlightOverridingMethodsHandler(editor, file, target, (GrTypeDefinition)grand);
}
return null;
}
}
@@ -1,4 +1,4 @@
class Pair {}
List<Pair> otherPairs = new ArrayList<Pair>();
List<Pair> pairs = otherPairs.findAll({it != null})
List<Date> pairs2 = <warning descr="Cannot assign 'Collection<Pair>' to 'List<Date>'">otherPairs.findAll({it != null})</warning>
List<Date> pairs2 = <warning descr="Cannot assign 'ArrayList<Pair>' to 'List<Date>'">otherPairs.findAll({it != null})</warning>
@@ -85,6 +85,10 @@ public final class OperationContext {
return is(PASTE);
}
public boolean isTree() {
return myArea.isTree();
}
public EditableArea getArea() {
return myArea;
}
@@ -21,6 +21,8 @@ import com.intellij.ide.palette.PaletteGroup;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
@@ -78,7 +80,8 @@ public abstract class MetaManager {
@SuppressWarnings("unchecked")
private void loadModel(ClassLoader classLoader, Element element) throws Exception {
Class<RadComponent> model = (Class<RadComponent>)classLoader.loadClass(element.getAttributeValue("model"));
String modelValue = element.getAttributeValue("model");
Class<RadComponent> model = modelValue == null ? null : (Class<RadComponent>)classLoader.loadClass(modelValue);
String target = element.getAttributeValue("class");
String tag = element.getAttributeValue(TAG);
@@ -95,15 +98,42 @@ public abstract class MetaManager {
}
Element palette = element.getChild("palette");
meta.setPaletteItem(
new Item(palette.getAttributeValue("title"), palette.getAttributeValue("icon"), palette.getAttributeValue("tooltip")));
if (palette != null) {
meta.setPaletteItem(
new Item(palette.getAttributeValue("title"), palette.getAttributeValue("icon"), palette.getAttributeValue("tooltip")));
}
Element creation = element.getChild("creation");
if (creation != null) {
meta.setCreation(creation.getTextTrim());
}
myTag2Model.put(tag, meta);
Element properties = element.getChild("properties");
if (properties != null) {
Attribute normal = properties.getAttribute("normal");
if (normal != null) {
meta.setNormalProperties(StringUtil.split(normal.getValue(), " "));
}
Attribute important = properties.getAttribute("important");
if (important != null) {
meta.setImportantProperties(StringUtil.split(important.getValue(), " "));
}
Attribute expert = properties.getAttribute("expert");
if (expert != null) {
meta.setExpertProperties(StringUtil.split(expert.getValue(), " "));
}
Attribute deprecated = properties.getAttribute("deprecated");
if (deprecated != null) {
meta.setDeprecatedProperties(StringUtil.split(deprecated.getValue(), " "));
}
}
if (tag != null) {
myTag2Model.put(tag, meta);
}
if (target != null) {
myTarget2Model.put(target, meta);
@@ -20,6 +20,8 @@ import com.intellij.openapi.util.IconLoader;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Collections;
import java.util.List;
/**
* @author Alexander Lobas
@@ -34,6 +36,10 @@ public class MetaModel {
private String myIconPath;
private Icon myIcon;
private String myCreation;
private List<String> myNormalProperties = Collections.emptyList();
private List<String> myImportantProperties = Collections.emptyList();
private List<String> myExpertProperties = Collections.emptyList();
private List<String> myDeprecatedProperties = Collections.emptyList();
public MetaModel(Class<RadComponent> model, String target, String tag) {
myModel = model;
@@ -97,4 +103,36 @@ public class MetaModel {
myPaletteItem = paletteItem;
myPaletteItem.setMetaModel(this);
}
public boolean isNormalProperty(String name) {
return myNormalProperties.contains(name);
}
public void setNormalProperties(List<String> normalProperties) {
myNormalProperties = normalProperties;
}
public boolean isImportantProperty(String name) {
return myImportantProperties.contains(name);
}
public void setImportantProperties(List<String> importantProperties) {
myImportantProperties = importantProperties;
}
public boolean isExpertProperty(String name) {
return myExpertProperties.contains(name);
}
public void setExpertProperties(List<String> expertProperties) {
myExpertProperties = expertProperties;
}
public boolean isDeprecatedProperty(String name) {
return myDeprecatedProperties.contains(name);
}
public void setDeprecatedProperties(List<String> deprecatedProperties) {
myDeprecatedProperties = deprecatedProperties;
}
}
@@ -117,6 +117,7 @@ public abstract class RadComponent {
public void setLayout(RadLayout layout) {
myLayout = layout;
myLayout.setContainer(this);
}
@Nullable
@@ -28,6 +28,12 @@ import java.util.List;
* @author Alexander Lobas
*/
public abstract class RadLayout {
protected RadComponent myContainer;
public void setContainer(RadComponent container) {
myContainer = container;
}
public abstract ComponentDecorator getChildSelectionDecorator(RadComponent component, List<RadComponent> selection);
@Nullable
@@ -16,7 +16,6 @@
package com.intellij.designer.propertyTable;
import com.intellij.designer.model.RadComponent;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -28,16 +27,17 @@ import java.util.List;
*/
public abstract class Property<T extends RadComponent> {
private final Property myParent;
@NotNull private final String myName;
private final String myName;
private boolean myImportant;
private boolean myExpert;
private boolean myDeprecated;
public Property(Property parent, @NotNull @NonNls String name) {
public Property(@Nullable Property parent, @NotNull String name) {
myParent = parent;
myName = name;
}
public abstract Property createForNewPresentation();
//////////////////////////////////////////////////////////////////////////////////////////
//
// Hierarchy
@@ -333,7 +333,7 @@ public final class PropertyTable extends JBTable implements ComponentSelectionLi
}
}
private static int findProperty(List<Property> properties, Property property) {
public static int findProperty(List<Property> properties, Property property) {
String name = property.getName();
int size = properties.size();
@@ -30,7 +30,7 @@ import java.awt.event.ActionListener;
* @author Vladimir Kondratyev
*/
public class BooleanEditor extends PropertyEditor {
private final JCheckBox myCheckBox;
protected final JCheckBox myCheckBox;
private boolean myInsideChange;
public BooleanEditor() {
@@ -52,12 +52,16 @@ public class BooleanEditor extends PropertyEditor {
return Boolean.valueOf(myCheckBox.isSelected());
}
protected boolean getValue(Object value) {
return value != null && (Boolean)value;
}
@NotNull
public JComponent getComponent(@Nullable RadComponent component, Object value) {
try {
myInsideChange = true;
myCheckBox.setBackground(UIUtil.getTableBackground());
myCheckBox.setSelected(value != null && (Boolean)value);
myCheckBox.setSelected(getValue(value));
return myCheckBox;
}
finally {
@@ -0,0 +1,74 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.designer.propertyTable.editors;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.propertyTable.PropertyEditor;
import com.intellij.openapi.ui.ComboBox;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
/**
* @author Alexander Lobas
*/
public class ComboEditor extends PropertyEditor {
protected final ComboBox myCombo;
public ComboEditor() {
myCombo = new ComboBox(-1);
myCombo.setBorder(null);
myCombo.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
// TODO: Auto-generated method stub
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// TODO: Auto-generated method stub
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// TODO: Auto-generated method stub
}
});
}
@Override
public void updateUI() {
SwingUtilities.updateComponentTreeUI(myCombo);
ListCellRenderer renderer = myCombo.getRenderer();
if (renderer instanceof JComponent) {
SwingUtilities.updateComponentTreeUI((JComponent)renderer);
}
}
@Override
public Object getValue() throws Exception {
return null; // TODO: Auto-generated method stub
}
@NotNull
@Override
public JComponent getComponent(@Nullable RadComponent component, Object value) {
return null; // TODO: Auto-generated method stub
}
}
@@ -28,6 +28,10 @@ import javax.swing.*;
* @author Vladimir Kondratyev
*/
public class BooleanRenderer extends JCheckBox implements PropertyRenderer {
protected boolean getValue(Object value) {
return value != null && (Boolean)value;
}
@NotNull
public JComponent getComponent(@Nullable RadComponent component, @Nullable Object value, boolean selected, boolean hasFocus) {
if (selected) {
@@ -39,7 +43,7 @@ public class BooleanRenderer extends JCheckBox implements PropertyRenderer {
setBackground(UIUtil.getTableBackground());
}
setSelected(value != null && (Boolean)value);
setSelected(getValue(value));
return this;
}
}