/*******************************************************************************
* Copyright (c) 2012-2016 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.ext.java.client.editor;
import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Frame;
import com.google.gwt.user.client.ui.Widget;
import org.eclipse.che.ide.api.editor.EditorAgent;
import org.eclipse.che.ide.api.icon.Icon;
import org.eclipse.che.ide.api.text.Position;
import org.eclipse.che.ide.ext.java.client.refactoring.RefactorInfo;
import org.eclipse.che.ide.ext.java.client.refactoring.RefactoringUpdater;
import org.eclipse.che.ide.ext.java.client.refactoring.move.RefactoredItemType;
import org.eclipse.che.ide.ext.java.shared.dto.Change;
import org.eclipse.che.ide.ext.java.shared.dto.LinkedData;
import org.eclipse.che.ide.ext.java.shared.dto.LinkedModeModel;
import org.eclipse.che.ide.ext.java.shared.dto.LinkedPositionGroup;
import org.eclipse.che.ide.ext.java.shared.dto.ProposalApplyResult;
import org.eclipse.che.ide.ext.java.shared.dto.Region;
import org.eclipse.che.ide.ext.java.shared.dto.refactoring.ChangeInfo;
import org.eclipse.che.ide.jseditor.client.codeassist.Completion;
import org.eclipse.che.ide.jseditor.client.codeassist.CompletionProposal;
import org.eclipse.che.ide.jseditor.client.codeassist.CompletionProposalExtension;
import org.eclipse.che.ide.jseditor.client.document.Document;
import org.eclipse.che.ide.jseditor.client.link.HasLinkedMode;
import org.eclipse.che.ide.jseditor.client.link.LinkedMode;
import org.eclipse.che.ide.jseditor.client.link.LinkedModel;
import org.eclipse.che.ide.jseditor.client.link.LinkedModelData;
import org.eclipse.che.ide.jseditor.client.link.LinkedModelGroup;
import org.eclipse.che.ide.jseditor.client.text.LinearRange;
import org.eclipse.che.ide.util.loging.Log;
import java.util.ArrayList;
import java.util.List;
/**
* @author Evgen Vidolob
*/
public class JavaCompletionProposal implements CompletionProposal, CompletionProposalExtension {
private final int id;
private final String display;
private final Icon icon;
private final JavaCodeAssistClient client;
private final RefactoringUpdater refactoringUpdater;
private final EditorAgent editorAgent;
private String sessionId;
private HasLinkedMode linkedEditor;
public JavaCompletionProposal(final int id,
final String display,
final Icon icon,
final JavaCodeAssistClient client,
String sessionId, HasLinkedMode linkedEditor,
RefactoringUpdater refactoringUpdater,
EditorAgent editorAgent) {
this.id = id;
this.display = display;
this.icon = icon;
this.client = client;
this.sessionId = sessionId;
this.linkedEditor = linkedEditor;
this.refactoringUpdater = refactoringUpdater;
this.editorAgent = editorAgent;
}
/** {@inheritDoc} */
@Override
public Widget getAdditionalProposalInfo() {
Frame frame = new Frame();
frame.setSize("100%", "100%");
frame.getElement().getStyle().setBorderStyle(Style.BorderStyle.NONE);
frame.getElement().setAttribute("sandbox", ""); // empty value, not null
frame.getElement().getStyle().setProperty("resize", "both");
frame.setUrl(client.getProposalDocUrl(id, sessionId));
return frame;
}
/** {@inheritDoc} */
@Override
public String getDisplayString() {
return display;
}
/** {@inheritDoc} */
@Override
public Icon getIcon() {
return icon;
}
@Override
public void getCompletion(final CompletionCallback callback) {
getCompletion(true, callback);
}
@Override
public void getCompletion(boolean insert, final CompletionCallback callback) {
client.applyProposal(sessionId, id, insert, new AsyncCallback<ProposalApplyResult>() {
@Override
public void onFailure(Throwable caught) {
Log.error(JavaCompletionProposal.class, caught);
}
@Override
public void onSuccess(ProposalApplyResult result) {
callback.onCompletion(new CompletionImpl(result.getChanges(), result.getSelection(), result.getLinkedModeModel()));
ArrayList selectedItems = new ArrayList(1);
selectedItems.add(editorAgent.getActiveEditor().getEditorInput().getFile());
RefactorInfo refactorInfo = RefactorInfo.of(RefactoredItemType.JAVA_ELEMENT, selectedItems);
ChangeInfo changeInfo = result.getChangeInfo();
if (changeInfo == null) {
return;
}
ArrayList<ChangeInfo> changes = new ArrayList<>(1);
changes.add(changeInfo);
refactoringUpdater.updateAfterRefactoring(refactorInfo, changes);
}
});
}
private class CompletionImpl implements Completion {
private final List<Change> changes;
private final Region region;
private LinkedModeModel linkedModeModel;
private int cursorOffset;
private CompletionImpl(final List<Change> changes, final Region region, final LinkedModeModel linkedModeModel) {
this.changes = changes;
this.region = region;
this.linkedModeModel = linkedModeModel;
}
/** {@inheritDoc} */
@Override
public void apply(final Document document) {
cursorOffset = document.getCursorOffset();
for (final Change change : changes) {
document.replace(change.getOffset(), change.getLength(), change.getText());
}
if (linkedEditor != null && linkedModeModel != null) {
LinkedMode mode = linkedEditor.getLinkedMode();
LinkedModel model = linkedEditor.createLinkedModel();
if (linkedModeModel.getEscapePosition() != 0) {
model.setEscapePosition(linkedModeModel.getEscapePosition());
} else {
model.setEscapePosition(cursorOffset);
}
List<LinkedModelGroup> groups = new ArrayList<>();
for (LinkedPositionGroup positionGroup : linkedModeModel.getGroups()) {
LinkedModelGroup group = linkedEditor.createLinkedGroup();
LinkedData data = positionGroup.getData();
if (data != null) {
LinkedModelData modelData = linkedEditor.createLinkedModelData();
modelData.setType("link");
modelData.setValues(data.getValues());
group.setData(modelData);
}
List<Position> positions = new ArrayList<>();
for (Region region : positionGroup.getPositions()) {
positions.add(new Position(region.getOffset(), region.getLength()));
}
group.setPositions(positions);
groups.add(group);
}
model.setGroups(groups);
mode.enterLinkedMode(model);
}
}
/** {@inheritDoc} */
@Override
public LinearRange getSelection(final Document document) {
if (region == null) {
//keep cursor location
return LinearRange.createWithStart(cursorOffset).andLength(0);
} else {
return LinearRange.createWithStart(region.getOffset()).andLength(region.getLength());
}
}
}
}