package net.sourceforge.tagsea.cloudsee.views;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeSet;
import net.sourceforge.tagsea.TagSEAPlugin;
import net.sourceforge.tagsea.TagSEAUtils;
import net.sourceforge.tagsea.clouds.widgets.Cloud;
import net.sourceforge.tagsea.clouds.widgets.CloudItem;
import net.sourceforge.tagsea.cloudsee.CloudSeePlugin;
import net.sourceforge.tagsea.cloudsee.ITagseaImages;
import net.sourceforge.tagsea.core.ITag;
import net.sourceforge.tagsea.core.ITagChangeListener;
import net.sourceforge.tagsea.core.TagDelta;
import net.sourceforge.tagsea.core.ui.ITagSEAImageConstants;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
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.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.part.ViewPart;
public class CloudSeeView extends ViewPart {
private Cloud cloud;
private String rootTag;
private ITagChangeListener tagsListener;
private Timer refreshTimer;
private TimerTask refreshTask;
private Action backAction;
private Action forwardAction;
private Action hierarchyAction;
protected boolean hierarchy;
private String basePartName;
public CloudSeeView() {
tagsListener = new ITagChangeListener() {
public void tagsChanged(TagDelta delta) {
scheduleViewerRefresh();
}
};
refreshTimer = new Timer();
hierarchy = true;
}
@Override
public void createPartControl(Composite parent) {
this.basePartName = getPartName();
Composite page = new Composite(parent, SWT.NONE);
page.setBackground(page.getDisplay().getSystemColor(SWT.COLOR_WHITE));
FillLayout layout = new FillLayout(SWT.HORIZONTAL);
page.setLayout(layout);
this.cloud = new Cloud(page, SWT.DOUBLE_BUFFERED | SWT.MULTI);
cloud.setBackground(page.getDisplay().getSystemColor(SWT.COLOR_WHITE));
cloud.setLayout(new FillLayout(SWT.HORIZONTAL));
this.rootTag = null;
makeActions();
cloud.addMouseListener(new MouseAdapter(){
@Override
public void mouseDoubleClick(MouseEvent e) {
if (e.button != 1) return;
CloudItem item = cloud.findItemAt(e.x, e.y);
if (item != null) {
if (item.getData("children") != null) {
rootTag = (String) item.getData();
refreshTags();
}
}
super.mouseDoubleClick(e);
}
});
cloud.addSelectionListener(new SelectionListener(){
public void widgetDefaultSelected(SelectionEvent e) {
}
public void widgetSelected(SelectionEvent e) {
CloudItem[] selection = cloud.getSelection();
if (selection.length > 0) {
forwardAction.setEnabled(selection[0].getData("children") != null);
} else {
forwardAction.setEnabled(false);
}
}
});
cloud.addKeyListener(new KeyListener(){
public void keyPressed(KeyEvent e) {
switch (e.keyCode) {
case SWT.CR:
if (forwardAction.isEnabled()) {
forwardAction.run();
}
break;
case SWT.BS:
if (backAction.isEnabled()) {
backAction.run();
}
break;
}
}
public void keyReleased(KeyEvent e) {
}
});
MenuManager menuMgr = new MenuManager("#PopupMenu");
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener()
{
public void menuAboutToShow(IMenuManager manager)
{
manager.add(backAction);
manager.add(forwardAction);
manager.add(new Separator());
manager.add(hierarchyAction);
}
});
Menu menu = menuMgr.createContextMenu(cloud);
cloud.setMenu(menu);
//getSite().registerContextMenu(menuMgr, cloud);
new ToolTip(cloud) {
private Composite page;
@Override
protected Composite createToolTipContentArea(Event event,
Composite parent) {
if (page != null && !page.isDisposed()) {
page.dispose();
}
page = new Composite(parent, SWT.NONE);
page.setLayout(new FillLayout());
page.setBackground(page.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
Label l = new Label(page, SWT.NONE);
CloudItem item = cloud.findItemAt(event.x, event.y);
if (item != null) {
l.setText(item.getData().toString() + ": " + item.getPriority() + " waypoints");
} else {
l.setText("Tag Cloud");
}
l.setBackground(page.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
page.pack();
Point size = page.computeSize(-1, -1);
Rectangle clientArea = event.display.getClientArea();
Point displayCoordinates = ((Composite)event.widget).toDisplay(event.x, event.y);
Point cursorSize = page.getDisplay().getCursorSizes()[0];
int xShift = cursorSize.x/2;
if (size.x + xShift + displayCoordinates.x > clientArea.width) {
xShift = -size.x;
}
int yShift = cursorSize.y/2;
if (size.y + yShift + displayCoordinates.y > clientArea.height) {
yShift = -size.y;
}
setShift(new Point(xShift, yShift));
return page;
}
};
fillToolbar();
refreshTags();
page.layout();
TagSEAPlugin.addTagChangeListener(tagsListener);
}
/**
*
*/
private void fillToolbar() {
IToolBarManager manager = getViewSite().getActionBars().getToolBarManager();
manager.add(backAction);
manager.add(forwardAction);
manager.add(new Separator());
manager.add(hierarchyAction);
}
/**
*
*/
private void makeActions() {
ITagseaImages images = CloudSeePlugin.getDefault().getImages();
ImageDescriptor descriptorBack = images.getDescriptor(ITagseaImages.IMG_UP_ARROW);
ImageDescriptor descriptorBackDisabled = images.getDescriptor(ITagseaImages.IMG_UP_ARROW_DISABLED);
ImageDescriptor hierarchyDescriptor = TagSEAPlugin.getDefault().getImageRegistry().getDescriptor(ITagSEAImageConstants.IMG_TAG_HIERARCHY);
backAction = new Action("Move Out", descriptorBack) {
@Override
public void run() {
if (rootTag != null) {
int dot = rootTag.lastIndexOf('.');
if (dot != -1) {
rootTag = rootTag.substring(0, dot);
refreshTags();
} else {
rootTag = null;
refreshTags();
}
}
}
};
backAction.setDisabledImageDescriptor(descriptorBackDisabled);
ImageDescriptor descriptorForward = images.getDescriptor(ITagseaImages.IMG_DOWN_ARROW);
ImageDescriptor descriptorForwardDisabled = images.getDescriptor(ITagseaImages.IMG_DOWN_ARROW_DISABLED);
forwardAction = new Action("Move In", descriptorForward) {
@Override
public void run() {
CloudItem[] selection = cloud.getSelection();
if (selection.length > 0) {
CloudItem item = selection[0];
if (item.getData("children") != null) {
rootTag = (String) item.getData();
refreshTags();
}
}
}
};
forwardAction.setDisabledImageDescriptor(descriptorForwardDisabled);
hierarchyAction = new Action("View as Hierarchy", SWT.TOGGLE) {
@Override
public void run() {
CloudSeeView.this.hierarchy = !CloudSeeView.this.hierarchy;
refreshTags();
}
};
hierarchyAction.setChecked(hierarchy);
hierarchyAction.setImageDescriptor(hierarchyDescriptor);
}
/**
*
*/
private void refreshTags() {
//dispose items
if (hierarchy) {
String partName = basePartName;
if (rootTag != null) {
partName += " (" + rootTag + ")";
}
setPartName(partName);
refreshTagsAsHierarchy();
} else {
setPartName(basePartName);
forwardAction.setEnabled(false);
backAction.setEnabled(false);
ITag[] tags = TagSEAPlugin.getTagsModel().getAllTags();
cloud.setRedraw(false);
for (CloudItem item : cloud.getItems()) {
item.dispose();
}
for (ITag tag : tags) {
CloudItem item = new CloudItem(cloud);
item.setText(tag.getName());
item.setData(tag.getName());
item.setPriority(tag.getWaypointCount());
}
cloud.setRedraw(true);
cloud.redraw();
}
}
/**
*
*/
private void refreshTagsAsHierarchy() {
cloud.setRedraw(false);
for (CloudItem item : cloud.getItems()) {
if (item != null && !item.isDisposed()) {
item.dispose();
}
}
String[] childNames;
TreeSet<String> hasChildSet = new TreeSet<String>();
HashMap<String, Integer> waypointCounts = new HashMap<String, Integer>();
if (rootTag == null) {
backAction.setEnabled(false);
childNames = TagSEAUtils.getRootTagNames();
for (String name : childNames) {
ITag tag = TagSEAPlugin.getTagsModel().getTag(name);
if (tag != null) {
ITag[] tags = TagSEAUtils.getAllChildTags(tag);
if (tags.length > 0) {
hasChildSet.add(name);
}
Integer count = waypointCounts.get(name);
if (count == null) {
count = 0;
}
count = count + tag.getWaypointCount();
for (ITag child : tags) {
count = count + child.getWaypointCount();
}
waypointCounts.put(name, count);
} else {
ITag[] parents = TagSEAUtils.getChildTagsForName(name);
if (parents.length > 0) {
hasChildSet.add(name);
}
for (ITag parent : parents) {
Integer count = waypointCounts.get(name);
if (count == null) {
count = 0;
}
count = count + parent.getWaypointCount();
for (ITag child : TagSEAUtils.getAllChildTags(parent)) {
count = count + child.getWaypointCount();
}
waypointCounts.put(name, count);
}
}
}
} else {
backAction.setEnabled(true);
ITag[] tags = TagSEAUtils.getChildTagsForName(rootTag);
TreeSet<String> childSet = new TreeSet<String>();
for (ITag tag : tags) {
String name = tag.getName();
name = name.substring(rootTag.length()+1);
int dot = name.indexOf('.');
if (dot != -1) {
name = name.substring(0, dot);
hasChildSet.add(rootTag + '.' + name);
}
name = rootTag + '.' + name;
Integer count = waypointCounts.get(name);
if (count == null) {
count = 0;
}
count = count + tag.getWaypointCount();
for (ITag child : TagSEAUtils.getAllChildTags(tag)) {
count = count + child.getWaypointCount();
}
childSet.add(name);
waypointCounts.put(name, count);
}
childNames = childSet.toArray(new String[childSet.size()]);
}
for (String name : childNames) {
CloudItem item = new CloudItem(cloud);
item.setData(name);
Integer priority = waypointCounts.get(name);
if (priority == null) {
priority = 0;
}
item.setPriority(priority);
if (hasChildSet.contains(name)) {
name += "+";
item.setForeground(cloud.getDisplay().getSystemColor(SWT.COLOR_DARK_CYAN));
item.setData("children", Boolean.TRUE);
}
if (rootTag != null) {
name = name.substring(rootTag.length()+1);
}
item.setText(name);
}
cloud.setRedraw(true);
//cloud.layout();
cloud.redraw();
}
@Override
public void setFocus() {
cloud.setFocus();
}
private void scheduleViewerRefresh() {
if (refreshTask != null) {
refreshTask.cancel();
}
if (!cloud.isDisposed()) {
refreshTask = new TimerTask() {
@Override
public void run() {
if (!cloud.isDisposed()) {
cloud.getDisplay().syncExec(new Runnable(){
public void run() {
refreshTags();
}
});
}
}
};
refreshTimer.schedule(refreshTask, 200);
}
}
@Override
public void dispose() {
refreshTimer.cancel();
TagSEAPlugin.removeTagChangeListener(tagsListener);
super.dispose();
}
}