/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.sdkuilib.internal.repository; import com.android.sdklib.internal.repository.Archive; import com.android.sdklib.internal.repository.IDescription; import com.android.sdklib.internal.repository.Package; import com.android.sdkuilib.repository.UpdaterWindow.ISdkListener; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; import java.io.File; /* * TODO list * - select => update desc, enable update + delete, enable home page if url * - home page callback * - update callback * - delete callback * - refresh callback */ public class LocalPackagesPage extends Composite implements ISdkListener { private final UpdaterData mUpdaterData; private Label mSdkLocLabel; private Text mSdkLocText; private Button mSdkLocBrowse; private TableViewer mTableViewerPackages; private Table mTablePackages; private TableColumn mColumnPackages; private Group mDescriptionContainer; private Composite mContainerButtons; private Button mUpdateButton; private Label mPlaceholder1; private Button mDeleteButton; private Label mPlaceholder2; private Button mRefreshButton; private Label mDescriptionLabel; /** * Create the composite. * @param parent The parent of the composite. * @param updaterData An instance of {@link UpdaterData}. */ public LocalPackagesPage(Composite parent, UpdaterData updaterData) { super(parent, SWT.BORDER); mUpdaterData = updaterData; createContents(this); postCreate(); //$hide$ } private void createContents(Composite parent) { parent.setLayout(new GridLayout(3, false)); createSdkLocation(parent); mTableViewerPackages = new TableViewer(parent, SWT.BORDER | SWT.FULL_SELECTION); mTablePackages = mTableViewerPackages.getTable(); mTablePackages.setHeaderVisible(true); mTablePackages.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); mTablePackages.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onTreeSelected(); //$hide$ } }); mColumnPackages = new TableColumn(mTablePackages, SWT.NONE); mColumnPackages.setWidth(377); mColumnPackages.setText("Installed Packages"); mDescriptionContainer = new Group(parent, SWT.NONE); mDescriptionContainer.setLayout(new GridLayout(1, false)); mDescriptionContainer.setText("Description"); mDescriptionContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1)); mDescriptionLabel = new Label(mDescriptionContainer, SWT.NONE); mDescriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true, 1, 1)); mDescriptionLabel.setText("Line1\nLine2\nLine3"); mContainerButtons = new Composite(parent, SWT.NONE); mContainerButtons.setLayout(new GridLayout(5, false)); mContainerButtons.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1)); mUpdateButton = new Button(mContainerButtons, SWT.NONE); mUpdateButton.setText("Update All..."); mUpdateButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onUpdateSelected(); //$hide$ (hide from SWT designer) } }); mPlaceholder1 = new Label(mContainerButtons, SWT.NONE); mPlaceholder1.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); mDeleteButton = new Button(mContainerButtons, SWT.NONE); mDeleteButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1)); mDeleteButton.setText("Delete..."); mDeleteButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onDeleteSelected(); //$hide$ (hide from SWT designer) } }); mPlaceholder2 = new Label(mContainerButtons, SWT.NONE); mPlaceholder2.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); mRefreshButton = new Button(mContainerButtons, SWT.NONE); mRefreshButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); mRefreshButton.setText("Refresh"); mRefreshButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onRefreshSelected(); //$hide$ (hide from SWT designer) } }); } private void createSdkLocation(Composite parent) { mSdkLocLabel = new Label(parent, SWT.NONE); mSdkLocLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); mSdkLocLabel.setText("SDK Location:"); // If the sdk path is not user-customizable, do not create // the browse button and use horizSpan=2 on the text field. mSdkLocText = new Text(parent, SWT.BORDER); mSdkLocText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); if (mUpdaterData.canUserChangeSdkRoot()) { mSdkLocBrowse = new Button(parent, SWT.NONE); mSdkLocBrowse.setText("Browse..."); } else { mSdkLocText.setEditable(false); ((GridData)mSdkLocText.getLayoutData()).horizontalSpan++; } if (mUpdaterData.getOsSdkRoot() != null) { mSdkLocText.setText(mUpdaterData.getOsSdkRoot()); } } @Override public void dispose() { mUpdaterData.removeListener(this); super.dispose(); } @Override protected void checkSubclass() { // Disable the check that prevents subclassing of SWT components } // -- Start of internal part ---------- // Hide everything down-below from SWT designer //$hide>>$ /** * Called by the constructor right after {@link #createContents(Composite)}. */ private void postCreate() { mUpdaterData.addListeners(this); adjustColumnsWidth(); updateButtonsState(); } /** * Adds a listener to adjust the columns width when the parent is resized. * <p/> * If we need something more fancy, we might want to use this: * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet77.java?view=co */ private void adjustColumnsWidth() { // Add a listener to resize the column to the full width of the table ControlAdapter resizer = new ControlAdapter() { @Override public void controlResized(ControlEvent e) { Rectangle r = mTablePackages.getClientArea(); mColumnPackages.setWidth(r.width); } }; mTablePackages.addControlListener(resizer); resizer.controlResized(null); } /** * Enable or disable buttons depending on list content and selection */ private void updateButtonsState() { ISelection sel = mTableViewerPackages.getSelection(); boolean hasSelection = sel != null && !sel.isEmpty(); mUpdateButton.setEnabled(mTablePackages.getItemCount() > 0); mDeleteButton.setEnabled(hasSelection); mRefreshButton.setEnabled(true); } /** * Called when an item in the package table viewer is selected. * If the items is an {@link IDescription} (as it should), this will display its long * description in the description area. Otherwise when the item is not of the expected * type or there is no selection, it empties the description area. */ private void onTreeSelected() { updateButtonsState(); ISelection sel = mTableViewerPackages.getSelection(); if (sel instanceof IStructuredSelection) { Object elem = ((IStructuredSelection) sel).getFirstElement(); if (elem instanceof IDescription) { mDescriptionLabel.setText(((IDescription) elem).getLongDescription()); mDescriptionContainer.layout(true); return; } } mDescriptionLabel.setText(""); //$NON-NLS1-$ } private void onUpdateSelected() { mUpdaterData.updateOrInstallAll(null /*selectedArchives*/); } private void onDeleteSelected() { ISelection sel = mTableViewerPackages.getSelection(); if (sel instanceof IStructuredSelection) { Object elem = ((IStructuredSelection) sel).getFirstElement(); if (elem instanceof Package) { String title = "Delete SDK Package"; String error = null; Package p = (Package) elem; Archive[] archives = p.getArchives(); if (archives.length == 1 && archives[0] != null && archives[0].isLocal()) { Archive archive = archives[0]; String osPath = archive.getLocalOsPath(); File dir = new File(osPath); if (dir.isDirectory()) { String msg = String.format("Are you sure you want to delete '%1$s' at '%2$s'? This cannot be undone.", p.getShortDescription(), osPath); if (MessageDialog.openQuestion(getShell(), title, msg)) { archive.deleteLocal(); // refresh list onRefreshSelected(); } } else { error = "Directory not found for this package"; } } else { error = "No local archive found for this package"; } if (error != null) { MessageDialog.openError(getShell(), title, error); } return; } } } private void onRefreshSelected() { mUpdaterData.reloadSdk(); updateButtonsState(); } public void onSdkChange() { LocalSdkAdapter localSdkAdapter = mUpdaterData.getLocalSdkAdapter(); mTableViewerPackages.setLabelProvider( localSdkAdapter.getLabelProvider()); mTableViewerPackages.setContentProvider(localSdkAdapter.getContentProvider()); mTableViewerPackages.setInput(localSdkAdapter); onTreeSelected(); } // End of hiding from SWT Designer //$hide<<$ }