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 1 commit
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,65 @@
/*******************************************************************************
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What reason have this class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a factory for common actions, at this moment for collapse/expand tree. It can be used to create dynamic actions that should not be registered in the ActionManager but displayed on the any tree you want.

* 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 com.google.common.annotations.Beta;

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

/**
* Utility methods to create basic common actions.
*
* @author Vlad Zhukovskyi
* @since 5.0.0
*/
@Beta
public class ActionFactory {

/**
* Returns the instance of the {@link TreeExpandAction} based on the given {@code expander}.
*
* @param expander
* tree expander
* @return instance of the {@link TreeExpandAction}
* @see TreeExpandAction
* @see TreeExpander
* @since 5.0.0
*/
public Action createExpandTreeAction(final TreeExpander expander) {
return new TreeExpandAction() {
@Override
public TreeExpander getTreeExpander() {
return expander;
}
};
}

/**
* Returns the instance of the {@link TreeCollapseAction} based on the given {@code expander}.
*
* @param expander
* tree expander
* @return instance of the {@link TreeCollapseAction}
* @see TreeCollapseAction
* @see TreeExpander
* @since 5.0.0
*/
public Action createCollapseTreeAction(final TreeExpander expander) {
return new TreeCollapseAction() {
@Override
public TreeExpander getTreeExpander() {
return expander;
}
};
}

}
@@ -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 TreeCollapseAction extends Action {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TreeCollapseAction -> CollapseTreeAction

public abstract TreeExpander getTreeExpander();

public TreeCollapseAction() {
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 TreeExpandAction extends Action {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TreeExpandAction -> ExpandTreeAction

public abstract TreeExpander getTreeExpander();

public TreeExpandAction() {
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 @@ -11,18 +11,28 @@
package org.eclipse.che.ide.part.explorer.project;

import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;

import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
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.action.Action;
import org.eclipse.che.ide.actions.common.ActionFactory;
import org.eclipse.che.ide.api.action.ActionManager;
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.keybinding.KeyBindingAgent;
import org.eclipse.che.ide.api.keybinding.KeyBuilder;
import org.eclipse.che.ide.api.mvp.View;
import org.eclipse.che.ide.api.parts.ProjectExplorerPart;
import org.eclipse.che.ide.api.parts.base.BasePresenter;
Expand All @@ -37,11 +47,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 All @@ -50,6 +62,8 @@
import javax.validation.constraints.NotNull;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.any;
import static org.eclipse.che.ide.api.resources.ResourceDelta.ADDED;
import static org.eclipse.che.ide.api.resources.ResourceDelta.MOVED_FROM;
import static org.eclipse.che.ide.api.resources.ResourceDelta.MOVED_TO;
Expand Down Expand Up @@ -85,7 +99,11 @@ public ProjectExplorerPresenter(final ProjectExplorerView view,
CoreLocalizationConstant locale,
Resources resources,
final ResourceNode.NodeFactory nodeFactory,
final SettingsProvider settingsProvider) {
final SettingsProvider settingsProvider,
ActionManager actionManager,
ActionFactory actionFactory,
final AppContext appContext,
KeyBindingAgent keyBindingAgent) {
this.view = view;
this.nodeFactory = nodeFactory;
this.settingsProvider = settingsProvider;
Expand All @@ -109,6 +127,78 @@ 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);
}
}
});

final TreeExpander treeExpander = new TreeExpander() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move it to dedicate class

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


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

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

return;
}

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

view.getTree().expandAll();
}
});
}

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

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

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

final Action expandTreeAction = actionFactory.createExpandTreeAction(treeExpander);
final Action collapseTreeAction = actionFactory.createCollapseTreeAction(treeExpander);

final String expandTreeActionId = "expandProjectExplorerTree";
final String collapseTreeActionId = "collapseProjectExplorerTree";

actionManager.registerAction(expandTreeActionId, expandTreeAction);
actionManager.registerAction(collapseTreeActionId, collapseTreeAction);

keyBindingAgent.getGlobal().addKey(new KeyBuilder().action().charCode('[').build(), expandTreeActionId);
keyBindingAgent.getGlobal().addKey(new KeyBuilder().action().charCode(']').build(), collapseTreeActionId);
}

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

return view.getTree().isExpanded(node);
}
};
}

@Override
Expand Down
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
Expand Up @@ -1163,6 +1163,10 @@ private void onExpand(Node node, NodeDescriptor nodeDescriptor, boolean deep) {
}

if (!fireCancellableEvent(new BeforeExpandNodeEvent(node))) {
if (deep) {
nodeDescriptor.setExpandDeep(false);
}

return;
}

Expand Down