1 /* 2 * Copyright (C) 2011 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.lint; 17 18 import com.android.ide.eclipse.adt.AdtPlugin; 19 import com.android.ide.eclipse.adt.AdtUtils; 20 import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; 21 22 import org.eclipse.core.resources.IFile; 23 import org.eclipse.core.resources.IMarker; 24 import org.eclipse.core.resources.IResource; 25 import org.eclipse.core.runtime.IStatus; 26 import org.eclipse.jface.dialogs.IDialogConstants; 27 import org.eclipse.jface.dialogs.TitleAreaDialog; 28 import org.eclipse.swt.SWT; 29 import org.eclipse.swt.events.SelectionEvent; 30 import org.eclipse.swt.events.SelectionListener; 31 import org.eclipse.swt.graphics.Point; 32 import org.eclipse.swt.layout.GridData; 33 import org.eclipse.swt.layout.GridLayout; 34 import org.eclipse.swt.widgets.Button; 35 import org.eclipse.swt.widgets.Composite; 36 import org.eclipse.swt.widgets.Control; 37 import org.eclipse.swt.widgets.Display; 38 import org.eclipse.swt.widgets.Label; 39 import org.eclipse.swt.widgets.Shell; 40 import org.eclipse.swt.widgets.Text; 41 import org.eclipse.ui.IEditorPart; 42 import org.eclipse.ui.IWorkbenchPage; 43 import org.eclipse.ui.IWorkbenchPartSite; 44 import org.eclipse.ui.PlatformUI; 45 import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; 46 47 import java.util.Collections; 48 import java.util.List; 49 50 @SuppressWarnings("restriction") // WST DOM access 51 class LintListDialog extends TitleAreaDialog implements SelectionListener { 52 private static final String PROJECT_LOGO_LARGE = "icons/android-64.png"; //$NON-NLS-1$ 53 private IFile mFile; 54 private Button mFixButton; 55 private Button mIgnoreButton; 56 private Button mShowButton; 57 private Text mDetailsText; 58 private Button mIgnoreTypeButton; 59 private LintList mList; 60 LintListDialog(Shell parentShell, IFile file)61 LintListDialog(Shell parentShell, IFile file) { 62 super(parentShell); 63 this.mFile = file; 64 } 65 66 @Override setShellStyle(int newShellStyle)67 protected void setShellStyle(int newShellStyle) { 68 // Allow resize 69 super.setShellStyle(newShellStyle | SWT.TITLE | SWT.MODELESS | SWT.RESIZE); 70 } 71 72 @Override close()73 public boolean close() { 74 mList.dispose(); 75 return super.close(); 76 } 77 78 @Override createContents(Composite parent)79 protected Control createContents(Composite parent) { 80 Control contents = super.createContents(parent); 81 setTitle("Lint Warnings in Layout"); 82 setMessage("Lint Errors found for the current layout:"); 83 setTitleImage(AdtPlugin.getImageDescriptor(PROJECT_LOGO_LARGE).createImage()); 84 return contents; 85 } 86 87 @SuppressWarnings("unused") // SWT constructors have side effects, they are not unused 88 @Override createDialogArea(Composite parent)89 protected Control createDialogArea(Composite parent) { 90 Composite area = (Composite) super.createDialogArea(parent); 91 Composite container = new Composite(area, SWT.NONE); 92 container.setLayoutData(new GridData(GridData.FILL_BOTH)); 93 94 container.setLayout(new GridLayout(2, false)); 95 IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); 96 IWorkbenchPartSite site = null; 97 if (page.getActivePart() != null) { 98 site = page.getActivePart().getSite(); 99 } 100 mList = new LintList(site, container, null /*memento*/, true /*singleFile*/); 101 mList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 5)); 102 103 mShowButton = new Button(container, SWT.NONE); 104 mShowButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); 105 mShowButton.setText("Show"); 106 mShowButton.addSelectionListener(this); 107 108 mIgnoreButton = new Button(container, SWT.NONE); 109 mIgnoreButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); 110 mIgnoreButton.setText("Ignore"); 111 mIgnoreButton.setEnabled(false); 112 mIgnoreButton.addSelectionListener(this); 113 114 mIgnoreTypeButton = new Button(container, SWT.NONE); 115 mIgnoreTypeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); 116 mIgnoreTypeButton.setText("Ignore Type"); 117 mIgnoreTypeButton.addSelectionListener(this); 118 119 mFixButton = new Button(container, SWT.NONE); 120 mFixButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); 121 mFixButton.setText("Fix"); 122 mFixButton.setEnabled(false); 123 mFixButton.addSelectionListener(this); 124 125 new Label(container, SWT.NONE); 126 127 mDetailsText = new Text(container, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP 128 | SWT.V_SCROLL | SWT.MULTI); 129 Display display = parent.getDisplay(); 130 mDetailsText.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); 131 mDetailsText.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); 132 GridData gdText = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); 133 gdText.heightHint = 80; 134 mDetailsText.setLayoutData(gdText); 135 136 new Label(container, SWT.NONE); 137 138 mList.addSelectionListener(this); 139 140 mList.setResources(Collections.<IResource>singletonList(mFile)); 141 if (mList.getSelectedMarkers().size() > 0) { 142 updateSelectionState(); 143 } 144 145 return area; 146 } 147 148 /** 149 * Create contents of the button bar. 150 */ 151 @Override createButtonsForButtonBar(Composite parent)152 protected void createButtonsForButtonBar(Composite parent) { 153 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); 154 } 155 156 /** 157 * Return the initial size of the dialog. 158 */ 159 @Override getInitialSize()160 protected Point getInitialSize() { 161 return new Point(600, 400); 162 } 163 selectMarker(IMarker marker)164 private void selectMarker(IMarker marker) { 165 if (marker == null) { 166 mDetailsText.setText(""); //$NON-NLS-1$ 167 return; 168 } 169 170 mDetailsText.setText(EclipseLintClient.describe(marker)); 171 } 172 173 // ---- Implements SelectionListener ---- 174 175 @Override widgetSelected(SelectionEvent e)176 public void widgetSelected(SelectionEvent e) { 177 Object source = e.getSource(); 178 if (source == mList.getTreeViewer().getControl()) { 179 // Enable/disable buttons 180 updateSelectionState(); 181 } else if (source == mShowButton) { 182 List<IMarker> selection = mList.getSelectedMarkers(); 183 if (selection.size() > 0) { 184 EclipseLintClient.showMarker(selection.get(0)); 185 } 186 } else if (source == mFixButton) { 187 List<IMarker> selection = mList.getSelectedMarkers(); 188 for (IMarker marker : selection) { 189 LintFix fix = LintFix.getFix(EclipseLintClient.getId(marker), marker); 190 IEditorPart editor = AdtUtils.getActiveEditor(); 191 if (editor instanceof AndroidXmlEditor) { 192 IStructuredDocument doc = ((AndroidXmlEditor) editor).getStructuredDocument(); 193 fix.apply(doc); 194 if (fix.needsFocus()) { 195 close(); 196 } 197 } else { 198 AdtPlugin.log(IStatus.ERROR, "Did not find associated editor to apply fix"); 199 } 200 } 201 } else if (source == mIgnoreTypeButton) { 202 for (IMarker marker : mList.getSelectedMarkers()) { 203 String id = EclipseLintClient.getId(marker); 204 if (id != null) { 205 LintFixGenerator.suppressDetector(id, true, mFile, true /*all*/); 206 } 207 } 208 } 209 } 210 updateSelectionState()211 private void updateSelectionState() { 212 List<IMarker> selection = mList.getSelectedMarkers(); 213 214 if (selection.size() == 1) { 215 selectMarker(selection.get(0)); 216 } else { 217 selectMarker(null); 218 } 219 220 boolean canFix = selection.size() > 0; 221 for (IMarker marker : selection) { 222 if (!LintFix.hasFix(EclipseLintClient.getId(marker))) { 223 canFix = false; 224 break; 225 } 226 227 // Some fixes cannot be run in bulk 228 if (selection.size() > 1) { 229 LintFix fix = LintFix.getFix(EclipseLintClient.getId(marker), marker); 230 if (!fix.isBulkCapable()) { 231 canFix = false; 232 break; 233 } 234 } 235 } 236 237 mFixButton.setEnabled(canFix); 238 } 239 240 @Override widgetDefaultSelected(SelectionEvent e)241 public void widgetDefaultSelected(SelectionEvent e) { 242 Object source = e.getSource(); 243 if (source == mList.getTreeViewer().getControl()) { 244 // Jump to editor 245 List<IMarker> selection = mList.getSelectedMarkers(); 246 if (selection.size() > 0) { 247 EclipseLintClient.showMarker(selection.get(0)); 248 close(); 249 } 250 } 251 } 252 } 253