mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-12 03:25:22 +02:00
LaunchBar: ui changes in selector
- added ability to filter by typing in selector pop-up - refactored list part of selection in its own components which is kind of list viewer - filter is visible by default if we have more than 7 elements in drop down - filter become visible if user start typing, even if it was not visible originally - moving storing of history size into the list viewer itself - hooked up proper focus support and keyboard traversal - modified CButton so we can re-use it for Edit button of selectors and list items - when filtering is activated history list is no longer available Change-Id: I2057ad658f5a5c9f8fbce203748d26d7e4b14dd6
This commit is contained in:
parent
bb7f665007
commit
edeec7aaaa
9 changed files with 1416 additions and 436 deletions
BIN
bundles/org.eclipse.launchbar.ui/icons/edit_cold.png
Normal file
BIN
bundles/org.eclipse.launchbar.ui/icons/edit_cold.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 574 B |
|
@ -99,7 +99,15 @@ public class Activator extends AbstractUIPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Image getImage(String id) {
|
public Image getImage(String id) {
|
||||||
return getImageRegistry().get(id);
|
Image im = getImageRegistry().get(id);
|
||||||
|
if (im == null) {
|
||||||
|
ImageDescriptor des = getImageDescriptor(id);
|
||||||
|
if (des != null) {
|
||||||
|
im = des.createImage();
|
||||||
|
getImageRegistry().put(id, im);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return im;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImageDescriptor getImageDescriptor(String path) {
|
public static ImageDescriptor getImageDescriptor(String path) {
|
||||||
|
|
|
@ -10,25 +10,27 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.launchbar.ui.internal.controls;
|
package org.eclipse.launchbar.ui.internal.controls;
|
||||||
|
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.events.MouseAdapter;
|
||||||
import org.eclipse.swt.events.MouseEvent;
|
import org.eclipse.swt.events.MouseEvent;
|
||||||
import org.eclipse.swt.events.MouseTrackAdapter;
|
import org.eclipse.swt.events.MouseTrackAdapter;
|
||||||
import org.eclipse.swt.events.PaintEvent;
|
import org.eclipse.swt.events.PaintEvent;
|
||||||
import org.eclipse.swt.events.PaintListener;
|
import org.eclipse.swt.events.PaintListener;
|
||||||
|
import org.eclipse.swt.events.SelectionListener;
|
||||||
import org.eclipse.swt.graphics.Image;
|
import org.eclipse.swt.graphics.Image;
|
||||||
import org.eclipse.swt.graphics.Point;
|
import org.eclipse.swt.graphics.Point;
|
||||||
import org.eclipse.swt.graphics.Rectangle;
|
import org.eclipse.swt.graphics.Rectangle;
|
||||||
import org.eclipse.swt.widgets.Canvas;
|
import org.eclipse.swt.widgets.Canvas;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.TypedListener;
|
||||||
|
|
||||||
public class CButton extends Canvas {
|
public class CButton extends Canvas {
|
||||||
|
|
||||||
private boolean inButton;
|
private boolean inButton;
|
||||||
private Image hotImage;
|
private Image hotImage;
|
||||||
private Image coldImage;
|
private Image coldImage;
|
||||||
|
|
||||||
public CButton(Composite parent, int style) {
|
public CButton(Composite parent, int style) {
|
||||||
super(parent, style);
|
super(parent, style);
|
||||||
|
|
||||||
addPaintListener(new PaintListener() {
|
addPaintListener(new PaintListener() {
|
||||||
@Override
|
@Override
|
||||||
public void paintControl(PaintEvent e) {
|
public void paintControl(PaintEvent e) {
|
||||||
|
@ -47,17 +49,28 @@ public class CButton extends Canvas {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
addMouseTrackListener(new MouseTrackAdapter() {
|
addMouseTrackListener(new MouseTrackAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseEnter(MouseEvent e) {
|
public void mouseEnter(MouseEvent e) {
|
||||||
inButton = true;
|
setSelected(true);
|
||||||
redraw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseExit(MouseEvent e) {
|
public void mouseExit(MouseEvent e) {
|
||||||
inButton = false;
|
setSelected(false);
|
||||||
redraw();
|
}
|
||||||
|
});
|
||||||
|
addMouseListener(new MouseAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseUp(MouseEvent e) {
|
||||||
|
setSelected(true);
|
||||||
|
handleSelection(inButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDoubleClick(MouseEvent e) {
|
||||||
|
setSelected(true);
|
||||||
|
handleDefaultSelection(inButton);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -65,10 +78,8 @@ public class CButton extends Canvas {
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
|
||||||
if (hotImage != null)
|
if (hotImage != null)
|
||||||
hotImage.dispose();
|
hotImage.dispose();
|
||||||
|
|
||||||
if (coldImage != null)
|
if (coldImage != null)
|
||||||
coldImage.dispose();
|
coldImage.dispose();
|
||||||
}
|
}
|
||||||
|
@ -100,4 +111,29 @@ public class CButton extends Canvas {
|
||||||
this.coldImage = image;
|
this.coldImage = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void handleSelection(boolean selection) {
|
||||||
|
// Send event
|
||||||
|
notifyListeners(SWT.Selection, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleDefaultSelection(boolean selection) {
|
||||||
|
// Send event
|
||||||
|
notifyListeners(SWT.DefaultSelection, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSelectionListener(SelectionListener listener) {
|
||||||
|
checkWidget();
|
||||||
|
TypedListener typedListener = new TypedListener(listener);
|
||||||
|
addListener(SWT.Selection, typedListener);
|
||||||
|
addListener(SWT.DefaultSelection, typedListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelected(boolean sel) {
|
||||||
|
inButton = sel;
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSelected() {
|
||||||
|
return inButton;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,52 +10,53 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.launchbar.ui.internal.controls;
|
package org.eclipse.launchbar.ui.internal.controls;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
import org.eclipse.jface.layout.GridDataFactory;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
import org.eclipse.jface.layout.GridLayoutFactory;
|
import org.eclipse.jface.layout.GridLayoutFactory;
|
||||||
|
import org.eclipse.jface.viewers.ICellModifier;
|
||||||
import org.eclipse.jface.viewers.ILabelProvider;
|
import org.eclipse.jface.viewers.ILabelProvider;
|
||||||
|
import org.eclipse.jface.viewers.ISelectionChangedListener;
|
||||||
import org.eclipse.jface.viewers.IStructuredContentProvider;
|
import org.eclipse.jface.viewers.IStructuredContentProvider;
|
||||||
|
import org.eclipse.jface.viewers.SelectionChangedEvent;
|
||||||
|
import org.eclipse.jface.viewers.StructuredSelection;
|
||||||
import org.eclipse.launchbar.ui.IHoverProvider;
|
import org.eclipse.launchbar.ui.IHoverProvider;
|
||||||
import org.eclipse.launchbar.ui.internal.Activator;
|
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
import org.eclipse.swt.custom.ScrolledComposite;
|
|
||||||
import org.eclipse.swt.events.DisposeEvent;
|
import org.eclipse.swt.events.DisposeEvent;
|
||||||
import org.eclipse.swt.events.DisposeListener;
|
import org.eclipse.swt.events.DisposeListener;
|
||||||
import org.eclipse.swt.events.MouseAdapter;
|
import org.eclipse.swt.events.MouseAdapter;
|
||||||
import org.eclipse.swt.events.MouseEvent;
|
import org.eclipse.swt.events.MouseEvent;
|
||||||
import org.eclipse.swt.events.MouseListener;
|
import org.eclipse.swt.events.MouseListener;
|
||||||
import org.eclipse.swt.events.MouseTrackAdapter;
|
|
||||||
import org.eclipse.swt.events.MouseTrackListener;
|
import org.eclipse.swt.events.MouseTrackListener;
|
||||||
import org.eclipse.swt.events.PaintEvent;
|
import org.eclipse.swt.events.PaintEvent;
|
||||||
import org.eclipse.swt.events.PaintListener;
|
import org.eclipse.swt.events.PaintListener;
|
||||||
import org.eclipse.swt.events.TraverseEvent;
|
import org.eclipse.swt.events.SelectionAdapter;
|
||||||
import org.eclipse.swt.events.TraverseListener;
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
import org.eclipse.swt.graphics.Color;
|
import org.eclipse.swt.graphics.Color;
|
||||||
import org.eclipse.swt.graphics.GC;
|
import org.eclipse.swt.graphics.GC;
|
||||||
import org.eclipse.swt.graphics.Image;
|
import org.eclipse.swt.graphics.Image;
|
||||||
import org.eclipse.swt.graphics.LineAttributes;
|
import org.eclipse.swt.graphics.LineAttributes;
|
||||||
import org.eclipse.swt.graphics.Point;
|
import org.eclipse.swt.graphics.Point;
|
||||||
import org.eclipse.swt.graphics.RGB;
|
|
||||||
import org.eclipse.swt.graphics.Rectangle;
|
import org.eclipse.swt.graphics.Rectangle;
|
||||||
import org.eclipse.swt.layout.GridData;
|
import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.layout.GridLayout;
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
import org.eclipse.swt.widgets.Canvas;
|
import org.eclipse.swt.widgets.Canvas;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Control;
|
import org.eclipse.swt.widgets.Control;
|
||||||
import org.eclipse.swt.widgets.Display;
|
|
||||||
import org.eclipse.swt.widgets.Event;
|
import org.eclipse.swt.widgets.Event;
|
||||||
import org.eclipse.swt.widgets.Label;
|
import org.eclipse.swt.widgets.Label;
|
||||||
import org.eclipse.swt.widgets.Listener;
|
import org.eclipse.swt.widgets.Listener;
|
||||||
import org.eclipse.swt.widgets.Sash;
|
|
||||||
import org.eclipse.swt.widgets.Shell;
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
|
||||||
public abstract class CSelector extends Composite {
|
public abstract class CSelector extends Composite {
|
||||||
private IStructuredContentProvider contentProvider;
|
private IStructuredContentProvider contentProvider;
|
||||||
private ILabelProvider labelProvider;
|
private ILabelProvider labelProvider;
|
||||||
private IHoverProvider hoverProvider;
|
private IHoverProvider hoverProvider;
|
||||||
private Comparator<Object> sorter;
|
private Comparator<?> sorter;
|
||||||
|
private Comparator<?> sorterTop;
|
||||||
private Object input;
|
private Object input;
|
||||||
private Composite buttonComposite;
|
private Composite buttonComposite;
|
||||||
private String toolTipText;
|
private String toolTipText;
|
||||||
|
@ -68,19 +69,10 @@ public abstract class CSelector extends Composite {
|
||||||
protected final Color highlightColor;
|
protected final Color highlightColor;
|
||||||
protected final Color white;
|
protected final Color white;
|
||||||
private boolean mouseOver;
|
private boolean mouseOver;
|
||||||
private Image editImage;
|
|
||||||
private boolean inEditButton;
|
|
||||||
private Image buttonImage;
|
|
||||||
private Label currentIcon;
|
private Label currentIcon;
|
||||||
private Label currentLabel;
|
private Label currentLabel;
|
||||||
private Shell popup;
|
private Shell popup;
|
||||||
private ListItem listItems[];
|
private LaunchBarListViewer listViewer;
|
||||||
private int selIndex;
|
|
||||||
private ScrolledComposite listScrolled;
|
|
||||||
private final int itemH = 30;
|
|
||||||
private int scrollBucket;
|
|
||||||
private final int maxScrollBucket = 7;
|
|
||||||
private int separatorIndex = -1;
|
|
||||||
private MouseTrackListener mouseTrackListener = new MouseTrackListener() {
|
private MouseTrackListener mouseTrackListener = new MouseTrackListener() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseEnter(MouseEvent e) {
|
public void mouseEnter(MouseEvent e) {
|
||||||
|
@ -130,43 +122,91 @@ public abstract class CSelector extends Composite {
|
||||||
@Override
|
@Override
|
||||||
public void mouseUp(MouseEvent event) {
|
public void mouseUp(MouseEvent event) {
|
||||||
if (popup == null || popup.isDisposed()) {
|
if (popup == null || popup.isDisposed()) {
|
||||||
|
setFocus();
|
||||||
openPopup();
|
openPopup();
|
||||||
} else {
|
} else {
|
||||||
closePopup();
|
closePopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected boolean isFocusAncestor(Control control) {
|
||||||
|
while (control != null && control != this && !(control instanceof Shell)) {
|
||||||
|
control = control.getParent();
|
||||||
|
}
|
||||||
|
return control == this;
|
||||||
|
}
|
||||||
private Listener focusOutListener = new Listener() {
|
private Listener focusOutListener = new Listener() {
|
||||||
|
private Job closingJob;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleEvent(Event event) {
|
public void handleEvent(Event event) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case SWT.FocusOut:
|
case SWT.FocusIn:
|
||||||
Control focusControl = getDisplay().getFocusControl();
|
if (closingJob != null)
|
||||||
if (focusControl != null && focusControl.getShell() == popup) {
|
closingJob.cancel();
|
||||||
Point loc = getDisplay().getCursorLocation();
|
if (event.widget instanceof Control && isFocusAncestor((Control) event.widget)) {
|
||||||
if (!getBounds().contains(toControl(loc))) {
|
break; // not closing
|
||||||
// Don't do it if we're in the selector, we'll deal with that later
|
}
|
||||||
closePopup();
|
if (!isPopUpInFocus()) {
|
||||||
}
|
closePopup();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SWT.MouseUp:
|
case SWT.FocusOut:
|
||||||
|
if (isPopUpInFocus()) {
|
||||||
|
// we about to loose focus from popup children, but it may go
|
||||||
|
// to another child, lets schedule a job to wait before we close
|
||||||
|
if (closingJob != null)
|
||||||
|
closingJob.cancel();
|
||||||
|
closingJob = new Job("Closing popup") {
|
||||||
|
@Override
|
||||||
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
|
if (monitor.isCanceled())
|
||||||
|
return Status.CANCEL_STATUS;
|
||||||
|
|
||||||
|
closePopup();
|
||||||
|
closingJob = null;
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
closingJob.schedule(300);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SWT.MouseUp: {
|
||||||
if (popup != null && !popup.isDisposed()) {
|
if (popup != null && !popup.isDisposed()) {
|
||||||
Point loc = getDisplay().getCursorLocation();
|
Point loc = getDisplay().getCursorLocation();
|
||||||
if (!popup.getBounds().contains(loc) && !getBounds().contains(toControl(loc))) {
|
if (!popup.getBounds().contains(loc) && !getBounds().contains(getParent().toControl(loc))) {
|
||||||
closePopup();
|
closePopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
private ICellModifier modifier = new ICellModifier() {
|
||||||
|
@Override
|
||||||
|
public void modify(Object element, String property, Object value) {
|
||||||
|
handleEdit(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue(Object element, String property) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canModify(Object element, String property) {
|
||||||
|
return isEditable(element);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public CSelector(Composite parent, int style) {
|
public CSelector(Composite parent, int style) {
|
||||||
super(parent, style);
|
super(parent, style);
|
||||||
backgroundColor = new Color(getDisplay(), new RGB(249, 249, 249));
|
backgroundColor = getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
|
||||||
outlineColor = new Color(getDisplay(), new RGB(189, 195, 200));
|
outlineColor = getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
|
||||||
highlightColor = new Color(getDisplay(), new RGB(223, 239, 241));
|
highlightColor = getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
|
||||||
white = getDisplay().getSystemColor(SWT.COLOR_WHITE);
|
white = getDisplay().getSystemColor(SWT.COLOR_WHITE);
|
||||||
GridLayout mainButtonLayout = new GridLayout();
|
GridLayout mainButtonLayout = new GridLayout();
|
||||||
setLayout(mainButtonLayout);
|
setLayout(mainButtonLayout);
|
||||||
|
@ -186,16 +226,17 @@ public abstract class CSelector extends Composite {
|
||||||
addMouseTrackListener(mouseTrackListener);
|
addMouseTrackListener(mouseTrackListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPopUpInFocus() {
|
||||||
|
Control focusControl = getDisplay().getFocusControl();
|
||||||
|
if (focusControl != null && focusControl.getShell() == popup) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
backgroundColor.dispose();
|
|
||||||
outlineColor.dispose();
|
|
||||||
highlightColor.dispose();
|
|
||||||
if (editImage != null)
|
|
||||||
editImage.dispose();
|
|
||||||
if (buttonImage != null)
|
|
||||||
buttonImage.dispose();
|
|
||||||
if (popup != null)
|
if (popup != null)
|
||||||
popup.dispose();
|
popup.dispose();
|
||||||
}
|
}
|
||||||
|
@ -272,11 +313,12 @@ public abstract class CSelector extends Composite {
|
||||||
arrow.addMouseListener(mouseListener);
|
arrow.addMouseListener(mouseListener);
|
||||||
arrow.addMouseTrackListener(mouseTrackListener);
|
arrow.addMouseTrackListener(mouseTrackListener);
|
||||||
if (editable) {
|
if (editable) {
|
||||||
Control editButton = createEditButton(buttonComposite, element);
|
final EditButton editButton = new EditButton(buttonComposite, SWT.NONE);
|
||||||
|
editButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, true));
|
||||||
editButton.setBackground(backgroundColor);
|
editButton.setBackground(backgroundColor);
|
||||||
editButton.addMouseListener(new MouseAdapter() {
|
editButton.addSelectionListener(new SelectionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseUp(MouseEvent e) {
|
public void widgetSelected(SelectionEvent e) {
|
||||||
// Need to run this after the current event storm
|
// Need to run this after the current event storm
|
||||||
// Or we get a disposed error.
|
// Or we get a disposed error.
|
||||||
getDisplay().asyncExec(new Runnable() {
|
getDisplay().asyncExec(new Runnable() {
|
||||||
|
@ -316,32 +358,25 @@ public abstract class CSelector extends Composite {
|
||||||
}
|
}
|
||||||
popup = new Shell(getShell(), SWT.TOOL | SWT.ON_TOP);
|
popup = new Shell(getShell(), SWT.TOOL | SWT.ON_TOP);
|
||||||
popup.setLayout(GridLayoutFactory.fillDefaults().spacing(0, 0).create());
|
popup.setLayout(GridLayoutFactory.fillDefaults().spacing(0, 0).create());
|
||||||
listScrolled = new ScrolledComposite(popup, SWT.V_SCROLL | SWT.NO_BACKGROUND);
|
|
||||||
listScrolled.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
|
||||||
listScrolled.setExpandHorizontal(true);
|
listViewer = new LaunchBarListViewer(popup);
|
||||||
final Composite listComp = new Composite(listScrolled, SWT.NONE);
|
initializeListViewer(listViewer);
|
||||||
listScrolled.setContent(listComp);
|
listViewer.setFilterVisible(elements.length > 7);
|
||||||
listComp.setLayout(GridLayoutFactory.fillDefaults().spacing(0, 0).create());
|
listViewer.setInput(input);
|
||||||
if (sorter != null)
|
listViewer.addSelectionChangedListener(new ISelectionChangedListener() {
|
||||||
Arrays.sort(elements, sorter);
|
@Override
|
||||||
listItems = new ListItem[elements.length];
|
public void selectionChanged(SelectionChangedEvent event) {
|
||||||
if (elements.length > 0) {
|
if (!listViewer.isFinalSelection())
|
||||||
listItems[0] = new ListItem(listComp, SWT.NONE, elements[0], 0);
|
return;
|
||||||
listItems[0].lazyInit();
|
StructuredSelection ss = (StructuredSelection) event.getSelection();
|
||||||
final int hHint = Math.max(listItems[0].computeSize(SWT.DEFAULT, SWT.DEFAULT).y, 16);
|
if (!ss.isEmpty()) {
|
||||||
for (int i = 1; i < elements.length; ++i) {
|
setSelection(ss.getFirstElement());
|
||||||
ListItem item = new ListItem(listComp, SWT.NONE, elements[i], i);
|
fireSelectionChanged();
|
||||||
if (i < maxScrollBucket) { // this is how many visible by default
|
|
||||||
item.lazyInit();
|
|
||||||
} else {
|
|
||||||
((GridData) item.getLayoutData()).heightHint = hHint;
|
|
||||||
}
|
}
|
||||||
listItems[i] = item;
|
closePopup();
|
||||||
}
|
}
|
||||||
createSash(listComp, hHint);
|
});
|
||||||
}
|
|
||||||
Point listCompSize = listComp.computeSize(SWT.DEFAULT, SWT.DEFAULT);
|
|
||||||
listComp.setSize(listCompSize);
|
|
||||||
if (hasActionArea())
|
if (hasActionArea())
|
||||||
createActionArea(popup);
|
createActionArea(popup);
|
||||||
Rectangle buttonBounds = getBounds();
|
Rectangle buttonBounds = getBounds();
|
||||||
|
@ -350,295 +385,53 @@ public abstract class CSelector extends Composite {
|
||||||
popup.setLocation(popupLocation.x, popupLocation.y + 5);
|
popup.setLocation(popupLocation.x, popupLocation.y + 5);
|
||||||
Point size = popup.computeSize(SWT.DEFAULT, SWT.DEFAULT);
|
Point size = popup.computeSize(SWT.DEFAULT, SWT.DEFAULT);
|
||||||
Point buttonSize = getSize();
|
Point buttonSize = getSize();
|
||||||
size.x = Math.min(size.x + 16, buttonSize.x * 4 / 3);
|
size.x = Math.max(size.x, buttonSize.x);
|
||||||
size.y = Math.min(size.y, 250);
|
size.y = Math.min(size.y, 300);
|
||||||
popup.setSize(size);
|
popup.setSize(size);
|
||||||
popup.setVisible(true);
|
popup.setVisible(true);
|
||||||
popup.setFocus();
|
popup.setFocus();
|
||||||
|
getDisplay().addFilter(SWT.FocusIn, focusOutListener);
|
||||||
getDisplay().addFilter(SWT.FocusOut, focusOutListener);
|
getDisplay().addFilter(SWT.FocusOut, focusOutListener);
|
||||||
getDisplay().addFilter(SWT.MouseUp, focusOutListener);
|
getDisplay().addFilter(SWT.MouseUp, focusOutListener);
|
||||||
popup.addDisposeListener(new DisposeListener() {
|
popup.addDisposeListener(new DisposeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void widgetDisposed(DisposeEvent e) {
|
public void widgetDisposed(DisposeEvent e) {
|
||||||
|
getDisplay().removeFilter(SWT.FocusIn, focusOutListener);
|
||||||
getDisplay().removeFilter(SWT.FocusOut, focusOutListener);
|
getDisplay().removeFilter(SWT.FocusOut, focusOutListener);
|
||||||
getDisplay().removeFilter(SWT.MouseUp, focusOutListener);
|
getDisplay().removeFilter(SWT.MouseUp, focusOutListener);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
selIndex = -1;
|
|
||||||
scrollBucket = 0;
|
|
||||||
if (hoverProvider != null) {
|
if (hoverProvider != null) {
|
||||||
hoverProvider.dismissHover(selection != null ? selection : null, true);
|
hoverProvider.dismissHover(selection != null ? selection : null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createSash(final Composite listComp, final int hHint) {
|
protected void initializeListViewer(LaunchBarListViewer listViewer) {
|
||||||
if (separatorIndex<0) return;
|
listViewer.setContentProvider(contentProvider);
|
||||||
|
listViewer.setLabelProvider(labelProvider);
|
||||||
final Sash sash = new Sash(listComp, SWT.BORDER | SWT.HORIZONTAL);
|
listViewer.setCellModifier(modifier);
|
||||||
sash.setLayoutData(GridDataFactory.fillDefaults().create());
|
listViewer.setComparator(sorter);
|
||||||
|
listViewer.setHistoryComparator(sorterTop);
|
||||||
if (separatorIndex < listItems.length)
|
|
||||||
sash.moveAbove(listItems[separatorIndex]);
|
|
||||||
else
|
|
||||||
sash.moveBelow(null);
|
|
||||||
|
|
||||||
sash.addListener(SWT.Selection, new Listener() {
|
|
||||||
@Override
|
|
||||||
public void handleEvent(Event e) {
|
|
||||||
separatorIndex = (e.y + hHint/2) / hHint;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sash.addMouseListener(new MouseListener() {
|
|
||||||
@Override
|
|
||||||
public void mouseUp(MouseEvent e) {
|
|
||||||
setSeparatorIndex(separatorIndex); // call setter if it was overriden
|
|
||||||
if (separatorIndex >= 0) {
|
|
||||||
if (separatorIndex < listItems.length)
|
|
||||||
sash.moveAbove(listItems[separatorIndex]);
|
|
||||||
else
|
|
||||||
sash.moveBelow(null);
|
|
||||||
listComp.layout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void mouseDown(MouseEvent e) {
|
|
||||||
sash.moveAbove(null); // keep on top so user see it when moving
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void mouseDoubleClick(MouseEvent e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sash.setToolTipText("Increase/Decrease size of recently used elements pane");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closePopup() {
|
private void closePopup() {
|
||||||
arrowTransition.to(arrowMax);
|
|
||||||
popup.setVisible(false);
|
|
||||||
getDisplay().asyncExec(new Runnable() {
|
getDisplay().asyncExec(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
if (popup == null || popup.isDisposed())
|
||||||
|
return;
|
||||||
|
arrowTransition.to(arrowMax);
|
||||||
|
popup.setVisible(false);
|
||||||
popup.dispose();
|
popup.dispose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
TraverseListener listItemTraverseListener = new TraverseListener() {
|
|
||||||
@Override
|
|
||||||
public void keyTraversed(TraverseEvent e) {
|
|
||||||
final ListItem currItem = selIndex >= 0 ? listItems[selIndex] : null;
|
|
||||||
if (currItem == null && e.keyCode != SWT.ARROW_DOWN) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (e.detail == SWT.TRAVERSE_ARROW_NEXT || e.detail == SWT.TRAVERSE_TAB_NEXT) {
|
|
||||||
if (inEditButton || e.keyCode == SWT.ARROW_DOWN) {
|
|
||||||
int maxIdx = listItems.length - 1;
|
|
||||||
if (selIndex < maxIdx) {
|
|
||||||
inEditButton = false;
|
|
||||||
if (currItem != null)
|
|
||||||
currItem.setBackground(white);
|
|
||||||
// move to next item
|
|
||||||
selIndex++;
|
|
||||||
if (scrollBucket < maxScrollBucket) {
|
|
||||||
scrollBucket++;
|
|
||||||
} else {
|
|
||||||
// need to scroll the list up 1 item
|
|
||||||
int sY = listScrolled.getOrigin().y;
|
|
||||||
listScrolled.setOrigin(0, sY + itemH);
|
|
||||||
}
|
|
||||||
listItems[selIndex].setBackground(highlightColor);
|
|
||||||
} else if (selIndex == maxIdx && maxIdx > maxScrollBucket) {
|
|
||||||
// level the scroll for any offset at the bottom of the list
|
|
||||||
listScrolled.setOrigin(0, itemH * (maxIdx - maxScrollBucket + 1));
|
|
||||||
}
|
|
||||||
} else if (currItem.editButton != null) {
|
|
||||||
// move focus on edit button
|
|
||||||
inEditButton = true;
|
|
||||||
currItem.editButton.redraw();
|
|
||||||
}
|
|
||||||
} else if (e.detail == SWT.TRAVERSE_ARROW_PREVIOUS || e.detail == SWT.TRAVERSE_TAB_PREVIOUS) {
|
|
||||||
if (!inEditButton || e.keyCode == SWT.ARROW_UP) {
|
|
||||||
if (selIndex > 0) {
|
|
||||||
inEditButton = false;
|
|
||||||
currItem.setBackground(white);
|
|
||||||
// move to previous item
|
|
||||||
selIndex--;
|
|
||||||
if (scrollBucket > 0) {
|
|
||||||
scrollBucket--;
|
|
||||||
} else {
|
|
||||||
// need to scroll the list down 1 item
|
|
||||||
int sY = listScrolled.getOrigin().y;
|
|
||||||
listScrolled.setOrigin(0, sY - itemH);
|
|
||||||
}
|
|
||||||
listItems[selIndex].setBackground(highlightColor);
|
|
||||||
} else if (selIndex == 0) {
|
|
||||||
// level any offset @ beginning
|
|
||||||
listScrolled.setOrigin(0, 0);
|
|
||||||
}
|
|
||||||
} else if (currItem.editButton != null) {
|
|
||||||
// remove focus from edit button
|
|
||||||
inEditButton = false;
|
|
||||||
currItem.editButton.redraw();
|
|
||||||
}
|
|
||||||
} else if (e.detail == SWT.TRAVERSE_RETURN) {
|
|
||||||
if (inEditButton) {
|
|
||||||
inEditButton = false;
|
|
||||||
// edit button in list item was pressed
|
|
||||||
getDisplay().asyncExec(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (CSelector.this.selection != null)
|
|
||||||
handleEdit(currItem.element);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// list item was pressed
|
|
||||||
popup.dispose();
|
|
||||||
setSelection(currItem.element);
|
|
||||||
fireSelectionChanged();
|
|
||||||
}
|
|
||||||
} else if (e.detail == SWT.TRAVERSE_ESCAPE) {
|
|
||||||
popup.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private class ListItem extends Composite {
|
|
||||||
protected final Object element;
|
|
||||||
private Label icon;
|
|
||||||
private Label label;
|
|
||||||
protected Control editButton;
|
|
||||||
private int index;
|
|
||||||
|
|
||||||
public ListItem(Composite parent, int style, Object _element, int index) {
|
|
||||||
super(parent, style);
|
|
||||||
this.element = _element;
|
|
||||||
this.index = index;
|
|
||||||
setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
|
||||||
addPaintListener(new PaintListener() {
|
|
||||||
@Override
|
|
||||||
public void paintControl(PaintEvent e) {
|
|
||||||
Point size = getSize();
|
|
||||||
GC gc = e.gc;
|
|
||||||
gc.setForeground(outlineColor);
|
|
||||||
gc.drawLine(0, size.y - 1, size.x, size.y - 1);
|
|
||||||
if (label == null)
|
|
||||||
lazyInit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// lazyInit();
|
|
||||||
} // end ListItem(..)
|
|
||||||
|
|
||||||
protected void lazyInit() {
|
|
||||||
Image image = labelProvider.getImage(element);
|
|
||||||
boolean editable = isEditable(element);
|
|
||||||
int columns = 1;
|
|
||||||
if (image != null)
|
|
||||||
columns++;
|
|
||||||
if (editable)
|
|
||||||
columns++;
|
|
||||||
GridLayout layout = new GridLayout(columns, false);
|
|
||||||
layout.marginWidth = layout.marginHeight = 7;
|
|
||||||
setLayout(layout);
|
|
||||||
MouseListener listItemMouseListener = new MouseAdapter() {
|
|
||||||
@Override
|
|
||||||
public void mouseUp(MouseEvent e) {
|
|
||||||
popup.dispose();
|
|
||||||
setSelection(element);
|
|
||||||
fireSelectionChanged();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
MouseTrackListener listItemMouseTrackListener = new MouseTrackAdapter() {
|
|
||||||
@Override
|
|
||||||
public void mouseEnter(MouseEvent e) {
|
|
||||||
setBackground(highlightColor);
|
|
||||||
int idx = getIndex();
|
|
||||||
if (idx != selIndex) {
|
|
||||||
if (selIndex >= 0) {
|
|
||||||
listItems[selIndex].setBackground(white);
|
|
||||||
scrollBucket = Math.max(Math.min(scrollBucket + idx - selIndex, maxScrollBucket), 0);
|
|
||||||
} else { // initially
|
|
||||||
scrollBucket = Math.min(idx, maxScrollBucket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selIndex = idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void mouseExit(MouseEvent e) {
|
|
||||||
setBackground(white);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
addMouseListener(listItemMouseListener);
|
|
||||||
// addMouseTrackListener(listItemMouseTrackListener);
|
|
||||||
if (image != null) {
|
|
||||||
icon = createImage(this, image);
|
|
||||||
icon.addMouseListener(listItemMouseListener);
|
|
||||||
icon.addMouseTrackListener(listItemMouseTrackListener);
|
|
||||||
}
|
|
||||||
label = createLabel(this, element);
|
|
||||||
label.addMouseListener(listItemMouseListener);
|
|
||||||
label.addMouseTrackListener(listItemMouseTrackListener);
|
|
||||||
if (editable) {
|
|
||||||
editButton = createEditButton(this, element);
|
|
||||||
editButton.setBackground(white);
|
|
||||||
editButton.addMouseTrackListener(listItemMouseTrackListener);
|
|
||||||
editButton.addMouseListener(new MouseAdapter() {
|
|
||||||
@Override
|
|
||||||
public void mouseUp(MouseEvent e) {
|
|
||||||
// Need to run this after the current event storm
|
|
||||||
// Or we get a disposed error.
|
|
||||||
getDisplay().asyncExec(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (CSelector.this.selection != null)
|
|
||||||
handleEdit(element);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
editButton.addTraverseListener(listItemTraverseListener);
|
|
||||||
} else {
|
|
||||||
addTraverseListener(listItemTraverseListener);
|
|
||||||
}
|
|
||||||
setBackground(white);
|
|
||||||
layout(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBackground(Color color) {
|
|
||||||
super.setBackground(color);
|
|
||||||
if (icon != null && !icon.isDisposed())
|
|
||||||
icon.setBackground(color);
|
|
||||||
if (label != null && !label.isDisposed())
|
|
||||||
label.setBackground(color);
|
|
||||||
if (editButton != null && !editButton.isDisposed())
|
|
||||||
editButton.setBackground(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setImage(Image image) {
|
|
||||||
if (icon != null && !icon.isDisposed())
|
|
||||||
icon.setImage(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setText(String text) {
|
|
||||||
if (!label.isDisposed())
|
|
||||||
label.setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getIndex() {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
} // end ListItem class
|
|
||||||
|
|
||||||
private Label createImage(Composite parent, Image image) {
|
private Label createImage(Composite parent, Image image) {
|
||||||
Rectangle bounds = image.getBounds();
|
Rectangle bounds = image.getBounds();
|
||||||
boolean disposeImage = false;
|
boolean disposeImage = false;
|
||||||
if (bounds.height > 16 || bounds.width > 16) {
|
if (bounds.height > 16 || bounds.width > 16) {
|
||||||
buttonImage = new Image(getDisplay(), 16, 16);
|
Image buttonImage = new Image(getDisplay(), 16, 16);
|
||||||
GC gc = new GC(buttonImage);
|
GC gc = new GC(buttonImage);
|
||||||
gc.setAntialias(SWT.ON);
|
gc.setAntialias(SWT.ON);
|
||||||
gc.setInterpolation(SWT.HIGH);
|
gc.setInterpolation(SWT.HIGH);
|
||||||
|
@ -646,6 +439,7 @@ public abstract class CSelector extends Composite {
|
||||||
image.getBounds().height, 0, 0, 16, 16);
|
image.getBounds().height, 0, 0, 16, 16);
|
||||||
gc.dispose();
|
gc.dispose();
|
||||||
image = buttonImage;
|
image = buttonImage;
|
||||||
|
disposeImage = true;
|
||||||
}
|
}
|
||||||
Label icon = new Label(parent, SWT.NONE);
|
Label icon = new Label(parent, SWT.NONE);
|
||||||
icon.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, true));
|
icon.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, true));
|
||||||
|
@ -670,43 +464,6 @@ public abstract class CSelector extends Composite {
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Control createEditButton(Composite parent, Object element) {
|
|
||||||
if (editImage == null) {
|
|
||||||
editImage = Activator.getImageDescriptor("icons/config_config.png").createImage();
|
|
||||||
}
|
|
||||||
final Canvas editButton = new Canvas(parent, SWT.NONE) {
|
|
||||||
@Override
|
|
||||||
public Point computeSize(int wHint, int hHint, boolean changed) {
|
|
||||||
Rectangle bounds = editImage.getBounds();
|
|
||||||
return new Point(bounds.width, bounds.height);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
editButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, true));
|
|
||||||
editButton.setToolTipText("Edit");
|
|
||||||
editButton.addPaintListener(new PaintListener() {
|
|
||||||
@Override
|
|
||||||
public void paintControl(PaintEvent e) {
|
|
||||||
GC gc = e.gc;
|
|
||||||
gc.setAlpha(inEditButton ? 255 : 64);
|
|
||||||
gc.drawImage(editImage, 0, 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
editButton.addMouseTrackListener(new MouseTrackAdapter() {
|
|
||||||
@Override
|
|
||||||
public void mouseEnter(MouseEvent e) {
|
|
||||||
inEditButton = true;
|
|
||||||
editButton.redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void mouseExit(MouseEvent e) {
|
|
||||||
inEditButton = false;
|
|
||||||
editButton.redraw();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return editButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContentProvider(IStructuredContentProvider contentProvider) {
|
public void setContentProvider(IStructuredContentProvider contentProvider) {
|
||||||
this.contentProvider = contentProvider;
|
this.contentProvider = contentProvider;
|
||||||
}
|
}
|
||||||
|
@ -731,10 +488,24 @@ public abstract class CSelector extends Composite {
|
||||||
return hoverProvider;
|
return hoverProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSorter(Comparator<Object> sorter) {
|
/**
|
||||||
|
* Set sorter for the bottom part of the selector
|
||||||
|
*
|
||||||
|
* @param sorter
|
||||||
|
*/
|
||||||
|
public void setSorter(Comparator<?> sorter) {
|
||||||
this.sorter = sorter;
|
this.sorter = sorter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set sorter for the "history" part of the selector
|
||||||
|
*
|
||||||
|
* @param sorter
|
||||||
|
*/
|
||||||
|
public void setHistorySortComparator(Comparator<?> sorter) {
|
||||||
|
this.sorterTop = sorter;
|
||||||
|
}
|
||||||
|
|
||||||
public void setInput(Object input) {
|
public void setInput(Object input) {
|
||||||
this.input = input;
|
this.input = input;
|
||||||
}
|
}
|
||||||
|
@ -757,15 +528,7 @@ public abstract class CSelector extends Composite {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (popup != null && !popup.isDisposed()) {
|
if (popup != null && !popup.isDisposed()) {
|
||||||
Object[] elements = contentProvider.getElements(input);
|
listViewer.update(element, null);
|
||||||
int i;
|
|
||||||
for (i = 0; i < elements.length; ++i)
|
|
||||||
if (element == elements[i])
|
|
||||||
break;
|
|
||||||
if (i != elements.length) {
|
|
||||||
listItems[i].setImage(labelProvider.getImage(element));
|
|
||||||
listItems[i].setText(labelProvider.getText(element));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,11 +548,4 @@ public abstract class CSelector extends Composite {
|
||||||
// nothing to do here
|
// nothing to do here
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSeparatorIndex() {
|
|
||||||
return separatorIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSeparatorIndex(int separatorIndex) {
|
|
||||||
this.separatorIndex = separatorIndex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.launchbar.ui.internal.controls;
|
package org.eclipse.launchbar.ui.internal.controls;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
@ -26,7 +25,6 @@ import org.eclipse.debug.internal.ui.DebugUIPlugin;
|
||||||
import org.eclipse.debug.internal.ui.launchConfigurations.LaunchGroupExtension;
|
import org.eclipse.debug.internal.ui.launchConfigurations.LaunchGroupExtension;
|
||||||
import org.eclipse.debug.ui.ILaunchGroup;
|
import org.eclipse.debug.ui.ILaunchGroup;
|
||||||
import org.eclipse.jface.dialogs.MessageDialog;
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
import org.eclipse.jface.preference.IPreferenceStore;
|
|
||||||
import org.eclipse.jface.viewers.ILabelProvider;
|
import org.eclipse.jface.viewers.ILabelProvider;
|
||||||
import org.eclipse.jface.viewers.IStructuredContentProvider;
|
import org.eclipse.jface.viewers.IStructuredContentProvider;
|
||||||
import org.eclipse.jface.viewers.LabelProvider;
|
import org.eclipse.jface.viewers.LabelProvider;
|
||||||
|
@ -79,27 +77,13 @@ public class ConfigSelector extends CSelector {
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] getElements(Object inputElement) {
|
public Object[] getElements(Object inputElement) {
|
||||||
ILaunchDescriptor[] descs = uiManager.getManager().getLaunchDescriptors();
|
ILaunchDescriptor[] descs = uiManager.getManager().getLaunchDescriptors();
|
||||||
if (descs.length > 0) {
|
if (descs.length == 0)
|
||||||
int separatorIndex = getSeparatorIndex();
|
return noConfigs;
|
||||||
if (descs.length > separatorIndex + 1) {
|
return descs;
|
||||||
ILaunchDescriptor[] descsCopy = new ILaunchDescriptor[separatorIndex + descs.length];
|
|
||||||
System.arraycopy(descs, 0, descsCopy, 0, separatorIndex); // copy first 3 elements
|
|
||||||
System.arraycopy(descs, 0, descsCopy, separatorIndex, descs.length); // copy all into rest
|
|
||||||
// sort rest
|
|
||||||
Arrays.sort(descsCopy, separatorIndex, descsCopy.length, new Comparator<ILaunchDescriptor>() {
|
|
||||||
@Override
|
|
||||||
public int compare(ILaunchDescriptor o1, ILaunchDescriptor o2) {
|
|
||||||
return o1.getName().compareTo(o2.getName());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return descsCopy;
|
|
||||||
} else
|
|
||||||
return descs;
|
|
||||||
}
|
|
||||||
return noConfigs;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -141,13 +125,23 @@ public class ConfigSelector extends CSelector {
|
||||||
return defaultProvider.getText(element);
|
return defaultProvider.getText(element);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// no sorter on view, data is sorted by provider
|
// no sorter for top, data is sorted by provider in historical order
|
||||||
setSorter(null);
|
setHistorySortComparator(null);
|
||||||
IPreferenceStore store = Activator.getDefault().getPreferenceStore();
|
// alphabetic sorter
|
||||||
int separator = store.getInt(Activator.PREF_LAUNCH_HISTORY_SIZE);
|
setSorter(new Comparator<ILaunchDescriptor>() {
|
||||||
if (separator <= 0)
|
@Override
|
||||||
separator = 1;
|
public int compare(ILaunchDescriptor o1, ILaunchDescriptor o2) {
|
||||||
setSeparatorIndex(separator);
|
return o1.getName().compareTo(o2.getName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initializeListViewer(LaunchBarListViewer listViewer) {
|
||||||
|
listViewer.setHistorySupported(true);
|
||||||
|
listViewer.setHistoryPreferenceName(Activator.PREF_LAUNCH_HISTORY_SIZE);
|
||||||
|
super.initializeListViewer(listViewer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -163,16 +157,6 @@ public class ConfigSelector extends CSelector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSeparatorIndex(int separatorIndex) {
|
|
||||||
super.setSeparatorIndex(separatorIndex);
|
|
||||||
IPreferenceStore store = Activator.getDefault().getPreferenceStore();
|
|
||||||
int separator = store.getInt(Activator.PREF_LAUNCH_HISTORY_SIZE);
|
|
||||||
if (separator != getSeparatorIndex()) {
|
|
||||||
store.setValue(Activator.PREF_LAUNCH_HISTORY_SIZE, getSeparatorIndex());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEditable(Object element) {
|
public boolean isEditable(Object element) {
|
||||||
return element instanceof ILaunchDescriptor;
|
return element instanceof ILaunchDescriptor;
|
||||||
|
@ -233,7 +217,7 @@ public class ConfigSelector extends CSelector {
|
||||||
GridLayout buttonLayout = new GridLayout();
|
GridLayout buttonLayout = new GridLayout();
|
||||||
buttonLayout.marginWidth = buttonLayout.marginHeight = 7;
|
buttonLayout.marginWidth = buttonLayout.marginHeight = 7;
|
||||||
createButton.setLayout(buttonLayout);
|
createButton.setLayout(buttonLayout);
|
||||||
createButton.setBackground(white);
|
createButton.setBackground(backgroundColor);
|
||||||
createButton.addPaintListener(new PaintListener() {
|
createButton.addPaintListener(new PaintListener() {
|
||||||
@Override
|
@Override
|
||||||
public void paintControl(PaintEvent e) {
|
public void paintControl(PaintEvent e) {
|
||||||
|
@ -247,7 +231,7 @@ public class ConfigSelector extends CSelector {
|
||||||
final Label createLabel = new Label(createButton, SWT.None);
|
final Label createLabel = new Label(createButton, SWT.None);
|
||||||
createLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
createLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
||||||
createLabel.setText("Create New Configuration...");
|
createLabel.setText("Create New Configuration...");
|
||||||
createLabel.setBackground(white);
|
createLabel.setBackground(backgroundColor);
|
||||||
|
|
||||||
MouseListener mouseListener = new MouseAdapter() {
|
MouseListener mouseListener = new MouseAdapter() {
|
||||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
|
public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
|
||||||
|
@ -281,8 +265,8 @@ public class ConfigSelector extends CSelector {
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void mouseExit(MouseEvent e) {
|
public void mouseExit(MouseEvent e) {
|
||||||
createButton.setBackground(white);
|
createButton.setBackground(backgroundColor);
|
||||||
createLabel.setBackground(white);
|
createLabel.setBackground(backgroundColor);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
createButton.addMouseTrackListener(mouseTrackListener);
|
createButton.addMouseTrackListener(mouseTrackListener);
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package org.eclipse.launchbar.ui.internal.controls;
|
||||||
|
|
||||||
|
import org.eclipse.launchbar.ui.internal.Activator;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
|
||||||
|
public class EditButton extends CButton {
|
||||||
|
public EditButton(Composite parent, int style) {
|
||||||
|
super(parent, style);
|
||||||
|
setHotImage(Activator.getDefault().getImage("icons/config_config.png"));
|
||||||
|
setColdImage(Activator.getDefault().getImage("icons/edit_cold.png"));
|
||||||
|
setToolTipText("Edit");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,472 @@
|
||||||
|
package org.eclipse.launchbar.ui.internal.controls;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
import org.eclipse.jface.layout.GridDataFactory;
|
||||||
|
import org.eclipse.jface.layout.GridLayoutFactory;
|
||||||
|
import org.eclipse.jface.viewers.ILabelProvider;
|
||||||
|
import org.eclipse.jface.viewers.StructuredSelection;
|
||||||
|
import org.eclipse.jface.viewers.Viewer;
|
||||||
|
import org.eclipse.jface.viewers.ViewerFilter;
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.accessibility.AccessibleAdapter;
|
||||||
|
import org.eclipse.swt.accessibility.AccessibleEvent;
|
||||||
|
import org.eclipse.swt.events.DisposeEvent;
|
||||||
|
import org.eclipse.swt.events.DisposeListener;
|
||||||
|
import org.eclipse.swt.events.FocusAdapter;
|
||||||
|
import org.eclipse.swt.events.FocusEvent;
|
||||||
|
import org.eclipse.swt.events.ModifyEvent;
|
||||||
|
import org.eclipse.swt.events.ModifyListener;
|
||||||
|
import org.eclipse.swt.events.MouseAdapter;
|
||||||
|
import org.eclipse.swt.events.MouseEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionAdapter;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.events.TraverseEvent;
|
||||||
|
import org.eclipse.swt.events.TraverseListener;
|
||||||
|
import org.eclipse.swt.graphics.Color;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.Text;
|
||||||
|
import org.eclipse.ui.internal.WorkbenchMessages;
|
||||||
|
import org.eclipse.ui.progress.WorkbenchJob;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple control that provides a text widget and controls a list viewer
|
||||||
|
*/
|
||||||
|
public class FilterControl extends Composite {
|
||||||
|
/**
|
||||||
|
* The filter text widget to be used by this tree. This value may be <code>null</code> if there is no filter widget, or if the
|
||||||
|
* controls have not yet been created.
|
||||||
|
*/
|
||||||
|
protected Text filterText;
|
||||||
|
/**
|
||||||
|
* The viewer for the filtered tree. This value should never be <code>null</code> after the widget creation methods are
|
||||||
|
* complete.
|
||||||
|
*/
|
||||||
|
protected LaunchBarListViewer listViewer;
|
||||||
|
|
||||||
|
protected ViewerFilter patternFilter;
|
||||||
|
/**
|
||||||
|
* The text to initially show in the filter text control.
|
||||||
|
*/
|
||||||
|
protected String initialText = ""; //$NON-NLS-1$
|
||||||
|
protected String patternText = null;
|
||||||
|
/**
|
||||||
|
* The job used to refresh the tree.
|
||||||
|
*/
|
||||||
|
private Job refreshJob;
|
||||||
|
/**
|
||||||
|
* The parent composite this control.
|
||||||
|
*/
|
||||||
|
protected Composite parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a filter control, to be fully function attachListViewer must be called shortly after
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
*/
|
||||||
|
public FilterControl(Composite parent) {
|
||||||
|
super(parent, SWT.NONE);
|
||||||
|
this.parent = parent;
|
||||||
|
patternFilter = new ViewerFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean select(Viewer viewer, Object parentElement, Object element) {
|
||||||
|
String text = ((ILabelProvider) listViewer.getLabelProvider()).getText(element);
|
||||||
|
if (patternText == null)
|
||||||
|
return true;
|
||||||
|
String trim = patternText.trim();
|
||||||
|
if (trim.isEmpty())
|
||||||
|
return true;
|
||||||
|
if (text == null)
|
||||||
|
return false;
|
||||||
|
if (text.contains(trim))
|
||||||
|
return true;
|
||||||
|
if (text.toLowerCase().contains(trim.toLowerCase()))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the filtered list.
|
||||||
|
*/
|
||||||
|
protected void init() {
|
||||||
|
createControl(this, SWT.NONE);
|
||||||
|
createRefreshJob();
|
||||||
|
setInitialText(WorkbenchMessages.FilteredTree_FilterMessage);
|
||||||
|
setFont(parent.getFont());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the filtered tree's controls. Subclasses should override.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* @param treeStyle
|
||||||
|
*/
|
||||||
|
protected void createControl(Composite parent, int treeStyle) {
|
||||||
|
setLayout(GridLayoutFactory.fillDefaults().spacing(0, 0).create());
|
||||||
|
if (parent.getLayout() instanceof GridLayout) {
|
||||||
|
setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
|
||||||
|
}
|
||||||
|
Composite fc = createFilterControls(parent);
|
||||||
|
fc.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the filter controls. By default, a text and corresponding tool bar button that clears the contents of the text is
|
||||||
|
* created. Subclasses may override.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* parent <code>Composite</code> of the filter controls
|
||||||
|
* @return the <code>Composite</code> that contains the filter controls
|
||||||
|
*/
|
||||||
|
protected Composite createFilterControls(Composite parent) {
|
||||||
|
createFilterText(parent);
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Control attachListViewer(LaunchBarListViewer listViewer) {
|
||||||
|
this.listViewer = listViewer;
|
||||||
|
// listViewer.getControl().setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
|
||||||
|
listViewer.getControl().addDisposeListener(new DisposeListener() {
|
||||||
|
@Override
|
||||||
|
public void widgetDisposed(DisposeEvent e) {
|
||||||
|
refreshJob.cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
listViewer.addFilter(patternFilter);
|
||||||
|
return listViewer.getControl();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the refresh job for the receiver.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void createRefreshJob() {
|
||||||
|
refreshJob = doCreateRefreshJob();
|
||||||
|
refreshJob.setSystem(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisible(boolean visible) {
|
||||||
|
boolean oldVisible = getVisible();
|
||||||
|
if (oldVisible == true && visible == false && listViewer != null && filterText.isFocusControl()) {
|
||||||
|
listViewer.setFocus();
|
||||||
|
}
|
||||||
|
if (getLayoutData() instanceof GridData) {
|
||||||
|
((GridData) getLayoutData()).heightHint = visible ? SWT.DEFAULT : 0;
|
||||||
|
}
|
||||||
|
super.setVisible(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a workbench job that will refresh the tree based on the current filter text. Subclasses may override.
|
||||||
|
*
|
||||||
|
* @return a workbench job that can be scheduled to refresh the tree
|
||||||
|
*
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
protected WorkbenchJob doCreateRefreshJob() {
|
||||||
|
return new WorkbenchJob("Refresh Filter") {//$NON-NLS-1$
|
||||||
|
@Override
|
||||||
|
public IStatus runInUIThread(IProgressMonitor monitor) {
|
||||||
|
if (listViewer == null)
|
||||||
|
return Status.CANCEL_STATUS;
|
||||||
|
if (listViewer.getControl().isDisposed()) {
|
||||||
|
return Status.CANCEL_STATUS;
|
||||||
|
}
|
||||||
|
updatePatternText();
|
||||||
|
if (patternText == null) {
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
Control redrawControl = listViewer.getControl();
|
||||||
|
try {
|
||||||
|
// don't want the user to see updates that will be made to
|
||||||
|
// the tree
|
||||||
|
// we are setting redraw(false) on the composite to avoid
|
||||||
|
// dancing scrollbar
|
||||||
|
redrawControl.setRedraw(false);
|
||||||
|
listViewer.setHistorySupported(patternText == null || patternText.isEmpty());
|
||||||
|
listViewer.refresh(true);
|
||||||
|
updateListSelection(false);
|
||||||
|
} finally {
|
||||||
|
redrawControl.setRedraw(true);
|
||||||
|
}
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the filter text and adds listeners. This method calls {@link #doCreateFilterText(Composite)} to create the text
|
||||||
|
* control. Subclasses should override {@link #doCreateFilterText(Composite)} instead of overriding this method.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* <code>Composite</code> of the filter text
|
||||||
|
*/
|
||||||
|
protected void createFilterText(Composite parent) {
|
||||||
|
filterText = doCreateFilterText(parent);
|
||||||
|
filterText.getAccessible().addAccessibleListener(
|
||||||
|
new AccessibleAdapter() {
|
||||||
|
@Override
|
||||||
|
public void getName(AccessibleEvent e) {
|
||||||
|
String filterTextString = filterText.getText();
|
||||||
|
if (filterTextString.length() == 0
|
||||||
|
|| filterTextString.equals(initialText)) {
|
||||||
|
e.result = initialText;
|
||||||
|
} else {
|
||||||
|
e.result = NLS.bind(
|
||||||
|
WorkbenchMessages.FilteredTree_AccessibleListenerFiltered,
|
||||||
|
new String[] {
|
||||||
|
filterTextString,
|
||||||
|
String.valueOf(getFilteredItemsCount()) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of filtered items
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private int getFilteredItemsCount() {
|
||||||
|
return listViewer.getItemCount();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
filterText.addFocusListener(new FocusAdapter() {
|
||||||
|
@Override
|
||||||
|
public void focusGained(FocusEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusLost(FocusEvent e) {
|
||||||
|
if (filterText.getText().equals(initialText)) {
|
||||||
|
setFilterText(""); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
filterText.addMouseListener(new MouseAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseDown(MouseEvent e) {
|
||||||
|
if (filterText.getText().equals(initialText)) {
|
||||||
|
clearText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// enter key set focus to tree
|
||||||
|
filterText.addTraverseListener(new TraverseListener() {
|
||||||
|
@Override
|
||||||
|
public void keyTraversed(TraverseEvent e) {
|
||||||
|
if (e.detail == SWT.TRAVERSE_RETURN) {
|
||||||
|
e.doit = false;
|
||||||
|
listViewer.setFocus();
|
||||||
|
updateListSelection(true);
|
||||||
|
} else if (e.detail == SWT.TRAVERSE_ARROW_NEXT) {
|
||||||
|
listViewer.setFocus();
|
||||||
|
updateListSelection(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
filterText.addModifyListener(new ModifyListener() {
|
||||||
|
@Override
|
||||||
|
public void modifyText(ModifyEvent e) {
|
||||||
|
textChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// if we're using a field with built in cancel we need to listen for
|
||||||
|
// default selection changes (which tell us the cancel button has been
|
||||||
|
// pressed)
|
||||||
|
if ((filterText.getStyle() & SWT.ICON_CANCEL) != 0) {
|
||||||
|
filterText.addSelectionListener(new SelectionAdapter() {
|
||||||
|
@Override
|
||||||
|
public void widgetDefaultSelected(SelectionEvent e) {
|
||||||
|
if (e.detail == SWT.ICON_CANCEL)
|
||||||
|
clearText();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
filterText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateListSelection(boolean enter) {
|
||||||
|
if (listViewer.getItemCount() == 0) {
|
||||||
|
if (enter)
|
||||||
|
Display.getCurrent().beep();
|
||||||
|
} else {
|
||||||
|
StructuredSelection sel;
|
||||||
|
// if the initial filter text hasn't changed, do not try to match
|
||||||
|
if (patternText != null && !patternText.trim().isEmpty()) {
|
||||||
|
// select item with triggering event, it may close the popup if list used as combo
|
||||||
|
sel = new StructuredSelection(listViewer.getTopFilteredElement());
|
||||||
|
} else {
|
||||||
|
sel = new StructuredSelection(listViewer.getTopElement());
|
||||||
|
}
|
||||||
|
if (enter)
|
||||||
|
listViewer.setDefaultSelection(sel);
|
||||||
|
else
|
||||||
|
listViewer.setSelection(sel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Text doCreateFilterText(Composite parent) {
|
||||||
|
return new Text(parent, SWT.SINGLE | SWT.BORDER | SWT.SEARCH
|
||||||
|
| SWT.ICON_CANCEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the receiver after the text has changed.
|
||||||
|
*/
|
||||||
|
protected void textChanged() {
|
||||||
|
String old = patternText;
|
||||||
|
updatePatternText();
|
||||||
|
if (patternText != null && old == null && patternText.isEmpty())
|
||||||
|
return;// we changing from initial selection to empty string
|
||||||
|
if (patternText == old)
|
||||||
|
return;
|
||||||
|
// cancel currently running job first, to prevent unnecessary redraw
|
||||||
|
refreshJob.cancel();
|
||||||
|
refreshJob.schedule(getRefreshJobDelay());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the time delay that should be used when scheduling the filter refresh job. Subclasses may override.
|
||||||
|
*
|
||||||
|
* @return a time delay in milliseconds before the job should run
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected long getRefreshJobDelay() {
|
||||||
|
return 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the background for the widgets that support the filter text area.
|
||||||
|
*
|
||||||
|
* @param background
|
||||||
|
* background <code>Color</code> to set
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setBackground(Color background) {
|
||||||
|
super.setBackground(background);
|
||||||
|
// listComposite.setBackground(background);
|
||||||
|
// filterText.setBackground(background);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the text in the filter text widget.
|
||||||
|
*/
|
||||||
|
protected void clearText() {
|
||||||
|
setFilterText(""); //$NON-NLS-1$
|
||||||
|
// textChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the text in the filter control.
|
||||||
|
*
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
protected void setFilterText(String string) {
|
||||||
|
if (filterText != null) {
|
||||||
|
filterText.setText(string);
|
||||||
|
selectAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Text getFilterText() {
|
||||||
|
return filterText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the tree viewer of the receiver.
|
||||||
|
*
|
||||||
|
* @return the tree viewer
|
||||||
|
*/
|
||||||
|
public LaunchBarListViewer getViewer() {
|
||||||
|
return listViewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the filter text for the receiver, if it was created. Otherwise return <code>null</code>.
|
||||||
|
*
|
||||||
|
* @return the filter Text, or null if it was not created
|
||||||
|
*/
|
||||||
|
public Text getFilterControl() {
|
||||||
|
return filterText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method to return the text of the filter control. If the text widget is not created, then null is returned.
|
||||||
|
*
|
||||||
|
* @return String in the text, or null if the text does not exist
|
||||||
|
*/
|
||||||
|
protected String getFilterString() {
|
||||||
|
return filterText != null ? filterText.getText() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the text that will be shown until the first focus. A default value is provided, so this method only need be called if
|
||||||
|
* overriding the default initial text is desired.
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
* initial text to appear in text field
|
||||||
|
*/
|
||||||
|
public void setInitialText(String text) {
|
||||||
|
initialText = text;
|
||||||
|
if (filterText != null) {
|
||||||
|
filterText.setMessage(text);
|
||||||
|
if (filterText.isFocusControl()) {
|
||||||
|
setFilterText(initialText);
|
||||||
|
textChanged();
|
||||||
|
} else {
|
||||||
|
getDisplay().asyncExec(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (!filterText.isDisposed() && filterText.isFocusControl()) {
|
||||||
|
setFilterText(initialText);
|
||||||
|
textChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setFilterText(initialText);
|
||||||
|
textChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select all text in the filter text field.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected void selectAll() {
|
||||||
|
if (filterText != null) {
|
||||||
|
filterText.selectAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the initial text for the receiver.
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
protected String getInitialText() {
|
||||||
|
return initialText;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePatternText() {
|
||||||
|
String text = getFilterString();
|
||||||
|
boolean initial = initialText != null
|
||||||
|
&& initialText.equals(text);
|
||||||
|
if (initial) {
|
||||||
|
patternText = null;
|
||||||
|
} else if (text != null) {
|
||||||
|
patternText = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,711 @@
|
||||||
|
package org.eclipse.launchbar.ui.internal.controls;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jface.layout.GridDataFactory;
|
||||||
|
import org.eclipse.jface.layout.GridLayoutFactory;
|
||||||
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
|
import org.eclipse.jface.viewers.ArrayContentProvider;
|
||||||
|
import org.eclipse.jface.viewers.ICellModifier;
|
||||||
|
import org.eclipse.jface.viewers.IFontProvider;
|
||||||
|
import org.eclipse.jface.viewers.ILabelProvider;
|
||||||
|
import org.eclipse.jface.viewers.IStructuredContentProvider;
|
||||||
|
import org.eclipse.jface.viewers.LabelProvider;
|
||||||
|
import org.eclipse.jface.viewers.StructuredSelection;
|
||||||
|
import org.eclipse.jface.viewers.StructuredViewer;
|
||||||
|
import org.eclipse.jface.viewers.Viewer;
|
||||||
|
import org.eclipse.jface.viewers.ViewerComparator;
|
||||||
|
import org.eclipse.jface.viewers.ViewerFilter;
|
||||||
|
import org.eclipse.launchbar.core.ILaunchDescriptor;
|
||||||
|
import org.eclipse.launchbar.ui.internal.Activator;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.custom.ScrolledComposite;
|
||||||
|
import org.eclipse.swt.events.DisposeEvent;
|
||||||
|
import org.eclipse.swt.events.DisposeListener;
|
||||||
|
import org.eclipse.swt.events.KeyEvent;
|
||||||
|
import org.eclipse.swt.events.KeyListener;
|
||||||
|
import org.eclipse.swt.events.MouseAdapter;
|
||||||
|
import org.eclipse.swt.events.MouseEvent;
|
||||||
|
import org.eclipse.swt.events.MouseListener;
|
||||||
|
import org.eclipse.swt.events.MouseTrackAdapter;
|
||||||
|
import org.eclipse.swt.events.MouseTrackListener;
|
||||||
|
import org.eclipse.swt.events.PaintEvent;
|
||||||
|
import org.eclipse.swt.events.PaintListener;
|
||||||
|
import org.eclipse.swt.events.SelectionAdapter;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.events.TraverseEvent;
|
||||||
|
import org.eclipse.swt.events.TraverseListener;
|
||||||
|
import org.eclipse.swt.graphics.Color;
|
||||||
|
import org.eclipse.swt.graphics.GC;
|
||||||
|
import org.eclipse.swt.graphics.Image;
|
||||||
|
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.layout.RowLayout;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.Event;
|
||||||
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
import org.eclipse.swt.widgets.Listener;
|
||||||
|
import org.eclipse.swt.widgets.Sash;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.eclipse.swt.widgets.Widget;
|
||||||
|
|
||||||
|
public class LaunchBarListViewer extends StructuredViewer {
|
||||||
|
private ScrolledComposite listScrolled;
|
||||||
|
private Composite listComposite;
|
||||||
|
private ListItem[] listItems;
|
||||||
|
private int selIndex;
|
||||||
|
private int itemH = 30;
|
||||||
|
private int scrollBucket;
|
||||||
|
private final int maxScrollBucket = 6;
|
||||||
|
private int separatorIndex = -1;
|
||||||
|
private boolean historySupported = true;
|
||||||
|
private ICellModifier modifier;
|
||||||
|
private ViewerComparator historyComparator;
|
||||||
|
private boolean finalSelection = false;
|
||||||
|
private FilterControl filterControl;
|
||||||
|
private Sash sash;
|
||||||
|
private String historyPref;
|
||||||
|
|
||||||
|
private static class LaunchBarListViewerComparator extends ViewerComparator {
|
||||||
|
public LaunchBarListViewerComparator(Comparator<?> comp) {
|
||||||
|
super(comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// have to override it because standard ViewerComparator compares by labels only
|
||||||
|
@Override
|
||||||
|
public int compare(Viewer viewer, Object e1, Object e2) {
|
||||||
|
return getComparator().compare(e1, e2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private TraverseListener listItemTraverseListener = new TraverseListener() {
|
||||||
|
@Override
|
||||||
|
public void keyTraversed(TraverseEvent e) {
|
||||||
|
final ListItem currItem = selIndex >= 0 ? listItems[selIndex] : null;
|
||||||
|
if (currItem == null && e.keyCode != SWT.ARROW_DOWN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.detail == SWT.TRAVERSE_ARROW_NEXT || e.detail == SWT.TRAVERSE_TAB_NEXT) {
|
||||||
|
if (e.keyCode == SWT.ARROW_DOWN) {
|
||||||
|
int maxIdx = listItems.length - 1;
|
||||||
|
if (selIndex < maxIdx) {
|
||||||
|
// move to next item
|
||||||
|
listItems[selIndex + 1].setSelected(true);
|
||||||
|
if (scrollBucket < maxScrollBucket) {
|
||||||
|
scrollBucket++;
|
||||||
|
} else {
|
||||||
|
// need to scroll the list up 1 item
|
||||||
|
int sY = listScrolled.getOrigin().y;
|
||||||
|
listScrolled.setOrigin(0, sY + itemH);
|
||||||
|
}
|
||||||
|
} else if (selIndex == maxIdx && maxIdx > maxScrollBucket) {
|
||||||
|
// level the scroll for any offset at the bottom of the list
|
||||||
|
listScrolled.setOrigin(0, itemH * (maxIdx - maxScrollBucket + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (e.detail == SWT.TRAVERSE_ARROW_PREVIOUS || e.detail == SWT.TRAVERSE_TAB_PREVIOUS) {
|
||||||
|
if (e.keyCode == SWT.ARROW_UP) {
|
||||||
|
if (selIndex > 0) {
|
||||||
|
// move to previous item
|
||||||
|
if (scrollBucket > 0) {
|
||||||
|
scrollBucket--;
|
||||||
|
} else {
|
||||||
|
// need to scroll the list down 1 item
|
||||||
|
int sY = listScrolled.getOrigin().y;
|
||||||
|
listScrolled.setOrigin(0, sY - itemH);
|
||||||
|
}
|
||||||
|
listItems[selIndex - 1].setSelected(true);
|
||||||
|
} else if (selIndex == 0) {
|
||||||
|
// level any offset @ beginning
|
||||||
|
listScrolled.setOrigin(0, 0);
|
||||||
|
}
|
||||||
|
} else if (currItem.editButton != null) {
|
||||||
|
// remove focus from edit button
|
||||||
|
currItem.editButton.setSelected(false);
|
||||||
|
currItem.editButton.redraw();
|
||||||
|
}
|
||||||
|
} else if (e.detail == SWT.TRAVERSE_RETURN) {
|
||||||
|
setDefaultSelection(new StructuredSelection(currItem.element));
|
||||||
|
} else if (e.detail == SWT.TRAVERSE_ESCAPE) {
|
||||||
|
setDefaultSelection(new StructuredSelection());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private class ListItem extends Composite {
|
||||||
|
protected final Object element;
|
||||||
|
private Label icon;
|
||||||
|
private Label label;
|
||||||
|
protected EditButton editButton;
|
||||||
|
private int index;
|
||||||
|
private Color backgroundColor = getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
|
||||||
|
private Color outlineColor = getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
|
||||||
|
private Color highlightColor = getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
|
||||||
|
private ILabelProvider labelProvider;
|
||||||
|
private ICellModifier modifer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[" + index + "] " + labelProvider.getText(element);
|
||||||
|
}
|
||||||
|
public ListItem(Composite parent, int style, Object element, int index, ILabelProvider labelProvider,
|
||||||
|
ICellModifier modifier) {
|
||||||
|
super(parent, style);
|
||||||
|
this.element = element;
|
||||||
|
this.index = index;
|
||||||
|
this.labelProvider = labelProvider;
|
||||||
|
this.modifer = modifier;
|
||||||
|
setData(element);
|
||||||
|
addPaintListener(new PaintListener() {
|
||||||
|
@Override
|
||||||
|
public void paintControl(PaintEvent e) {
|
||||||
|
Point size = getSize();
|
||||||
|
GC gc = e.gc;
|
||||||
|
gc.setForeground(outlineColor);
|
||||||
|
gc.drawLine(0, size.y - 1, size.x, size.y - 1);
|
||||||
|
if (label == null)
|
||||||
|
lazyInit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// lazyInit();
|
||||||
|
} // end ListItem(..)
|
||||||
|
|
||||||
|
protected void lazyInit() {
|
||||||
|
Image image = labelProvider.getImage(element);
|
||||||
|
boolean editable = isEditable(element);
|
||||||
|
int columns = 1;
|
||||||
|
if (image != null)
|
||||||
|
columns++;
|
||||||
|
if (editable)
|
||||||
|
columns++;
|
||||||
|
GridLayout layout = new GridLayout(columns, false);
|
||||||
|
layout.marginWidth = layout.marginHeight = 7;
|
||||||
|
setLayout(layout);
|
||||||
|
MouseListener listItemMouseListener = new MouseAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseUp(MouseEvent e) {
|
||||||
|
setDefaultSelection(new StructuredSelection(element));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MouseTrackListener listItemMouseTrackListener = new MouseTrackAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseEnter(MouseEvent e) {
|
||||||
|
setSelected(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseExit(MouseEvent e) {
|
||||||
|
setSelected(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addMouseListener(listItemMouseListener);
|
||||||
|
addMouseTrackListener(listItemMouseTrackListener);
|
||||||
|
if (image != null) {
|
||||||
|
icon = createImage(this, image);
|
||||||
|
icon.addMouseListener(listItemMouseListener);
|
||||||
|
icon.addMouseTrackListener(listItemMouseTrackListener);
|
||||||
|
}
|
||||||
|
label = createLabel(this, element);
|
||||||
|
label.addMouseListener(listItemMouseListener);
|
||||||
|
label.addMouseTrackListener(listItemMouseTrackListener);
|
||||||
|
if (editable) {
|
||||||
|
editButton = new EditButton(this, SWT.NONE);
|
||||||
|
editButton.addSelectionListener(new SelectionAdapter() {
|
||||||
|
@Override
|
||||||
|
public void widgetSelected(SelectionEvent e) {
|
||||||
|
// Need to run this after the current event storm
|
||||||
|
// Or we get a disposed error.
|
||||||
|
getDisplay().asyncExec(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (editButton.isSelected())
|
||||||
|
handleEdit(element);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editButton.setBackground(backgroundColor);
|
||||||
|
editButton.addMouseTrackListener(listItemMouseTrackListener);
|
||||||
|
editButton.addTraverseListener(listItemTraverseListener);
|
||||||
|
} else {
|
||||||
|
// add traverse listnener to control which will have keyboard focus
|
||||||
|
addTraverseListener(listItemTraverseListener);
|
||||||
|
}
|
||||||
|
addKeyListener(new KeyListener() {
|
||||||
|
@Override
|
||||||
|
public void keyReleased(KeyEvent e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
if (e.character != 0 && !filterControl.isVisible()) {
|
||||||
|
// enable filter control and send the character there
|
||||||
|
filterControl.setVisible(true);
|
||||||
|
filterControl.setFocus();
|
||||||
|
filterControl.getParent().layout(true);
|
||||||
|
filterControl.getFilterText().setText(e.character + "");
|
||||||
|
filterControl.getFilterText().setSelection(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setBackground(backgroundColor);
|
||||||
|
layout(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelected(boolean selected) {
|
||||||
|
if (selected) {
|
||||||
|
setBackground(highlightColor);
|
||||||
|
int idx = getIndex();
|
||||||
|
if (idx != selIndex) {
|
||||||
|
if (selIndex >= 0) {
|
||||||
|
listItems[selIndex].setBackground(backgroundColor);
|
||||||
|
scrollBucket = Math.max(Math.min(scrollBucket + idx - selIndex, maxScrollBucket), 0);
|
||||||
|
} else { // initially
|
||||||
|
scrollBucket = Math.min(idx, maxScrollBucket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selIndex = idx;
|
||||||
|
} else {
|
||||||
|
setBackground(backgroundColor);
|
||||||
|
}
|
||||||
|
if (editButton != null) {
|
||||||
|
editButton.setSelected(selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isEditable(Object element) {
|
||||||
|
if (modifer != null) {
|
||||||
|
return modifer.canModify(element, null);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleEdit(Object element) {
|
||||||
|
if (modifer != null) {
|
||||||
|
modifer.modify(element, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBackground(Color color) {
|
||||||
|
super.setBackground(color);
|
||||||
|
if (icon != null && !icon.isDisposed())
|
||||||
|
icon.setBackground(color);
|
||||||
|
if (label != null && !label.isDisposed())
|
||||||
|
label.setBackground(color);
|
||||||
|
if (editButton != null && !editButton.isDisposed())
|
||||||
|
editButton.setBackground(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImage(Image image) {
|
||||||
|
if (icon != null && !icon.isDisposed())
|
||||||
|
icon.setImage(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(String text) {
|
||||||
|
if (!label.isDisposed())
|
||||||
|
label.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setFocus() {
|
||||||
|
super.setFocus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getIndex() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Label createImage(Composite parent, Image image) {
|
||||||
|
Rectangle bounds = image.getBounds();
|
||||||
|
boolean disposeImage = false;
|
||||||
|
if (bounds.height > 16 || bounds.width > 16) {
|
||||||
|
Image buttonImage = new Image(getDisplay(), 16, 16);
|
||||||
|
GC gc = new GC(buttonImage);
|
||||||
|
gc.setAntialias(SWT.ON);
|
||||||
|
gc.setInterpolation(SWT.HIGH);
|
||||||
|
// resize to 16 pixels
|
||||||
|
gc.drawImage(image, 0, 0, image.getBounds().width,
|
||||||
|
image.getBounds().height, 0, 0, 16, 16);
|
||||||
|
gc.dispose();
|
||||||
|
image = buttonImage;
|
||||||
|
disposeImage = true;
|
||||||
|
}
|
||||||
|
Label icon = new Label(parent, SWT.NONE);
|
||||||
|
icon.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, true));
|
||||||
|
icon.setImage(image);
|
||||||
|
if (disposeImage) {
|
||||||
|
final Image disposableImage = image;
|
||||||
|
icon.addDisposeListener(new DisposeListener() {
|
||||||
|
@Override
|
||||||
|
public void widgetDisposed(DisposeEvent e) {
|
||||||
|
disposableImage.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Label createLabel(Composite parent, Object element) {
|
||||||
|
Label label = new Label(parent, SWT.NONE);
|
||||||
|
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
|
||||||
|
ILabelProvider labelProvider = (ILabelProvider) getLabelProvider();
|
||||||
|
label.setText(labelProvider.getText(element));
|
||||||
|
if (labelProvider instanceof IFontProvider) {
|
||||||
|
label.setFont(((IFontProvider) labelProvider).getFont(element));
|
||||||
|
}
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
} // end ListItem class
|
||||||
|
|
||||||
|
public LaunchBarListViewer(Composite parent) {
|
||||||
|
filterControl = new FilterControl(parent);
|
||||||
|
listScrolled = new ScrolledComposite(parent, SWT.V_SCROLL | SWT.NO_BACKGROUND);
|
||||||
|
listScrolled.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||||
|
listScrolled.setExpandHorizontal(true);
|
||||||
|
listComposite = new Composite(listScrolled, SWT.NONE);
|
||||||
|
listScrolled.setContent(listComposite);
|
||||||
|
listComposite.setLayout(GridLayoutFactory.fillDefaults().spacing(0, 0).create());
|
||||||
|
selIndex = -1;
|
||||||
|
scrollBucket = 0;
|
||||||
|
filterControl.attachListViewer(this);
|
||||||
|
historySupported = false;
|
||||||
|
setHistoryPreferenceName(getHistoryPreferenceName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSash(final Composite listComp) {
|
||||||
|
if (separatorIndex < 0 || !historySupported)
|
||||||
|
return;
|
||||||
|
sash = new Sash(listComp, SWT.BORDER | SWT.HORIZONTAL);
|
||||||
|
sash.setLayoutData(GridDataFactory.fillDefaults().create());
|
||||||
|
if (separatorIndex < listItems.length)
|
||||||
|
sash.moveAbove(listItems[separatorIndex]);
|
||||||
|
else
|
||||||
|
sash.moveBelow(null);
|
||||||
|
sash.addListener(SWT.Selection, new Listener() {
|
||||||
|
@Override
|
||||||
|
public void handleEvent(Event e) {
|
||||||
|
separatorIndex = (e.y + itemH / 2) / itemH;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sash.addMouseListener(new MouseListener() {
|
||||||
|
@Override
|
||||||
|
public void mouseUp(MouseEvent e) {
|
||||||
|
setSeparatorIndex(separatorIndex); // call setter if it was overriden
|
||||||
|
if (separatorIndex >= 0) {
|
||||||
|
if (separatorIndex < listItems.length)
|
||||||
|
sash.moveAbove(listItems[separatorIndex]);
|
||||||
|
else
|
||||||
|
sash.moveBelow(null);
|
||||||
|
listComp.layout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDown(MouseEvent e) {
|
||||||
|
sash.moveAbove(null); // keep on top so user see it when moving
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDoubleClick(MouseEvent e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sash.setToolTipText("Increase/Decrease size of recently used elements pane");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Control getControl() {
|
||||||
|
return listScrolled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void inputChanged(Object input, Object oldInput) {
|
||||||
|
super.inputChanged(input, oldInput);
|
||||||
|
refreshAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void refreshAll() {
|
||||||
|
selIndex = -1;
|
||||||
|
Control[] children = listComposite.getChildren();
|
||||||
|
for (Control control : children) {
|
||||||
|
control.dispose();
|
||||||
|
}
|
||||||
|
Object[] origElements = getElements();
|
||||||
|
Object[] elements = filterElements(origElements);
|
||||||
|
listItems = new ListItem[elements.length];
|
||||||
|
if (elements.length > 0) {
|
||||||
|
listItems[0] = createListItem(elements, 0);
|
||||||
|
itemH = Math.max(listItems[0].computeSize(SWT.DEFAULT, SWT.DEFAULT).y, 16);
|
||||||
|
for (int i = 1; i < elements.length; ++i) {
|
||||||
|
listItems[i] = createListItem(elements, i);
|
||||||
|
}
|
||||||
|
createSash(listComposite);
|
||||||
|
}
|
||||||
|
listComposite.pack(true);
|
||||||
|
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||||
|
if (elements.length > maxScrollBucket) {
|
||||||
|
Rectangle bounds = listItems[maxScrollBucket].getBounds();
|
||||||
|
gd.heightHint = Math.max(bounds.y + bounds.height, itemH * (maxScrollBucket + 1));
|
||||||
|
}
|
||||||
|
listScrolled.setLayoutData(gd);
|
||||||
|
listScrolled.layout(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ListItem createListItem(Object[] elements, int i) {
|
||||||
|
ListItem item = new ListItem(listComposite, SWT.NONE, elements[i], i, (ILabelProvider) getLabelProvider(), modifier);
|
||||||
|
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
|
||||||
|
item.setLayoutData(gd);
|
||||||
|
if (i <= maxScrollBucket) { // this is how many visible by default
|
||||||
|
item.lazyInit();
|
||||||
|
} else {
|
||||||
|
gd.heightHint = itemH;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Widget doFindInputItem(Object element) {
|
||||||
|
return doFindItem(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Widget doFindItem(Object element) {
|
||||||
|
if (listItems == null)
|
||||||
|
return null;
|
||||||
|
for (ListItem listItem : listItems) {
|
||||||
|
if (listItem.element.equals(element))
|
||||||
|
return listItem;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doUpdateItem(Widget item, Object element, boolean fullMap) {
|
||||||
|
if (item instanceof ListItem) {
|
||||||
|
((ListItem) item).lazyInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List getSelectionFromWidget() {
|
||||||
|
ArrayList<Object> arrayList = new ArrayList<>();
|
||||||
|
if (selIndex >= 0)
|
||||||
|
arrayList.add(listItems[selIndex].element);
|
||||||
|
return arrayList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRefresh(Object element) {
|
||||||
|
if (element == null || element == getRoot()) {
|
||||||
|
refreshAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ListItem item = (ListItem) doFindItem(element);
|
||||||
|
ILabelProvider lp = (ILabelProvider) getLabelProvider();
|
||||||
|
if (lp == null || item == null)
|
||||||
|
return;
|
||||||
|
item.setImage(lp.getImage(element));
|
||||||
|
item.setText(lp.getText(element));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object[] filterElements(Object[] elements) {
|
||||||
|
Object[] topElements = elements.clone();
|
||||||
|
if (getComparator() != null)
|
||||||
|
getComparator().sort(this, elements);
|
||||||
|
if (getTopComparator() != null)
|
||||||
|
getTopComparator().sort(this, topElements);
|
||||||
|
// only bottom part will be filtered
|
||||||
|
Object[] result = elements;
|
||||||
|
if (getFilters() != null) {
|
||||||
|
for (ViewerFilter f : getFilters()) {
|
||||||
|
result = f.filter(this, (Object) null, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (separatorIndex <= 0 || !historySupported)
|
||||||
|
return result;
|
||||||
|
if (separatorIndex >= topElements.length) {
|
||||||
|
return topElements; // all elements will fit in top elements
|
||||||
|
}
|
||||||
|
ILaunchDescriptor[] descsCopy = new ILaunchDescriptor[separatorIndex + result.length];
|
||||||
|
System.arraycopy(topElements, 0, descsCopy, 0, separatorIndex); // copy first N elements
|
||||||
|
System.arraycopy(result, 0, descsCopy, separatorIndex, result.length); // copy all into rest
|
||||||
|
return descsCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object[] getElements() {
|
||||||
|
IStructuredContentProvider cp = (IStructuredContentProvider) getContentProvider();
|
||||||
|
if (cp == null)
|
||||||
|
return new Object[0];
|
||||||
|
Object[] elements = cp.getElements(getInput());
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reveal(Object element) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultSelection(StructuredSelection selection) {
|
||||||
|
finalSelection = true;
|
||||||
|
setSelection(selection, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setSelectionToWidget(List l, boolean reveal) {
|
||||||
|
if (l.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Object sel = l.get(0);
|
||||||
|
Widget wid = doFindItem(sel);
|
||||||
|
if (wid instanceof ListItem) {
|
||||||
|
ListItem listItem = (ListItem) wid;
|
||||||
|
listItem.setSelected(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSeparatorIndex() {
|
||||||
|
return separatorIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSeparatorIndex(int separatorIndex) {
|
||||||
|
this.separatorIndex = separatorIndex;
|
||||||
|
if (separatorIndex <= 0)
|
||||||
|
return;
|
||||||
|
IPreferenceStore store = Activator.getDefault().getPreferenceStore();
|
||||||
|
String prefName = getHistoryPreferenceName();
|
||||||
|
if (prefName != null && store.getInt(prefName) != getSeparatorIndex()) {
|
||||||
|
store.setValue(prefName, getSeparatorIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getHistoryPreferenceName() {
|
||||||
|
return historyPref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCellModifier(ICellModifier modifier) {
|
||||||
|
this.modifier = modifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getItemCount() {
|
||||||
|
return listItems.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns top element (provider element) in the begging on non-history list
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Object getTopFilteredElement() {
|
||||||
|
if (listItems.length > 0) {
|
||||||
|
if (separatorIndex <= 0 || separatorIndex >= listItems.length || !historySupported)
|
||||||
|
return listItems[0].element;
|
||||||
|
else
|
||||||
|
return listItems[separatorIndex].element;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getTopElement() {
|
||||||
|
if (listItems.length > 0) {
|
||||||
|
return listItems[0].element;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewerComparator getTopComparator() {
|
||||||
|
return historyComparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewerComparator comparator labels of elements by default
|
||||||
|
*
|
||||||
|
* @param comp
|
||||||
|
*/
|
||||||
|
public void setHistoryComparator(ViewerComparator comp) {
|
||||||
|
historyComparator = comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHistoryComparator(Comparator<?> comp) {
|
||||||
|
historyComparator = comp == null ? null : new LaunchBarListViewerComparator(comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComparator(Comparator<?> comp) {
|
||||||
|
setComparator(comp == null ? null : new LaunchBarListViewerComparator(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHistorySupported() {
|
||||||
|
return historySupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHistorySupported(boolean historySupported) {
|
||||||
|
this.historySupported = historySupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHistoryPreferenceName(String historyPreferenceName) {
|
||||||
|
this.historyPref = historyPreferenceName;
|
||||||
|
if (historyPreferenceName != null) {
|
||||||
|
IPreferenceStore store = Activator.getDefault().getPreferenceStore();
|
||||||
|
int separator = store.getInt(historyPreferenceName);
|
||||||
|
if (separator <= 0)
|
||||||
|
separator = 1;
|
||||||
|
setSeparatorIndex(separator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* final selection will be set to true when user made a final selection in a list for example when double click on entry or
|
||||||
|
* pressed enter key
|
||||||
|
*/
|
||||||
|
public boolean isFinalSelection() {
|
||||||
|
return finalSelection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFinalSelection(boolean finalSelection) {
|
||||||
|
this.finalSelection = finalSelection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Display display = Display.getDefault();
|
||||||
|
Shell shell = new Shell();
|
||||||
|
RowLayout rowLayout = new RowLayout();
|
||||||
|
shell.setLayout(rowLayout);
|
||||||
|
(new Label(shell, SWT.NULL)).setText("Hello");
|
||||||
|
LaunchBarListViewer v = new LaunchBarListViewer(shell);
|
||||||
|
v.setContentProvider(new ArrayContentProvider());
|
||||||
|
v.setLabelProvider(new LabelProvider());
|
||||||
|
v.setInput(new String[] { "aaa", "bbb", "ccc" });
|
||||||
|
shell.pack();
|
||||||
|
shell.open();
|
||||||
|
// textUser.forceFocus();
|
||||||
|
// Set up the event loop.
|
||||||
|
while (!shell.isDisposed()) {
|
||||||
|
if (!display.readAndDispatch()) {
|
||||||
|
// If no more entries in event queue
|
||||||
|
display.sleep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
display.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFocus() {
|
||||||
|
if (selIndex >= 0 && listItems != null && listItems.length < selIndex)
|
||||||
|
listItems[selIndex].setFocus();
|
||||||
|
else
|
||||||
|
getControl().setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilterVisible(boolean vis) {
|
||||||
|
filterControl.setVisible(vis);
|
||||||
|
}
|
||||||
|
}
|
|
@ -184,7 +184,7 @@ public class TargetSelector extends CSelector {
|
||||||
GridLayout buttonLayout = new GridLayout();
|
GridLayout buttonLayout = new GridLayout();
|
||||||
buttonLayout.marginWidth = buttonLayout.marginHeight = 7;
|
buttonLayout.marginWidth = buttonLayout.marginHeight = 7;
|
||||||
createButton.setLayout(buttonLayout);
|
createButton.setLayout(buttonLayout);
|
||||||
createButton.setBackground(white);
|
createButton.setBackground(backgroundColor);
|
||||||
createButton.addPaintListener(new PaintListener() {
|
createButton.addPaintListener(new PaintListener() {
|
||||||
@Override
|
@Override
|
||||||
public void paintControl(PaintEvent e) {
|
public void paintControl(PaintEvent e) {
|
||||||
|
@ -198,7 +198,7 @@ public class TargetSelector extends CSelector {
|
||||||
final Label createLabel = new Label(createButton, SWT.None);
|
final Label createLabel = new Label(createButton, SWT.None);
|
||||||
createLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
createLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
||||||
createLabel.setText("Create New Target...");
|
createLabel.setText("Create New Target...");
|
||||||
createLabel.setBackground(white);
|
createLabel.setBackground(backgroundColor);
|
||||||
|
|
||||||
MouseListener mouseListener = new MouseAdapter() {
|
MouseListener mouseListener = new MouseAdapter() {
|
||||||
public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
|
public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue