blob: 36354ff7a4305852c213ddf5da1f8ba0c724d7c9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2015 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare;
import org.eclipse.compare.SharedDocumentAdapter;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.IElementStateListener;
/**
* A shared document adapter that tracks whether the element is connected to a
* shared document and whether the contents have been flushed from a compare
* viewer. When contents are flushed, this adapter will connect to the document
* provider to ensure that the changes are not lost (see
* {@link #hasBufferedContents()}). In order to avoid a leak, the buffer must
* either be saved (see
* {@link #saveDocument(IEditorInput, IProgressMonitor)}) or released
* (see {@link #releaseBuffer()}).
* <p>
* This adapter must have a one-to-one correspondence to a typed element.
*
* @since 3.7 - Copied from
* org.eclipse.team.internal.ui.synchronize.EditableSharedDocumentAdapter
*/
public class EditableSharedDocumentAdapter extends SharedDocumentAdapter implements IElementStateListener {
private int connectionCount;
private final ISharedDocumentAdapterListener listener;
private IEditorInput bufferedKey;
/**
* Interface that provides this adapter with the action of the typed element
* and supports call backs to the element when the adapter action changes.
*/
public interface ISharedDocumentAdapterListener {
/**
* Method that is invoked when the adapter connects to the document
* provider. This method is only invoked when the adapter first connects
* to the document.
*/
void handleDocumentConnected();
/**
* Method that is invoked when the adapter disconnects from the document
* provider. This method is only invoked when the adapter no longer has
* any connection to the document provider.
*/
void handleDocumentDisconnected();
/**
* Method invoked when changes in the document are flushed to the
* adapter.
*/
void handleDocumentFlushed();
/**
* Method invoked when the file behind the shared document is deleted.
*/
void handleDocumentDeleted();
/**
* Method invoked when the document dirty action changes from dirty to
* clean.
*/
void handleDocumentSaved();
}
/**
* Create the shared document adapter for the given element.
*
* @param listener
* access to element internals
*/
public EditableSharedDocumentAdapter(ISharedDocumentAdapterListener listener) {
super();
this.listener = listener;
}
/* (non-Javadoc)
* @see org.eclipse.compare.SharedDocumentAdapter#connect(org.eclipse.ui.texteditor.IDocumentProvider, org.eclipse.ui.IEditorInput)
*/
@Override
public void connect(IDocumentProvider provider, IEditorInput documentKey)
throws CoreException {
super.connect(provider, documentKey);
connectionCount++;
if (connectionCount == 1) {
provider.addElementStateListener(this);
listener.handleDocumentConnected();
}
}
/* (non-Javadoc)
* @see org.eclipse.compare.SharedDocumentAdapter#disconnect(org.eclipse.ui.texteditor.IDocumentProvider, org.eclipse.ui.IEditorInput)
*/
@Override
public void disconnect(IDocumentProvider provider, IEditorInput documentKey) {
try {
super.disconnect(provider, documentKey);
} finally {
if (connectionCount > 0)
connectionCount--;
if (connectionCount == 0) {
provider.removeElementStateListener(this);
listener.handleDocumentDisconnected();
}
}
}
/**
* Return whether the element is connected to a shared document.
*
* @return whether the element is connected to a shared document
*/
public boolean isConnected() {
return connectionCount > 0;
}
/**
* Save the shared document of the element of this adapter.
*
* @param input
* the document key of the element.
* @param monitor
* a progress monitor
* @return whether the save succeeded or not
* @throws CoreException
*/
public boolean saveDocument(IEditorInput input, IProgressMonitor monitor)
throws CoreException {
if (isConnected()) {
IDocumentProvider provider = SharedDocumentAdapter
.getDocumentProvider(input);
try {
saveDocument(provider, input, provider.getDocument(input),
true, monitor);
} finally {
// When we write the document, remove out hold on the buffer
releaseBuffer();
}
return true;
}
return false;
}
/**
* Release the buffer if this adapter has buffered the contents in response
* to a
* {@link #flushDocument(IDocumentProvider, IEditorInput, IDocument, boolean)}
* .
*/
public void releaseBuffer() {
if (bufferedKey != null) {
IDocumentProvider provider = SharedDocumentAdapter
.getDocumentProvider(bufferedKey);
provider.disconnect(bufferedKey);
bufferedKey = null;
}
}
/* (non-Javadoc)
* @see org.eclipse.compare.ISharedDocumentAdapter#flushDocument(org.eclipse.ui.texteditor.IDocumentProvider, org.eclipse.ui.IEditorInput, org.eclipse.jface.text.IDocument, boolean)
*/
@Override
public void flushDocument(IDocumentProvider provider,
IEditorInput documentKey, IDocument document, boolean overwrite)
throws CoreException {
if (!hasBufferedContents()) {
// On a flush, make an extra connection to the shared document so it
// will be kept even
// if it is no longer being viewed.
bufferedKey = documentKey;
provider.connect(bufferedKey);
}
this.listener.handleDocumentFlushed();
}
/* (non-Javadoc)
* @see org.eclipse.ui.texteditor.IElementStateListener#elementContentAboutToBeReplaced(java.lang.Object)
*/
@Override
public void elementContentAboutToBeReplaced(Object element) {
// Nothing to do
}
/* (non-Javadoc)
* @see org.eclipse.ui.texteditor.IElementStateListener#elementContentReplaced(java.lang.Object)
*/
@Override
public void elementContentReplaced(Object element) {
// Nothing to do
}
/* (non-Javadoc)
* @see org.eclipse.ui.texteditor.IElementStateListener#elementDeleted(java.lang.Object)
*/
@Override
public void elementDeleted(Object element) {
listener.handleDocumentDeleted();
}
/* (non-Javadoc)
* @see org.eclipse.ui.texteditor.IElementStateListener#elementDirtyStateChanged(java.lang.Object, boolean)
*/
@Override
public void elementDirtyStateChanged(Object element, boolean isDirty) {
if (!isDirty) {
this.listener.handleDocumentSaved();
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.texteditor.IElementStateListener#elementMoved(java.lang.Object, java.lang.Object)
*/
@Override
public void elementMoved(Object originalElement, Object movedElement) {
// Nothing to do
}
/**
* Return whether the adapter has buffered contents. The adapter buffers
* contents by connecting to the document through the document provider.
* This means that the adapter must be disconnected either by saving or
* discarding the buffer.
*
* @return whether the adapter has buffered contents
*/
public boolean hasBufferedContents() {
return bufferedKey != null;
}
/**
* Override getDocumentKey in the super class to provide an editor input
* when the element is a <code>LocalTypedElement</code>.
*/
@Override
public IEditorInput getDocumentKey(Object element) {
if (element instanceof LocalTypedElement) {
LocalTypedElement localElement = (LocalTypedElement) element;
return localElement.getEditorInput();
}
return super.getDocumentKey(element);
}
}