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