/******************************************************************************* * Copyright 2011 Google Inc. All Rights Reserved. * * 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 * * 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.google.gdt.eclipse.core.ui.controls; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; 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.events.SelectionListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import java.util.ArrayList; import java.util.List; /** * The SelectableControlList represents a UI list component with custom controls * as elements. The type of control is parameterized. * * @param <C> The type of control. */ public class SelectableControlList<C extends SelectableControl> extends ScrolledComposite { private Composite scrolledCanvas; @SuppressWarnings("unchecked") private List<C> items = (List<C>) new ArrayList<SelectableControl>(); private List<SelectionListener> selectionListeners = new ArrayList<SelectionListener>(); private List<SelectionChangeListener<SelectableControl>> selectionChangeListeners = new ArrayList<SelectionChangeListener<SelectableControl>>(); public SelectableControlList(Composite parent, int style) { super(parent, style); setupScrolledComposite(); } public void addSelectionChangeListener( SelectionChangeListener<SelectableControl> listener) { if (!selectionChangeListeners.contains(listener)) { selectionChangeListeners.add(listener); } } public void addSelectionListener(SelectionListener listener) { if (!selectionListeners.contains(listener)) { selectionListeners.add(listener); } } public void clear() { for (C item : items) { for (SelectionListener listener : item.getSelectionListeners()) { item.removeSelectionListener(listener); } } for (Control child : scrolledCanvas.getChildren()) { child.dispose(); } items.clear(); doUpdateContentSize(); } public void clearSelections() { for (SelectableControl sc : items) { sc.setSelected(false); } } public List<C> getItems() { return items; } public void registerItem(final C selectableControl) { items.add(selectableControl); selectableControl.addSelectionListener(new SelectionAdapter() { @Override public void widgetDefaultSelected(SelectionEvent e) { fireDefaultSelectedEvent(e); } @Override public void widgetSelected(SelectionEvent e) { itemSelected(selectableControl, e.stateMask); } }); selectableControl.addSelectionChangeListener(new SelectionChangeListener<SelectableControl>() { public void selectionChanged(List<SelectableControl> selection) { fireSelectionChangeEvent(); } }); } @Override public void setBackground(Color color) { super.setBackground(color); updateBackground(scrolledCanvas, color); } public void updateContents( SelectableControlListUpdateCallback selectableControlListUpdateCallback) { scrolledCanvas.setRedraw(false); try { selectableControlListUpdateCallback.execute(scrolledCanvas); } finally { scrolledCanvas.layout(true); scrolledCanvas.setRedraw(true); doUpdateContentSize(); } } protected void addSeparator(Composite scrolledContents) { // a separator between connector descriptors Composite separator = new Composite(scrolledContents, SWT.NULL); GridDataFactory.fillDefaults().grab(true, false).hint(SWT.DEFAULT, 1).applyTo( separator); GridLayoutFactory.fillDefaults().applyTo(separator); separator.addPaintListener(new BorderPainter()); } protected void fireDefaultSelectedEvent(SelectionEvent e) { for (SelectionListener listener : selectionListeners) { listener.widgetDefaultSelected(e); } } protected void fireSelectionChangeEvent() { List<SelectableControl> selectedList = new ArrayList<SelectableControl>(); for (SelectableControl item : items) { if (item.isSelected()) { selectedList.add(item); } } for (SelectionChangeListener<SelectableControl> listener : selectionChangeListeners) { listener.selectionChanged(selectedList); } } /** * * @param selectableControl * @param stateMask */ protected void itemSelected(SelectableControl control, int stateMask) { if (!control.isDisabled()) { if (ctrlClicked(stateMask)) { control.setSelected(!control.isSelected()); } else { control.setSelected(true); for (SelectableControl sc : items) { if (sc != control) { sc.setSelected(false); } } } } } /** * Internal to ControlList * * @param stateMask * @return */ boolean ctrlClicked(int stateMask) { return (SWT.MOD1 & stateMask) != 0; } Composite getScrolledCanvas() { return scrolledCanvas; } private void doUpdateContentSize() { updateSize(scrolledCanvas); } /** * Do layout. Several magic #s in here... * * @param scrolledComposite */ private void setupScrolledComposite() { setAlwaysShowScrollBars(true); scrolledCanvas = new Composite(this, SWT.NONE); GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(scrolledCanvas); setMinWidth(100); setMinHeight(100); setExpandHorizontal(true); setExpandVertical(true); setMinHeight(1); Point size = scrolledCanvas.computeSize(getParent().getSize().x, SWT.DEFAULT, true); scrolledCanvas.setSize(size); addControlListener(new ControlAdapter() { @Override public void controlResized(ControlEvent e) { doUpdateContentSize(); updateScrollIncrements(); } }); setContent(scrolledCanvas); } private void updateBackground(Composite composite, Color background) { composite.setBackground(background); for (Control control : composite.getChildren()) { if (control instanceof Composite) { updateBackground((Composite) control, background); } else { control.setBackground(background); } } } private void updateScrollIncrements() { int pageInc = getBounds().height; getVerticalBar().setIncrement(20); getVerticalBar().setPageIncrement(pageInc); } private void updateSize(Control control) { if (control == null) { return; } Point size = control.computeSize(getClientArea().width - 20, SWT.DEFAULT, true); control.setSize(size); setMinSize(size); } }