Search in sources :

Example 11 with HtmlBuilder

use of com.android.utils.HtmlBuilder in project android by JetBrains.

the class CreateResourceFileDialogBase method setupDeviceConfigurationPanel.

protected DeviceConfiguratorPanel setupDeviceConfigurationPanel(final JTextField directoryNameTextField, final TemplateKindCombo resourceTypeCombo, final JBLabel errorLabel) {
    return new DeviceConfiguratorPanel() {

        @Override
        public void applyEditors() {
            try {
                doApplyEditors();
                final FolderConfiguration config = this.getConfiguration();
                final CreateTypedResourceFileAction selectedAction = getSelectedAction(resourceTypeCombo);
                errorLabel.setText("");
                directoryNameTextField.setText("");
                if (selectedAction != null) {
                    final ResourceFolderType resFolderType = selectedAction.getResourceFolderType();
                    directoryNameTextField.setText(config.getFolderName(resFolderType));
                }
            } catch (InvalidOptionValueException e) {
                errorLabel.setText(new HtmlBuilder().openHtmlBody().coloredText(JBColor.RED, e.getMessage()).closeHtmlBody().getHtml());
                directoryNameTextField.setText("");
            }
            updateOkAction();
        }
    };
}
Also used : ResourceFolderType(com.android.resources.ResourceFolderType) HtmlBuilder(com.android.utils.HtmlBuilder) InvalidOptionValueException(org.jetbrains.android.uipreview.InvalidOptionValueException) FolderConfiguration(com.android.ide.common.resources.configuration.FolderConfiguration) DeviceConfiguratorPanel(org.jetbrains.android.uipreview.DeviceConfiguratorPanel)

Example 12 with HtmlBuilder

use of com.android.utils.HtmlBuilder in project android by JetBrains.

the class ManifestPanel method getHtml.

@NotNull
String getHtml(@NotNull AndroidFacet facet, @NotNull SourceFilePosition sourceFilePosition) {
    HtmlBuilder sb = new HtmlBuilder();
    describePosition(sb, facet, sourceFilePosition);
    return sb.getHtml();
}
Also used : HtmlBuilder(com.android.utils.HtmlBuilder) NotNull(org.jetbrains.annotations.NotNull)

Example 13 with HtmlBuilder

use of com.android.utils.HtmlBuilder in project android by JetBrains.

the class ManifestPanel method getErrorRemoveHtml.

