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