blob: 8a557364571b13ff771185372b72858444660999 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.help.ui.internal;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.Accessible;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleControlAdapter;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TypedListener;
/**
*
* A canvas holding a hyperlink label. Need this to deal with focus selection.
*/
public class HyperlinkLabel extends Canvas {
Label label;
boolean hasFocus;
/**
* Constructor for Hyperlink.
*
* @param parent
* @param style
*/
public HyperlinkLabel(Composite parent, int style) {
super(parent, style);
GridLayout layout = new GridLayout();
layout.marginHeight = 3;
layout.marginWidth = 2;
layout.numColumns = 1;
this.setLayout(layout);
this.label = new Label(this, style);
addPaintListener(this::paint);
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.character == '\r') {
// Activation
notifyListeners(SWT.DefaultSelection);
}
}
});
addListener(SWT.Traverse, e -> {
switch (e.detail) {
// let arrows move focus
case SWT.TRAVERSE_ARROW_NEXT:
e.detail = SWT.TRAVERSE_TAB_NEXT;
break;
case SWT.TRAVERSE_ARROW_PREVIOUS:
e.detail = SWT.TRAVERSE_TAB_PREVIOUS;
break;
case SWT.TRAVERSE_PAGE_NEXT:
case SWT.TRAVERSE_PAGE_PREVIOUS:
case SWT.TRAVERSE_RETURN:
e.doit = false;
return;
}
e.doit = true;
});
addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
if (!hasFocus) {
hasFocus = true;
notifyListeners(SWT.Selection);
redraw();
}
}
@Override
public void focusLost(FocusEvent e) {
if (hasFocus) {
hasFocus = false;
notifyListeners(SWT.Selection);
redraw();
}
}
});
GridData data = new GridData();
data.horizontalAlignment = GridData.HORIZONTAL_ALIGN_BEGINNING;
data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING;
label.setLayoutData(data);
initAccessibleLink();
initAccessibleLabel();
}
public void setText(String text) {
label.setText(text);
}
public boolean getSelection() {
return hasFocus;
}
public Label getLabel() {
return label;
}
void notifyListeners(int eventType) {
Event event = new Event();
event.type = eventType;
event.widget = this;
notifyListeners(eventType, event);
}
protected void paint(PaintEvent e) {
if (hasFocus) {
GC gc = e.gc;
Point size = getSize();
gc.setForeground(getForeground());
gc.drawFocus(0, 0, size.x, size.y);
}
}
public void addSelectionListener(SelectionListener listener) {
checkWidget();
if (listener == null)
return;
TypedListener typedListener = new TypedListener(listener);
addListener(SWT.Selection, typedListener);
addListener(SWT.DefaultSelection, typedListener);
}
public void removeSelectionListener(SelectionListener listener) {
checkWidget();
if (listener == null)
return;
removeListener(SWT.Selection, listener);
removeListener(SWT.DefaultSelection, listener);
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
int innerWidth = wHint;
if (innerWidth != SWT.DEFAULT)
innerWidth -= 4;
Point textSize = label.computeSize(wHint, hHint, changed);//computeTextSize(innerWidth,
// hHint);
int textWidth = textSize.x + 4;
int textHeight = textSize.y + 6;
return new Point(textWidth, textHeight);
}
@Override
public void addMouseListener(MouseListener l) {
//super.addMouseListener(l);
label.addMouseListener(l);
}
@Override
public void addMouseTrackListener(MouseTrackListener l) {
//super.addMouseTrackListener(l);
label.addMouseTrackListener(l);
}
@Override
public void addPaintListener(PaintListener l) {
super.addPaintListener(l);
label.addPaintListener(l);
}
@Override
public void setBackground(Color c) {
super.setBackground(c);
label.setBackground(c);
}
@Override
public void setForeground(Color c) {
super.setForeground(c);
label.setForeground(c);
}
@Override
public void setCursor(Cursor c) {
super.setCursor(c);
label.setCursor(c);
}
private void initAccessibleLink() {
Accessible accessible = this.getAccessible();
accessible.addAccessibleListener(new AccessibleAdapter() {
@Override
public void getName(AccessibleEvent e) {
e.result = label.getText();
}
@Override
public void getHelp(AccessibleEvent e) {
e.result = label.getToolTipText();
}
});
accessible.addAccessibleControlListener(new AccessibleControlAdapter() {
@Override
public void getRole(AccessibleControlEvent e) {
e.detail = ACC.ROLE_LINK;
}
@Override
public void getState(AccessibleControlEvent e) {
if (hasFocus)
e.detail = ACC.STATE_FOCUSABLE | ACC.STATE_LINKED
| ACC.STATE_FOCUSED;
else
e.detail = ACC.STATE_FOCUSABLE | ACC.STATE_LINKED;
}
});
}
private void initAccessibleLabel() {
Accessible accessible = label.getAccessible();
accessible.addAccessibleControlListener(new AccessibleControlAdapter() {
@Override
public void getState(AccessibleControlEvent e) {
if (hasFocus)
e.detail = ACC.STATE_READONLY | ACC.STATE_FOCUSABLE
| ACC.STATE_SELECTABLE | ACC.STATE_LINKED
| ACC.STATE_FOCUSED;
else
e.detail = ACC.STATE_READONLY | ACC.STATE_FOCUSABLE
| ACC.STATE_SELECTABLE | ACC.STATE_LINKED;
}
});
}
}