/******************************************************************************* * Copyright (c) 2016 Bruno Medeiros and other Contributors. * 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: * Bruno Medeiros - initial API and implementation *******************************************************************************/ package melnorme.lang.ide.ui.editor; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import org.eclipse.jface.text.IDocument; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.texteditor.ITextEditor; import melnorme.lang.ide.core.text.ISourceBufferExt; import melnorme.lang.ide.core.utils.EclipseUtils; import melnorme.lang.ide.ui.utils.operations.WorkbenchOperationExecutor; import melnorme.lang.tooling.common.ISourceBuffer; import melnorme.lang.tooling.common.ops.IOperationMonitor.NullOperationMonitor; import melnorme.lang.tooling.common.ops.ResultOperation; import melnorme.utilbox.concurrency.ICancelMonitor; import melnorme.utilbox.concurrency.IRunnableFuture2; import melnorme.utilbox.concurrency.OperationCancellation; import melnorme.utilbox.core.CommonException; import melnorme.utilbox.core.fntypes.OperationResult; import melnorme.utilbox.misc.Location; /** * An abstraction of the buffer of an editor, or af a source viewer. * Note that location is not immutable! */ public class EditorSourceBuffer implements ISourceBufferExt { protected final ITextEditor editor; public EditorSourceBuffer(ITextEditor editor) { this.editor = assertNotNull(editor); } @Override public Location getLocation_orNull() { return EditorUtils.getInputLocationOrNull(editor); } @Override public IDocument getDocument() { return EditorUtils.getEditorDocument(editor); } @Override public boolean isDirty() { return editor.isDirty(); } @Override public void doTrySaveBuffer() throws CommonException, OperationCancellation { if(Display.getCurrent() == null) { ResultOperation<Void> operationCallable2 = (om) -> { saveBuffer(); return null; }; IRunnableFuture2<OperationResult<Void>> resultRunnable = operationCallable2.toRunnableFuture( new NullOperationMonitor()); Display.getDefault().syncExec(resultRunnable); resultRunnable.awaitResult2().get(); // unwrap result and exceptions } else { saveBuffer(); } } protected void saveBuffer() throws CommonException, OperationCancellation { // Run under a progress dialog, but in the UI thread new WorkbenchOperationExecutor(true).execute(this::doSaveBuffer); } public void doSaveBuffer(ICancelMonitor cm) throws OperationCancellation { cm.checkCancellation(); if(editor instanceof AbstractLangEditor) { AbstractLangEditor langEditor = (AbstractLangEditor) editor; langEditor.saveWithoutSaveActions2(cm); } else { editor.doSave(EclipseUtils.pm(cm)); } } public static final CommonException CANNOT_SAVE_ReadOnlyView = new CommonException("Cannot save editor, read-only view."); @Override public ISourceBuffer getReadOnlyView() { return new EditorSourceBuffer(editor) { @Override public void doTrySaveBuffer() throws CommonException { throw CANNOT_SAVE_ReadOnlyView; } }; } /* ----------------- ----------------- */ public static class DocumentSourceBuffer implements ISourceBufferExt { protected final IDocument document; public DocumentSourceBuffer(IDocument document) { this.document = assertNotNull(document); } @Override public Location getLocation_orNull() { return null; } @Override public IDocument getDocument() { return document; } @Override public boolean isDirty() { // a source buffer with no location in the filesystem is always considered dirty // note: subclasses may override this return true; } @Override public void doTrySaveBuffer() throws CommonException { throw new CommonException("Cannot save document for this source buffer"); } @Override public ISourceBuffer getReadOnlyView() { return this; // This buffer is already readOnly } } }