package com.hundsun.ares.studio.ui;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
public class ColumnViewerHoverToolTip{
/**���*/
ColumnViewer viewer;
/**��ǰ������ڵĵ�Ԫ��*/
ViewerCell cell;
String text = "";
/**tooltip��ʾ��*/
Shell currentShell;
/**tooltip��ʾ����Ϣ��*/
StyledText txtInfo;
Listener treeViewerListener = new TreeViewerListener();
Listener toolTipListener = new ToolTipListener();
Control control;
protected ColumnViewerHoverToolTip(ColumnViewer viewer) {
this.viewer = viewer;
this.control = viewer.getControl();
this.control.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
deactivate();
}
});
activate();
}
public static void enableFor(ColumnViewer viewer) {
new ColumnViewerHoverToolTip(viewer);
}
protected Composite createToolTipContentArea(Event event, Composite parent) {
control.forceFocus();
int textStyle=SWT.V_SCROLL | SWT.WRAP;
final Composite composite= new Composite(parent, SWT.NONE);
composite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
String text = getText();
txtInfo = new StyledText(composite, textStyle);
txtInfo.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
txtInfo.setFont(new Font(txtInfo.getDisplay(),"����",9,SWT.NORMAL));
if (text != null) {
txtInfo.setText(text);
txtInfo.setCaret(null);
txtInfo.setEditable(false);
}
//������ֻ���ڰ���F2�������ͣ����tooltip�ϵ�ʱ�����ʾ
setScrollBarVisible(false);
Label separator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
CLabel label = new CLabel(composite, SWT.NONE);
label.setText("Press F2 for focus");
label.setFont(new Font(label.getDisplay(),"����",7,SWT.NORMAL));
label.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
composite.setLayout(new GridLayout(1, false));
GridDataFactory.fillDefaults().grab(true, true).applyTo(txtInfo);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, false).applyTo(separator);
GridDataFactory.fillDefaults().hint(-1,7).align(SWT.END, SWT.FILL).grab(true, false).applyTo(label);
toolTipActivate(composite);
composite.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
toolTipDeactivate(composite);
}
});
return txtInfo;
}
private void toolTipShow(Shell tip, Event event) {
if (!tip.isDisposed()) {
tip.pack();
Point size = tip.getSize();
//tooltip�����������Ϊ200
if(size.x > 200){
size = new Point(200, size.y + 36);
tip.setSize(size);
}
Rectangle cellBound = cell.getBounds();
Point location = fixupDisplayBounds(size, getLocation(cellBound.x,cellBound.y + cellBound.height));
tip.setLocation(location);
tip.setVisible(true);
control.forceFocus();
txtInfo.setFocus();
txtInfo.setText(getText());
if(!txtInfo.getVerticalBar().isVisible()){
//Ĭ��״̬����ʾ4�У��ܹ�Լ110���ֽڡ������Ļ������...
if(getText().getBytes().length>110){
int end = 54;
String tmp = StringUtils.substring(getText(), 0, end);
while(tmp.getBytes().length<=105){
end += (110-tmp.getBytes().length)/2;
String addStr = StringUtils.substring(getText(), tmp.length(),end);
if(addStr.length() == 0){
break;
}
tmp += addStr;
}
txtInfo.setText(tmp + "...");
}
}
}
}
/**��ȡ�����table/tree���������*/
public Point getLocation(int x, int y) {
return control.toDisplay(x , y);
}
//tipSize��tooltip�Ŀ�� location:tooltip�ij�ʼ��ʾ���꣨��Ԫ�������λ�ã�
private Point fixupDisplayBounds(Point tipSize, Point location) {
//���ճ�ʼ��ʾλ�úͿ��ȡ����tooltip����������
Point rightBounds = new Point(tipSize.x + location.x, tipSize.y
+ location.y);
Rectangle clientArea = ((Composite)control).getClientArea();
Point pt = control.toDisplay(clientArea.x,clientArea.y);
Rectangle bounds = new Rectangle(pt.x, pt.y, control.getSize().x, control.getSize().y);
//���tooltip�ķ�Χ�����˱������Ҫ���е���
if (!(bounds.contains(location) && bounds.contains(rightBounds))) {
//���tootilp���ұ߳����˱���ұ�
if (rightBounds.x > bounds.x + bounds.width) {
//��ʼλ�����ƣ�ֱ��tootip���ұߺͱ����ұ�һ��
location.x -= rightBounds.x - (bounds.x + bounds.width);
}
//���tootip���±߳����˱����±�
if (rightBounds.y > bounds.y + bounds.height) {
//��ʼλ�������ƣ�ֱ��tooltip���±ߺ͵�Ԫ����ϱ�һ��
location.y = location.y - cell.getBounds().height - tipSize.y;//-= rightBounds.y - (bounds.y + bounds.height);
}
//��֤���ƻ������ƺ��ʼxy����û�г���������ϱ�
if (location.x < bounds.x) {
location.x = bounds.x;
}
if (location.y < bounds.y) {
location.y = bounds.y;
}
}
return location;
}
protected boolean shouldCreateToolTip(Event event) {
boolean rv = false;
//�ж�ǰ��tooltip�Ƿ���ڣ������ǰtootip�������ˣ���cell��Ϊnull
if(currentShell == null || currentShell.isDisposed()){
cell = null;
}
try{
Point point = new Point(event.x, event.y);
ViewerCell curCell = viewer.getCell(point);
//����͵�ǰ��ʾtooltip�ĵ�Ԫ����ͬһ��
if(cell != null && cell.equals(curCell)){
return false;
}
//�����ǰ������ڵ�Ԫ����
cell = curCell;
if(curCell == null){
return false;
}
Object element = cell.getElement();
CellLabelProvider labelProvider = viewer.getLabelProvider(cell.getColumnIndex());
String text = labelProvider.getToolTipText(element);
setText(text);
rv = StringUtils.isNotBlank(getText());
}catch(Exception e){
return false;
}
return rv;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
private void toolTipHide(){
if(currentShell != null && !currentShell.isDisposed()){
currentShell.close();
currentShell.dispose();
}
};
private void setScrollBarVisible(boolean visible){
if(txtInfo != null && !txtInfo.isDisposed() && txtInfo.getVerticalBar().getVisible() == !visible){
txtInfo.getVerticalBar().setVisible(visible);
if(visible){
txtInfo.setFocus();
txtInfo.setText(getText());
currentShell.setSize(currentShell.getSize().x + txtInfo.getVerticalBar().getSize().x, currentShell.getSize().y);
}
}
}
public void toolTipActivate(Control control) {
toolTipDeactivate(control);
control.addListener(SWT.MouseHover,toolTipListener);
control.addListener(SWT.MouseDown,toolTipListener);
control.addListener(SWT.FocusOut,toolTipListener);
control.addListener(SWT.KeyDown,toolTipListener);
if (control instanceof Composite) {
for(Control child : ((Composite)control).getChildren()){
toolTipActivate(child);
}
}
}
/**
* Deactivate tooltip support for the underlying control
*/
public void toolTipDeactivate(Control control) {
control.removeListener(SWT.MouseHover,toolTipListener);
control.removeListener(SWT.MouseDown,toolTipListener);
control.removeListener(SWT.FocusOut,toolTipListener);
control.removeListener(SWT.KeyDown,toolTipListener);
if (control instanceof Composite) {
for(Control child : ((Composite)control).getChildren()){
toolTipDeactivate(child);
}
}
}
public void activate() {
deactivate();
control.addListener(SWT.MouseHover, treeViewerListener);
control.addListener(SWT.KeyDown, treeViewerListener);
control.addListener(SWT.MouseMove, treeViewerListener);
}
/**
* Deactivate tooltip support for the underlying control
*/
public void deactivate() {
control.removeListener(SWT.MouseHover, treeViewerListener);
control.removeListener(SWT.KeyDown, treeViewerListener);
control.removeListener(SWT.MouseMove, treeViewerListener);
}
class TreeViewerListener implements Listener{
@Override
public void handleEvent(Event event) {
if (event.widget instanceof Control) {
Control c = (Control) event.widget;
switch (event.type) {
//���ͣ��
case SWT.MouseHover:
if(shouldCreateToolTip(event)){
//�Ȱѵ�ǰ�Ѿ���tooltip��������������һ���µ�tooltip����ʾ����
toolTipHide();
currentShell = new Shell(c.getShell(), SWT.ON_TOP | SWT.TOOL
| SWT.NO_FOCUS | SWT.RESIZE);
currentShell.setLayout(new FillLayout());
createToolTipContentArea(event, currentShell);
toolTipShow(currentShell, event);
currentShell.addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
setScrollBarVisible(true);
}
});
}
break;
case SWT.KeyDown:
//esc�����ٵ�ǰ��tooltip
if(event.keyCode == SWT.ESC){
toolTipHide();
}else if(event.keyCode == SWT.F2){
//F2��ǰtooltip��ȡ���㣬��������ʾ
setScrollBarVisible(true);
}
break;
case SWT.MouseMove:
Point point = new Point(event.x, event.y);
if(currentShell != null && !currentShell.isDisposed() && cell != null){
if(!currentShell.getBounds().contains(point) && !txtInfo.getVerticalBar().isVisible() && !cell.getBounds().contains(point)){
//������λ�ò��ڵ�Ԫ���tooltip��Χ�ڣ���tooltipû�л�ȡ���㣬������tooltip
toolTipHide();
}
}
break;
}
}
}
}
class ToolTipListener implements Listener{
@Override
public void handleEvent(Event event) {
switch (event.type) {
case SWT.MouseHover:
case SWT.MouseDown:
setScrollBarVisible(true);
break;
case SWT.KeyDown:
if(event.keyCode == SWT.ESC){
toolTipHide();
}else if(event.keyCode == SWT.F2){
setScrollBarVisible(true);
}
break;
case SWT.FocusOut:
//tooltipʧȥ����������
toolTipHide();
break;
default:
break;
}
}
}
}