Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hotkey for expand/collapse project tree #3083

Merged
merged 6 commits into from Nov 17, 2016
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,47 @@
/*******************************************************************************
* 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.api.data.tree;

import com.google.common.annotations.Beta;

/**
* Component which performs basic tree operation such as expand and collapse.
*
* @author Vlad Zhukovskyi
* @since 5.0.0
*/
@Beta
public interface TreeExpander {

/**
* Perform tree expand in case if {@link #isExpandEnabled()} returns {@code true}.
*/
void expandTree();

/**
* Returns {@code true} in case if tree expand is possible.
*
* @return {@code true} in case if tree expand is possible, otherwise {@code false}
*/
boolean isExpandEnabled();

/**
* Perform tree collapse in case if {@link #isCollapseEnabled()} returns {@code true}.
*/
void collapseTree();

/**
* Returns {@code true} in case if tree collapse is possible.
*
* @return {@code true} in case if tree collapse is possible, otherwise {@code false}
*/
boolean isCollapseEnabled();
}
@@ -0,0 +1,53 @@
/*******************************************************************************
* 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.actions.common;

import org.eclipse.che.ide.api.action.Action;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.data.tree.TreeExpander;

import static com.google.common.base.Preconditions.checkNotNull;

/**
* Base tree collapse action which consumes instance of {@link TreeExpander}.
*
* @author Vlad Zhukovskyi
* @see TreeExpander
* @since 5.0.0
*/
public abstract class CollapseTreeAction extends Action {

public abstract TreeExpander getTreeExpander();

public CollapseTreeAction() {
super("Collapse All");
}

@Override
public void actionPerformed(ActionEvent e) {
final TreeExpander treeExpander = getTreeExpander();

checkNotNull(treeExpander);

if (!treeExpander.isCollapseEnabled()) {
return;
}

treeExpander.collapseTree();
}

@Override
public void update(ActionEvent e) {
final TreeExpander treeExpander = getTreeExpander();

e.getPresentation().setEnabledAndVisible(treeExpander.isCollapseEnabled());
}
}
@@ -0,0 +1,53 @@
/*******************************************************************************
* 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.actions.common;

import org.eclipse.che.ide.api.action.Action;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.data.tree.TreeExpander;

import static com.google.common.base.Preconditions.checkNotNull;

/**
* Base tree expand action which consumes instance of {@link TreeExpander}.
*
* @author Vlad Zhukovskyi
* @see TreeExpander
* @since 5.0.0
*/
public abstract class ExpandTreeAction extends Action {

public abstract TreeExpander getTreeExpander();

public ExpandTreeAction() {
super("Expand All");
}

@Override
public void actionPerformed(ActionEvent e) {
final TreeExpander treeExpander = getTreeExpander();

checkNotNull(treeExpander);

if (!treeExpander.isExpandEnabled()) {
return;
}

treeExpander.expandTree();
}

@Override
public void update(ActionEvent e) {
final TreeExpander treeExpander = getTreeExpander();

e.getPresentation().setEnabledAndVisible(treeExpander.isExpandEnabled());
}
}
Expand Up @@ -20,7 +20,9 @@
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.ide.CoreLocalizationConstant;
import org.eclipse.che.ide.Resources;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.data.tree.Node;
import org.eclipse.che.ide.api.data.tree.TreeExpander;
import org.eclipse.che.ide.api.data.tree.settings.NodeSettings;
import org.eclipse.che.ide.api.data.tree.settings.SettingsProvider;
import org.eclipse.che.ide.api.mvp.View;
Expand All @@ -37,11 +39,13 @@
import org.eclipse.che.ide.api.selection.Selection;
import org.eclipse.che.ide.api.workspace.event.WorkspaceStoppedEvent;
import org.eclipse.che.ide.part.explorer.project.ProjectExplorerView.ActionDelegate;
import org.eclipse.che.ide.project.node.SyntheticNode;
import org.eclipse.che.ide.project.node.SyntheticNodeUpdateEvent;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.resources.tree.ResourceNode;
import org.eclipse.che.ide.ui.smartTree.NodeDescriptor;
import org.eclipse.che.ide.ui.smartTree.Tree;
import org.eclipse.che.ide.ui.smartTree.event.BeforeExpandNodeEvent;
import org.eclipse.che.ide.ui.smartTree.event.SelectionChangedEvent;
import org.eclipse.che.ide.ui.smartTree.event.SelectionChangedEvent.SelectionChangedHandler;
import org.eclipse.che.providers.DynaObject;
Expand Down Expand Up @@ -74,6 +78,7 @@ public class ProjectExplorerPresenter extends BasePresenter implements ActionDel
private final SettingsProvider settingsProvider;
private final CoreLocalizationConstant locale;
private final Resources resources;
private final TreeExpander treeExpander;