@NotNull
private static String getErrorRemoveHtml(@NotNull final AndroidFacet facet, @NotNull String message, @NotNull final SourceFilePosition position, @NotNull HtmlLinkManager htmlLinkManager, @Nullable final VirtualFile currentlyOpenFile) {
    /*
    Example Input:
    ERROR Overlay manifest:package attribute declared at AndroidManifest.xml:3:5-49
    value=(com.foo.manifestapplication.debug) has a different value=(com.foo.manifestapplication)
    declared in main manifest at AndroidManifest.xml:5:5-43 Suggestion: remove the overlay
    declaration at AndroidManifest.xml and place it in the build.gradle: flavorName
    { applicationId = "com.foo.manifestapplication.debug" } AndroidManifest.xml (debug)
     */
    HtmlBuilder sb = new HtmlBuilder();
    int start = message.indexOf('{');
    int end = message.indexOf('}', start + 1);
    final String declaration = message.substring(start + 1, end).trim();
    if (!declaration.startsWith("applicationId")) {
        throw new IllegalArgumentException("unexpected remove suggestion format " + message);
    }
    final GradleBuildFile buildFile = GradleBuildFile.get(facet.getModule());
    Runnable link = null;
    if (buildFile != null) {
        final String applicationId = declaration.substring(declaration.indexOf('"') + 1, declaration.lastIndexOf('"'));
        final File manifestOverlayFile = position.getFile().getSourceFile();
        assert manifestOverlayFile != null;
        VirtualFile manifestOverlayVirtualFile = LocalFileSystem.getInstance().findFileByIoFile(manifestOverlayFile);
        assert manifestOverlayVirtualFile != null;
        IdeaSourceProvider sourceProvider = ManifestUtils.findManifestSourceProvider(facet, manifestOverlayVirtualFile);
        assert sourceProvider != null;
        final String name = sourceProvider.getName();
        AndroidModuleModel androidModuleModel = AndroidModuleModel.get(facet.getModule());
        assert androidModuleModel != null;
        final XmlFile manifestOverlayPsiFile = (XmlFile) PsiManager.getInstance(facet.getModule().getProject()).findFile(manifestOverlayVirtualFile);
        assert manifestOverlayPsiFile != null;
        if (androidModuleModel.getBuildTypeNames().contains(name)) {
            final String packageName = MergedManifest.get(facet).getPackage();
            assert packageName != null;
            if (applicationId.startsWith(packageName)) {
                link = () -> new WriteCommandAction.Simple(facet.getModule().getProject(), "Apply manifest suggestion", buildFile.getPsiFile(), manifestOverlayPsiFile) {

                    @Override
                    protected void run() throws Throwable {
                        if (currentlyOpenFile != null) {
                            // We mark this action as affecting the currently open file, so the Undo is available in this editor
                            CommandProcessor.getInstance().addAffectedFiles(facet.getModule().getProject(), currentlyOpenFile);
                        }
                        removePackageAttribute(manifestOverlayPsiFile);
                        final String applicationIdSuffix = applicationId.substring(packageName.length());
                        @SuppressWarnings("unchecked") List<NamedObject> buildTypes = (List<NamedObject>) buildFile.getValue(BuildFileKey.BUILD_TYPES);
                        if (buildTypes == null) {
                            buildTypes = new ArrayList<>();
                        }
                        NamedObject buildType = find(buildTypes, name);
                        if (buildType == null) {
                            buildType = new NamedObject(name);
                            buildTypes.add(buildType);
                        }
                        buildType.setValue(BuildFileKey.APPLICATION_ID_SUFFIX, applicationIdSuffix);
                        buildFile.setValue(BuildFileKey.BUILD_TYPES, buildTypes);
                        GradleSyncInvoker.getInstance().requestProjectSyncAndSourceGeneration(facet.getModule().getProject(), null);
                    }
                }.execute();
            }
        } else if (androidModuleModel.getProductFlavorNames().contains(name)) {
            link = () -> new WriteCommandAction.Simple(facet.getModule().getProject(), "Apply manifest suggestion", buildFile.getPsiFile(), manifestOverlayPsiFile) {

                @Override
                protected void run() throws Throwable {
                    if (currentlyOpenFile != null) {
                        // We mark this action as affecting the currently open file, so the Undo is available in this editor
                        CommandProcessor.getInstance().addAffectedFiles(facet.getModule().getProject(), currentlyOpenFile);
                    }
                    removePackageAttribute(manifestOverlayPsiFile);
                    @SuppressWarnings("unchecked") List<NamedObject> flavors = (List<NamedObject>) buildFile.getValue(BuildFileKey.FLAVORS);
                    assert flavors != null;
                    NamedObject flavor = find(flavors, name);
                    assert flavor != null;
                    flavor.setValue(BuildFileKey.APPLICATION_ID, applicationId);
                    buildFile.setValue(BuildFileKey.FLAVORS, flavors);
                    GradleSyncInvoker.getInstance().requestProjectSyncAndSourceGeneration(facet.getModule().getProject(), null);
                }
            }.execute();
        }
    }
    if (link != null) {
        sb.addLink(message.substring(0, end + 1), htmlLinkManager.createRunnableLink(link));
        sb.add(message.substring(end + 1));
    } else {
        sb.add(message);
    }
    return sb.getHtml();
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) WriteCommandAction(com.intellij.openapi.command.WriteCommandAction) GradleBuildFile(com.android.tools.idea.gradle.parser.GradleBuildFile) XmlFile(com.intellij.psi.xml.XmlFile) HtmlBuilder(com.android.utils.HtmlBuilder) NamedObject(com.android.tools.idea.gradle.parser.NamedObject) IdeaSourceProvider(org.jetbrains.android.facet.IdeaSourceProvider) AndroidModuleModel(com.android.tools.idea.gradle.project.model.AndroidModuleModel) List(java.util.List) XmlFile(com.intellij.psi.xml.XmlFile) VirtualFile(com.intellij.openapi.vfs.VirtualFile) SourceFile(com.android.ide.common.blame.SourceFile) GradleBuildFile(com.android.tools.idea.gradle.parser.GradleBuildFile) File(java.io.File) NotNull(org.jetbrains.annotations.NotNull)

