blob: ef64c4e2b3035167df9b386389c0bcee385b3a39 [file] [log] [blame]
package org.eclipse.jdt.internal.ui.preferences;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
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.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
public final class PreferenceHighlight implements PaintListener {
private static final int HIGHLIGHT_FOCUS= SWT.COLOR_WIDGET_DARK_SHADOW;
private static final int HIGHLIGHT_MOUSE= SWT.COLOR_WIDGET_NORMAL_SHADOW;
private final Composite fParent;
private final Control fLabelControl;
private final Control fMainControl;
private boolean fHover;
private boolean fFocus;
private PreferenceHighlight(Composite parent, Control labelControl, Control mainControl) {
fParent= parent;
fLabelControl= labelControl;
fMainControl= mainControl;
}
@Override
public void paintControl(PaintEvent e) {
if ((!fHover && !fFocus) || !fMainControl.isEnabled() || ((GridData) fLabelControl.getLayoutData()).exclude)
return;
final int GAP= 7;
final int ARROW= 3;
Rectangle l= fLabelControl.getBounds();
Point c= fMainControl.getLocation();
e.gc.setForeground(e.display.getSystemColor(fFocus ? HIGHLIGHT_FOCUS : HIGHLIGHT_MOUSE));
int x2= c.x - GAP;
int y= l.y + l.height / 2 + 1;
e.gc.drawLine(l.x + l.width + GAP, y, x2, y);
e.gc.drawLine(x2 - ARROW, y - ARROW, x2, y);
e.gc.drawLine(x2 - ARROW, y + ARROW, x2, y);
}
/**
* Adds the highlight feature to a pair of controls, that is an arrow painted between the label
* and the main control for easier selection and to show when the control has focus. Both
* controls must have the same parent.
*
* @param labelControl the control acting as label
* @param mainControl the main control
* @param autoFocus if true, focus highlight will be switched automatically based on main
* controls focus state
* @return highlight handler
*/
public static PreferenceHighlight addHighlight(Control labelControl, Control mainControl, boolean autoFocus) {
final Composite parent= labelControl.getParent();
PreferenceHighlight highlight= new PreferenceHighlight(parent, labelControl, mainControl);
parent.addPaintListener(highlight);
if (autoFocus) {
mainControl.addFocusListener(new FocusListener() {
@Override
public void focusLost(FocusEvent e) {
highlight.setFocus(false);
}
@Override
public void focusGained(FocusEvent e) {
highlight.setFocus(true);
}
});
}
MouseTrackAdapter labelComboListener= new MouseTrackAdapter() {
@Override
public void mouseEnter(MouseEvent e) {
highlight.setHover(true);
}
@Override
public void mouseExit(MouseEvent e) {
highlight.setHover(false);
}
};
mainControl.addMouseTrackListener(labelComboListener);
labelControl.addMouseTrackListener(labelComboListener);
parent.addMouseMoveListener(e -> {
highlight.setHover(highlight.isAroundLabel(e));
});
parent.addMouseTrackListener(MouseTrackListener.mouseExitAdapter(e -> {
highlight.setHover(false);
}));
parent.addMouseListener(MouseListener.mouseDownAdapter(e -> {
if (highlight.isAroundLabel(e))
mainControl.setFocus();
}));
if (labelControl instanceof Label) {
labelControl.addMouseListener(MouseListener.mouseDownAdapter(e -> mainControl.setFocus()));
}
return highlight;
}
public void setFocus(boolean focus) {
if (fFocus != focus) {
fFocus= focus;
fParent.redraw();
}
}
public void setHover(boolean hover) {
if (fHover != hover) {
fHover= hover;
fParent.redraw();
}
}
private boolean isAroundLabel(MouseEvent e) {
int lx= fLabelControl.getLocation().x;
Rectangle c= fMainControl.getBounds();
int x= e.x;
int y= e.y;
return lx - 5 < x && x < c.x && c.y - 2 < y && y < c.y + c.height + 2;
}
}