/******************************************************************************* * This file is protected by Copyright. * Please refer to the COPYRIGHT file distributed with this source distribution. * * This file is part of REDHAWK IDE. * * All rights reserved. This program and the accompanying materials are made available under * the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package gov.redhawk.ide.sad.internal.ui.editor; import java.util.ArrayList; import java.util.Collection; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.swt.widgets.Shell; public class XViewerListCellEditor extends XViewerCellEditor { private Shell popup = null; private List list = null; private java.util.List<Object> items; private SelectionListener selectionListener; private Object value = null; private ILabelProvider labelProvider = null; public XViewerListCellEditor(Composite parent, Collection< ? > items) { super(parent); this.items = new ArrayList<Object>(items); setValueValid(true); } @Override public void dispose() { popup.dispose(); super.dispose(); } @Override public boolean setFocus() { if (popup == null) { createPopup(getParent()); } // Determine the bounds of the list--since it is going to pop over the cell, we can use whatever size we want. // Use the width of the cell, but for height try to determine how large it should be to show a reasonable // number of items (logic borrowed from SWT's CCombo). int itemHeight = list.getItemHeight(); int maxHeight = getMonitor().getClientArea().height / 3; int visibleItemCount = Math.max(5, maxHeight / itemHeight); int itemCount = Math.min(list.getItemCount(), visibleItemCount); Point listSize = list.computeSize(SWT.DEFAULT, itemCount * itemHeight, false); int width = getSize().x; int height = listSize.y; // Also borrowed from CCombo: if the horizontal scroll bar isn't shown, offset the size so as not to waste // vertical real estate ScrollBar hBar = list.getHorizontalBar(); if (!hBar.isVisible()) { height -= hBar.getSize().y; } // Pop up the Shell directly on top of the cell, sized to exactly match our computed list size Display display = getDisplay(); Point position = display.map(getParent(), null, getLocation()); popup.setBounds(position.x, position.y, width, height); list.setBounds(0, 0, width, height); popup.setVisible(true); return list.setFocus(); } public void setLabelProvider(ILabelProvider labelProvider) { this.labelProvider = labelProvider; } @Override protected void doSetValue(Object value) { this.value = value; if (list != null) { list.removeSelectionListener(selectionListener); if (value != null) { list.setSelection(new String[] { (String) value }); } else { list.setSelection(0); } list.addSelectionListener(selectionListener); } } @Override protected Object doGetValue() { int index = list.getSelectionIndex(); if (index >= 0) { return items.get(index); } else { return null; } } protected void createPopup(Control parent) { popup = new Shell(getShell(), SWT.NO_TRIM | SWT.ON_TOP); list = new List(popup, SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL); list.setBackground(parent.getBackground()); list.setForeground(parent.getForeground()); list.setFont(parent.getFont()); list.setItems(getListItems()); int index = Math.max(0, items.indexOf(value)); list.setSelection(index); selectionListener = new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { } @Override public void widgetDefaultSelected(SelectionEvent e) { deactivate(); } }; list.addSelectionListener(selectionListener); list.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { deactivate(); } }); forwardEvents(SWT.FocusOut, list, true); forwardEvents(SWT.Traverse, list, true); } protected String[] getListItems() { ArrayList<String> stringItems = new ArrayList<String>(items.size()); for (Object item : items) { String label = getText(item); stringItems.add(label); } return stringItems.toArray(new String[stringItems.size()]); } protected String getText(Object object) { if (labelProvider != null) { return labelProvider.getText(object); } else if (object != null) { return object.toString(); } else { return ""; } } }