package LinGUIne.parts.advanced;
import java.io.File;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.core.services.log.Logger;
import org.eclipse.e4.ui.di.UIEventTopic;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import LinGUIne.events.LinGUIneEvents;
import LinGUIne.events.OpenProjectDataEvent;
import LinGUIne.extensions.IProjectDataEditor;
import LinGUIne.model.AnnotationSet;
import LinGUIne.model.AnnotationSetContents;
import LinGUIne.model.IProjectData;
import LinGUIne.model.Project;
import LinGUIne.model.Project.Subdirectory;
/**
* Handles the opening of ProjectDataEditors by listening for OpenProjectData
* events, finding a compatible editor/viewer for the requested ProjectData, and
* then opening a new instance of the ProjectDataEditor that was found.
*
* @author Kyle Mullins
*/
public class DataEditorManager {
private static final String CONTAINER_PART_ID = "linguine.partdescriptor."
+ "projectDataEditorContainer";
@Inject
private EModelService modelService;
@Inject
private EPartService partService;
@Inject
private MApplication application;
@Inject
private Logger logger;
private MPartStack partStack;
@PostConstruct
public void setup(IEventBroker eventBroker){
partStack = (MPartStack)modelService.find("linguine.partstack.advanced."
+ "dataEditorPartStack", application);
eventBroker.subscribe(LinGUIneEvents.UILifeCycle.OPEN_PROJECT_DATA,
new EventHandler(){
@Override
public void handleEvent(Event event) {
if(event != null){
for(String propName: event.getPropertyNames()){
//Does nothing, but I'm afraid to get rid of it
}
}
}
});
}
/**
* Called when a user attempts to open a File.
*/
@Inject
public void fileOpenEvent(@Optional @UIEventTopic(LinGUIneEvents.
UILifeCycle.OPEN_PROJECT_DATA) OpenProjectDataEvent openEvent){
if(openEvent != null){
IProjectData projData = openEvent.getProjectData();
Project project = openEvent.getParentProject();
//Check if any open editors have the file asking to be opened,
//if so, simply activate that part and skip the rest of this
MPart existingPart = findAssociatedPart(projData, project);
if(existingPart != null){
partService.activate(existingPart);
return;
}
IProjectDataEditor dataEditor = null;
//Handle cases for our built-in editors
if(new TextAnnotationSetEditor().canOpenData(projData, project)){
dataEditor = new TextAnnotationSetEditor();
}
else if(new TextDataEditor().canOpenData(projData, project)){
dataEditor = new TextDataEditor();
}
else if(new VisualResultViewEditor().canOpenData(projData, project)){
dataEditor = new VisualResultViewEditor();
}
else if(new UneditableTextViewer().canOpenData(projData, project)){
dataEditor = new UneditableTextViewer();
}
else{
IConfigurationElement[] configElements = Platform.
getExtensionRegistry().getConfigurationElementsFor(
"LinGUIne.LinGUIne.extensions.IProjectDataEditor");
for(IConfigurationElement configElement: configElements){
try {
IProjectDataEditor editor = (IProjectDataEditor)
configElement.createExecutableExtension("class");
if(editor.canOpenData(projData, project)){
dataEditor = editor;
break;
}
}
catch(CoreException ce) {
logger.error(ce);
}
}
}
//If we found a compatible editor, create the part
if(dataEditor != null){
MPart newPart = partService.createPart(CONTAINER_PART_ID);
partStack.getChildren().add(newPart);
partService.activate(newPart);
ContextInjectionFactory.inject(dataEditor, application.getContext());
dataEditor.setInputData(projData, project);
ProjectDataEditorContainer editorContainer =
(ProjectDataEditorContainer)newPart.getObject();
editorContainer.setProjectDataEditor(dataEditor);
}
}
}
/**
* Called when a user attempts to edit the Annotations on a file.
*/
@Inject
public void editAnnotations(@Optional @UIEventTopic(LinGUIneEvents.
UILifeCycle.EDIT_ANNOTATIONS) IProjectDataEditor dataEditor){
if(dataEditor != null){
IProjectData projData = dataEditor.getInputProjectData();
Project project = dataEditor.getInputParentProject();
MPart parentPart = findAssociatedPart(projData, project);
AnnotationSet annotations;
if(project.isAnnotated(projData)){
annotations = project.getAnnotation(projData);
}
//Create a new AnnotationSet for the ProjectData
else{
String annotationName = projData.getName() + ".ann";
File annotationFile = project.getSubdirectory(
Subdirectory.Annotations).append(annotationName).toFile();
annotations = new AnnotationSet(annotationFile);
annotations.updateContents(new AnnotationSetContents());
project.addAnnotation(annotations, projData);
}
OpenProjectDataEvent openEvent = new OpenProjectDataEvent(annotations,
project);
partService.hidePart(parentPart);
parentPart.getParent().getChildren().remove(parentPart);
fileOpenEvent(openEvent);
}
}
/**
* Returns the MPart that is associated with the given ProjectData and
* Project or null if there isn't one.
*/
private MPart findAssociatedPart(IProjectData projData, Project project){
for(MPart part: modelService.findElements(application,
CONTAINER_PART_ID, MPart.class, null)){
if(part.isVisible() && part.getObject() != null){
ProjectDataEditorContainer editorContainer =
(ProjectDataEditorContainer)part.getObject();
IProjectDataEditor editor =
editorContainer.getProjectDataEditor();
if(editor.getInputParentProject().equals(project) &&
editor.getInputProjectData().equals(projData)){
return part;
}
}
}
return null;
}
}