/******************************************************************************* * Copyright (c) 2008 Ralf Ebert * 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: * Ralf Ebert - initial API and implementation *******************************************************************************/ package com.swtxml.ide; import java.io.File; import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentExtension4; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IPartListener; import org.eclipse.ui.IPropertyListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.editors.text.ILocationProvider; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.part.ViewPart; import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; import com.swtxml.swt.SwtXmlParser; @SuppressWarnings("restriction") public class PreviewViewPart extends ViewPart { public static final String VIEW_ID = PreviewViewPart.class.getName(); private IEditorPart swtXmlEditorPart; private IEditorPart propertiesFileEditorPart; /** * Updates preview when opened property file is saved (so you see i18n * changes) */ private final IPropertyListener updatePreviewOnSavePropertiesFile = new IPropertyListener() { public void propertyChanged(Object source, int propId) { if (propId == IEditorPart.PROP_DIRTY) { if (source == propertiesFileEditorPart && !propertiesFileEditorPart.isDirty()) { updatePreview(true); } } } }; /** * Updates preview when opened SWT/XML editor saved */ private final IPropertyListener updatePreviewOnSaveSwtXml = new IPropertyListener() { public void propertyChanged(Object source, int propId) { if (propId == IEditorPart.PROP_DIRTY) { if (source == swtXmlEditorPart && !swtXmlEditorPart.isDirty()) { updatePreview(false); } } } }; /** * Tracks currently opened editor and attaches / removes property listeners * as needed to get preview updated on save events of relevant files. */ private final IPartListener trackRelevantEditorsPartListener = new IPartListener() { public void partActivated(IWorkbenchPart part) { tryConnectTo(part); } public void partBroughtToTop(IWorkbenchPart part) { } public void partClosed(IWorkbenchPart part) { partDeactivated(part); if (part == swtXmlEditorPart) { clearSWTXMLConnection(); } } public void partDeactivated(IWorkbenchPart part) { if (part == propertiesFileEditorPart) { clearPropertiesFileConnection(); } } public void partOpened(IWorkbenchPart part) { } }; private long lastPreviewModificationStamp; private Composite container; private Action resizeAction; @Override public void createPartControl(final Composite parent) { resizeAction = new Action("Resize", SWT.TOGGLE) { @Override public void run() { updatePreview(true); } }; resizeAction.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "/icons/resize.png")); GridLayoutFactory.fillDefaults().numColumns(2).spacing(0, 0).applyTo(parent); ToolBar toolbar = new ToolBar(parent, SWT.VERTICAL | SWT.FLAT); toolbar.setBackground(toolbar.getDisplay().getSystemColor(SWT.COLOR_GRAY)); ToolBarManager toolbarManager = new ToolBarManager(toolbar); toolbarManager.add(resizeAction); GridDataFactory.fillDefaults().grab(false, true).align(SWT.BEGINNING, SWT.FILL).applyTo( toolbar); toolbarManager.update(true); container = new Composite(parent, SWT.NONE); container.setLayout(new FillLayout()); GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL) .applyTo(container); getSite().getPage().addPartListener(trackRelevantEditorsPartListener); tryConnectTo(getSite().getPage().getActiveEditor()); } @Override public void dispose() { getSite().getPage().removePartListener(trackRelevantEditorsPartListener); clearSWTXMLConnection(); clearPropertiesFileConnection(); super.dispose(); } private void tryConnectTo(IWorkbenchPart part) { if (part instanceof IEditorPart) { IStructuredModel model = (IStructuredModel) part.getAdapter(IStructuredModel.class); if (part != swtXmlEditorPart && model != null && SwtXmlModelHandler.associatedContentTypeID.equals(model .getContentTypeIdentifier())) { connectTo(part); } else if (((IEditorPart) part).getEditorInput() instanceof FileEditorInput) { if (((FileEditorInput) (((IEditorPart) part).getEditorInput())).getFile() .toString().endsWith(".properties")) { propertiesFileEditorPart = (IEditorPart) part; propertiesFileEditorPart.addPropertyListener(updatePreviewOnSavePropertiesFile); } } } } private void connectTo(IWorkbenchPart part) { clearSWTXMLConnection(); clearPropertiesFileConnection(); swtXmlEditorPart = (IEditorPart) part; part.addPropertyListener(updatePreviewOnSaveSwtXml); updatePreview(false); } private void clearPropertiesFileConnection() { if (propertiesFileEditorPart != null) { propertiesFileEditorPart.removePropertyListener(updatePreviewOnSavePropertiesFile); propertiesFileEditorPart = null; } } public void clearSWTXMLConnection() { if (swtXmlEditorPart != null) { swtXmlEditorPart.removePropertyListener(updatePreviewOnSaveSwtXml); setContent(null); swtXmlEditorPart = null; } } private void updatePreview(boolean force) { if (swtXmlEditorPart == null) { setContent(null); return; } IDocument doc = (IDocument) swtXmlEditorPart.getAdapter(IDocument.class); IDocumentExtension4 document = (IDocumentExtension4) doc; if (force || document.getModificationStamp() != lastPreviewModificationStamp) { try { ResizableComposite resizableComposite = null; Composite newComposite; Composite swtXmlComposite; if (resizeAction.isChecked()) { resizableComposite = new ResizableComposite(container); newComposite = resizableComposite; swtXmlComposite = resizableComposite.getResizeableComposite(); } else { newComposite = swtXmlComposite = new Composite(container, SWT.None); } IEditorInput editorInput = swtXmlEditorPart.getEditorInput(); ILocationProvider locationProvider = (ILocationProvider) editorInput .getAdapter(ILocationProvider.class); File file = (locationProvider == null) ? null : locationProvider.getPath( editorInput).toFile(); FileEditorInput input = (FileEditorInput) editorInput; SwtXmlParser parser = new SwtXmlParser(swtXmlComposite, new PreviewResource( getProjectRootDir(input), file, doc), null); parser.parse(); setContent(newComposite); if (resizableComposite != null) { resizableComposite.resetSize(); } } catch (Exception e) { Activator.getDefault().getLog().log( new Status(Status.ERROR, Activator.PLUGIN_ID, e.getMessage(), e)); setContent(new ErrorComposite(container, SWT.NONE, e)); } finally { lastPreviewModificationStamp = document.getModificationStamp(); container.layout(); } } } private File getProjectRootDir(FileEditorInput input) { return new File(input.getFile().getProject().getLocationURI()); } /** * Disposes all elements except the new content. content might be null to * clear preview. */ private void setContent(Composite content) { for (Control c : container.getChildren()) { if (c != content) { c.dispose(); } } } @Override public void setFocus() { if (container != null) { container.setFocus(); } } }