1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.eclipse.org/org/documents/epl-v10.php
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
17 
18 import com.android.annotations.NonNull;
19 import com.android.ide.eclipse.adt.AdtPlugin;
20 import com.android.ide.eclipse.adt.AdtUtils;
21 import com.android.ide.eclipse.adt.internal.editors.formatting.EclipseXmlPrettyPrinter;
22 import com.android.ide.eclipse.adt.internal.editors.layout.configuration.Configuration;
23 import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationChooser;
24 import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationDescription;
25 import com.android.sdklib.devices.Device;
26 import com.google.common.base.Charsets;
27 import com.google.common.collect.Lists;
28 import com.google.common.io.Files;
29 
30 import org.eclipse.core.resources.IProject;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.core.runtime.QualifiedName;
33 import org.w3c.dom.Document;
34 import org.w3c.dom.Element;
35 
36 import java.io.File;
37 import java.io.IOException;
38 import java.util.ArrayList;
39 import java.util.Collection;
40 import java.util.List;
41 
42 /** A list of render previews */
43 class RenderPreviewList {
44     /** Name of file saved in project directory storing previews */
45     private static final String PREVIEW_FILE_NAME = "previews.xml"; //$NON-NLS-1$
46 
47     /** Qualified name for the per-project persistent property include-map */
48     private final static QualifiedName PREVIEW_LIST = new QualifiedName(AdtPlugin.PLUGIN_ID,
49             "previewlist");//$NON-NLS-1$
50 
51     private final IProject mProject;
52     private final List<ConfigurationDescription> mList = Lists.newArrayList();
53 
RenderPreviewList(@onNull IProject project)54     private RenderPreviewList(@NonNull IProject project) {
55         mProject = project;
56     }
57 
58     /**
59      * Returns the {@link RenderPreviewList} for the given project
60      *
61      * @param project the project the list is associated with
62      * @return a {@link RenderPreviewList} for the given project, never null
63      */
64     @NonNull
get(@onNull IProject project)65     public static RenderPreviewList get(@NonNull IProject project) {
66         RenderPreviewList list = null;
67         try {
68             list = (RenderPreviewList) project.getSessionProperty(PREVIEW_LIST);
69         } catch (CoreException e) {
70             // Not a problem; we will just create a new one
71         }
72 
73         if (list == null) {
74             list = new RenderPreviewList(project);
75             try {
76                 project.setSessionProperty(PREVIEW_LIST, list);
77             } catch (CoreException e) {
78                 AdtPlugin.log(e, null);
79             }
80         }
81 
82         return list;
83     }
84 
getManualFile()85     private File getManualFile() {
86         return new File(AdtUtils.getAbsolutePath(mProject).toFile(), PREVIEW_FILE_NAME);
87     }
88 
load(Collection<Device> deviceList)89     void load(Collection<Device> deviceList) throws IOException {
90         File file = getManualFile();
91         if (file.exists()) {
92             load(file, deviceList);
93         }
94     }
95 
save()96     void save() throws IOException {
97         deleteFile();
98         if (!mList.isEmpty()) {
99             File file = getManualFile();
100             save(file);
101         }
102     }
103 
save(File file)104     private void save(File file) throws IOException {
105         //Document document = DomUtilities.createEmptyPlainDocument();
106         Document document = DomUtilities.createEmptyDocument();
107         if (document != null) {
108             for (ConfigurationDescription description : mList) {
109                 description.toXml(document);
110             }
111             String xml = EclipseXmlPrettyPrinter.prettyPrint(document, true);
112             Files.write(xml, file, Charsets.UTF_8);
113         }
114     }
115 
load(File file, Collection<Device> deviceList)116     void load(File file, Collection<Device> deviceList) throws IOException {
117         mList.clear();
118 
119         String xml = Files.toString(file, Charsets.UTF_8);
120         Document document = DomUtilities.parseDocument(xml, true);
121         if (document == null || document.getDocumentElement() == null) {
122             return;
123         }
124         List<Element> elements = DomUtilities.getChildren(document.getDocumentElement());
125         for (Element element : elements) {
126             ConfigurationDescription description = ConfigurationDescription.fromXml(
127                     mProject, element, deviceList);
128             if (description != null) {
129                 mList.add(description);
130             }
131         }
132     }
133 
134     /**
135      * Create a list of previews for the given canvas that matches the internal
136      * configuration preview list
137      *
138      * @param canvas the associated canvas
139      * @return a new list of previews linked to the given canvas
140      */
141     @NonNull
createPreviews(LayoutCanvas canvas)142     List<RenderPreview> createPreviews(LayoutCanvas canvas) {
143         if (mList.isEmpty()) {
144             return new ArrayList<RenderPreview>();
145         }
146         List<RenderPreview> previews = Lists.newArrayList();
147         RenderPreviewManager manager = canvas.getPreviewManager();
148         ConfigurationChooser chooser = canvas.getEditorDelegate().getGraphicalEditor()
149                 .getConfigurationChooser();
150 
151         Configuration chooserConfig = chooser.getConfiguration();
152         for (ConfigurationDescription description : mList) {
153             Configuration configuration = Configuration.create(chooser);
154             configuration.setDisplayName(description.displayName);
155             configuration.setActivity(description.activity);
156             configuration.setLocale(
157                     description.locale != null ? description.locale : chooserConfig.getLocale(),
158                             true);
159             // TODO: Make sure this layout isn't in some v-folder which is incompatible
160             // with this target!
161             configuration.setTarget(
162                     description.target != null ? description.target : chooserConfig.getTarget(),
163                             true);
164             configuration.setTheme(
165                 description.theme != null ? description.theme : chooserConfig.getTheme());
166             configuration.setDevice(
167                 description.device != null ? description.device : chooserConfig.getDevice(),
168                         true);
169             configuration.setDeviceState(
170                 description.state != null ? description.state : chooserConfig.getDeviceState(),
171                         true);
172             configuration.setNightMode(
173                 description.nightMode != null ? description.nightMode
174                         : chooserConfig.getNightMode(), true);
175             configuration.setUiMode(
176                 description.uiMode != null ? description.uiMode : chooserConfig.getUiMode(), true);
177 
178             //configuration.syncFolderConfig();
179             configuration.getFullConfig().set(description.folder);
180 
181             RenderPreview preview = RenderPreview.create(manager, configuration);
182 
183             preview.setDescription(description);
184             previews.add(preview);
185         }
186 
187         return previews;
188     }
189 
remove(@onNull RenderPreview preview)190     void remove(@NonNull RenderPreview preview) {
191         ConfigurationDescription description = preview.getDescription();
192         if (description != null) {
193             mList.remove(description);
194         }
195     }
196 
isEmpty()197     boolean isEmpty() {
198         return mList.isEmpty();
199     }
200 
add(@onNull RenderPreview preview)201     void add(@NonNull RenderPreview preview) {
202         Configuration configuration = preview.getConfiguration();
203         ConfigurationDescription description =
204                 ConfigurationDescription.fromConfiguration(mProject, configuration);
205         // RenderPreviews can have display names that aren't reflected in the configuration
206         description.displayName = preview.getDisplayName();
207         mList.add(description);
208         preview.setDescription(description);
209     }
210 
delete()211     void delete() {
212         mList.clear();
213         deleteFile();
214     }
215 
deleteFile()216     private void deleteFile() {
217         File file = getManualFile();
218         if (file.exists()) {
219             file.delete();
220         }
221     }
222 }
223