/*******************************************************************************
* Copyright (c) 2009, 2010 Progress Software Corporation.
* 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.eclipse.org/legal/epl-v10.html
******************************************************************************/
// Copyright (c) 2009 Progress Software Corporation.
package org.fusesource.tools.messaging.cnf.ui;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.TreeItem;
import org.fusesource.tools.messaging.MsgProjectStateManager;
import org.fusesource.tools.messaging.ProjectStateEvent;
import org.fusesource.tools.messaging.ProjectStateListener;
import org.fusesource.tools.messaging.cnf.actions.OpenMessagesEditorAction;
import org.fusesource.tools.messaging.cnf.model.BaseComponent;
import org.fusesource.tools.messaging.cnf.model.BaseGroupComponent;
import org.fusesource.tools.messaging.cnf.model.IModelConstants;
import org.fusesource.tools.messaging.cnf.model.ListenerComponent;
import org.fusesource.tools.messaging.cnf.model.ListenersRootComponent;
import org.fusesource.tools.messaging.core.IListener;
/**
* Handles UI changes to the Messaging Projects in CNF
*/
public class MsgProjectChangeHandler implements IResourceChangeListener, IResourceDeltaVisitor {
private StructuredViewer viewer;
private final MsgProjectStateListener prjStateListener;
public static Font DEFAULT_FONT, BOLD_FONT;
public MsgProjectChangeHandler() {
prjStateListener = new MsgProjectStateListener();
ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
MsgProjectStateManager.getInstance().addProjectStateListener(prjStateListener);
}
public void resourceChanged(IResourceChangeEvent event) {
IResourceDelta delta = event.getDelta();
try {
// Interested only in the content change event...
delta.accept(this, IResourceDelta.CONTENT);
} catch (CoreException e) {
e.printStackTrace();
}
}
public boolean visit(IResourceDelta delta) {
IResource source = delta.getResource();
switch (source.getType()) {
case IResource.FILE:
final IFile file = (IFile) source;
Object element = ((StructuredSelection) viewer.getSelection()).getFirstElement();
// There is one case where we have to handle refresh for the
// Listeners node, we auto create listener for reply to destination,
// but that doen't show up until we explicitly refresh the project
// See notes in UI-365 for more details;
if (IModelConstants.SENDERS_FILE_NAME.equals(file.getName())) {
updateUI(element);
} else if (IModelConstants.LISTENERS_FILE_NAME.equals(file.getName())) {
if (element instanceof ListenersRootComponent || element instanceof ListenerComponent) {
updateUI(element);
} else {
updateUI(findListenersRootComponent(file));
}
}
return false;
}
return true;
}
public void updateUI(final Object element) {
if (viewer == null || element == null) {
return;
}
Runnable runnable = new Runnable() {
public void run() {
Object elementToRefresh = element;
if (element instanceof IListener) {
elementToRefresh = findListenerComponent((IListener) element);
// TODO could not refresh the collapsed listener components
} else if (element instanceof BaseComponent) {
elementToRefresh = ((BaseComponent) element).getParent();
}
if (elementToRefresh == null) {
return;
}
viewer.refresh(elementToRefresh, true);
// If we are creating Senders/Listeners we want to show
// expand and show the complete subtree
if (elementToRefresh instanceof BaseGroupComponent) {
((TreeViewer) viewer).expandToLevel(elementToRefresh, AbstractTreeViewer.ALL_LEVELS);
}
}
};
Display.getDefault().asyncExec(runnable);
}
/**
* Find the corresponding ListenerComponent to refresh the tree...
*
* @param element
* @return
*/
private ListenerComponent findListenerComponent(IListener element) {
TreeItem[] items = ((TreeViewer) viewer).getTree().getItems();
for (int i = 0; i < items.length; i++) {
if (!(items[i].getData() instanceof IProject)) {
continue;
}
// Get Project's children
TreeItem[] projectChildren = items[i].getItems();
for (TreeItem element2 : projectChildren) {
if (element2.getData() instanceof ListenersRootComponent) {
ListenersRootComponent listenersRoot = (ListenersRootComponent) element2.getData();
Object[] listenerComponents = listenersRoot.getChildren();
if (listenerComponents == null) {
break;// Only one listeners root component is expected in a project
}
// Iterate over each ListenerComponent
for (Object listenerComponent2 : listenerComponents) {
if (listenerComponent2 instanceof ListenerComponent) {
ListenerComponent listenerComponent = (ListenerComponent) listenerComponent2;
if (element.equals(listenerComponent.getListener())) {
return listenerComponent;
}
}
}
}
}
}
return null;
}
/**
* Find the corresponding ListenersRootComponent to refresh the tree...
*
* @param modelFile
* @return
*/
private ListenersRootComponent findListenersRootComponent(final IFile modelFile) {
if (viewer == null) {
return null;
}
final ListenersRootComponent[] root = new ListenersRootComponent[] { null };
Runnable runnable = new Runnable() {
public void run() {
TreeItem[] items = ((TreeViewer) viewer).getTree().getItems();
// Iterate over the correct project item
for (TreeItem item : items) {
if (item.getData().equals(modelFile.getProject())) {
root[0] = searchListenersNode(modelFile, item.getItems());
return;
}
}
return;
}
};
Display.getDefault().syncExec(runnable);
return root[0];
}
private ListenersRootComponent searchListenersNode(IFile modelFile, TreeItem[] items) {
for (TreeItem item : items) {
if (item.getData() instanceof ListenersRootComponent) {
ListenersRootComponent root = (ListenersRootComponent) item.getData();
if (root.getFile().equals(modelFile)) {
return root;
}
}
}
return null;
}
/**
* The class will be notified when a server state is changed Based on the event, we can refresh
* any UI decorations if required
*/
class MsgProjectStateListener implements ProjectStateListener {
public void stateChanged(ProjectStateEvent event) {
IProject[] projects = event.getProjects();
for (IProject project : projects) {
updateUI(project);
}
}
}
// TODO move this to some UI utils...
private void initFonts() {
DEFAULT_FONT = ((TreeViewer) viewer).getTree().getFont();
if (BOLD_FONT == null) {
FontData[] fontData = DEFAULT_FONT.getFontData();
for (FontData fdata : fontData) {
fdata.setStyle(fdata.getStyle() | SWT.BOLD);
}
BOLD_FONT = new Font(((TreeViewer) viewer).getTree().getDisplay(), fontData);
}
}
public void cleanUp() {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
MsgProjectStateManager.getInstance().removeProjectStateListener(prjStateListener);
}
public void initViewer(StructuredViewer viewer2) {
this.viewer = viewer2;
viewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
Object firstElement = ((StructuredSelection) event.getSelection()).getFirstElement();
if (!(firstElement instanceof ListenerComponent)) {
return;
}
try {
new OpenMessagesEditorAction().OpenMessagesEditor((ListenerComponent) firstElement);
} catch (Exception e) {
e.printStackTrace();
MessageDialog.openError(Display.getCurrent().getActiveShell(), "Error", "Failed To Open Editor");
}
}
});
initFonts();
}
}