Java tutorial
// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package org.chromium.debug.ui.actions; import java.util.AbstractList; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.chromium.debug.core.model.ConnectedTargetData; import org.chromium.debug.core.util.ScriptTargetMapping; import org.chromium.debug.ui.TableUtils; import org.chromium.debug.ui.TableUtils.ColumnBasedLabelProvider; import org.chromium.debug.ui.TableUtils.ColumnData; import org.chromium.debug.ui.TableUtils.ColumnLabelProvider; import org.chromium.debug.ui.TableUtils.ValueAdapter; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; /** * A UI control that presents the list of connections with remote V8 VMs. User may choose * several VMs. */ public class ChooseVmControl { public static Logic create(Composite parent) { final Table table = new Table(parent, SWT.CHECK | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION); table.setFont(parent.getFont()); final CheckboxTableViewer tableViewer = new CheckboxTableViewer(table); table.setHeaderVisible(true); tableViewer.setContentProvider(new ContentProviderImpl()); ValueAdapter<ScriptTargetMapping, ConnectedTargetData> pairToTargetAdapter = new ValueAdapter<ScriptTargetMapping, ConnectedTargetData>() { public ConnectedTargetData convert(ScriptTargetMapping from) { return from.getConnectedTargetData(); } }; List<ColumnData<ScriptTargetMapping, ?>> columnDataList = createLaunchTargetColumns(pairToTargetAdapter); for (ColumnData<?, ?> data : columnDataList) { data.getLabelProvider().createColumn(table); } ValueAdapter<Object, ScriptTargetMapping> rowElementAdapter = TableUtils .createCastAdapter(ScriptTargetMapping.class); ColumnBasedLabelProvider<ScriptTargetMapping> labelProvider = new ColumnBasedLabelProvider<ScriptTargetMapping>( rowElementAdapter, columnDataList); tableViewer.setLabelProvider(labelProvider); final List<Logic.Listener> listeners = new ArrayList<Logic.Listener>(1); tableViewer.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { for (Logic.Listener listener : listeners) { listener.checkStateChanged(); } } }); return new Logic() { public Control getControl() { return table; } public void setData(List<? extends ScriptTargetMapping> targets) { TableData input = new TableData(targets); tableViewer.setInput(input); } public List<ScriptTargetMapping> getSelected() { final Object[] array = tableViewer.getCheckedElements(); return new AbstractList<ScriptTargetMapping>() { @Override public ScriptTargetMapping get(int index) { return (ScriptTargetMapping) array[index]; } @Override public int size() { return array.length; } }; } public void selectAll() { tableViewer.setAllChecked(true); } public void addListener(Listener listener) { listeners.add(listener); } public void removeListener(Listener listener) { listeners.remove(listener); } }; } /** * A public logic-oriented interface to this control. */ public interface Logic { Control getControl(); void setData(List<? extends ScriptTargetMapping> targets); List<ScriptTargetMapping> getSelected(); void selectAll(); void addListener(Listener listener); void removeListener(Listener listener); interface Listener { void checkStateChanged(); } } /** * A non-generic class that wraps generic List. Eclipse works in terms of Objects, but you cannot * safely cast to generic types on runtime (e.g. to List<String>) so we wrap the value before * passing it into Eclipse. */ private static class TableData { final List<? extends ScriptTargetMapping> targets; TableData(List<? extends ScriptTargetMapping> targets) { this.targets = targets; } } private static class ContentProviderImpl implements IStructuredContentProvider { public Object[] getElements(Object inputElement) { TableData input = (TableData) inputElement; return input.targets.toArray(); } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } } private static class LaunchNameLabelProvider extends ColumnLabelProvider<ConnectedTargetData> { private Map<ConnectedTargetData, Image> createdImages = new HashMap<ConnectedTargetData, Image>(); @Override public Image getColumnImage(ConnectedTargetData connectedTargetData) { Image result = createdImages.get(connectedTargetData); if (result == null) { ImageDescriptor imageDescriptor = DebugUITools.getDefaultImageDescriptor( connectedTargetData.getDebugTarget().getLaunch().getLaunchConfiguration()); result = imageDescriptor.createImage(); createdImages.put(connectedTargetData, result); } return result; } @Override public String getColumnText(ConnectedTargetData connectedTargetData) { return connectedTargetData.getDebugTarget().getLaunch().getLaunchConfiguration().getName(); } @Override public TableColumn createColumn(Table table) { TableColumn launchCol = new TableColumn(table, SWT.NONE); launchCol.setText(Messages.ChooseVmControl_LAUNCH); launchCol.setWidth(200); return launchCol; } @Override public void dispose() { for (Image image : createdImages.values()) { image.dispose(); } } } private static class TargetNameLabelProvider extends ColumnLabelProvider<ConnectedTargetData> { @Override public Image getColumnImage(ConnectedTargetData connectedTargetData) { return null; } @Override public String getColumnText(ConnectedTargetData connectedTargetData) { return connectedTargetData.getName(); } @Override public TableColumn createColumn(Table table) { TableColumn targetCol = new TableColumn(table, SWT.NONE); targetCol.setText(Messages.ChooseVmControl_TARGET); targetCol.setWidth(200); return targetCol; } } /** * Returns the list of column providers for launch/target columns that could be used in other * controls; they only have to provide there row->column value adapter. */ public static <R> List<ColumnData<R, ?>> createLaunchTargetColumns( ValueAdapter<R, ConnectedTargetData> rowValueAdapter) { List<ColumnData<R, ?>> result = new ArrayList<ColumnData<R, ?>>(2); result.add(ColumnData.create(rowValueAdapter, new LaunchNameLabelProvider())); result.add(ColumnData.create(rowValueAdapter, new TargetNameLabelProvider())); return result; } }