📄 hyperlink.java
字号:
/*******************************************************************************
* Copyright (c) 2004 Stefan Zeiger and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.novocode.com/legal/epl-v10.html
*
* Contributors:
* Stefan Zeiger (szeiger@novocode.com) - initial API and implementation
* IBM Corporation - original SWT CLabel implementation on which this class is based
*******************************************************************************/
package com.novocode.naf.swt.custom;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.events.*;
/**
* A hyperlink text label.
* <p>
* This control displays a line of text (with an optional underline) which can
* be clicked to send a Selection event. Colors for the text and underline in
* their normal, mouse hover and active state can be set independently. The text
* can contain a mnemonic character for triggering the link via keyboard. Unless
* the control is created with the NO_FOCUS style, it accepts keyboard focus and
* can be triggered with RETURN and SPACE while focused.
* </p><p>
* Note: This control should not be resized beyond its minimum / preferred size.
* </p><p>
* <dl>
* <dt><b>Styles:</b>
* <dd>NO_FOCUS</dd>
* <dt><b>Events:</b>
* <dd>Selection</dd>
* </dl>
* </p>
*
* @author Stefan Zeiger (szeiger@novocode.com)
* @since Mar 2, 2004
* @version $Id: Hyperlink.java,v 1.6 2005/06/04 19:21:45 szeiger Exp $
*/
public final class Hyperlink extends Canvas
{
private String text = "";
private Cursor handCursor, arrowCursor;
private Color normalForeground, activeForeground, hoverForeground;
private Color normalUnderline, activeUndeline, hoverUnderline;
private boolean isActive;
private boolean cursorInControl;
private Rectangle cachedClientArea;
private Listener shellListener;
private Shell shell;
private int mnemonic = -1;
/**
* Constructs a new instance of this class given its parent
* and a style value describing its behavior and appearance.
* <p>
* The style value is either one of the style constants defined in
* class <code>SWT</code> which is applicable to instances of this
* class, or must be built by <em>bitwise OR</em>'ing together
* (that is, using the <code>int</code> "|" operator) two or more
* of those <code>SWT</code> style constants. The class description
* lists the style constants that are applicable to the class.
* Style bits are also inherited from superclasses.
* </p>
*
* @param parent a widget which will be the parent of the new instance (cannot be null)
* @param style the style of widget to construct
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
* </ul>
*/
public Hyperlink(Composite parent, int style)
{
super(parent, checkStyle(style));
handCursor = new Cursor(getDisplay(), SWT.CURSOR_HAND);
arrowCursor = new Cursor(getDisplay(), SWT.CURSOR_ARROW);
setCursor(handCursor);
normalForeground = getDisplay().getSystemColor(SWT.COLOR_BLUE);
hoverForeground = normalForeground;
activeForeground = getDisplay().getSystemColor(SWT.COLOR_RED);
normalUnderline = null;
hoverUnderline = normalForeground;
activeUndeline = activeForeground;
super.setForeground(normalForeground);
addPaintListener(new PaintListener()
{
public void paintControl(PaintEvent event)
{
onPaint(event);
}
});
addDisposeListener(new DisposeListener()
{
public void widgetDisposed(DisposeEvent e)
{
if(handCursor != null)
{
handCursor.dispose();
handCursor = null;
}
if(arrowCursor != null)
{
arrowCursor.dispose();
arrowCursor = null;
}
if(shellListener != null)
{
shell.removeListener(SWT.Activate, shellListener);
shell.removeListener(SWT.Deactivate, shellListener);
shellListener = null;
}
text = null;
}
});
addListener(SWT.MouseDown, new Listener()
{
public void handleEvent(Event event)
{
isActive = true;
cursorInControl = true;
redraw();
}
});
addListener(SWT.MouseUp, new Listener()
{
public void handleEvent(Event event)
{
isActive = false;
redraw();
if(cursorInControl) linkActivated();
}
});
addListener(SWT.Resize, new Listener()
{
public void handleEvent(Event event)
{
cachedClientArea = getClientArea();
}
});
Listener mouseListener = new Listener()
{
public void handleEvent(Event event)
{
boolean newCursorInControl = isInClientArea(event);
if(cursorInControl != newCursorInControl)
{
cursorInControl = newCursorInControl;
if(cursorInControl) setCursor(handCursor);
else if(isActive) setCursor(arrowCursor);
if(isActive || (normalForeground != hoverForeground) || (normalUnderline != hoverUnderline)) redraw();
}
}
};
addListener(SWT.MouseMove, mouseListener);
addListener(SWT.MouseEnter, mouseListener);
addListener(SWT.MouseExit, mouseListener);
cachedClientArea = getClientArea();
if((style & SWT.NO_FOCUS) == 0) // Take focus
{
addListener(SWT.KeyDown, new Listener()
{
public void handleEvent(Event event)
{
if(event.character == ' ') linkActivated();
}
});
addListener(SWT.Traverse, new Listener()
{
public void handleEvent(Event event)
{
if(event.detail == SWT.TRAVERSE_RETURN)
{
linkActivated();
event.doit = false;
}
else if(event.detail == SWT.TRAVERSE_MNEMONIC)
{
if(mnemonic != -1 && Character.toLowerCase(event.character) == mnemonic)
{
setFocus();
linkActivated();
event.doit = false;
}
else event.doit = true;
}
else event.doit = true; // Accept all other traversal keys
}
});
addListener(SWT.FocusIn, new Listener()
{
public void handleEvent(Event event)
{
//System.out.println("FocusIn");
redraw();
}
});
addListener(SWT.FocusOut, new Listener()
{
public void handleEvent(Event event)
{
//System.out.println("FocusOut");
redraw();
}
});
}
else // Don't take focus but still support mnemonics
{
addListener(SWT.Traverse, new Listener()
{
public void handleEvent(Event event)
{
if(event.detail == SWT.TRAVERSE_MNEMONIC && mnemonic != -1 && Character.toLowerCase(event.character) == mnemonic)
{
linkActivated();
event.doit = false;
}
}
});
}
Composite shellComp = getParent();
while(shellComp != null && (!(shellComp instanceof Shell))) shellComp = shellComp.getParent();
shell = (Shell)shellComp;
if(shell != null)
{
shellListener = new Listener() // Remove stale mouse hover on shell activation / deactivation
{
public void handleEvent(Event event)
{
boolean newCursorInControl = getDisplay().getCursorControl() == Hyperlink.this;
//System.out.println("Shell (de)activated. Cursor over control: "+newCursorInControl);
if(cursorInControl != newCursorInControl)
{
cursorInControl = newCursorInControl;
if(cursorInControl) setCursor(handCursor);
else if(isActive) setCursor(arrowCursor);
if(isActive || (normalForeground != hoverForeground) || (normalUnderline != hoverUnderline)) redraw();
}
}
};
shell.addListener(SWT.Activate, shellListener);
shell.addListener(SWT.Deactivate, shellListener);
}
}
private void linkActivated()
{
//System.out.println("Link clicked!");
Event e = new Event();
e.widget = this;
e.type = SWT.Selection;
notifyListeners(SWT.Selection, e);
}
private boolean isInClientArea(Event event)
{
return event.x >= cachedClientArea.x && event.x < cachedClientArea.x+cachedClientArea.width &&
event.y >= cachedClientArea.y && event.y < cachedClientArea.y+cachedClientArea.height;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -