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.common.resources.configuration.FolderConfiguration;
20 import com.android.ide.eclipse.adt.AdtPlugin;
21 import com.android.ide.eclipse.adt.AdtUtils;
22 import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationChooser;
23 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
24 import com.android.resources.ResourceFolderType;
25 import com.google.common.base.Charsets;
26 
27 import org.eclipse.core.resources.IFile;
28 import org.eclipse.core.resources.IFolder;
29 import org.eclipse.core.resources.IWorkspaceRoot;
30 import org.eclipse.core.resources.ResourcesPlugin;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.core.runtime.IProgressMonitor;
33 import org.eclipse.core.runtime.IStatus;
34 import org.eclipse.core.runtime.Status;
35 import org.eclipse.core.runtime.jobs.Job;
36 import org.eclipse.swt.widgets.Display;
37 import org.eclipse.ui.PartInitException;
38 
39 import java.io.ByteArrayInputStream;
40 import java.io.IOException;
41 
42 /** Job which creates a new layout file for a given configuration */
43 class CreateNewConfigJob extends Job {
44     private final GraphicalEditorPart mEditor;
45     private final IFile mFromFile;
46     private final FolderConfiguration mConfig;
47 
CreateNewConfigJob( @onNull GraphicalEditorPart editor, @NonNull IFile fromFile, @NonNull FolderConfiguration config)48     CreateNewConfigJob(
49             @NonNull GraphicalEditorPart editor,
50             @NonNull IFile fromFile,
51             @NonNull FolderConfiguration config) {
52         super("Create Alternate Layout");
53         mEditor = editor;
54         mFromFile = fromFile;
55         mConfig = config;
56     }
57 
58     @Override
run(IProgressMonitor monitor)59     protected IStatus run(IProgressMonitor monitor) {
60         // get the folder name
61         String folderName = mConfig.getFolderName(ResourceFolderType.LAYOUT);
62         try {
63             // look to see if it exists.
64             // get the res folder
65             IFolder res = (IFolder) mFromFile.getParent().getParent();
66 
67             IFolder newParentFolder = res.getFolder(folderName);
68             AdtUtils.ensureExists(newParentFolder);
69             final IFile file = newParentFolder.getFile(mFromFile.getName());
70             if (file.exists()) {
71                 String message = String.format("File 'res/%1$s/%2$s' already exists!",
72                         folderName, mFromFile.getName());
73                 return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, message);
74             }
75 
76             // Read current document contents instead of from file: mFromFile.getContents()
77             String text = mEditor.getEditorDelegate().getEditor().getStructuredDocument().get();
78             ByteArrayInputStream input = new ByteArrayInputStream(text.getBytes(Charsets.UTF_8));
79             file.create(input, false, monitor);
80             input.close();
81 
82             // Ensure that the project resources updates itself to notice the new configuration.
83             // In theory, this shouldn't be necessary, but we need to make sure the
84             // resource manager knows about this immediately such that the call below
85             // to find the best configuration takes the new folder into account.
86             ResourceManager resourceManager = ResourceManager.getInstance();
87             IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
88             IFolder folder = root.getFolder(newParentFolder.getFullPath());
89             resourceManager.getResourceFolder(folder);
90 
91             // Switch to the new file
92             Display display = mEditor.getConfigurationChooser().getDisplay();
93             display.asyncExec(new Runnable() {
94                 @Override
95                 public void run() {
96                     // The given old layout has been forked into a new layout
97                     // for a given configuration. This means that the old layout
98                     // is no longer a match for the configuration, which is
99                     // probably what it is still showing. We have to modify
100                     // its configuration to no longer be an impossible
101                     // configuration.
102                     ConfigurationChooser chooser = mEditor.getConfigurationChooser();
103                     chooser.onAlternateLayoutCreated();
104 
105                     // Finally open the new layout
106                     try {
107                         AdtPlugin.openFile(file, null, false);
108                     } catch (PartInitException e) {
109                         AdtPlugin.log(e, null);
110                     }
111                 }
112             });
113         } catch (IOException e2) {
114             String message = String.format(
115                     "Failed to create File 'res/%1$s/%2$s' : %3$s",
116                     folderName, mFromFile.getName(), e2.getMessage());
117             AdtPlugin.displayError("Layout Creation", message);
118 
119             return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
120                     message, e2);
121         } catch (CoreException e2) {
122             String message = String.format(
123                     "Failed to create File 'res/%1$s/%2$s' : %3$s",
124                     folderName, mFromFile.getName(), e2.getMessage());
125             AdtPlugin.displayError("Layout Creation", message);
126 
127             return e2.getStatus();
128         }
129 
130         return Status.OK_STATUS;
131     }
132 }
133