content: /*******************************************************************************
   * Copyright (c) 2006, 2008 Abstratt Technologies and others.
   * 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:
   *    Rafael Chaves (Abstratt Technologies) - initial API and implementation
   *    Massimiliano Federici - bug 2127735 - multi-line comments lose highlighting
   *******************************************************************************/
  package com.abstratt.mdd.internal.ui.editors.source;
  
  import org.eclipse.core.resources.IFile;
  import org.eclipse.core.runtime.CoreException;
  import org.eclipse.core.runtime.IProgressMonitor;
  import org.eclipse.jface.action.IAction;
  import org.eclipse.jface.text.IDocument;
  import org.eclipse.jface.text.IDocumentPartitioner;
  import org.eclipse.jface.text.ITextInputListener;
  import org.eclipse.jface.text.ITextSelection;
  import org.eclipse.jface.text.rules.FastPartitioner;
  import org.eclipse.jface.text.source.ISourceViewer;
  import org.eclipse.jface.text.source.IVerticalRuler;
  import org.eclipse.swt.custom.BusyIndicator;
  import org.eclipse.swt.widgets.Composite;
  import org.eclipse.swt.widgets.Display;
  import org.eclipse.swt.widgets.Shell;
  import org.eclipse.ui.IFileEditorInput;
  import org.eclipse.ui.IWorkbenchPartSite;
  import org.eclipse.ui.editors.text.FileDocumentProvider;
  import org.eclipse.ui.editors.text.TextEditor;
  import org.eclipse.ui.texteditor.ContentAssistAction;
  import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
  import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
  
  import com.abstratt.mdd.frontend.ui.IMDDEditor;
  import com.abstratt.mdd.internal.frontend.textuml.TextUMLCompiler;
  import com.abstratt.mdd.internal.ui.TextUMLUIPlugin;
  import com.abstratt.mdd.internal.ui.editors.WorkingCopy;
  import com.abstratt.mdd.internal.ui.editors.WorkingCopyRegistry;
  
  public class SourceEditor extends TextEditor implements IMDDEditor {
  
      protected SourceContentOutlinePage outlinePage;
  
      public SourceEditor() {
          setSourceViewerConfiguration(new TextUMLSourceViewerConfiguration(this));
          // set the document provider to create the partitioner
          setDocumentProvider(new FileDocumentProvider() {
              protected IDocument createDocument(Object element) throws CoreException {
                  IDocument document = super.createDocument(element);
                  if (document != null) {
                      // this will create partitions
                      IDocumentPartitioner partitioner = new FastPartitioner(new PartitionScanner(),
                              ContentTypes.CONFIGURED_CONTENT_TYPES);
                      partitioner.connect(document);
                      document.setDocumentPartitioner(partitioner);
                  }
                  return document;
              }
          });
      }
  
      @Override
      protected void createActions() {
          super.createActions();
  
          IAction contentAssistAction = new ContentAssistAction(Messages.RESOURCE_BUNDLE, "ContentAssistProposal.", this);
          contentAssistAction.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
          setAction("ContentAssistProposal", contentAssistAction);
          markAsStateDependentAction("ContentAssistProposal", true);
      }
  
      @Override
      protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
          ISourceViewer viewer = super.createSourceViewer(parent, ruler, styles);
  
          // register IDocument with Jabal registry
          viewer.addTextInputListener(new ITextInputListener() {
              public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
                  // nothing for now
              }
  
              public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
                  WorkingCopyRegistry registry = WorkingCopyRegistry.getInstance();
                  if (oldInput != null) {
                      registry.unregister(oldInput);
                  }
                  if (newInput != null) {
                      final IFile file = getFile();
                      if (file != null)
                          registry.register(newInput, file);
                  }
              }
          });
  
          return viewer;
      }
  
      @Override
      public void doSave(IProgressMonitor progressMonitor) {
          super.doSave(progressMonitor);
          // TODO: we need a better solution to update the outline
          if (outlinePage != null)
              outlinePage.refresh();
      }
  
      @Override
      protected void performSaveAs(IProgressMonitor progressMonitor) {
          if (TextUMLUIPlugin.getDefault().getPluginPreferences().getBoolean(TextUMLUIPlugin.FORMAT_ON_SAVE))
              doFormat();
          super.performSaveAs(progressMonitor);
      }
  
      @Override
      protected void performSave(boolean overwrite, IProgressMonitor progressMonitor) {
          if (TextUMLUIPlugin.getDefault().getPluginPreferences().getBoolean(TextUMLUIPlugin.FORMAT_ON_SAVE))
              doFormat();
          super.performSave(overwrite, progressMonitor);
      }
  
      public void format() {
          Display display = null;
          IWorkbenchPartSite site = getSite();
          Shell shell = site.getShell();
          if (shell != null && !shell.isDisposed())
              display = shell.getDisplay();
          BusyIndicator.showWhile(display, new Runnable() {
              public void run() {
                  doFormat();
              }
          });
      }
  
      @Override
      public Object getAdapter(Class adapter) {
          if (IContentOutlinePage.class.equals(adapter)) {
              if (outlinePage == null) {
                  outlinePage = new SourceContentOutlinePage(this);
              }
              return outlinePage;
          }
          return super.getAdapter(adapter);
      }
  
      /**
       * Returns the corresponding file, if any.
       * 
       * @return
       */
      protected IFile getFile() {
          if (!(getEditorInput() instanceof IFileEditorInput))
              return null;
          IFileEditorInput input = (IFileEditorInput) getEditorInput();
          return input.getFile();
      }
  
      public IFile getModelFile() {
          final WorkingCopy workingCopy = getWorkingCopy();
          if (workingCopy == null)
              return null;
          IDocument document = workingCopy.getDocument();
          String toFormat = document.get();
          String modelName = new TextUMLCompiler().findModelName(toFormat);
          if (modelName == null)
              modelName = getFile().getFullPath().removeFileExtension().lastSegment();
          // TODO clean-up
          IFile modelFile = getFile().getProject().getFile(modelName + ".uml");
          return modelFile;
      }
  
      public WorkingCopy getWorkingCopy() {
          WorkingCopyRegistry registry = WorkingCopyRegistry.getInstance();
          IDocument document = getSourceViewer().getDocument();
          return registry.getWorkingCopy(document);
      }
  
      private void doFormat() {
          ITextSelection selection = (ITextSelection) getSelectionProvider().getSelection();
          IDocument document = getWorkingCopy().getDocument();
          String toFormat = document.get();
          String formatted = new TextUMLCompiler().format(toFormat);
          document.set(formatted);
          getSelectionProvider().setSelection(selection);
      }
  }