Example 14 with HtmlBuilder

use of com.android.utils.HtmlBuilder in project android by JetBrains.

the class SdkQuickfixUtils method createDialog.

@VisibleForTesting
@Nullable
static ModelWizardDialog createDialog(@Nullable Project project, @Nullable Component parent, @Nullable Collection<String> requestedPaths, @Nullable Collection<UpdatablePackage> requestedPackages, @Nullable Collection<LocalPackage> requestedUninstalls, @Nullable AndroidSdkHandler sdkHandler, boolean backgroundable) {
    if (sdkHandler == null) {
        return null;
    }
    RepoManager mgr = sdkHandler.getSdkManager(REPO_LOGGER);
    if (mgr.getLocalPath() == null) {
        String title = "SDK Problem";
        String msg = "<html>" + "Your Android SDK is missing or out of date." + "<br>" + "You can configure your SDK via <b>Configure | Project Defaults | Project Structure | SDKs</b></html>";
        Messages.showErrorDialog(msg, title);
        return null;
    }
    List<String> unknownPaths = new ArrayList<>();
    List<UpdatablePackage> resolvedPackages;
    mgr.loadSynchronously(0, new StudioLoggerProgressIndicator(SdkQuickfixUtils.class), new StudioDownloader(), StudioSettingsController.getInstance());
    RepositoryPackages packages = mgr.getPackages();
    if (requestedPackages == null) {
        requestedPackages = new ArrayList<>();
    }
    requestedPackages.addAll(lookupPaths(requestedPaths, packages, unknownPaths));
    try {
        resolvedPackages = resolve(requestedPackages, packages);
    } catch (PackageResolutionException e) {
        Messages.showErrorDialog(e.getMessage(), "Error Resolving Packages");
        return null;
    }
    Set<LocalPackage> resolvedUninstalls = new HashSet<>();
    if (requestedUninstalls != null) {
        resolvedUninstalls.addAll(requestedUninstalls);
        // We don't want to uninstall something required by a package we're installing
        resolvedPackages.forEach(updatable -> resolvedUninstalls.remove(updatable.getLocal()));
    }
    List<UpdatablePackage> unavailableDownloads = Lists.newArrayList();
    verifyAvailability(resolvedPackages, unavailableDownloads);
    // If there were requests we didn't understand or can't download, show an error.
    if (!unknownPaths.isEmpty() || !unavailableDownloads.isEmpty()) {
        String title = "Packages Unavailable";
        HtmlBuilder builder = new HtmlBuilder();
        builder.openHtmlBody().add(String.format("%1$s packages are not available for download!", resolvedPackages.isEmpty() ? "All" : "Some")).newline().newline().add("The following packages are not available:").beginList();
        for (UpdatablePackage p : unavailableDownloads) {
            builder.listItem().add(p.getRepresentative().getDisplayName());
        }
        for (String p : unknownPaths) {
            builder.listItem().add("Package id " + p);
        }
        builder.endList().closeHtmlBody();
        Messages.showErrorDialog(builder.getHtml(), title);
    }
    // If everything was removed, don't continue.
    if (resolvedPackages.isEmpty() && resolvedUninstalls.isEmpty()) {
        return null;
    }
    List<RemotePackage> installRequests = resolvedPackages.stream().map(UpdatablePackage::getRemote).collect(Collectors.toList());
    ModelWizard.Builder wizardBuilder = new ModelWizard.Builder();
    wizardBuilder.addStep(new LicenseAgreementStep(new LicenseAgreementModel(mgr.getLocalPath()), installRequests));
    InstallSelectedPackagesStep installStep = new InstallSelectedPackagesStep(resolvedPackages, resolvedUninstalls, sdkHandler, backgroundable);
    wizardBuilder.addStep(installStep);
    ModelWizard wizard = wizardBuilder.build();
    String title = "SDK Quickfix Installation";
    return new StudioWizardDialogBuilder(wizard, title, parent).setProject(project).setModalityType(DialogWrapper.IdeModalityType.IDE).setCancellationPolicy(ModelWizardDialog.CancellationPolicy.CAN_CANCEL_UNTIL_CAN_FINISH).build();
}
Also used : HtmlBuilder(com.android.utils.HtmlBuilder) StudioWizardDialogBuilder(com.android.tools.idea.ui.wizard.StudioWizardDialogBuilder) RepositoryPackages(com.android.repository.impl.meta.RepositoryPackages) ModelWizard(com.android.tools.idea.wizard.model.ModelWizard) HtmlBuilder(com.android.utils.HtmlBuilder) StudioDownloader(com.android.tools.idea.sdk.StudioDownloader) StudioLoggerProgressIndicator(com.android.tools.idea.sdk.progress.StudioLoggerProgressIndicator) StudioWizardDialogBuilder(com.android.tools.idea.ui.wizard.StudioWizardDialogBuilder) VisibleForTesting(com.android.annotations.VisibleForTesting) Nullable(org.jetbrains.annotations.Nullable)

