1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 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.sdkuilib.internal.repository.sdkman1; 18 19 import com.android.sdklib.internal.repository.Archive; 20 import com.android.sdklib.internal.repository.IDescription; 21 import com.android.sdklib.internal.repository.Package; 22 import com.android.sdkuilib.internal.repository.UpdaterData; 23 import com.android.sdkuilib.internal.repository.UpdaterPage; 24 import com.android.sdkuilib.repository.ISdkChangeListener; 25 26 import org.eclipse.jface.dialogs.MessageDialog; 27 import org.eclipse.jface.viewers.ISelection; 28 import org.eclipse.jface.viewers.IStructuredSelection; 29 import org.eclipse.jface.viewers.TableViewer; 30 import org.eclipse.swt.SWT; 31 import org.eclipse.swt.events.ControlAdapter; 32 import org.eclipse.swt.events.ControlEvent; 33 import org.eclipse.swt.events.SelectionAdapter; 34 import org.eclipse.swt.events.SelectionEvent; 35 import org.eclipse.swt.graphics.Rectangle; 36 import org.eclipse.swt.layout.GridData; 37 import org.eclipse.swt.layout.GridLayout; 38 import org.eclipse.swt.widgets.Button; 39 import org.eclipse.swt.widgets.Composite; 40 import org.eclipse.swt.widgets.Group; 41 import org.eclipse.swt.widgets.Label; 42 import org.eclipse.swt.widgets.Table; 43 import org.eclipse.swt.widgets.TableColumn; 44 45 import java.io.File; 46 47 /** 48 * Page that displays all locally installed packages from the current SDK. 49 */ 50 public class LocalPackagesPage extends UpdaterPage implements ISdkChangeListener { 51 52 private final UpdaterData mUpdaterData; 53 54 private Label mSdkLocLabel; 55 private TableViewer mTableViewerPackages; 56 private Table mTablePackages; 57 private TableColumn mColumnPackages; 58 private Group mDescriptionContainer; 59 private Composite mContainerButtons; 60 private Button mUpdateButton; 61 private Label mPlaceholder1; 62 private Button mDeleteButton; 63 private Label mPlaceholder2; 64 private Button mRefreshButton; 65 private Label mDescriptionLabel; 66 67 68 /** 69 * Create the composite. 70 * @param parent The parent of the composite. 71 * @param updaterData An instance of {@link UpdaterData}. 72 */ 73 public LocalPackagesPage(Composite parent, int swtStyle, UpdaterData updaterData) { 74 super(parent, swtStyle); 75 76 mUpdaterData = updaterData; 77 78 createContents(this); 79 postCreate(); //$hide$ 80 } 81 82 private void createContents(Composite parent) { 83 parent.setLayout(new GridLayout(3, false)); 84 85 mSdkLocLabel = new Label(parent, SWT.NONE); 86 mSdkLocLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false, 3, 1)); 87 mSdkLocLabel.setText("SDK Location: " + 88 (mUpdaterData.getOsSdkRoot() != null ? mUpdaterData.getOsSdkRoot() 89 : "<unknown>")); 90 91 mTableViewerPackages = new TableViewer(parent, SWT.BORDER | SWT.FULL_SELECTION); 92 mTablePackages = mTableViewerPackages.getTable(); 93 mTablePackages.setHeaderVisible(true); 94 mTablePackages.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); 95 mTablePackages.addSelectionListener(new SelectionAdapter() { 96 @Override 97 public void widgetSelected(SelectionEvent e) { 98 onTreeSelected(); //$hide$ 99 } 100 }); 101 102 mColumnPackages = new TableColumn(mTablePackages, SWT.NONE); 103 mColumnPackages.setWidth(377); 104 mColumnPackages.setText("Installed packages"); 105 106 mDescriptionContainer = new Group(parent, SWT.NONE); 107 mDescriptionContainer.setLayout(new GridLayout(1, false)); 108 mDescriptionContainer.setText("Description"); 109 mDescriptionContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1)); 110 111 mDescriptionLabel = new Label(mDescriptionContainer, SWT.NONE); 112 mDescriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true, 1, 1)); 113 mDescriptionLabel.setText("Line1\nLine2\nLine3"); 114 115 mContainerButtons = new Composite(parent, SWT.NONE); 116 mContainerButtons.setLayout(new GridLayout(5, false)); 117 mContainerButtons.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1)); 118 119 mUpdateButton = new Button(mContainerButtons, SWT.NONE); 120 mUpdateButton.setText("Update All..."); 121 mUpdateButton.addSelectionListener(new SelectionAdapter() { 122 @Override 123 public void widgetSelected(SelectionEvent e) { 124 onUpdateSelected(); //$hide$ (hide from SWT designer) 125 } 126 }); 127 128 mPlaceholder1 = new Label(mContainerButtons, SWT.NONE); 129 mPlaceholder1.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); 130 131 mDeleteButton = new Button(mContainerButtons, SWT.NONE); 132 mDeleteButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1)); 133 mDeleteButton.setText("Delete..."); 134 mDeleteButton.addSelectionListener(new SelectionAdapter() { 135 @Override 136 public void widgetSelected(SelectionEvent e) { 137 onDeleteSelected(); //$hide$ (hide from SWT designer) 138 } 139 }); 140 141 mPlaceholder2 = new Label(mContainerButtons, SWT.NONE); 142 mPlaceholder2.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); 143 144 mRefreshButton = new Button(mContainerButtons, SWT.NONE); 145 mRefreshButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); 146 mRefreshButton.setText("Refresh"); 147 mRefreshButton.addSelectionListener(new SelectionAdapter() { 148 @Override 149 public void widgetSelected(SelectionEvent e) { 150 onRefreshSelected(); //$hide$ (hide from SWT designer) 151 } 152 }); 153 } 154 155 @Override 156 public void dispose() { 157 mUpdaterData.removeListener(this); 158 super.dispose(); 159 } 160 161 @Override 162 protected void checkSubclass() { 163 // Disable the check that prevents subclassing of SWT components 164 } 165 166 // -- Start of internal part ---------- 167 // Hide everything down-below from SWT designer 168 //$hide>>$ 169 170 /** 171 * Called by the constructor right after {@link #createContents(Composite)}. 172 */ 173 private void postCreate() { 174 mUpdaterData.addListeners(this); 175 adjustColumnsWidth(); 176 updateButtonsState(); 177 } 178 179 /** 180 * Adds a listener to adjust the columns width when the parent is resized. 181 * <p/> 182 * If we need something more fancy, we might want to use this: 183 * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet77.java?view=co 184 */ 185 private void adjustColumnsWidth() { 186 // Add a listener to resize the column to the full width of the table 187 ControlAdapter resizer = new ControlAdapter() { 188 @Override 189 public void controlResized(ControlEvent e) { 190 Rectangle r = mTablePackages.getClientArea(); 191 mColumnPackages.setWidth(r.width); 192 } 193 }; 194 mTablePackages.addControlListener(resizer); 195 resizer.controlResized(null); 196 } 197 198 /** 199 * Enable or disable buttons depending on list content and selection 200 */ 201 private void updateButtonsState() { 202 ISelection sel = mTableViewerPackages.getSelection(); 203 boolean hasSelection = sel != null && !sel.isEmpty(); 204 205 mUpdateButton.setEnabled(mTablePackages.getItemCount() > 0); 206 mDeleteButton.setEnabled(hasSelection); 207 mRefreshButton.setEnabled(true); 208 } 209 210 /** 211 * Called when an item in the package table viewer is selected. 212 * If the items is an {@link IDescription} (as it should), this will display its long 213 * description in the description area. Otherwise when the item is not of the expected 214 * type or there is no selection, it empties the description area. 215 */ 216 private void onTreeSelected() { 217 updateButtonsState(); 218 219 ISelection sel = mTableViewerPackages.getSelection(); 220 if (sel instanceof IStructuredSelection) { 221 Object elem = ((IStructuredSelection) sel).getFirstElement(); 222 if (elem instanceof IDescription) { 223 mDescriptionLabel.setText(((IDescription) elem).getLongDescription()); 224 mDescriptionContainer.layout(true); 225 return; 226 } 227 } 228 mDescriptionLabel.setText(""); //$NON-NLS1-$ 229 } 230 231 /** User selected the 'update all' button. */ 232 private void onUpdateSelected() { 233 mUpdaterData.updateOrInstallAll_WithGUI( 234 null /*selectedArchives*/, 235 false /* includeObsoletes */, 236 0 /* flags */); 237 } 238 239 private void onDeleteSelected() { 240 ISelection sel = mTableViewerPackages.getSelection(); 241 if (sel instanceof IStructuredSelection) { 242 Object elem = ((IStructuredSelection) sel).getFirstElement(); 243 if (elem instanceof Package) { 244 245 String title = "Delete SDK Package"; 246 String error = null; 247 248 Package p = (Package) elem; 249 Archive[] archives = p.getArchives(); 250 if (archives.length == 1 && archives[0] != null && archives[0].isLocal()) { 251 Archive archive = archives[0]; 252 String osPath = archive.getLocalOsPath(); 253 254 File dir = new File(osPath); 255 if (dir.isDirectory()) { 256 String msg = String.format("Are you sure you want to delete '%1$s' at '%2$s'? This cannot be undone.", 257 p.getShortDescription(), osPath); 258 259 if (MessageDialog.openQuestion(getShell(), title, msg)) { 260 archive.deleteLocal(); 261 262 // refresh list 263 onRefreshSelected(); 264 } 265 } else { 266 error = "Directory not found for this package"; 267 } 268 } else { 269 error = "No local archive found for this package"; 270 } 271 272 if (error != null) { 273 MessageDialog.openError(getShell(), title, error); 274 } 275 276 return; 277 } 278 } 279 } 280 281 private void onRefreshSelected() { 282 mUpdaterData.reloadSdk(); 283 updateButtonsState(); 284 } 285 286 // --- Implementation of ISdkChangeListener --- 287 288 public void onSdkLoaded() { 289 onSdkReload(); 290 } 291 292 public void onSdkReload() { 293 LocalSdkAdapter localSdkAdapter = mUpdaterData.getLocalSdkAdapter(); 294 mTableViewerPackages.setLabelProvider( localSdkAdapter.getLabelProvider()); 295 mTableViewerPackages.setContentProvider(localSdkAdapter.getContentProvider()); 296 mTableViewerPackages.setInput(localSdkAdapter); 297 onTreeSelected(); 298 } 299 300 public void preInstallHook() { 301 // nothing to be done for now. 302 } 303 304 public void postInstallHook() { 305 // nothing to be done for now. 306 } 307 308 // End of hiding from SWT Designer 309 //$hide<<$ 310 } 311