/*******************************************************************************
* 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.ext.java.client.search.node;
import elemental.html.SpanElement;
import com.google.common.base.Optional;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Element;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
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.commons.annotation.Nullable;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.data.tree.HasAction;
import org.eclipse.che.ide.api.data.tree.Node;
import org.eclipse.che.ide.api.editor.EditorAgent;
import org.eclipse.che.ide.api.editor.EditorPartPresenter;
import org.eclipse.che.ide.api.editor.OpenEditorCallbackImpl;
import org.eclipse.che.ide.api.editor.text.LinearRange;
import org.eclipse.che.ide.api.editor.texteditor.TextEditor;
import org.eclipse.che.ide.api.resources.File;
import org.eclipse.che.ide.api.resources.Project;
import org.eclipse.che.ide.api.resources.Resource;
import org.eclipse.che.ide.api.resources.SyntheticFile;
import org.eclipse.che.ide.api.resources.VirtualFile;
import org.eclipse.che.ide.ext.java.client.JavaResources;
import org.eclipse.che.ide.ext.java.client.navigation.service.JavaNavigationService;
import org.eclipse.che.ide.ext.java.shared.dto.ClassContent;
import org.eclipse.che.ide.ext.java.shared.dto.Region;
import org.eclipse.che.ide.ext.java.shared.dto.model.ClassFile;
import org.eclipse.che.ide.ext.java.shared.dto.model.CompilationUnit;
import org.eclipse.che.ide.ext.java.shared.dto.search.Match;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.ui.smartTree.TreeStyles;
import org.eclipse.che.ide.ui.smartTree.presentation.NodePresentation;
import org.eclipse.che.ide.util.dom.Elements;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* Node represent Match for find usages search.
*
* @author Evgen Vidolob
*/
public class MatchNode extends AbstractPresentationNode implements HasAction {
private TreeStyles styles;
private JavaResources resources;
private EditorAgent editorAgent;
private AppContext appContext;
private Match match;
private CompilationUnit compilationUnit;
private ClassFile classFile;
private final JavaNavigationService service;
@Inject
public MatchNode(TreeStyles styles,
JavaResources resources,
EditorAgent editorAgent,
AppContext appContext,
@Assisted Match match,
@Nullable @Assisted CompilationUnit compilationUnit,
@Nullable @Assisted ClassFile classFile,
JavaNavigationService service) {
this.styles = styles;
this.resources = resources;
this.editorAgent = editorAgent;
this.appContext = appContext;
this.match = match;
this.compilationUnit = compilationUnit;
this.classFile = classFile;
this.service = service;
}
@Override
protected Promise<List<Node>> getChildrenImpl() {
return null;
}
@Override
public void updatePresentation(@NotNull NodePresentation presentation) {
SpanElement spanElement = Elements.createSpanElement(styles.styles().presentableTextContainer());
SpanElement lineNumberElement = Elements.createSpanElement();
lineNumberElement.setInnerHTML(String.valueOf(match.getMatchLineNumber() + 1) + ": ");
spanElement.appendChild(lineNumberElement);
SpanElement textElement = Elements.createSpanElement();
Region matchInLine = match.getMatchInLine();
String matchedLine = match.getMatchedLine();
if (matchedLine != null && matchInLine != null) {
String startLine = matchedLine.substring(0, matchInLine.getOffset());
textElement.appendChild(Elements.createTextNode(startLine));
SpanElement highlightElement = Elements.createSpanElement(resources.css().searchMatch());
highlightElement
.setInnerText(matchedLine.substring(matchInLine.getOffset(), matchInLine.getOffset() + matchInLine.getLength()));
textElement.appendChild(highlightElement);
textElement.appendChild(Elements.createTextNode(matchedLine.substring(matchInLine.getOffset() + matchInLine.getLength())));
} else {
textElement.appendChild(Elements.createTextNode("Can't find sources"));
}
spanElement.appendChild(textElement);
presentation.setPresentableIcon(resources.searchMatch());
presentation.setUserElement((Element)spanElement);
}
@Override
public String getName() {
return match.getMatchedLine();
}
@Override
public boolean isLeaf() {
return true;
}
public Match getMatch() {
return match;
}
@Override
public void actionPerformed() {
if (compilationUnit != null) {
final EditorPartPresenter editorPartPresenter = editorAgent.getOpenedEditor(Path.valueOf(compilationUnit.getPath()));
if (editorPartPresenter != null) {
selectRange(editorPartPresenter);
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
@Override
public void execute() {
editorAgent.activateEditor(editorPartPresenter);
}
});
return;
}
appContext.getWorkspaceRoot().getFile(compilationUnit.getPath()).then(new Operation<Optional<File>>() {
@Override
public void apply(Optional<File> file) throws OperationException {
if (file.isPresent()) {
editorAgent.openEditor(file.get(), new OpenEditorCallbackImpl() {
@Override
public void onEditorOpened(EditorPartPresenter editor) {
selectRange(editor);
}
});
}
}
});
} else if (classFile != null) {
final String className = classFile.getElementName();
final Resource resource = appContext.getResource();
if (resource == null) {
return;
}
final Project project = resource.getRelatedProject().get();
service.getContent(project.getLocation(), className)
.then(new Operation<ClassContent>() {
@Override
public void apply(ClassContent content) throws OperationException {
final VirtualFile file = new SyntheticFile(Path.valueOf(className.replace('.', '/')).lastSegment(),
content.getContent());
editorAgent.openEditor(file, new OpenEditorCallbackImpl() {
@Override
public void onEditorOpened(EditorPartPresenter editor) {
selectRange(editor);
}
});
}
});
}
}
private void selectRange(EditorPartPresenter editor) {
if (editor instanceof TextEditor) {
((TextEditor)editor).getDocument().setSelectedRange(
LinearRange.createWithStart(match.getFileMatchRegion().getOffset()).andLength(match.getFileMatchRegion().getLength()),
true);
}
}
}