private static final int PART_SIZE = 500;

Expand All @@ -85,7 +90,8 @@ public ProjectExplorerPresenter(final ProjectExplorerView view,
CoreLocalizationConstant locale,
Resources resources,
final ResourceNode.NodeFactory nodeFactory,
final SettingsProvider settingsProvider) {
final SettingsProvider settingsProvider,
final AppContext appContext) {
this.view = view;
this.nodeFactory = nodeFactory;
this.settingsProvider = settingsProvider;
Expand All @@ -109,6 +115,50 @@ public void onSelectionChanged(SelectionChangedEvent event) {
setSelection(new Selection<>(event.getSelection()));
}
});

view.getTree().addBeforeExpandHandler(new BeforeExpandNodeEvent.BeforeExpandNodeHandler() {
@Override
public void onBeforeExpand(BeforeExpandNodeEvent event) {
final NodeDescriptor nodeDescriptor = view.getTree().getNodeDescriptor(event.getNode());

if (event.getNode() instanceof SyntheticNode && nodeDescriptor != null && nodeDescriptor.isExpandDeep()) {
event.setCancelled(true);
}
}
});

treeExpander = new ProjectExplorerTreeExpander(view.getTree(), appContext);

registerNative();
}

/* Expose Project Explorer's internal API to the world, to allow automated Selenium scripts expand all projects tree. */
private native void registerNative() /*-{
var that = this;

var ProjectExplorer = {};

ProjectExplorer.expandAll = $entry(function() {
that.@org.eclipse.che.ide.part.explorer.project.ProjectExplorerPresenter::doExpand()();
})

ProjectExplorer.collapseAll = $entry(function() {
that.@org.eclipse.che.ide.part.explorer.project.ProjectExplorerPresenter::doCollapse()();
})

$wnd.IDE.ProjectExplorer = ProjectExplorer;
}-*/;

private void doExpand() {
if (treeExpander.isExpandEnabled()) {
treeExpander.expandTree();
}
}

private void doCollapse() {
if (treeExpander.isCollapseEnabled()) {
treeExpander.collapseTree();
}
}

@Override
Expand Down
@@ -0,0 +1,80 @@
package org.eclipse.che.ide.part.explorer.project;

import com.google.common.base.Predicate;

import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.data.tree.Node;
import org.eclipse.che.ide.api.data.tree.TreeExpander;
import org.eclipse.che.ide.api.resources.Resource;
import org.eclipse.che.ide.ui.smartTree.Tree;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.any;

/**
* Project explorer tree expander. Takes care about resources loading state, in case if tree has been never expanded before, it requests
* infinite resource tree from the server and then expands project tree on the UI. On the second time it just expands project tree without
* additional resource requests.
*
* @author Vlad Zhukovskyi
* @since 5.0.0
* @see TreeExpander
*/
final class ProjectExplorerTreeExpander implements TreeExpander {

private Tree tree;
private AppContext appContext;

public ProjectExplorerTreeExpander(Tree tree, AppContext appContext) {
this.tree = tree;
this.appContext = appContext;
}

private final boolean[] everExpanded = new boolean[]{false};

@Override
public void expandTree() {
if (everExpanded[0]) {
tree.expandAll();

return;
}

appContext.getWorkspaceRoot().getTree(-1).then(new Operation<Resource[]>() {
@Override
public void apply(Resource[] ignored) throws OperationException {
everExpanded[0] = true;

tree.expandAll();
}
});
}

@Override
public boolean isExpandEnabled() {
return tree.getNodeStorage().getAllItemsCount() != 0;
}

@Override
public void collapseTree() {
tree.collapseAll();
}

@Override
public boolean isCollapseEnabled() {
return any(tree.getRootNodes(), isExpanded());
}

private Predicate<Node> isExpanded() {
return new Predicate<Node>() {
@Override
public boolean apply(@javax.annotation.Nullable Node node) {
checkNotNull(node);

return tree.isExpanded(node);
}
};
}
}
Expand Up @@ -631,10 +631,10 @@ Promise<Resource[]> getRemoteResources(final Container container, final int dept
return promises.resolve(NO_RESOURCES);
}

int depthToReload = depth;
final Optional<Resource[]> descendants = store.getAll(container.getLocation());

int depthToReload = depth;
if (descendants.isPresent()) {
if (depthToReload != -1 && descendants.isPresent()) {
for (Resource resource : descendants.get()) {
if (resource.getLocation().segmentCount() - container.getLocation().segmentCount() > depth) {
depthToReload = resource.getLocation().segmentCount() - container.getLocation().segmentCount();
Expand Down