/******************************************************************************* * Copyright (c) 2005, 2011 IBM Corporation and others. * 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 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.commons.ui; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; /** * Based on <code>org.eclipse.ui.internal.progress.ProgressInfoItem</code>. * * @author Steffen Pingel * @since 3.7 */ public abstract class ControlListItem extends Composite { static String DARK_COLOR_KEY = "org.eclipse.mylyn.commons.ui.ControlListItem.DARK_COLOR"; //$NON-NLS-1$ interface IndexListener { /** * Select the item previous to the receiver. */ public void selectPrevious(); /** * Select the next previous to the receiver. */ public void selectNext(); /** * Select the receiver. */ public void select(); public void open(); } IndexListener indexListener; private int currentIndex; private boolean selected; private final MouseAdapter mouseListener; private boolean isShowing = true; private final MouseTrackAdapter mouseTrackListener; private boolean hot; static { // Mac has different Gamma value int shift = "carbon".equals(SWT.getPlatform()) ? -25 : -10;//$NON-NLS-1$ Color lightColor = Display.getDefault().getSystemColor(SWT.COLOR_LIST_BACKGROUND); // Determine a dark color by shifting the list color RGB darkRGB = new RGB(Math.max(0, lightColor.getRed() + shift), Math.max(0, lightColor.getGreen() + shift), Math.max(0, lightColor.getBlue() + shift)); JFaceResources.getColorRegistry().put(DARK_COLOR_KEY, darkRGB); } /** * Create a new instance of the receiver with the specified parent, style and info object/ * * @param parent * @param style * @param progressInfo */ public ControlListItem(Composite parent, int style, Object element) { super(parent, style | SWT.NO_FOCUS); setData(element); setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); mouseListener = doCreateMouseListener(); mouseTrackListener = doCreateMouseTrackListener(); createContent(); registerChild(this); Control[] children = getChildren(); for (Control child : children) { registerChild(child); } setHot(false); refresh(); } private MouseTrackAdapter doCreateMouseTrackListener() { return new MouseTrackAdapter() { private int enterCount; @Override public void mouseEnter(MouseEvent e) { enterCount++; updateHotState(); } @Override public void mouseExit(MouseEvent e) { enterCount--; getDisplay().asyncExec(new Runnable() { public void run() { if (!isDisposed()) { updateHotState(); } } }); } private void updateHotState() { if (enterCount == 0) { if (isHot()) { setHot(false); } } else { if (!isHot()) { setHot(true); } } } }; } private MouseAdapter doCreateMouseListener() { return new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { if (indexListener != null) { if (e.count == 2) { indexListener.open(); } else { indexListener.select(); } } } }; } /** * Create the child widgets of the receiver. */ protected abstract void createContent(); public boolean isHot() { return hot; } public void setHot(boolean hot) { this.hot = hot; } protected void registerChild(Control child) { child.addMouseListener(mouseListener); child.addMouseTrackListener(mouseTrackListener); } /** * Refresh the contents of the receiver. */ protected abstract void refresh(); /** * Set the color base on the index * * @param index */ public void updateColors(int index) { currentIndex = index; if (selected) { setBackground(getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION)); setForeground(getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); } else { if (index % 2 == 0) { setBackground(JFaceResources.getColorRegistry().get(DARK_COLOR_KEY)); } else { setBackground(getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); } setForeground(getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND)); } } @Override public void setForeground(Color color) { super.setForeground(color); Control[] children = getChildren(); for (Control child : children) { child.setForeground(color); } } @Override public void setBackground(Color color) { super.setBackground(color); Control[] children = getChildren(); for (Control child : children) { child.setBackground(color); } } /** * Set the selection colors. * * @param select * boolean that indicates whether or not to show selection. */ public void setSelected(boolean select) { selected = select; updateColors(currentIndex); } /** * Set the listener for index changes. * * @param indexListener */ void setIndexListener(IndexListener indexListener) { this.indexListener = indexListener; } /** * Return whether or not the receiver is selected. * * @return boolean */ public boolean isSelected() { return selected; } /** * Set whether or not the receiver is being displayed based on the top and bottom of the currently visible area. * * @param top * @param bottom */ void setDisplayed(int top, int bottom) { int itemTop = getLocation().y; int itemBottom = itemTop + getBounds().height; setDisplayed(itemTop <= bottom && itemBottom > top); } /** * Set whether or not the receiver is being displayed * * @param displayed */ private void setDisplayed(boolean displayed) { // See if this element has been turned off boolean refresh = !isShowing && displayed; isShowing = displayed; if (refresh) { refresh(); } } }