/*******************************************************************************
* Copyright (c) 2012-2015 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.jseditor.client.texteditor;
import org.eclipse.che.ide.Resources;
import org.eclipse.che.ide.api.texteditor.outline.CodeBlock;
import org.eclipse.che.ide.api.texteditor.outline.OutlineModel;
import org.eclipse.che.ide.api.texteditor.outline.OutlinePresenter;
import org.eclipse.che.ide.jseditor.client.document.Document;
import org.eclipse.che.ide.jseditor.client.text.TextPosition;
import org.eclipse.che.ide.outline.CodeBlockDataAdapter;
import org.eclipse.che.ide.outline.OutlineView;
import org.eclipse.che.ide.outline.OutlineViewImpl;
import org.eclipse.che.ide.texteditor.selection.CursorModelWithHandler;
import org.eclipse.che.ide.texteditor.selection.CursorModelWithHandler.CursorHandler;
import org.eclipse.che.ide.ui.tree.Tree;
import org.eclipse.che.ide.ui.tree.Tree.Listener;
import org.eclipse.che.ide.ui.tree.TreeNodeElement;
import org.eclipse.che.ide.util.input.SignalEvent;
import org.eclipse.che.ide.util.loging.Log;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import elemental.events.KeyboardEvent;
import elemental.events.MouseEvent;
/**
* Implementation of {@link OutlinePresenter} for the embedded editors.
*
* @author <a href="mailto:evidolob@exoplatform.com">Evgen Vidolob</a>
* @version $Id:
*/
public class OutlineImpl implements OutlinePresenter {
private final OutlineView view;
private final OutlineModel model;
private final CodeBlockDataAdapter dataAdapter;
private CodeBlock blockToSync;
private boolean thisCursorMove;
public OutlineImpl(final Resources resources, final OutlineModel model) {
this.model = model;
this.dataAdapter = new CodeBlockDataAdapter();
this.view = new OutlineViewImpl(resources, this.dataAdapter, this.model.getRenderer());
this.model.setListener(new OutlineModel.OutlineModelListener() {
@Override
public void rootUpdated() {
view.renderTree();
}
@Override
public void rootChanged(final CodeBlock newRoot) {
view.rootChanged(newRoot);
}
});
}
/**
* Binds the Outline to the given cursor model.
* @param cursorModel the cursor model
* @param document the document
*/
void bind(final CursorModelWithHandler cursorModel, final Document document) {
if (cursorModel == null) {
Log.debug(OutlineImpl.class, "No cursor model !!");
return;
}
this.view.setTreeEventHandler(new Listener<CodeBlock>() {
@Override
public void onNodeAction(final TreeNodeElement<CodeBlock> node) {
}
@Override
public void onNodeClosed(final TreeNodeElement<CodeBlock> node) {
}
@Override
public void onNodeContextMenu(final int mouseX, final int mouseY, final TreeNodeElement<CodeBlock> node) {
}
@Override
public void onNodeDragStart(final TreeNodeElement<CodeBlock> node, final MouseEvent event) {
}
@Override
public void onNodeDragDrop(final TreeNodeElement<CodeBlock> node, final MouseEvent event) {
}
@Override
public void onNodeExpanded(final TreeNodeElement<CodeBlock> node) {
}
@Override
public void onNodeSelected(final TreeNodeElement<CodeBlock> node, final SignalEvent event) {
thisCursorMove = true;
final CodeBlock data = node.getData();
final int offset = data.getOffset();
if (cursorModel != null) {
cursorModel.setCursorPosition(offset);
}
}
@Override
public void onRootContextMenu(final int mouseX, final int mouseY) {
}
@Override
public void onRootDragDrop(final MouseEvent event) {
}
@Override
public void onKeyboard(final KeyboardEvent event) {
}
});
if (document != null) {
Log.debug(OutlineImpl.class, "Cursor model available, adding cursor handler");
cursorModel.addCursorHandler(new CursorHandler() {
@Override
public void onCursorChange(final int line, final int column, final boolean isExplicitChange) {
if (thisCursorMove) {
thisCursorMove = false;
return;
}
if (model.getRoot() == null) {
return;
}
final TextPosition position = document.getCursorPosition();
final int offset = document.getIndexFromPosition(position);
blockToSync = null;
Tree.iterateDfs(model.getRoot(), dataAdapter, new Tree.Visitor<CodeBlock>() {
@Override
public boolean shouldVisit(final CodeBlock node) {
if (offset + 1 > node.getOffset() && offset - 1 < node.getOffset() + node.getLength()) {
return true;
} else {
return false;
}
}
@Override
public void visit(final CodeBlock node, final boolean willVisitChildren) {
blockToSync = node;
}
});
if (blockToSync != null) {
if (!CodeBlock.ROOT_TYPE.equals(blockToSync.getType())) {
view.selectAndExpand(blockToSync);
return;
}
}
}
});
} else {
Log.debug(OutlineImpl.class, "No document !!");
}
}
@Override
public void go(final AcceptsOneWidget container) {
container.setWidget(view);
}
}