/*******************************************************************************
* Copyright (c) 2012 OpenLegacy Inc.
* 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
*
* Contributors:
* OpenLegacy Inc. - initial API and implementation
*******************************************************************************/
package org.openlegacy.ide.eclipse.editors;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.ui.StructuredTextEditor;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.openlegacy.designtime.DesigntimeException;
import org.openlegacy.ide.eclipse.Messages;
import org.openlegacy.ide.eclipse.actions.GenerateModelDialog;
import org.openlegacy.ide.eclipse.components.SnapshotComposite;
import org.openlegacy.ide.eclipse.util.PathsUtil;
import org.openlegacy.terminal.TerminalSnapshot;
import org.openlegacy.terminal.TerminalSnapshot.SnapshotType;
import org.openlegacy.terminal.modules.trail.TerminalPersistedTrail;
import org.openlegacy.utils.XmlSerializationUtil;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
@SuppressWarnings("restriction")
public class TrailEditor extends MultiPageEditorPart implements IResourceChangeListener {
private StructuredTextEditor editor;
private SnapshotComposite snapshotComposite;
private TableViewer tableViewer;
private Composite trailComposite;
public TrailEditor() {
super();
ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
}
private void createXmlPage() {
try {
editor = new StructuredTextEditor();
int index = addPage(editor, getEditorInput());
setPageText(index, Messages.page_name_source);
} catch (PartInitException e) {
ErrorDialog.openError(getSite().getShell(), Messages.error_creating_text_editor, null, e.getStatus());
}
}
void createTrailPage() {
trailComposite = new Composite(getContainer(), SWT.NONE);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 2;
GridData gd = new GridData();
trailComposite.setLayoutData(gd);
trailComposite.setLayout(gridLayout);
TerminalPersistedTrail terminalSessionTrail = loadTrail();
if (terminalSessionTrail == null) {
return;
}
createTable(trailComposite, terminalSessionTrail);
snapshotComposite = new SnapshotComposite(trailComposite, terminalSessionTrail.getSnapshots().get(0));
if (getPageCount() == 2) {
removePage(0);
}
addPage(0, trailComposite);
setPageText(0, Messages.page_name_snapshots);
}
private Element extractDocumentRoot() {
IDocument document = editor.getDocumentProvider().getDocument(getEditorInput());
Object model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
Element root = ((IDOMModel)model).getDocument().getDocumentElement();
return root;
}
private TerminalPersistedTrail loadTrail() {
FileEditorInput input = (FileEditorInput)getEditorInput();
File file = PathsUtil.toOsLocation(input.getFile());
if (file.length() == 0) {
return null;
}
TerminalPersistedTrail terminalSessionTrail = null;
try {
terminalSessionTrail = XmlSerializationUtil.deserialize(TerminalPersistedTrail.class, new FileInputStream(file));
} catch (Exception e) {
throw (new DesigntimeException(Messages.error_unable_to_open_trail_file, e));
}
if (terminalSessionTrail.getSnapshots().size() == 0) {
throw (new DesigntimeException(Messages.error_no_snapshots_found));
}
return terminalSessionTrail;
}
private void createTable(final Composite composite, final TerminalPersistedTrail terminalSessionTrail) {
tableViewer = new TableViewer(composite);
tableViewer.setContentProvider(new ArrayContentProvider());
tableViewer.setInput(terminalSessionTrail.getSnapshots().toArray());
Menu menu = new Menu(tableViewer.getTable());
MenuItem menuItem = new MenuItem(menu, SWT.PUSH);
menuItem.setText(Messages.menu_generate_model);
menuItem.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent event) {
int[] selectionIndexes = tableViewer.getTable().getSelectionIndices();
TerminalSnapshot[] snapshots = new TerminalSnapshot[selectionIndexes.length];
for (int i = 0; i < selectionIndexes.length; i++) {
TerminalSnapshot snapshot = terminalSessionTrail.getSnapshots().get(selectionIndexes[i]);
snapshots[i] = snapshot;
}
GenerateModelDialog dialog = new GenerateModelDialog(getEditorSite().getShell(),
((FileEditorInput)getEditorInput()).getFile(), snapshots);
dialog.open();
}
public void widgetDefaultSelected(SelectionEvent arg0) {
widgetSelected(arg0);
}
});
tableViewer.getTable().setMenu(menu);
GridData data = new GridData(GridData.FILL_BOTH);
data.horizontalSpan = 1;
data.widthHint = 280;
tableViewer.getTable().setLayoutData(data);
tableViewer.getTable().addKeyListener(new KeyListener() {
public void keyReleased(KeyEvent event) {}
public void keyPressed(KeyEvent event) {
// delete
if (event.keyCode == SWT.DEL) {
Table table = (Table)event.getSource();
int selectionIndex = table.getSelectionIndex();
terminalSessionTrail.getSnapshots().remove(selectionIndex);
table.remove(selectionIndex);
try {
Element root = extractDocumentRoot();
List<Element> snapshots = DomUtils.getChildElementsByTagName(root, "snapshot"); //$NON-NLS-1$
root.removeChild(snapshots.get(selectionIndex));
} catch (Exception e) {
throw (new DesigntimeException(e));
}
}
}
});
TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.NONE);
column.getColumn().setWidth(100);
column.getColumn().setText(Messages.label_sequence);
column.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
TerminalSnapshot snapshot = (TerminalSnapshot)element;
String direction = snapshot.getSnapshotType() == SnapshotType.INCOMING ? Messages.label_screen_in
: Messages.label_screen_out;
return String.valueOf(Messages.label_screen_prefix + snapshot.getSequence() + direction);
}
});
tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
Object firstElement = ((StructuredSelection)selection).getFirstElement();
TerminalSnapshot snapshot = (TerminalSnapshot)firstElement;
snapshotComposite.setSnapshot(snapshot);
tableViewer.getTable().getMenu().getItem(0).setEnabled(snapshot.getSnapshotType() == SnapshotType.INCOMING);
}
});
refreshSnapshots();
}
/**
* Creates the pages of the multi-page editor.
*/
@SuppressWarnings("deprecation")
@Override
protected void createPages() {
FileEditorInput fileInput = (FileEditorInput)getEditorInput();
setTitle(fileInput.getName());
createTrailPage();
createXmlPage();
}
/**
* The <code>MultiPageEditorPart</code> implementation of this <code>IWorkbenchPart</code> method disposes all nested editors.
* Subclasses may extend.
*/
@Override
public void dispose() {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
super.dispose();
}
/**
* Saves the multi-page editor's document.
*/
@Override
public void doSave(IProgressMonitor monitor) {
Element root = extractDocumentRoot();
List<Element> snapshots = DomUtils.getChildElementsByTagName(root, "snapshot"); //$NON-NLS-1$
for (int i = 0; i < snapshots.size(); i++) {
snapshots.get(i).setAttribute("sequence", String.valueOf(i + 1));
}
getEditor(getPageCount() - 1).doSave(monitor);
createTrailPage();
}
private void refreshSnapshots() {
tableViewer.refresh();
tableViewer.getTable().select(0);
}
/**
* Saves the multi-page editor's document as another file. Also updates the text for page 0's tab, and updates this multi-page
* editor's input to correspond to the nested editor's.
*/
@Override
public void doSaveAs() {
IEditorPart editor = getEditor(1);
editor.doSaveAs();
setPageText(1, editor.getTitle());
setInput(editor.getEditorInput());
}
/*
* (non-Javadoc) Method declared on IEditorPart
*/
public void gotoMarker(IMarker marker) {
setActivePage(0);
IDE.gotoMarker(getEditor(0), marker);
}
/**
* The <code>MultiPageEditorExample</code> implementation of this method checks that the input is an instance of
* <code>IFileEditorInput</code>.
*/
@Override
public void init(IEditorSite site, IEditorInput editorInput) throws PartInitException {
if (!(editorInput instanceof IFileEditorInput)) {
throw new PartInitException(Messages.error_invalid_input_file);
}
super.init(site, editorInput);
}
/*
* (non-Javadoc) Method declared on IEditorPart.
*/
@Override
public boolean isSaveAsAllowed() {
return true;
}
/**
* Closes all project files on project close.
*/
public void resourceChanged(final IResourceChangeEvent event) {
if (event.getType() == IResourceChangeEvent.PRE_CLOSE) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
IWorkbenchPage[] pages = getSite().getWorkbenchWindow().getPages();
for (IWorkbenchPage page : pages) {
if (((FileEditorInput)editor.getEditorInput()).getFile().getProject().equals(event.getResource())) {
IEditorPart editorPart = page.findEditor(editor.getEditorInput());
page.closeEditor(editorPart, true);
}
}
}
});
}
}
}