/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.actions;
import com.google.common.base.Optional;
import com.google.gwt.core.client.Callback;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.HandlerRegistration;
import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.callback.CallbackPromiseHelper.Call;
import org.eclipse.che.api.promises.client.js.JsPromiseError;
import org.eclipse.che.api.promises.client.js.Promises;
import org.eclipse.che.ide.CoreLocalizationConstant;
import org.eclipse.che.ide.api.action.Action;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.action.PromisableAction;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.editor.EditorAgent;
import org.eclipse.che.ide.api.editor.EditorPartPresenter;
import org.eclipse.che.ide.api.editor.text.TextPosition;
import org.eclipse.che.ide.api.editor.texteditor.TextEditor;
import org.eclipse.che.ide.api.event.ActivePartChangedEvent;
import org.eclipse.che.ide.api.event.ActivePartChangedHandler;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.api.resources.File;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.util.loging.Log;
import static org.eclipse.che.api.promises.client.callback.CallbackPromiseHelper.createFromCallback;
import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.FLOAT_MODE;
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL;
/**
* TODO maybe rename it to factory open file?
*
* @author Sergii Leschenko
* @author Vlad Zhukovskyi
*/
@Singleton
public class OpenFileAction extends Action implements PromisableAction {
/** ID of the parameter to specify file path to open. */
public static final String FILE_PARAM_ID = "file";
public static final String LINE_PARAM_ID = "line";
private final EventBus eventBus;
private final CoreLocalizationConstant localization;
private final NotificationManager notificationManager;
private final AppContext appContext;
private final EditorAgent editorAgent;
private Callback<Void, Throwable> actionCompletedCallback;
@Inject
public OpenFileAction(EventBus eventBus,
CoreLocalizationConstant localization,
NotificationManager notificationManager,
AppContext appContext,
EditorAgent editorAgent) {
this.eventBus = eventBus;
this.localization = localization;
this.notificationManager = notificationManager;
this.appContext = appContext;
this.editorAgent = editorAgent;
}
@Override
public void actionPerformed(ActionEvent event) {
if (event.getParameters() == null) {
Log.error(getClass(), localization.canNotOpenFileWithoutParams());
return;
}
final String pathToOpen = event.getParameters().get(FILE_PARAM_ID);
if (pathToOpen == null) {
Log.error(getClass(), localization.fileToOpenIsNotSpecified());
return;
}
appContext.getWorkspaceRoot().getFile(pathToOpen).then(new Operation<Optional<File>>() {
@Override
public void apply(Optional<File> optionalFile) throws OperationException {
if (optionalFile.isPresent()) {
if (actionCompletedCallback != null) {
actionCompletedCallback.onSuccess(null);
}
editorAgent.openEditor(optionalFile.get(), new EditorAgent.OpenEditorCallback() {
@Override
public void onEditorOpened(EditorPartPresenter editor) {
if (!(editor instanceof TextEditor)) {
return;
}
try {
int lineNumber = Integer.parseInt(event.getParameters().get(LINE_PARAM_ID)) - 1;
((TextEditor)editor).getDocument()
.setCursorPosition(new TextPosition(lineNumber, 0));
} catch (NumberFormatException e) {
Log.error(getClass(), localization.fileToOpenLineIsNotANumber());
}
}
@Override
public void onInitializationFailed() {
}
@Override
public void onEditorActivated(EditorPartPresenter editor) {
}
});
} else {
if (actionCompletedCallback != null) {
actionCompletedCallback.onFailure(null);
}
notificationManager.notify(localization.unableOpenResource(pathToOpen), FAIL, FLOAT_MODE);
}
}
});
}
@Override
public Promise<Void> promise(final ActionEvent actionEvent) {
if (actionEvent.getParameters() == null) {
return Promises.reject(JsPromiseError.create(localization.canNotOpenFileWithoutParams()));
}
final String pathToOpen = actionEvent.getParameters().get(FILE_PARAM_ID);
if (pathToOpen == null) {
return Promises.reject(JsPromiseError.create(localization.fileToOpenIsNotSpecified()));
}
final Call<Void, Throwable> call = new Call<Void, Throwable>() {
HandlerRegistration handlerRegistration;
@Override
public void makeCall(final Callback<Void, Throwable> callback) {
actionCompletedCallback = callback;
handlerRegistration = eventBus.addHandler(ActivePartChangedEvent.TYPE, new ActivePartChangedHandler() {
@Override
public void onActivePartChanged(ActivePartChangedEvent event) {
if (event.getActivePart() instanceof EditorPartPresenter) {
EditorPartPresenter editor = (EditorPartPresenter)event.getActivePart();
handlerRegistration.removeHandler();
if (Path.valueOf(pathToOpen).equals(editor.getEditorInput().getFile().getLocation())) {
callback.onSuccess(null);
}
}
}
});
actionPerformed(actionEvent);
}
};
return createFromCallback(call);
}
}