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 17 package com.android.ide.eclipse.adt.internal.editors.layout.configuration; 18 19 import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewMode.CUSTOM; 20 import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewMode.DEFAULT; 21 import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewMode.INCLUDES; 22 import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewMode.LOCALES; 23 import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewMode.NONE; 24 import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewMode.SCREENS; 25 import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewMode.VARIATIONS; 26 27 import com.android.annotations.NonNull; 28 import com.android.annotations.Nullable; 29 import com.android.ide.common.resources.ResourceFolder; 30 import com.android.ide.common.resources.configuration.FolderConfiguration; 31 import com.android.ide.eclipse.adt.AdtPlugin; 32 import com.android.ide.eclipse.adt.AdtUtils; 33 import com.android.ide.eclipse.adt.internal.editors.IconFactory; 34 import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; 35 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.IncludeFinder; 36 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.IncludeFinder.Reference; 37 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.LayoutCanvas; 38 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewManager; 39 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewMode; 40 import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; 41 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; 42 43 import org.eclipse.core.resources.IFile; 44 import org.eclipse.core.resources.IFolder; 45 import org.eclipse.core.resources.IProject; 46 import org.eclipse.swt.SWT; 47 import org.eclipse.swt.events.SelectionAdapter; 48 import org.eclipse.swt.events.SelectionEvent; 49 import org.eclipse.swt.graphics.Point; 50 import org.eclipse.swt.graphics.Rectangle; 51 import org.eclipse.swt.widgets.Menu; 52 import org.eclipse.swt.widgets.MenuItem; 53 import org.eclipse.swt.widgets.ToolItem; 54 import org.eclipse.ui.IEditorPart; 55 import org.eclipse.ui.PartInitException; 56 57 import java.util.List; 58 59 /** 60 * The {@linkplain ConfigurationMenuListener} class is responsible for 61 * generating the configuration menu in the {@link ConfigurationChooser}. 62 */ 63 class ConfigurationMenuListener extends SelectionAdapter { 64 private static final String ICON_NEW_CONFIG = "newConfig"; //$NON-NLS-1$ 65 private static final int ACTION_SELECT_CONFIG = 1; 66 private static final int ACTION_CREATE_CONFIG_FILE = 2; 67 private static final int ACTION_ADD = 3; 68 private static final int ACTION_DELETE_ALL = 4; 69 private static final int ACTION_PREVIEW_MODE = 5; 70 71 private final ConfigurationChooser mConfigChooser; 72 private final int mAction; 73 private final IFile mResource; 74 private final RenderPreviewMode mMode; 75 76 ConfigurationMenuListener( 77 @NonNull ConfigurationChooser configChooser, 78 int action, 79 @Nullable IFile resource, 80 @Nullable RenderPreviewMode mode) { 81 mConfigChooser = configChooser; 82 mAction = action; 83 mResource = resource; 84 mMode = mode; 85 } 86 87 @Override 88 public void widgetSelected(SelectionEvent e) { 89 switch (mAction) { 90 case ACTION_SELECT_CONFIG: { 91 try { 92 AdtPlugin.openFile(mResource, null, false); 93 } catch (PartInitException ex) { 94 AdtPlugin.log(ex, null); 95 } 96 return; 97 } 98 case ACTION_CREATE_CONFIG_FILE: { 99 ConfigurationClient client = mConfigChooser.getClient(); 100 if (client != null) { 101 client.createConfigFile(); 102 } 103 return; 104 } 105 } 106 107 IEditorPart activeEditor = AdtUtils.getActiveEditor(); 108 LayoutEditorDelegate delegate = LayoutEditorDelegate.fromEditor(activeEditor); 109 IFile editedFile = mConfigChooser.getEditedFile(); 110 111 if (delegate == null || editedFile == null) { 112 return; 113 } 114 // (Only do this when the two files are in the same project) 115 IProject project = delegate.getEditor().getProject(); 116 if (project == null || 117 !project.equals(editedFile.getProject())) { 118 return; 119 } 120 LayoutCanvas canvas = delegate.getGraphicalEditor().getCanvasControl(); 121 RenderPreviewManager previewManager = canvas.getPreviewManager(); 122 123 switch (mAction) { 124 case ACTION_ADD: { 125 previewManager.addAsThumbnail(); 126 break; 127 } 128 case ACTION_PREVIEW_MODE: { 129 previewManager.selectMode(mMode); 130 break; 131 } 132 case ACTION_DELETE_ALL: { 133 previewManager.deleteManualPreviews(); 134 break; 135 } 136 default: assert false : mAction; 137 } 138 canvas.setFitScale(true /*onlyZoomOut*/, false /*allowZoomIn*/); 139 canvas.redraw(); 140 } 141 142 static void show(ConfigurationChooser chooser, ToolItem combo) { 143 Menu menu = new Menu(chooser.getShell(), SWT.POP_UP); 144 RenderPreviewMode mode = AdtPrefs.getPrefs().getRenderPreviewMode(); 145 146 // Configuration Previews 147 create(menu, "Add As Thumbnail...", 148 new ConfigurationMenuListener(chooser, ACTION_ADD, null, null), 149 SWT.PUSH, false); 150 if (mode == RenderPreviewMode.CUSTOM) { 151 MenuItem item = create(menu, "Delete All Thumbnails", 152 new ConfigurationMenuListener(chooser, ACTION_DELETE_ALL, null, null), 153 SWT.PUSH, false); 154 IEditorPart activeEditor = AdtUtils.getActiveEditor(); 155 LayoutEditorDelegate delegate = LayoutEditorDelegate.fromEditor(activeEditor); 156 if (delegate != null) { 157 LayoutCanvas canvas = delegate.getGraphicalEditor().getCanvasControl(); 158 RenderPreviewManager previewManager = canvas.getPreviewManager(); 159 if (!previewManager.hasManualPreviews()) { 160 item.setEnabled(false); 161 } 162 } 163 } 164 165 @SuppressWarnings("unused") 166 MenuItem configSeparator = new MenuItem(menu, SWT.SEPARATOR); 167 168 create(menu, "Preview Representative Sample", 169 new ConfigurationMenuListener(chooser, ACTION_PREVIEW_MODE, null, 170 DEFAULT), SWT.RADIO, mode == DEFAULT); 171 create(menu, "Preview All Screen Sizes", 172 new ConfigurationMenuListener(chooser, ACTION_PREVIEW_MODE, null, 173 SCREENS), SWT.RADIO, mode == SCREENS); 174 175 MenuItem localeItem = create(menu, "Preview All Locales", 176 new ConfigurationMenuListener(chooser, ACTION_PREVIEW_MODE, null, 177 LOCALES), SWT.RADIO, mode == LOCALES); 178 if (chooser.getLocaleList().size() <= 1) { 179 localeItem.setEnabled(false); 180 } 181 182 boolean canPreviewIncluded = false; 183 IProject project = chooser.getProject(); 184 if (project != null) { 185 IncludeFinder finder = IncludeFinder.get(project); 186 final List<Reference> includedBy = finder.getIncludedBy(chooser.getEditedFile()); 187 canPreviewIncluded = includedBy != null && !includedBy.isEmpty(); 188 } 189 //if (!graphicalEditor.renderingSupports(Capability.EMBEDDED_LAYOUT)) { 190 // canPreviewIncluded = false; 191 //} 192 MenuItem includedItem = create(menu, "Preview Included", 193 new ConfigurationMenuListener(chooser, ACTION_PREVIEW_MODE, null, 194 INCLUDES), SWT.RADIO, mode == INCLUDES); 195 if (!canPreviewIncluded) { 196 includedItem.setEnabled(false); 197 } 198 199 IFile file = chooser.getEditedFile(); 200 List<IFile> variations = AdtUtils.getResourceVariations(file, true); 201 MenuItem variationsItem = create(menu, "Preview Layout Versions", 202 new ConfigurationMenuListener(chooser, ACTION_PREVIEW_MODE, null, 203 VARIATIONS), SWT.RADIO, mode == VARIATIONS); 204 if (variations.size() <= 1) { 205 variationsItem.setEnabled(false); 206 } 207 208 create(menu, "Manual Previews", 209 new ConfigurationMenuListener(chooser, ACTION_PREVIEW_MODE, null, 210 CUSTOM), SWT.RADIO, mode == CUSTOM); 211 create(menu, "None", 212 new ConfigurationMenuListener(chooser, ACTION_PREVIEW_MODE, null, 213 NONE), SWT.RADIO, mode == NONE); 214 215 if (variations.size() > 1) { 216 @SuppressWarnings("unused") 217 MenuItem separator = new MenuItem(menu, SWT.SEPARATOR); 218 219 ResourceManager manager = ResourceManager.getInstance(); 220 for (final IFile resource : variations) { 221 IFolder parent = (IFolder) resource.getParent(); 222 ResourceFolder parentResource = manager.getResourceFolder(parent); 223 FolderConfiguration configuration = parentResource.getConfiguration(); 224 String title = configuration.toDisplayString(); 225 226 MenuItem item = create(menu, title, 227 new ConfigurationMenuListener(chooser, ACTION_SELECT_CONFIG, 228 resource, null), 229 SWT.CHECK, false); 230 231 if (file != null) { 232 boolean selected = file.equals(resource); 233 if (selected) { 234 item.setSelection(true); 235 item.setEnabled(false); 236 } 237 } 238 } 239 } 240 241 Configuration configuration = chooser.getConfiguration(); 242 if (configuration.getEditedConfig() != null && 243 !configuration.getEditedConfig().equals(configuration.getFullConfig())) { 244 if (variations.size() > 0) { 245 @SuppressWarnings("unused") 246 MenuItem separator = new MenuItem(menu, SWT.SEPARATOR); 247 } 248 249 // Add action for creating a new configuration 250 MenuItem item = create(menu, "Create New...", 251 new ConfigurationMenuListener(chooser, ACTION_CREATE_CONFIG_FILE, 252 null, null), 253 SWT.PUSH, false); 254 item.setImage(IconFactory.getInstance().getIcon(ICON_NEW_CONFIG)); 255 } 256 257 Rectangle bounds = combo.getBounds(); 258 Point location = new Point(bounds.x, bounds.y + bounds.height); 259 location = combo.getParent().toDisplay(location); 260 menu.setLocation(location.x, location.y); 261 menu.setVisible(true); 262 } 263 264 @NonNull 265 public static MenuItem create(@NonNull Menu menu, String title, 266 ConfigurationMenuListener listener, int style, boolean selected) { 267 MenuItem item = new MenuItem(menu, style); 268 item.setText(title); 269 item.addSelectionListener(listener); 270 if (selected) { 271 item.setSelection(true); 272 } 273 return item; 274 } 275 276 @NonNull 277 static MenuItem addTogglePreviewModeAction( 278 @NonNull Menu menu, 279 @NonNull String title, 280 @NonNull ConfigurationChooser chooser, 281 @NonNull RenderPreviewMode mode) { 282 boolean selected = AdtPrefs.getPrefs().getRenderPreviewMode() == mode; 283 if (selected) { 284 mode = RenderPreviewMode.NONE; 285 } 286 return create(menu, title, 287 new ConfigurationMenuListener(chooser, ACTION_PREVIEW_MODE, null, mode), 288 SWT.CHECK, selected); 289 } 290 } 291