Example 15 with HtmlBuilder

use of com.android.utils.HtmlBuilder in project android by JetBrains.

the class AndroidResourceRenameResourceProcessor method findExistingNameConflicts.

@Override
public void findExistingNameConflicts(final PsiElement originalElement, String newName, final MultiMap<PsiElement, String> conflicts) {
    ResourceType type = getResourceType(originalElement);
    if (type == null) {
        return;
    }
    PsiElement element = LazyValueResourceElementWrapper.computeLazyElement(originalElement);
    if (element == null) {
        return;
    }
    AndroidFacet facet = AndroidFacet.getInstance(element);
    if (facet == null) {
        return;
    }
    // First check to see if the new name is conflicting with an existing resource
    if (element instanceof PsiFile) {
        // The name of a file resource is the name of the file without the extension.
        // So when dealing with a file, we must first remove the extension in the name
        // before checking if it is already used.
        newName = AndroidCommonUtils.getResourceName(type.getName(), newName);
    }
    AppResourceRepository appResources = AppResourceRepository.getAppResources(facet, true);
    if (appResources.hasResourceItem(type, newName)) {
        boolean foundElements = false;
        PsiField[] resourceFields = AndroidResourceUtil.findResourceFields(facet, type.getName(), newName, true);
        String message = String.format("Resource @%1$s/%2$s already exists", type, newName);
        if (resourceFields.length > 0) {
            // Use find usages to find the actual declaration location such that they can be shown in the conflicts view
            AndroidFindUsagesHandlerFactory factory = new AndroidFindUsagesHandlerFactory();
            if (factory.canFindUsages(originalElement)) {
                FindUsagesHandler handler = factory.createFindUsagesHandler(resourceFields[0], false);
                if (handler != null) {
                    PsiElement[] elements = ArrayUtil.mergeArrays(handler.getPrimaryElements(), handler.getSecondaryElements());
                    for (PsiElement e : elements) {
                        if (e instanceof LightElement) {
                            // AndroidLightField does not work in the conflicts view; UsageInfo throws NPE
                            continue;
                        }
                        conflicts.putValue(e, message);
                        foundElements = true;
                    }
                }
            }
        }
        if (!foundElements) {
            conflicts.putValue(originalElement, message);
        }
    }
    // Next see if the renamed resource is also defined externally, in which case we should ask the
    // user if they really want to continue. Despite the name of this method ("findExistingNameConflicts")
    // and the dialog used to show the message (ConflictsDialog), this isn't conflict specific; the
    // dialog title simply says "Problems Detected" and the label for the text view is "The following
    // problems were found". We need to use this because it's the only facility in the rename processor
    // which lets us ask the user whether to continue and to have the answer either bail out of the operation
    // or to resume.
    // See if this is a locally defined resource (you can't rename fields from libraries such as appcompat)
    // e.g. ?attr/listPreferredItemHeightSmall
    String name = getResourceName(originalElement);
    if (name != null) {
        Project project = facet.getModule().getProject();
        List<ResourceItem> all = appResources.getResourceItem(type, name);
        if (all == null) {
            all = Collections.emptyList();
        }
        List<ResourceItem> local = ProjectResourceRepository.getProjectResources(facet, true).getResourceItem(type, name);
        if (local == null) {
            local = Collections.emptyList();
        }
        HtmlBuilder builder = null;
        if (local.size() == 0 && all.size() > 0) {
            builder = new HtmlBuilder(new StringBuilder(300));
            builder.add("Resource is also only defined in external libraries and cannot be renamed.");
        } else if (local.size() < all.size()) {
            // This item is also defined in one of the libraries, not just locally: we can't rename it. Should we
            // display some sort of warning?
            builder = new HtmlBuilder(new StringBuilder(300));
            builder.add("The resource ").beginBold().add(PREFIX_RESOURCE_REF).add(type.getName()).add("/").add(name).endBold();
            builder.add(" is defined outside of the project (in one of the libraries) and cannot ");
            builder.add("be updated. This can change the behavior of the application.").newline().newline();
            builder.add("Are you sure you want to do this?");
        }
        if (builder != null) {
            appendUnhandledReferences(project, facet, all, local, builder);
            conflicts.putValue(originalElement, builder.getHtml());
        }
    }
}
Also used : FindUsagesHandler(com.intellij.find.findUsages.FindUsagesHandler) HtmlBuilder(com.android.utils.HtmlBuilder) ResourceType(com.android.resources.ResourceType) AppResourceRepository(com.android.tools.idea.res.AppResourceRepository) AndroidFacet(org.jetbrains.android.facet.AndroidFacet) LightElement(com.intellij.psi.impl.light.LightElement) Project(com.intellij.openapi.project.Project) ResourceItem(com.android.ide.common.res2.ResourceItem)

