com.android.tools.idea.editors.theme.ThemeEditorProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.android.tools.idea.editors.theme.ThemeEditorProvider.java

Source

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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.android.tools.idea.editors.theme;

import com.android.resources.ResourceFolderType;
import com.android.tools.analytics.UsageTracker;
import com.android.tools.idea.res.ResourceHelper;
import com.google.wireless.android.sdk.stats.AndroidStudioEvent;
import com.google.wireless.android.sdk.stats.AndroidStudioEvent.EventCategory;
import com.google.wireless.android.sdk.stats.AndroidStudioEvent.EventKind;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorPolicy;
import com.intellij.openapi.fileEditor.FileEditorProvider;
import com.intellij.openapi.fileEditor.FileEditorState;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static com.android.SdkConstants.TAG_RESOURCES;
import static com.android.SdkConstants.TAG_STYLE;

public class ThemeEditorProvider implements FileEditorProvider, DumbAware {
    public final static boolean THEME_EDITOR_ENABLE = true;

    private final static String THEME_NAME = "theme-name";
    private final static String STYLE_NAME = "style-name";
    private final static String MODULE_NAME = "module-name";
    private final static String PROPORTION = "proportion";

    @Override
    public boolean accept(@NotNull Project project, @NotNull VirtualFile file) {
        if (!THEME_EDITOR_ENABLE) {
            return false;
        }

        return file instanceof ThemeEditorVirtualFile;
    }

    @NotNull
    @Override
    public FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile file) {
        UsageTracker.getInstance().log(AndroidStudioEvent.newBuilder().setCategory(EventCategory.THEME_EDITOR)
                .setKind(EventKind.THEME_EDITOR_OPEN));
        return new ThemeEditor(project, file);
    }

    @Override
    public void disposeEditor(@NotNull FileEditor editor) {
        Disposer.dispose(editor);
    }

    @NotNull
    @Override
    public FileEditorState readState(@NotNull Element sourceElement, @NotNull Project project,
            @NotNull VirtualFile file) {
        String themeName = sourceElement.getAttributeValue(THEME_NAME);
        String styleName = sourceElement.getAttributeValue(STYLE_NAME);
        String moduleName = sourceElement.getAttributeValue(MODULE_NAME);

        Float proportion = null;
        try {
            String proportionString = sourceElement.getAttributeValue(PROPORTION);
            if (proportionString != null) {
                proportion = Float.parseFloat(proportionString);
            }
        } catch (NumberFormatException e) {
            // ignore
        }

        return new ThemeEditorState(themeName, styleName, proportion, moduleName);
    }

    @Override
    public void writeState(@NotNull FileEditorState state, @NotNull Project project,
            @NotNull Element targetElement) {
        if (!(state instanceof ThemeEditorState)) {
            return;
        }

        ThemeEditorState editorState = (ThemeEditorState) state;

        setAttributeIfNotNull(targetElement, THEME_NAME, editorState.getThemeName());
        setAttributeIfNotNull(targetElement, STYLE_NAME, editorState.getSubStyleName());
        setAttributeIfNotNull(targetElement, MODULE_NAME, editorState.getModuleName());

        targetElement.setAttribute(PROPORTION, Float.toString(editorState.getProportion()));
    }

    private static void setAttributeIfNotNull(@NotNull Element targetElement, String paramName, String paramValue) {
        if (paramValue != null) {
            targetElement.setAttribute(paramName, paramValue);
        }
    }

    @NotNull
    @Override
    public String getEditorTypeId() {
        return "themeEditor";
    }

    @NotNull
    @Override
    public FileEditorPolicy getPolicy() {
        return FileEditorPolicy.PLACE_AFTER_DEFAULT_EDITOR;
    }

    public static boolean isAndroidTheme(@Nullable PsiFile file) {
        if (!THEME_EDITOR_ENABLE) {
            return false;
        }

        if (ResourceHelper.getFolderType(file) != ResourceFolderType.VALUES || !(file instanceof XmlFile)) {
            return false;
        }

        final String name = file.getName();
        if (name.equals("strings.xml")) {
            // Optimization: strings.xml can contain a lot of tags and has a separate editor,
            // so we just skip all checks and return false
            return false;
        } else if (name.equals("styles.xml")) {
            // styles.xml is a conventional name for XML resource file with style definitions.
            // So, we are going to show notification for styles.xml even if there are no style
            // definitions in that file yet
            return true;
        }

        XmlTag rootTag = ((XmlFile) file).getRootTag();
        if (rootTag == null || !rootTag.getName().equals(TAG_RESOURCES)) {
            return false;
        }

        for (XmlTag child : rootTag.getSubTags()) {
            if (child.getName().equals(TAG_STYLE)) {
                return true;
            }
        }

        return false;
    }
}