aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/properties/LibraryProperties.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/properties/LibraryProperties.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/properties/LibraryProperties.java374
1 files changed, 374 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/properties/LibraryProperties.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/properties/LibraryProperties.java
new file mode 100644
index 000000000..a734b4168
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/properties/LibraryProperties.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.internal.properties;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper;
+import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper.IProjectChooserFilter;
+import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
+import com.android.ide.eclipse.adt.internal.sdk.ProjectState.LibraryState;
+import com.android.ide.eclipse.adt.internal.sdk.Sdk;
+import com.android.sdklib.internal.project.ProjectProperties;
+import com.android.sdklib.internal.project.ProjectPropertiesWorkingCopy;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+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.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * Self-contained UI to edit the library dependencies of a Project.
+ */
+final class LibraryProperties {
+
+ private Composite mTop;
+ private Table mTable;
+ private Image mMatchIcon;
+ private Image mErrorIcon;
+ private Button mAddButton;
+ private Button mRemoveButton;
+ private Button mUpButton;
+ private Button mDownButton;
+ private ProjectChooserHelper mProjectChooser;
+
+ /**
+ * Original ProjectState being edited. This is read-only.
+ * @see #mPropertiesWorkingCopy
+ */
+ private ProjectState mState;
+ /**
+ * read-write copy of the properties being edited.
+ */
+ private ProjectPropertiesWorkingCopy mPropertiesWorkingCopy;
+
+ private final List<ItemData> mItemDataList = new ArrayList<ItemData>();
+ private boolean mMustSave = false;
+
+ /**
+ * Internal struct to store library info in the table item.
+ */
+ private final static class ItemData {
+ String relativePath;
+ IProject project;
+ }
+
+ /**
+ * {@link IProjectChooserFilter} implementation that dynamically ignores libraries
+ * that are already dependencies.
+ */
+ IProjectChooserFilter mFilter = new IProjectChooserFilter() {
+ @Override
+ public boolean accept(IProject project) {
+ // first check if it's a library
+ ProjectState state = Sdk.getProjectState(project);
+ if (state != null) {
+ if (state.isLibrary() == false || project == mState.getProject()) {
+ return false;
+ }
+
+ // then check if the library is not already part of the dependencies.
+ for (ItemData data : mItemDataList) {
+ if (data.project == project) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean useCache() {
+ return false;
+ }
+ };
+
+ LibraryProperties(Composite parent) {
+
+ mMatchIcon = AdtPlugin.getImageDescriptor("/icons/match.png").createImage(); //$NON-NLS-1$
+ mErrorIcon = AdtPlugin.getImageDescriptor("/icons/error.png").createImage(); //$NON-NLS-1$
+
+ // Layout has 2 column
+ mTop = new Composite(parent, SWT.NONE);
+ mTop.setLayout(new GridLayout(2, false));
+ mTop.setLayoutData(new GridData(GridData.FILL_BOTH));
+ mTop.setFont(parent.getFont());
+ mTop.addDisposeListener(new DisposeListener() {
+ @Override
+ public void widgetDisposed(DisposeEvent e) {
+ mMatchIcon.dispose();
+ mErrorIcon.dispose();
+ }
+ });
+
+ mTable = new Table(mTop, SWT.BORDER | SWT.FULL_SELECTION | SWT.SINGLE);
+ mTable.setLayoutData(new GridData(GridData.FILL_BOTH));
+ mTable.setHeaderVisible(true);
+ mTable.setLinesVisible(false);
+ mTable.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ resetEnabled();
+ }
+ });
+
+ final TableColumn column0 = new TableColumn(mTable, SWT.NONE);
+ column0.setText("Reference");
+ final TableColumn column1 = new TableColumn(mTable, SWT.NONE);
+ column1.setText("Project");
+
+ Composite buttons = new Composite(mTop, SWT.NONE);
+ buttons.setLayout(new GridLayout());
+ buttons.setLayoutData(new GridData(GridData.FILL_VERTICAL));
+
+ mProjectChooser = new ProjectChooserHelper(parent.getShell(), mFilter);
+
+ mAddButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
+ mAddButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mAddButton.setText("Add...");
+ mAddButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ IJavaProject javaProject = mProjectChooser.chooseJavaProject(null /*projectName*/,
+ "Please select a library project");
+ if (javaProject != null) {
+ IProject iProject = javaProject.getProject();
+ IPath relativePath = iProject.getLocation().makeRelativeTo(
+ mState.getProject().getLocation());
+
+ addItem(relativePath.toString(), iProject, -1);
+ resetEnabled();
+ mMustSave = true;
+ }
+ }
+ });
+
+ mRemoveButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
+ mRemoveButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mRemoveButton.setText("Remove");
+ mRemoveButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ // selection is ensured and in single mode.
+ TableItem selection = mTable.getSelection()[0];
+ ItemData data = (ItemData) selection.getData();
+ mItemDataList.remove(data);
+ mTable.remove(mTable.getSelectionIndex());
+ resetEnabled();
+ mMustSave = true;
+ }
+ });
+
+ Label l = new Label(buttons, SWT.SEPARATOR | SWT.HORIZONTAL);
+ l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ mUpButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
+ mUpButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mUpButton.setText("Up");
+ mUpButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ int index = mTable.getSelectionIndex();
+ ItemData data = mItemDataList.remove(index);
+ mTable.remove(index);
+
+ // add at a lower index.
+ addItem(data.relativePath, data.project, index - 1);
+
+ // reset the selection
+ mTable.select(index - 1);
+ resetEnabled();
+ mMustSave = true;
+ }
+ });
+
+ mDownButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
+ mDownButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mDownButton.setText("Down");
+ mDownButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ int index = mTable.getSelectionIndex();
+ ItemData data = mItemDataList.remove(index);
+ mTable.remove(index);
+
+ // add at a higher index.
+ addItem(data.relativePath, data.project, index + 1);
+
+ // reset the selection
+ mTable.select(index + 1);
+ resetEnabled();
+ mMustSave = true;
+ }
+ });
+
+ adjustColumnsWidth(mTable, column0, column1);
+ }
+
+ /**
+ * Sets or reset the content.
+ * @param state the {@link ProjectState} to display. This is read-only.
+ * @param propertiesWorkingCopy the working copy of {@link ProjectProperties} to modify.
+ */
+ void setContent(ProjectState state, ProjectPropertiesWorkingCopy propertiesWorkingCopy) {
+ mState = state;
+ mPropertiesWorkingCopy = propertiesWorkingCopy;
+
+ // reset content
+ mTable.removeAll();
+ mItemDataList.clear();
+
+ // get the libraries and make a copy of the data we need.
+ List<LibraryState> libs = state.getLibraries();
+
+ for (LibraryState lib : libs) {
+ ProjectState libState = lib.getProjectState();
+ addItem(lib.getRelativePath(), libState != null ? libState.getProject() : null, -1);
+ }
+
+ mMustSave = false;
+
+ resetEnabled();
+ }
+
+ /**
+ * Saves the state of the UI into the {@link ProjectProperties} object that was returned by
+ * {@link #setContent}.
+ * <p/>This does not update the {@link ProjectState} object that was provided, nor does it save
+ * the new properties on disk. Saving the properties on disk, via
+ * {@link ProjectPropertiesWorkingCopy#save()}, and updating the {@link ProjectState} instance,
+ * via {@link ProjectState#reloadProperties()} must be done by the caller.
+ * @return <code>true</code> if there was actually new data saved in the project state, false
+ * otherwise.
+ */
+ boolean save() {
+ boolean mustSave = mMustSave;
+ if (mMustSave) {
+ // remove all previous library dependencies.
+ Set<String> keys = mPropertiesWorkingCopy.keySet();
+ for (String key : keys) {
+ if (key.startsWith(ProjectProperties.PROPERTY_LIB_REF)) {
+ mPropertiesWorkingCopy.removeProperty(key);
+ }
+ }
+
+ // now add the new libraries.
+ int index = 1;
+ for (ItemData data : mItemDataList) {
+ mPropertiesWorkingCopy.setProperty(ProjectProperties.PROPERTY_LIB_REF + index++,
+ data.relativePath);
+ }
+ }
+
+ mMustSave = false;
+ return mustSave;
+ }
+
+ /**
+ * Enables or disables the whole widget.
+ * @param enabled whether the widget must be enabled or not.
+ */
+ void setEnabled(boolean enabled) {
+ if (enabled == false) {
+ mTable.setEnabled(false);
+ mAddButton.setEnabled(false);
+ mRemoveButton.setEnabled(false);
+ mUpButton.setEnabled(false);
+ mDownButton.setEnabled(false);
+ } else {
+ mTable.setEnabled(true);
+ mAddButton.setEnabled(true);
+ resetEnabled();
+ }
+ }
+
+ private void resetEnabled() {
+ int index = mTable.getSelectionIndex();
+ mRemoveButton.setEnabled(index != -1);
+ mUpButton.setEnabled(index > 0);
+ mDownButton.setEnabled(index != -1 && index < mTable.getItemCount() - 1);
+ }
+
+ /**
+ * Adds a new item and stores a {@link Stuff} into {@link #mStuff}.
+ *
+ * @param relativePath the relative path of the library entry
+ * @param project the associated IProject
+ * @param index if different than -1, the index at which to insert the item.
+ */
+ private void addItem(String relativePath, IProject project, int index) {
+ ItemData data = new ItemData();
+ data.relativePath = relativePath;
+ data.project = project;
+ TableItem item;
+ if (index == -1) {
+ mItemDataList.add(data);
+ item = new TableItem(mTable, SWT.NONE);
+ } else {
+ mItemDataList.add(index, data);
+ item = new TableItem(mTable, SWT.NONE, index);
+ }
+ item.setData(data);
+ item.setText(0, data.relativePath);
+ item.setImage(data.project != null ? mMatchIcon : mErrorIcon);
+ item.setText(1, data.project != null ? data.project.getName() : "?");
+ }
+
+ /**
+ * 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(final Table table,
+ final TableColumn column0,
+ final TableColumn column1) {
+ // Add a listener to resize the column to the full width of the table
+ table.addControlListener(new ControlAdapter() {
+ @Override
+ public void controlResized(ControlEvent e) {
+ Rectangle r = table.getClientArea();
+ column0.setWidth(r.width * 50 / 100); // 50%
+ column1.setWidth(r.width * 50 / 100); // 50%
+ }
+ });
+ }
+}
+