diff options
Diffstat (limited to 'sdkmanager/libs/sdkuilib')
4 files changed, 453 insertions, 7 deletions
diff --git a/sdkmanager/libs/sdkuilib/.classpath b/sdkmanager/libs/sdkuilib/.classpath new file mode 100644 index 0000000..eb5af7e --- /dev/null +++ b/sdkmanager/libs/sdkuilib/.classpath @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANDROID_SWT"/> + <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/sdkmanager/libs/sdkuilib/.project b/sdkmanager/libs/sdkuilib/.project new file mode 100644 index 0000000..da430c8 --- /dev/null +++ b/sdkmanager/libs/sdkuilib/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>SdkUiLib</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java index ddc492e..fc951f2 100644 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java @@ -40,6 +40,11 @@ import java.util.ArrayList; /** * The SDK target selector is a table that is added to the given parent composite. + * <p/> + * To use, create it using {@link #SdkTargetSelector(Composite, IAndroidTarget[], boolean)} then + * call {@link #setSelection(IAndroidTarget)}, {@link #setSelectionListener(SelectionListener)} + * and finally use {@link #getFirstSelected()} or {@link #getAllSelected()} to retrieve the + * selection. */ public class SdkTargetSelector { @@ -49,6 +54,14 @@ public class SdkTargetSelector { private Table mTable; private Label mDescription; + /** + * Creates a new SDK Target Selector. + * + * @param parent The parent composite where the selector will be added. + * @param targets The list of targets. This is <em>not</em> copied, the caller must not modify. + * @param allowMultipleSelection True if more than one SDK target can be selected at the same + * time. + */ public SdkTargetSelector(Composite parent, IAndroidTarget[] targets, boolean allowMultipleSelection) { mTargets = targets; @@ -81,14 +94,25 @@ public class SdkTargetSelector { column1.setText("Vendor"); final TableColumn column2 = new TableColumn(mTable, SWT.NONE); column2.setText("API Level"); + final TableColumn column3 = new TableColumn(mTable, SWT.NONE); + column3.setText("SDK"); - adjustColumnsWidth(mTable, column0, column1, column2); + adjustColumnsWidth(mTable, column0, column1, column2, column3); setupSelectionListener(mTable); fillTable(mTable); setupTooltip(mTable); } /** + * Returns the list of known targets. + * <p/> + * This is not a copy. Callers must <em>not</em> modify this array. + */ + public IAndroidTarget[] getTargets() { + return mTargets; + } + + /** * Sets a selection listener. Set it to null to remove it. * The listener will be called <em>after</em> this table processed its selection * events so that the caller can see the updated state. @@ -107,20 +131,33 @@ public class SdkTargetSelector { /** * Sets the current target selection. + * <p/> + * If the selection is actually changed, this will invoke the selection listener + * (if any) with a null event. + * * @param target the target to be selection * @return true if the target could be selected, false otherwise. */ public boolean setSelection(IAndroidTarget target) { boolean found = false; + boolean modified = false; for (TableItem i : mTable.getItems()) { if ((IAndroidTarget) i.getData() == target) { found = true; - i.setChecked(true); - } else { + if (!i.getChecked()) { + modified = true; + i.setChecked(true); + } + } else if (i.getChecked()) { + modified = true; i.setChecked(false); } } + if (modified && mSelectionListener != null) { + mSelectionListener.widgetSelected(null); + } + return found; } @@ -166,15 +203,17 @@ public class SdkTargetSelector { private void adjustColumnsWidth(final Table table, final TableColumn column0, final TableColumn column1, - final TableColumn column2) { + final TableColumn column2, + final TableColumn column3) { // 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 * 3 / 10); // 30% - column1.setWidth(r.width * 5 / 10); // 50% - column2.setWidth(r.width * 2 / 10); // 20% + column0.setWidth(r.width * 30 / 100); // 30% + column1.setWidth(r.width * 45 / 100); // 45% + column2.setWidth(r.width * 15 / 100); // 15% + column3.setWidth(r.width * 10 / 100); // 10% } }); } @@ -238,6 +277,7 @@ public class SdkTargetSelector { * <li>column 0: sdk name * <li>column 1: sdk vendor * <li>column 2: sdk api name + * <li>column 3: sdk version * </ul> */ private void fillTable(final Table table) { @@ -249,6 +289,7 @@ public class SdkTargetSelector { item.setText(0, target.getName()); item.setText(1, target.getVendor()); item.setText(2, target.getApiVersionName()); + item.setText(3, Integer.toString(target.getApiVersionNumber())); } } else { table.setEnabled(false); @@ -257,6 +298,7 @@ public class SdkTargetSelector { item.setText(0, "--"); item.setText(1, "No target available"); item.setText(2, "--"); + item.setText(3, "--"); } } diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/VmSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/VmSelector.java new file mode 100644 index 0000000..dcc0b9e --- /dev/null +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/VmSelector.java @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2008 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.sdkuilib; + +import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.vm.VmManager.VmInfo; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; + +import java.util.ArrayList; + + +/** + * The VM selector is a table that is added to the given parent composite. + * <p/> + * To use, create it using {@link #VmSelector(Composite, VmInfo[], boolean)} then + * call {@link #setSelection(VmInfo)}, {@link #setSelectionListener(SelectionListener)} + * and finally use {@link #getFirstSelected()} or {@link #getAllSelected()} to retrieve the + * selection. + */ +public final class VmSelector { + + private VmInfo[] mVms; + private final boolean mAllowMultipleSelection; + private SelectionListener mSelectionListener; + private Table mTable; + private Label mDescription; + + /** + * Creates a new SDK Target Selector. + * + * @param parent The parent composite where the selector will be added. + * @param vms The list of vms. This is <em>not</em> copied, the caller must not modify. + * @param allowMultipleSelection True if more than one SDK target can be selected at the same + * time. + */ + public VmSelector(Composite parent, VmInfo[] vms, boolean allowMultipleSelection) { + mVms = vms; + + // Layout has 1 column + Composite group = new Composite(parent, SWT.NONE); + group.setLayout(new GridLayout()); + group.setLayoutData(new GridData(GridData.FILL_BOTH)); + group.setFont(parent.getFont()); + + mAllowMultipleSelection = allowMultipleSelection; + mTable = new Table(group, SWT.CHECK | SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER); + mTable.setHeaderVisible(true); + mTable.setLinesVisible(false); + + GridData data = new GridData(); + data.grabExcessVerticalSpace = true; + data.grabExcessHorizontalSpace = true; + data.horizontalAlignment = GridData.FILL; + data.verticalAlignment = GridData.FILL; + mTable.setLayoutData(data); + + mDescription = new Label(group, SWT.WRAP); + mDescription.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // create the table columns + final TableColumn column0 = new TableColumn(mTable, SWT.NONE); + column0.setText("VM Name"); + final TableColumn column1 = new TableColumn(mTable, SWT.NONE); + column1.setText("Target Name"); + final TableColumn column2 = new TableColumn(mTable, SWT.NONE); + column2.setText("API Level"); + final TableColumn column3 = new TableColumn(mTable, SWT.NONE); + column3.setText("SDK"); + + adjustColumnsWidth(mTable, column0, column1, column2, column3); + setupSelectionListener(mTable); + fillTable(mTable, null /* target filter */); + setupTooltip(mTable); + } + + /** + * Sets a new set of VM, with an optional filter. + * <p/>This must be called from the UI thread. + * + * @param vms The list of vms. This is <em>not</em> copied, the caller must not modify. + * @param filter An IAndroidTarget. If non-null, only VM whose target are compatible with the + * filter target will displayed an available for selection. + */ + public void setVms(VmInfo[] vms, IAndroidTarget filter) { + mVms = vms; + fillTable(mTable, filter); + } + + /** + * Returns the list of known Vms. + * <p/> + * This is not a copy. Callers must <em>not</em> modify this array. + */ + public VmInfo[] getVms() { + return mVms; + } + + /** + * Sets a selection listener. Set it to null to remove it. + * The listener will be called <em>after</em> this table processed its selection + * events so that the caller can see the updated state. + * <p/> + * The event's item contains a {@link TableItem}. + * The {@link TableItem#getData()} contains an {@link IAndroidTarget}. + * <p/> + * It is recommended that the caller uses the {@link #getFirstSelected()} and + * {@link #getAllSelected()} methods instead. + * + * @param selectionListener The new listener or null to remove it. + */ + public void setSelectionListener(SelectionListener selectionListener) { + mSelectionListener = selectionListener; + } + + /** + * Sets the current target selection. + * <p/> + * If the selection is actually changed, this will invoke the selection listener + * (if any) with a null event. + * + * @param target the target to be selection + * @return true if the target could be selected, false otherwise. + */ + public boolean setSelection(VmInfo target) { + boolean found = false; + boolean modified = false; + for (TableItem i : mTable.getItems()) { + if ((VmInfo) i.getData() == target) { + found = true; + if (!i.getChecked()) { + modified = true; + i.setChecked(true); + } + } else if (i.getChecked()) { + modified = true; + i.setChecked(false); + } + } + + if (modified && mSelectionListener != null) { + mSelectionListener.widgetSelected(null); + } + + return found; + } + + /** + * Returns all selected items. + * This is useful when the table is in multiple-selection mode. + * + * @see #getFirstSelected() + * @return An array of selected items. The list can be empty but not null. + */ + public VmInfo[] getAllSelected() { + ArrayList<IAndroidTarget> list = new ArrayList<IAndroidTarget>(); + for (TableItem i : mTable.getItems()) { + if (i.getChecked()) { + list.add((IAndroidTarget) i.getData()); + } + } + return list.toArray(new VmInfo[list.size()]); + } + + /** + * Returns the first selected item. + * This is useful when the table is in single-selection mode. + * + * @see #getAllSelected() + * @return The first selected item or null. + */ + public VmInfo getFirstSelected() { + for (TableItem i : mTable.getItems()) { + if (i.getChecked()) { + return (VmInfo) i.getData(); + } + } + return null; + } + + /** + * 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, + final TableColumn column2, + final TableColumn column3) { + // 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 * 30 / 100); // 30% + column1.setWidth(r.width * 45 / 100); // 45% + column2.setWidth(r.width * 15 / 100); // 15% + column3.setWidth(r.width * 10 / 100); // 10% + } + }); + } + + + /** + * Creates a selection listener that will check or uncheck the whole line when + * double-clicked (aka "the default selection"). + */ + private void setupSelectionListener(final Table table) { + // Add a selection listener that will check/uncheck items when they are double-clicked + table.addSelectionListener(new SelectionListener() { + /** Default selection means double-click on "most" platforms */ + public void widgetDefaultSelected(SelectionEvent e) { + if (e.item instanceof TableItem) { + TableItem i = (TableItem) e.item; + i.setChecked(!i.getChecked()); + enforceSingleSelection(i); + updateDescription(i); + } + + if (mSelectionListener != null) { + mSelectionListener.widgetDefaultSelected(e); + } + } + + public void widgetSelected(SelectionEvent e) { + if (e.item instanceof TableItem) { + TableItem i = (TableItem) e.item; + enforceSingleSelection(i); + updateDescription(i); + } + + if (mSelectionListener != null) { + mSelectionListener.widgetSelected(e); + } + } + + /** + * If we're not in multiple selection mode, uncheck all other + * items when this one is selected. + */ + private void enforceSingleSelection(TableItem item) { + if (!mAllowMultipleSelection && item.getChecked()) { + Table parentTable = item.getParent(); + for (TableItem i2 : parentTable.getItems()) { + if (i2 != item && i2.getChecked()) { + i2.setChecked(false); + } + } + } + } + }); + } + + /** + * Fills the table with all VM. + * The table columns are: + * <ul> + * <li>column 0: sdk name + * <li>column 1: sdk vendor + * <li>column 2: sdk api name + * <li>column 3: sdk version + * </ul> + */ + private void fillTable(final Table table, IAndroidTarget filter) { + table.removeAll(); + if (mVms != null && mVms.length > 0) { + table.setEnabled(true); + for (VmInfo vm : mVms) { + if (filter == null || filter.isCompatibleBaseFor(vm.getTarget())) { + TableItem item = new TableItem(table, SWT.NONE); + item.setData(vm); + item.setText(0, vm.getName()); + IAndroidTarget target = vm.getTarget(); + item.setText(1, target.getFullName()); + item.setText(2, target.getApiVersionName()); + item.setText(3, Integer.toString(target.getApiVersionNumber())); + } + } + } + + if (table.getItemCount() == 0) { + table.setEnabled(false); + TableItem item = new TableItem(table, SWT.NONE); + item.setData(null); + item.setText(0, "--"); + item.setText(1, "No VM available"); + item.setText(2, "--"); + item.setText(3, "--"); + } + } + + /** + * Sets up a tooltip that displays the current item description. + * <p/> + * Displaying a tooltip over the table looks kind of odd here. Instead we actually + * display the description in a label under the table. + */ + private void setupTooltip(final Table table) { + /* + * Reference: + * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet125.java?view=markup + */ + + final Listener listener = new Listener() { + public void handleEvent(Event event) { + + switch(event.type) { + case SWT.KeyDown: + case SWT.MouseExit: + case SWT.MouseDown: + return; + + case SWT.MouseHover: + updateDescription(table.getItem(new Point(event.x, event.y))); + break; + + case SWT.Selection: + if (event.item instanceof TableItem) { + updateDescription((TableItem) event.item); + } + break; + + default: + return; + } + + } + }; + + table.addListener(SWT.Dispose, listener); + table.addListener(SWT.KeyDown, listener); + table.addListener(SWT.MouseMove, listener); + table.addListener(SWT.MouseHover, listener); + } + + /** + * Updates the description label with the path of the item's VM, if any. + */ + private void updateDescription(TableItem item) { + if (item != null) { + Object data = item.getData(); + if (data instanceof VmInfo) { + String newTooltip = ((VmInfo) data).getPath(); + mDescription.setText(newTooltip == null ? "" : newTooltip); //$NON-NLS-1$ + } + } + } +} |