Aggregations

HtmlBuilder (com.android.utils.HtmlBuilder)36 NotNull (org.jetbrains.annotations.NotNull)9 XmlFile (com.intellij.psi.xml.XmlFile)8 Module (com.intellij.openapi.module.Module)7 Project (com.intellij.openapi.project.Project)7 File (java.io.File)6 IOException (java.io.IOException)3 AndroidFacet (org.jetbrains.android.facet.AndroidFacet)3 VisibleForTesting (com.android.annotations.VisibleForTesting)2 SourceFile (com.android.ide.common.blame.SourceFile)2 ResourceResolver (com.android.ide.common.resources.ResourceResolver)2 FolderConfiguration (com.android.ide.common.resources.configuration.FolderConfiguration)2 RepositoryPackages (com.android.repository.impl.meta.RepositoryPackages)2 ResourceFolderType (com.android.resources.ResourceFolderType)2 AndroidVersion (com.android.sdklib.AndroidVersion)2 IAndroidTarget (com.android.sdklib.IAndroidTarget)2 GradleBuildFile (com.android.tools.idea.gradle.parser.GradleBuildFile)2 AndroidModuleModel (com.android.tools.idea.gradle.project.model.AndroidModuleModel)2 AndroidModuleInfo (com.android.tools.idea.model.AndroidModuleInfo)2 EditorDesignSurface (com.android.tools.idea.ui.designer.EditorDesignSurface)2