parent
1ff9b22221
commit
bbd0c1abb2
|
|
@ -4,7 +4,7 @@
|
|||
outline none
|
||||
width 24px
|
||||
height 16px
|
||||
top 4px
|
||||
top 9px
|
||||
background-color $navbar-ide-iframe-button-background-color
|
||||
color $light-gray-color
|
||||
font-size 8px
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ che-nav-bar
|
|||
|
||||
.navbar-iframe-button-left-border
|
||||
position absolute
|
||||
top 4px
|
||||
top 9px
|
||||
right 0
|
||||
width 0
|
||||
height 16px
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ public interface IdeActions {
|
|||
|
||||
String GROUP_OTHER_MENU = "otherMenu";
|
||||
String GROUP_LEFT_MAIN_MENU = "leftMainMenu";
|
||||
@Deprecated
|
||||
String GROUP_RIGHT_MAIN_MENU = "rightMainMenu";
|
||||
|
||||
String GROUP_CENTER_STATUS_PANEL = "centerStatusPanelGroup";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
/*******************************************************************************
|
||||
* 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.api.command;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Base implementation of the {@link CommandGoal}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class BaseCommandGoal implements CommandGoal {
|
||||
|
||||
private final String id;
|
||||
|
||||
public BaseCommandGoal(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof CommandGoal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CommandGoal other = (CommandGoal)o;
|
||||
|
||||
return Objects.equals(getId(), other.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*******************************************************************************
|
||||
* 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.api.command;
|
||||
|
||||
import org.eclipse.che.api.core.model.machine.Command;
|
||||
import org.eclipse.che.api.core.model.machine.Machine;
|
||||
import org.eclipse.che.ide.api.macro.Macro;
|
||||
|
||||
/**
|
||||
* Allows to execute a command.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface CommandExecutor {
|
||||
|
||||
/**
|
||||
* Sends the the given {@code command} to the specified {@code machine} for execution.
|
||||
* <p><b>Note</b> that all {@link Macro}s will be expanded into
|
||||
* real values before sending the {@code command} for execution.
|
||||
*
|
||||
* @param command
|
||||
* command to execute
|
||||
* @param machine
|
||||
* machine to execute the command
|
||||
* @see Macro
|
||||
*/
|
||||
void executeCommand(Command command, Machine machine);
|
||||
|
||||
/**
|
||||
* Sends the the given {@code command} for execution.
|
||||
* <p>If any machine is currently selected it will be used as execution target.
|
||||
* Otherwise user will be asked for choosing execution target.
|
||||
* <p><b>Note</b> that all {@link Macro}s will be expanded into
|
||||
* real values before sending the {@code command} for execution.
|
||||
*
|
||||
* @param command
|
||||
* command to execute
|
||||
* @see Macro
|
||||
*/
|
||||
void executeCommand(CommandImpl command);
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*******************************************************************************
|
||||
* 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.api.command;
|
||||
|
||||
/**
|
||||
* Contract for command goal.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface CommandGoal {
|
||||
|
||||
/** Returns goal ID. */
|
||||
String getId();
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*******************************************************************************
|
||||
* 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.api.command;
|
||||
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Registry of command goals.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface CommandGoalRegistry {
|
||||
|
||||
/** Returns all registered predefined {@link CommandGoal}s. */
|
||||
List<CommandGoal> getAllPredefinedGoals();
|
||||
|
||||
/** Returns the default command goal which is used for grouping commands which doesn't belong to any goal. */
|
||||
CommandGoal getDefaultGoal();
|
||||
|
||||
/**
|
||||
* Returns an optional {@link CommandGoal} by the given ID
|
||||
* or {@code Optional.absent()} if none was registered.
|
||||
*
|
||||
* @param id
|
||||
* the ID of the predefined command goal to get
|
||||
* @return an optional {@link CommandGoal} or {@code Optional.absent()} if none was registered
|
||||
*/
|
||||
Optional<CommandGoal> getPredefinedGoalById(String id);
|
||||
|
||||
/**
|
||||
* Returns a predefined {@link CommandGoal} by the given ID
|
||||
* or the custom (non-predefined) goal if none was registered
|
||||
* or the default goal if the given {@code id} is {@code null} or empty string.
|
||||
*
|
||||
* @param id
|
||||
* the ID of the command goal
|
||||
* @return a predefined {@link CommandGoal} with the given ID
|
||||
* or the custom (non-predefined) goal if none was registered
|
||||
* or the default goal if the given {@code id} is {@code null} or empty string. Never null.
|
||||
*/
|
||||
CommandGoal getGoalForId(@Nullable String id);
|
||||
}
|
||||
|
|
@ -11,42 +11,38 @@
|
|||
package org.eclipse.che.ide.api.command;
|
||||
|
||||
import org.eclipse.che.api.core.model.machine.Command;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Model of the command.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static org.eclipse.che.api.workspace.shared.Constants.COMMAND_GOAL_ATTRIBUTE_NAME;
|
||||
|
||||
/** Data object for {@link Command}. */
|
||||
public class CommandImpl implements Command {
|
||||
|
||||
private final String type;
|
||||
private final String typeId;
|
||||
private final ApplicableContext context;
|
||||
private String name;
|
||||
private String commandLine;
|
||||
private Map<String, String> attributes;
|
||||
|
||||
/**
|
||||
* Creates new command of the specified type with the given name and command line.
|
||||
*
|
||||
* @param name
|
||||
* command name
|
||||
* @param commandLine
|
||||
* command line
|
||||
* @param type
|
||||
* type of the command
|
||||
*/
|
||||
public CommandImpl(String name, String commandLine, String type) {
|
||||
this(name, commandLine, type, Collections.<String, String>emptyMap());
|
||||
/** Creates new {@link CommandImpl} based on the given data. */
|
||||
public CommandImpl(Command command, ApplicableContext context) {
|
||||
this(command.getName(),
|
||||
command.getCommandLine(),
|
||||
command.getType(),
|
||||
new HashMap<>(command.getAttributes()),
|
||||
context);
|
||||
}
|
||||
|
||||
public CommandImpl(String name, String commandLine, String type, Map<String, String> attributes) {
|
||||
this.name = name;
|
||||
this.commandLine = commandLine;
|
||||
this.type = type;
|
||||
this.attributes = attributes;
|
||||
/** Creates new {@link CommandImpl} based on the provided data. */
|
||||
public CommandImpl(String name, String commandLine, String typeId) {
|
||||
this(name, commandLine, typeId, new HashMap<>());
|
||||
}
|
||||
|
||||
/** Creates copy of the given {@link Command}. */
|
||||
|
|
@ -54,7 +50,34 @@ public class CommandImpl implements Command {
|
|||
this(command.getName(),
|
||||
command.getCommandLine(),
|
||||
command.getType(),
|
||||
command.getAttributes());
|
||||
new HashMap<>(command.getAttributes()));
|
||||
}
|
||||
|
||||
/** Creates copy of the given {@code command}. */
|
||||
public CommandImpl(CommandImpl command) {
|
||||
this(command.getName(),
|
||||
command.getCommandLine(),
|
||||
command.getType(),
|
||||
new HashMap<>(command.getAttributes()),
|
||||
new ApplicableContext(command.getApplicableContext()));
|
||||
}
|
||||
|
||||
/** Creates new {@link CommandImpl} based on the provided data. */
|
||||
public CommandImpl(String name, String commandLine, String typeId, Map<String, String> attributes) {
|
||||
this.name = name;
|
||||
this.commandLine = commandLine;
|
||||
this.typeId = typeId;
|
||||
this.attributes = attributes;
|
||||
this.context = new ApplicableContext();
|
||||
}
|
||||
|
||||
/** Creates new {@link CommandImpl} based on the provided data. */
|
||||
public CommandImpl(String name, String commandLine, String typeId, Map<String, String> attributes, ApplicableContext context) {
|
||||
this.name = name;
|
||||
this.commandLine = commandLine;
|
||||
this.typeId = typeId;
|
||||
this.attributes = attributes;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -77,7 +100,7 @@ public class CommandImpl implements Command {
|
|||
|
||||
@Override
|
||||
public String getType() {
|
||||
return type;
|
||||
return typeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -89,6 +112,27 @@ public class CommandImpl implements Command {
|
|||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
/** Returns ID of the command's goal or {@code null} if none. */
|
||||
@Nullable
|
||||
public String getGoal() {
|
||||
return getAttributes().get(COMMAND_GOAL_ATTRIBUTE_NAME);
|
||||
}
|
||||
|
||||
/** Sets command's goal ID. */
|
||||
public void setGoal(String goalId) {
|
||||
getAttributes().put(COMMAND_GOAL_ATTRIBUTE_NAME, goalId);
|
||||
}
|
||||
|
||||
/** Returns command's applicable context. */
|
||||
public ApplicableContext getApplicableContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see #equalsIgnoreContext(CommandImpl)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
|
@ -102,13 +146,109 @@ public class CommandImpl implements Command {
|
|||
CommandImpl other = (CommandImpl)o;
|
||||
|
||||
return Objects.equals(getName(), other.getName())
|
||||
&& Objects.equals(type, other.type)
|
||||
&& Objects.equals(typeId, other.typeId)
|
||||
&& Objects.equals(commandLine, other.commandLine)
|
||||
&& Objects.equals(getAttributes(), other.getAttributes());
|
||||
&& Objects.equals(getAttributes(), other.getAttributes())
|
||||
&& Objects.equals(getApplicableContext(), other.getApplicableContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this {@link CommandImpl} to another {@link CommandImpl}, ignoring applicable context considerations.
|
||||
*
|
||||
* @param anotherCommand
|
||||
* the {@link CommandImpl} to compare this {@link CommandImpl} against
|
||||
* @return {@code true} if the argument represents an equivalent {@link CommandImpl}
|
||||
* ignoring applicable context; {@code false} otherwise
|
||||
*/
|
||||
public boolean equalsIgnoreContext(CommandImpl anotherCommand) {
|
||||
if (this == anotherCommand) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Objects.equals(getName(), anotherCommand.getName())
|
||||
&& Objects.equals(typeId, anotherCommand.typeId)
|
||||
&& Objects.equals(commandLine, anotherCommand.commandLine)
|
||||
&& Objects.equals(getAttributes(), anotherCommand.getAttributes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, type, commandLine, getAttributes());
|
||||
return Objects.hash(name, typeId, commandLine, getAttributes(), getApplicableContext());
|
||||
}
|
||||
|
||||
/** Defines the context in which command is applicable. */
|
||||
public static class ApplicableContext {
|
||||
|
||||
private boolean workspaceApplicable;
|
||||
private List<String> projects;
|
||||
|
||||
/** Creates new {@link ApplicableContext} which is workspace applicable. */
|
||||
public ApplicableContext() {
|
||||
workspaceApplicable = true;
|
||||
projects = new ArrayList<>();
|
||||
}
|
||||
|
||||
/** Creates new {@link ApplicableContext} which is applicable to the single project only. */
|
||||
public ApplicableContext(String projectPath) {
|
||||
projects = new ArrayList<>();
|
||||
projects.add(projectPath);
|
||||
}
|
||||
|
||||
/** Creates new {@link ApplicableContext} based on the provided data. */
|
||||
public ApplicableContext(boolean workspaceApplicable, List<String> projects) {
|
||||
this.workspaceApplicable = workspaceApplicable;
|
||||
this.projects = projects;
|
||||
}
|
||||
|
||||
/** Creates copy of the given {@code context}. */
|
||||
public ApplicableContext(ApplicableContext context) {
|
||||
this(context.isWorkspaceApplicable(), new ArrayList<>(context.getApplicableProjects()));
|
||||
}
|
||||
|
||||
/** Returns {@code true} if command is applicable to the workspace and {@code false} otherwise. */
|
||||
public boolean isWorkspaceApplicable() {
|
||||
return workspaceApplicable;
|
||||
}
|
||||
|
||||
/** Sets whether the command should be applicable to the workspace or not. */
|
||||
public void setWorkspaceApplicable(boolean applicable) {
|
||||
this.workspaceApplicable = applicable;
|
||||
}
|
||||
|
||||
/** Returns <b>immutable</b> list of the paths of the applicable projects. */
|
||||
public List<String> getApplicableProjects() {
|
||||
return unmodifiableList(projects);
|
||||
}
|
||||
|
||||
/** Adds applicable project's path. */
|
||||
public void addProject(String path) {
|
||||
projects.add(path);
|
||||
}
|
||||
|
||||
/** Removes applicable project's path. */
|
||||
public void removeProject(String path) {
|
||||
projects.remove(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof ApplicableContext)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ApplicableContext other = (ApplicableContext)o;
|
||||
|
||||
return workspaceApplicable == other.workspaceApplicable &&
|
||||
Objects.equals(projects, other.projects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(workspaceApplicable, projects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,73 +10,158 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.api.command;
|
||||
|
||||
import org.eclipse.che.api.core.model.machine.Machine;
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.ide.api.macro.Macro;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl.ApplicableContext;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Facade for command related operations.
|
||||
* Facade for command management.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
* @see CommandImpl
|
||||
*/
|
||||
public interface CommandManager {
|
||||
|
||||
/** Returns all commands. */
|
||||
List<CommandImpl> getCommands();
|
||||
|
||||
/**
|
||||
* Creates new command of the specified type.
|
||||
* <p><b>Note</b> that command's name will be generated by {@link CommandManager}
|
||||
* and command line will be provided by an appropriate {@link CommandType}.
|
||||
*/
|
||||
Promise<CommandImpl> create(String type);
|
||||
/** Returns optional command by the specified name or {@link Optional#empty()} if none. */
|
||||
Optional<CommandImpl> getCommand(String name);
|
||||
|
||||
/** Returns commands which are applicable to the current IDE context. */
|
||||
List<CommandImpl> getApplicableCommands();
|
||||
|
||||
/** Checks whether the given {@code command} is applicable to the current IDE context or not. */
|
||||
boolean isCommandApplicable(CommandImpl command);
|
||||
|
||||
/**
|
||||
* Creates new command with the specified arguments.
|
||||
* <p><b>Note</b> that name of the created command may differ from
|
||||
* the specified {@code desirableName} in order to prevent name duplication.
|
||||
* Creates new command based on the given data.
|
||||
* Command's name and command line will be generated automatically.
|
||||
* Command will be bound to the workspace.
|
||||
*
|
||||
* @param goalId
|
||||
* ID of the goal to which created command should belong
|
||||
* @param typeId
|
||||
* ID of the type to which created command should belong
|
||||
* @return created command
|
||||
*/
|
||||
Promise<CommandImpl> create(String desirableName, String commandLine, String type, Map<String, String> attributes);
|
||||
Promise<CommandImpl> createCommand(String goalId, String typeId);
|
||||
|
||||
/**
|
||||
* Creates new command based on the given data.
|
||||
* Command's name and command line will be generated automatically.
|
||||
*
|
||||
* @param goalId
|
||||
* ID of the goal to which created command should belong
|
||||
* @param typeId
|
||||
* ID of the type to which created command should belong
|
||||
* @param context
|
||||
* command's {@link ApplicableContext}
|
||||
* @return created command
|
||||
*/
|
||||
Promise<CommandImpl> createCommand(String goalId, String typeId, ApplicableContext context);
|
||||
|
||||
/**
|
||||
* Creates new command based on the given data. Command will be bound to the workspace.
|
||||
*
|
||||
* @param goalId
|
||||
* ID of the goal to which created command should belong
|
||||
* @param typeId
|
||||
* ID of the type to which created command should belong
|
||||
* @param name
|
||||
* command's name.
|
||||
* <strong>Note</strong> that actual name may differ from the given one in order to prevent duplication.
|
||||
* If {@code null}, name will be generated automatically.
|
||||
* @param commandLine
|
||||
* actual command line. If {@code null}, command line will be generated by the corresponding command type.
|
||||
* @param attributes
|
||||
* command's attributes
|
||||
* @return created command
|
||||
*/
|
||||
Promise<CommandImpl> createCommand(String goalId,
|
||||
String typeId,
|
||||
@Nullable String name,
|
||||
@Nullable String commandLine,
|
||||
Map<String, String> attributes);
|
||||
|
||||
/**
|
||||
* Creates new command based on the given data.
|
||||
*
|
||||
* @param goalId
|
||||
* ID of the goal to which created command should belong
|
||||
* @param typeId
|
||||
* ID of the type to which created command should belong
|
||||
* @param name
|
||||
* command's name.
|
||||
* <strong>Note</strong> that actual name may differ from the given one in order to prevent duplication.
|
||||
* If {@code null}, name will be generated automatically.
|
||||
* @param commandLine
|
||||
* actual command line. If {@code null}, command line will be generated by the corresponding command type.
|
||||
* @param attributes
|
||||
* command's attributes
|
||||
* @param context
|
||||
* command's {@link ApplicableContext}
|
||||
* @return created command
|
||||
*/
|
||||
Promise<CommandImpl> createCommand(String goalId,
|
||||
String typeId,
|
||||
@Nullable String name,
|
||||
@Nullable String commandLine,
|
||||
Map<String, String> attributes,
|
||||
ApplicableContext context);
|
||||
|
||||
/**
|
||||
* Creates copy of the given {@code command}.
|
||||
* <p><b>Note</b> that name of the created command may differ from
|
||||
* the given {@code command}'s name in order to prevent name duplication.
|
||||
*/
|
||||
Promise<CommandImpl> createCommand(CommandImpl command);
|
||||
|
||||
/**
|
||||
* Updates the command with the specified {@code name} by replacing it with the given {@code command}.
|
||||
* <p><b>Note</b> that name of the updated command may differ from the name provided by the given {@code command}
|
||||
* in order to prevent name duplication.
|
||||
*/
|
||||
Promise<CommandImpl> update(String name, CommandImpl command);
|
||||
Promise<CommandImpl> updateCommand(String name, CommandImpl command);
|
||||
|
||||
/** Removes the command with the specified {@code name}. */
|
||||
Promise<Void> remove(String name);
|
||||
/** Removes command with the specified {@code commandName}. */
|
||||
Promise<Void> removeCommand(String commandName);
|
||||
|
||||
/** Returns the pages for editing command of the specified {@code type}. */
|
||||
List<CommandPage> getPages(String type);
|
||||
void addCommandLoadedListener(CommandLoadedListener listener);
|
||||
|
||||
/**
|
||||
* Sends the the given {@code command} to the specified {@code machine} for execution.
|
||||
* <p><b>Note</b> that all {@link Macro}s will be expanded into
|
||||
* real values before sending the {@code command} for execution.
|
||||
*
|
||||
* @param command
|
||||
* command to execute
|
||||
* @param machine
|
||||
* machine to execute the command
|
||||
* @see Macro
|
||||
*/
|
||||
void executeCommand(CommandImpl command, Machine machine);
|
||||
void removeCommandLoadedListener(CommandLoadedListener listener);
|
||||
|
||||
void addCommandChangedListener(CommandChangedListener listener);
|
||||
|
||||
void removeCommandChangedListener(CommandChangedListener listener);
|
||||
|
||||
/** Listener that will be called when command has been changed. */
|
||||
/** Listener to notify when all commands have been loaded. */
|
||||
interface CommandLoadedListener {
|
||||
|
||||
/** Called when all commands have been loaded. */
|
||||
void onCommandsLoaded();
|
||||
}
|
||||
|
||||
/** Listener to notify when command has been changed. */
|
||||
interface CommandChangedListener {
|
||||
|
||||
/** Called when command has been added. */
|
||||
void onCommandAdded(CommandImpl command);
|
||||
|
||||
void onCommandUpdated(CommandImpl command);
|
||||
/**
|
||||
* Called when command has been updated.
|
||||
*
|
||||
* @param previousCommand
|
||||
* command before updating
|
||||
* @param command
|
||||
* updated command
|
||||
*/
|
||||
void onCommandUpdated(CommandImpl previousCommand, CommandImpl command);
|
||||
|
||||
/** Called when command has been removed. */
|
||||
void onCommandRemoved(CommandImpl command);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.api.editor;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
|
||||
import org.eclipse.che.ide.api.parts.AbstractPartPresenter;
|
||||
|
|
@ -89,4 +90,9 @@ public abstract class AbstractEditorPresenter extends AbstractPartPresenter impl
|
|||
public void onFileChanged() {
|
||||
firePropertyChange(TITLE_PROPERTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosing(AsyncCallback<Void> callback) {
|
||||
callback.onSuccess(null);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,4 +112,13 @@ public interface EditorPartPresenter extends PartPresenter {
|
|||
* <code>true</code> if unsaved changed should be saved, and <code>false</code> if unsaved changed should be discarded
|
||||
*/
|
||||
void close(boolean save);
|
||||
|
||||
/**
|
||||
* Called when part is going to closing.
|
||||
* Part can deny closing, by calling {@code callback#onFailure}.
|
||||
*
|
||||
* @param callback
|
||||
* callback to allow or deny closing the part
|
||||
*/
|
||||
void onClosing(AsyncCallback<Void> callback);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ public class DocumentStorageImpl implements DocumentStorage {
|
|||
@Override
|
||||
public void apply(Void arg) throws OperationException {
|
||||
Log.debug(DocumentStorageImpl.class, "Document saved (" + file.getLocation() + ").");
|
||||
DocumentStorageImpl.this.eventBus.fireEvent(FileEvent.createSaveFileEvent(file));
|
||||
DocumentStorageImpl.this.eventBus.fireEvent(FileEvent.createFileSavedEvent(file));
|
||||
try {
|
||||
callback.onSuccess(editorInput);
|
||||
} catch (final Exception e) {
|
||||
|
|
|
|||
|
|
@ -79,6 +79,18 @@ public interface EditorWidget extends IsWidget,
|
|||
*/
|
||||
void setReadOnly(boolean isReadOnly);
|
||||
|
||||
/** Sets whether the annotation ruler is visible. */
|
||||
void setAnnotationRulerVisible(boolean show);
|
||||
|
||||
/** Sets whether the folding ruler is visible. */
|
||||
void setFoldingRulerVisible(boolean show);
|
||||
|
||||
/** Sets whether the zoom ruler is visible. */
|
||||
void setZoomRulerVisible(boolean show);
|
||||
|
||||
/** Sets whether the overview ruler is visible. */
|
||||
void setOverviewRulerVisible(boolean show);
|
||||
|
||||
/**
|
||||
* Returns the readonly state of the editor.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -10,19 +10,21 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.api.event;
|
||||
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.api.parts.EditorTab;
|
||||
import org.eclipse.che.ide.api.resources.VirtualFile;
|
||||
|
||||
import com.google.gwt.event.shared.EventHandler;
|
||||
import com.google.gwt.event.shared.GwtEvent;
|
||||
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.api.editor.EditorAgent;
|
||||
import org.eclipse.che.ide.api.editor.EditorPartPresenter;
|
||||
import org.eclipse.che.ide.api.parts.EditorTab;
|
||||
import org.eclipse.che.ide.api.resources.VirtualFile;
|
||||
|
||||
import static org.eclipse.che.ide.api.event.FileEvent.FileOperation.CLOSE;
|
||||
import static org.eclipse.che.ide.api.event.FileEvent.FileOperation.OPEN;
|
||||
import static org.eclipse.che.ide.api.event.FileEvent.FileOperation.SAVE;
|
||||
|
||||
/**
|
||||
* Event that describes the fact that file is going to be opened.
|
||||
* Event that describes the fact that file is opened/closed/saved.
|
||||
*
|
||||
* @author Nikolay Zamosenchuk
|
||||
* @author Artem Zatsarynnyi
|
||||
|
|
@ -30,11 +32,6 @@ import static org.eclipse.che.ide.api.event.FileEvent.FileOperation.SAVE;
|
|||
*/
|
||||
public class FileEvent extends GwtEvent<FileEvent.FileEventHandler> {
|
||||
|
||||
/** Handles OpenFileEvent */
|
||||
public interface FileEventHandler extends EventHandler {
|
||||
void onFileOperation(FileEvent event);
|
||||
}
|
||||
|
||||
public static Type<FileEventHandler> TYPE = new Type<>();
|
||||
private VirtualFile file;
|
||||
private FileOperation fileOperation;
|
||||
|
|
@ -69,6 +66,12 @@ public class FileEvent extends GwtEvent<FileEvent.FileEventHandler> {
|
|||
/**
|
||||
* Creates a event for {@code FileOperation.OPEN}.
|
||||
*/
|
||||
public static FileEvent createFileOpenedEvent(VirtualFile file) {
|
||||
return new FileEvent(file, OPEN);
|
||||
}
|
||||
|
||||
/** @deprecated use {@link EditorAgent#openEditor(org.eclipse.che.ide.api.resources.VirtualFile)} */
|
||||
@Deprecated
|
||||
public static FileEvent createOpenFileEvent(VirtualFile file) {
|
||||
return new FileEvent(file, OPEN);
|
||||
}
|
||||
|
|
@ -80,6 +83,12 @@ public class FileEvent extends GwtEvent<FileEvent.FileEventHandler> {
|
|||
* @param tab
|
||||
* tab of the file to close
|
||||
*/
|
||||
public static FileEvent createFileClosedEvent(EditorTab tab) {
|
||||
return new FileEvent(tab, CLOSE);
|
||||
}
|
||||
|
||||
/** @deprecated use {@link EditorAgent#closeEditor(EditorPartPresenter)} */
|
||||
@Deprecated
|
||||
public static FileEvent createCloseFileEvent(EditorTab tab) {
|
||||
return new FileEvent(tab, CLOSE);
|
||||
}
|
||||
|
|
@ -87,6 +96,11 @@ public class FileEvent extends GwtEvent<FileEvent.FileEventHandler> {
|
|||
/**
|
||||
* Creates a event for {@code FileOperation.SAVE}.
|
||||
*/
|
||||
public static FileEvent createFileSavedEvent(VirtualFile file) {
|
||||
return new FileEvent(file, SAVE);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static FileEvent createSaveFileEvent(VirtualFile file) {
|
||||
return new FileEvent(file, SAVE);
|
||||
}
|
||||
|
|
@ -120,4 +134,9 @@ public class FileEvent extends GwtEvent<FileEvent.FileEventHandler> {
|
|||
public enum FileOperation {
|
||||
OPEN, SAVE, CLOSE
|
||||
}
|
||||
|
||||
/** Handles OpenFileEvent */
|
||||
public interface FileEventHandler extends EventHandler {
|
||||
void onFileOperation(FileEvent event);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,11 +14,10 @@ import com.google.gwt.core.client.GWT;
|
|||
import com.google.gwt.resources.client.ImageResource;
|
||||
import com.google.gwt.user.client.ui.Image;
|
||||
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.vectomatic.dom.svg.ui.SVGImage;
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Icon.
|
||||
*
|
||||
|
|
@ -129,4 +128,14 @@ public class Icon {
|
|||
}
|
||||
return new SVGImage(svgResource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link SVGResource} widget.
|
||||
*
|
||||
* @return {@link SVGResource} widget
|
||||
*/
|
||||
@Nullable
|
||||
public SVGResource getSVGResource() {
|
||||
return svgResource;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,13 @@
|
|||
* Contributors:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.extension.machine.client.processes;
|
||||
package org.eclipse.che.ide.api.machine.events;
|
||||
|
||||
import com.google.gwt.event.shared.EventHandler;
|
||||
import com.google.gwt.event.shared.GwtEvent;
|
||||
|
||||
import org.eclipse.che.api.core.model.machine.Machine;
|
||||
|
||||
/**
|
||||
* @author Dmitry Shnurenko
|
||||
*/
|
||||
|
|
@ -27,16 +29,22 @@ public class ProcessFinishedEvent extends GwtEvent<ProcessFinishedEvent.Handler>
|
|||
|
||||
public static final Type<ProcessFinishedEvent.Handler> TYPE = new Type<>();
|
||||
|
||||
private final int processID;
|
||||
private final int processID;
|
||||
private final Machine machine;
|
||||
|
||||
public ProcessFinishedEvent(int processID) {
|
||||
public ProcessFinishedEvent(int processID, Machine machine) {
|
||||
this.processID = processID;
|
||||
this.machine = machine;
|
||||
}
|
||||
|
||||
public int getProcessID() {
|
||||
return processID;
|
||||
}
|
||||
|
||||
public Machine getMachine() {
|
||||
return machine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<ProcessFinishedEvent.Handler> getAssociatedType() {
|
||||
return TYPE;
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*******************************************************************************
|
||||
* 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.api.machine.events;
|
||||
|
||||
import com.google.gwt.event.shared.EventHandler;
|
||||
import com.google.gwt.event.shared.GwtEvent;
|
||||
|
||||
import org.eclipse.che.api.core.model.machine.Machine;
|
||||
|
||||
public class ProcessStartedEvent extends GwtEvent<ProcessStartedEvent.Handler> {
|
||||
|
||||
public static final Type<ProcessStartedEvent.Handler> TYPE = new Type<>();
|
||||
|
||||
private final int processID;
|
||||
private final Machine machine;
|
||||
|
||||
public ProcessStartedEvent(int processID, Machine machine) {
|
||||
this.processID = processID;
|
||||
this.machine = machine;
|
||||
}
|
||||
|
||||
public int getProcessID() {
|
||||
return processID;
|
||||
}
|
||||
|
||||
public Machine getMachine() {
|
||||
return machine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<ProcessStartedEvent.Handler> getAssociatedType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatch(Handler handler) {
|
||||
handler.onProcessStarted(this);
|
||||
}
|
||||
|
||||
public interface Handler extends EventHandler {
|
||||
|
||||
void onProcessStarted(ProcessStartedEvent event);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,32 +8,29 @@
|
|||
* Contributors:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.macro;
|
||||
package org.eclipse.che.ide.api.macro;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.api.promises.client.js.Promises;
|
||||
import org.eclipse.che.ide.api.macro.Macro;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Custom macro provider which allows to register user's macro with the provided value.
|
||||
* Base implementation of {@link Macro}.
|
||||
*
|
||||
* @author Vlad Zhukovskyi
|
||||
* @see Macro
|
||||
* @since 4.7.0
|
||||
*/
|
||||
@Beta
|
||||
public class CustomMacro implements Macro {
|
||||
public class BaseMacro implements Macro {
|
||||
|
||||
private final String key;
|
||||
private final String value;
|
||||
private final String description;
|
||||
|
||||
public CustomMacro(String key, String value, String description) {
|
||||
public BaseMacro(String key, String value, String description) {
|
||||
this.key = checkNotNull(key, "Key should not be null");
|
||||
this.value = checkNotNull(value, "Value should not be null");
|
||||
this.description = checkNotNull(description, "Description should not be null");
|
||||
|
|
@ -61,7 +58,7 @@ public class CustomMacro implements Macro {
|
|||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CustomMacro that = (CustomMacro)o;
|
||||
BaseMacro that = (BaseMacro)o;
|
||||
return Objects.equal(key, that.key) &&
|
||||
Objects.equal(value, that.value) &&
|
||||
Objects.equal(description, that.description);
|
||||
|
|
@ -76,7 +73,7 @@ public class CustomMacro implements Macro {
|
|||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CustomMacro{" +
|
||||
return "BaseMacro{" +
|
||||
"key='" + key + '\'' +
|
||||
", value='" + value + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
|
|
@ -22,6 +22,7 @@ import java.util.Set;
|
|||
* Also macro can be registered in 'runtime' with {@link MacroRegistry#register(Set)}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
* @see BaseMacro
|
||||
* @see MacroProcessor#expandMacros(String)
|
||||
* @see MacroRegistry
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -10,17 +10,13 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.api.macro;
|
||||
|
||||
import org.eclipse.che.api.core.model.machine.Machine;
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
|
||||
/**
|
||||
* Expands all {@link Macro}s in the given string.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
* @see Macro
|
||||
* @see CommandManager#executeCommand(CommandImpl, Machine)
|
||||
*/
|
||||
public interface MacroProcessor {
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@ import org.eclipse.che.ide.resource.Path;
|
|||
* Implementation for {@link VirtualFile} which describe resource which doesn't exist on file system and is auto generated.
|
||||
* For example it may be effective version of such resource.
|
||||
* <p/>
|
||||
* This file is read only and doesn't have link to the content url.
|
||||
* Calling {@link #updateContent(String)} will cause {@link UnsupportedOperationException}.
|
||||
* This file doesn't have link to the content url.
|
||||
*
|
||||
* @author Vlad Zhukovskiy
|
||||
* @see VirtualFile
|
||||
|
|
@ -77,7 +76,9 @@ public class SyntheticFile implements VirtualFile {
|
|||
|
||||
@Override
|
||||
public Promise<Void> updateContent(String content) {
|
||||
throw new UnsupportedOperationException("Synthetic file is read only");
|
||||
this.content = content;
|
||||
|
||||
return Promises.resolve(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -8,13 +8,10 @@
|
|||
* Contributors:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.machine;
|
||||
package org.eclipse.che.ide.api.macro;
|
||||
|
||||
import com.google.gwtmockito.GwtMockitoTestRunner;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.ide.macro.CustomMacro;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
@ -22,42 +19,39 @@ import org.junit.runner.RunWith;
|
|||
import static org.junit.Assert.assertSame;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link CustomMacro}
|
||||
* Unit tests for the {@link BaseMacro}
|
||||
*
|
||||
* @author Vlad Zhukovskyi
|
||||
*/
|
||||
@RunWith(GwtMockitoTestRunner.class)
|
||||
public class CustomMacroTest {
|
||||
public class BaseMacroTest {
|
||||
|
||||
public static final String KEY = "key";
|
||||
public static final String VALUE = "value";
|
||||
public static final String NAME = "name";
|
||||
public static final String VALUE = "value";
|
||||
public static final String DESCRIPTION = "description";
|
||||
|
||||
private CustomMacro provider;
|
||||
private BaseMacro macro;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
provider = new CustomMacro(KEY, VALUE, DESCRIPTION);
|
||||
macro = new BaseMacro(NAME, VALUE, DESCRIPTION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getKey() throws Exception {
|
||||
assertSame(provider.getName(), KEY);
|
||||
assertSame(macro.getName(), NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValue() throws Exception {
|
||||
provider.expand().then(new Operation<String>() {
|
||||
@Override
|
||||
public void apply(String value) throws OperationException {
|
||||
assertSame(value, VALUE);
|
||||
}
|
||||
macro.expand().then(value -> {
|
||||
assertSame(value, VALUE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDescription() throws Exception {
|
||||
assertSame(provider.getDescription(), DESCRIPTION);
|
||||
assertSame(macro.getDescription(), DESCRIPTION);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -279,27 +279,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!--<plugin>-->
|
||||
<!--<groupId>org.eclipse.che.core</groupId>-->
|
||||
<!--<artifactId>che-core-api-dto-maven-plugin</artifactId>-->
|
||||
<!--<version>${project.version}</version>-->
|
||||
<!--<executions>-->
|
||||
<!--<execution>-->
|
||||
<!--<phase>process-sources</phase>-->
|
||||
<!--<goals>-->
|
||||
<!--<goal>generate</goal>-->
|
||||
<!--</goals>-->
|
||||
<!--</execution>-->
|
||||
<!--</executions>-->
|
||||
<!--<configuration>-->
|
||||
<!--<dtoPackages>-->
|
||||
<!--<package>org.eclipse.che.ide.statepersistance.dto</package>-->
|
||||
<!--</dtoPackages>-->
|
||||
<!--<outputDirectory>${dto-generator-out-directory}</outputDirectory>-->
|
||||
<!--<genClassName>org.eclipse.che.ide.statepersistance.dto.DtoClientImpls</genClassName>-->
|
||||
<!--<impl>client</impl>-->
|
||||
<!--</configuration>-->
|
||||
<!--</plugin>-->
|
||||
<plugin>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-dyna-provider-generator-maven-plugin</artifactId>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import com.google.gwt.resources.client.CssResource.NotStrict;
|
|||
import com.google.gwt.resources.client.TextResource;
|
||||
|
||||
import org.eclipse.che.ide.api.parts.PartStackUIResources;
|
||||
import org.eclipse.che.ide.command.CommandResources;
|
||||
import org.eclipse.che.ide.menu.MenuResources;
|
||||
import org.eclipse.che.ide.notification.NotificationResources;
|
||||
import org.eclipse.che.ide.projecttype.wizard.ProjectWizardResources;
|
||||
|
|
@ -46,7 +47,8 @@ public interface Resources extends Tree.Resources,
|
|||
CellTreeResources,
|
||||
CategoriesList.Resources,
|
||||
ButtonLoaderResources,
|
||||
ProjectWizardResources {
|
||||
ProjectWizardResources,
|
||||
CommandResources {
|
||||
|
||||
@Source({"Core.css", "org/eclipse/che/ide/ui/constants.css", "org/eclipse/che/ide/api/ui/style.css"})
|
||||
@NotStrict
|
||||
|
|
@ -208,5 +210,8 @@ public interface Resources extends Tree.Resources,
|
|||
String createWsTagsPopup();
|
||||
|
||||
String tagsPanel();
|
||||
|
||||
@ClassName("codeassistant-highlight")
|
||||
String codeassistantHighlight();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,13 +12,12 @@ package org.eclipse.che.ide.actions;
|
|||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.web.bindery.event.shared.EventBus;
|
||||
|
||||
import org.eclipse.che.ide.Resources;
|
||||
import org.eclipse.che.ide.api.action.AbstractPerspectiveAction;
|
||||
import org.eclipse.che.ide.api.action.ActionEvent;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.event.FileEvent;
|
||||
import org.eclipse.che.ide.api.editor.EditorAgent;
|
||||
import org.eclipse.che.ide.api.resources.File;
|
||||
import org.eclipse.che.ide.api.resources.Resource;
|
||||
|
||||
|
|
@ -38,17 +37,16 @@ import static org.eclipse.che.ide.workspace.perspectives.project.ProjectPerspect
|
|||
@Singleton
|
||||
public class EditFileAction extends AbstractPerspectiveAction {
|
||||
|
||||
|
||||
private final AppContext appContext;
|
||||
private final EventBus eventBus;
|
||||
private final AppContext appContext;
|
||||
private final EditorAgent editorAgent;
|
||||
|
||||
@Inject
|
||||
public EditFileAction(AppContext appContext,
|
||||
EventBus eventBus,
|
||||
Resources resources) {
|
||||
Resources resources,
|
||||
EditorAgent editorAgent) {
|
||||
super(singletonList(PROJECT_PERSPECTIVE_ID), "Edit file", null, null, resources.defaultFile());
|
||||
this.appContext = appContext;
|
||||
this.eventBus = eventBus;
|
||||
this.editorAgent = editorAgent;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
|
@ -59,7 +57,7 @@ public class EditFileAction extends AbstractPerspectiveAction {
|
|||
checkState(resources != null && resources.length == 1 && resources[0] instanceof File,
|
||||
"Files only are allowed to be opened in editor");
|
||||
|
||||
eventBus.fireEvent(FileEvent.createOpenFileEvent((File)resources[0]));
|
||||
editorAgent.openEditor((File)resources[0]);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@ import org.eclipse.che.ide.api.action.Action;
|
|||
import org.eclipse.che.ide.api.action.ActionEvent;
|
||||
import org.eclipse.che.ide.api.action.PromisableAction;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.editor.EditorAgent;
|
||||
import org.eclipse.che.ide.api.editor.EditorPartPresenter;
|
||||
import org.eclipse.che.ide.api.event.ActivePartChangedEvent;
|
||||
import org.eclipse.che.ide.api.event.ActivePartChangedHandler;
|
||||
import org.eclipse.che.ide.api.event.FileEvent;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.resources.File;
|
||||
import org.eclipse.che.ide.resource.Path;
|
||||
|
|
@ -43,6 +43,7 @@ import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAI
|
|||
|
||||
/**
|
||||
* TODO maybe rename it to factory open file?
|
||||
*
|
||||
* @author Sergii Leschenko
|
||||
* @author Vlad Zhukovskyi
|
||||
*/
|
||||
|
|
@ -56,6 +57,7 @@ public class OpenFileAction extends Action implements PromisableAction {
|
|||
private final CoreLocalizationConstant localization;
|
||||
private final NotificationManager notificationManager;
|
||||
private final AppContext appContext;
|
||||
private final EditorAgent editorAgent;
|
||||
|
||||
private Callback<Void, Throwable> actionCompletedCallback;
|
||||
|
||||
|
|
@ -63,11 +65,13 @@ public class OpenFileAction extends Action implements PromisableAction {
|
|||
public OpenFileAction(EventBus eventBus,
|
||||
CoreLocalizationConstant localization,
|
||||
NotificationManager notificationManager,
|
||||
AppContext appContext) {
|
||||
AppContext appContext,
|
||||
EditorAgent editorAgent) {
|
||||
this.eventBus = eventBus;
|
||||
this.localization = localization;
|
||||
this.notificationManager = notificationManager;
|
||||
this.appContext = appContext;
|
||||
this.editorAgent = editorAgent;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -91,7 +95,7 @@ public class OpenFileAction extends Action implements PromisableAction {
|
|||
actionCompletedCallback.onSuccess(null);
|
||||
}
|
||||
|
||||
eventBus.fireEvent(FileEvent.createOpenFileEvent(optionalFile.get()));
|
||||
editorAgent.openEditor(optionalFile.get());
|
||||
} else {
|
||||
if (actionCompletedCallback != null) {
|
||||
actionCompletedCallback.onFailure(null);
|
||||
|
|
|
|||
|
|
@ -10,11 +10,10 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.client;
|
||||
|
||||
import com.google.gwt.dom.client.Document;
|
||||
|
||||
import com.google.gwt.core.client.Callback;
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
import com.google.gwt.dom.client.Document;
|
||||
import com.google.gwt.event.logical.shared.CloseEvent;
|
||||
import com.google.gwt.event.logical.shared.CloseHandler;
|
||||
import com.google.gwt.user.client.Window;
|
||||
|
|
@ -97,7 +96,7 @@ public class BootstrapController {
|
|||
|
||||
@Inject
|
||||
private void startComponents(Map<String, Provider<Component>> components) {
|
||||
startComponents(components.entrySet().iterator());
|
||||
startComponents(components.values().iterator());
|
||||
}
|
||||
|
||||
@Inject
|
||||
|
|
@ -132,37 +131,23 @@ public class BootstrapController {
|
|||
});
|
||||
}
|
||||
|
||||
private void startComponents(final Iterator<Map.Entry<String, Provider<Component>>> componentIterator) {
|
||||
if (componentIterator.hasNext()) {
|
||||
Map.Entry<String, Provider<Component>> entry = componentIterator.next();
|
||||
final String componentName = entry.getKey();
|
||||
private void startComponents(final Iterator<Provider<Component>> componentProviderIterator) {
|
||||
if (componentProviderIterator.hasNext()) {
|
||||
Provider<Component> componentProvider = componentProviderIterator.next();
|
||||
|
||||
try {
|
||||
Provider<Component> componentProvider = entry.getValue();
|
||||
|
||||
final Component component = componentProvider.get();
|
||||
component.start(new Callback<Component, Exception>() {
|
||||
@Override
|
||||
public void onSuccess(Component result) {
|
||||
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
||||
@Override
|
||||
public void execute() {
|
||||
startComponents(componentIterator);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception reason) {
|
||||
Log.error(getClass(), "Unable to start " + componentName, reason);
|
||||
initializationFailed(reason.getMessage());
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Log.error(getClass(), "Unable to start " + componentName, e);
|
||||
initializationFailed(e.getMessage());
|
||||
}
|
||||
final Component component = componentProvider.get();
|
||||
component.start(new Callback<Component, Exception>() {
|
||||
@Override
|
||||
public void onSuccess(Component result) {
|
||||
startComponents(componentProviderIterator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception reason) {
|
||||
Log.error(component.getClass(), reason);
|
||||
initializationFailed(reason.getMessage());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
startExtensionsAndDisplayUI();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,10 +13,63 @@ package org.eclipse.che.ide.command;
|
|||
import com.google.gwt.inject.client.AbstractGinModule;
|
||||
import com.google.gwt.inject.client.assistedinject.GinFactoryModuleBuilder;
|
||||
import com.google.gwt.inject.client.multibindings.GinMapBinder;
|
||||
import com.google.gwt.inject.client.multibindings.GinMultibinder;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
import org.eclipse.che.ide.Resources;
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandGoalRegistry;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
import org.eclipse.che.ide.api.command.CommandType;
|
||||
import org.eclipse.che.ide.api.command.CommandTypeRegistry;
|
||||
import org.eclipse.che.ide.api.component.Component;
|
||||
import org.eclipse.che.ide.api.filetypes.FileType;
|
||||
import org.eclipse.che.ide.command.editor.CommandEditorView;
|
||||
import org.eclipse.che.ide.command.editor.CommandEditorViewImpl;
|
||||
import org.eclipse.che.ide.command.editor.page.goal.GoalPageView;
|
||||
import org.eclipse.che.ide.command.editor.page.goal.GoalPageViewImpl;
|
||||
import org.eclipse.che.ide.command.editor.page.name.NamePageView;
|
||||
import org.eclipse.che.ide.command.editor.page.name.NamePageViewImpl;
|
||||
import org.eclipse.che.ide.command.editor.page.project.ProjectsPageView;
|
||||
import org.eclipse.che.ide.command.editor.page.project.ProjectsPageViewImpl;
|
||||
import org.eclipse.che.ide.command.editor.page.text.PageWithTextEditorView;
|
||||
import org.eclipse.che.ide.command.editor.page.text.PageWithTextEditorViewImpl;
|
||||
import org.eclipse.che.ide.command.execute.ExecuteCommandActionFactory;
|
||||
import org.eclipse.che.ide.command.execute.ExecuteCommandActionManager;
|
||||
import org.eclipse.che.ide.command.execute.GoalPopUpGroupFactory;
|
||||
import org.eclipse.che.ide.command.explorer.CommandsExplorerPresenter;
|
||||
import org.eclipse.che.ide.command.explorer.CommandsExplorerView;
|
||||
import org.eclipse.che.ide.command.explorer.CommandsExplorerViewImpl;
|
||||
import org.eclipse.che.ide.command.goal.BuildGoal;
|
||||
import org.eclipse.che.ide.command.goal.CommandGoalRegistryImpl;
|
||||
import org.eclipse.che.ide.command.goal.CommonGoal;
|
||||
import org.eclipse.che.ide.command.goal.DebugGoal;
|
||||
import org.eclipse.che.ide.command.goal.DeployGoal;
|
||||
import org.eclipse.che.ide.command.goal.RunGoal;
|
||||
import org.eclipse.che.ide.command.goal.TestGoal;
|
||||
import org.eclipse.che.ide.command.manager.CommandManagerImpl;
|
||||
import org.eclipse.che.ide.command.node.NodeFactory;
|
||||
import org.eclipse.che.ide.command.palette.CommandsPaletteView;
|
||||
import org.eclipse.che.ide.command.palette.CommandsPaletteViewImpl;
|
||||
import org.eclipse.che.ide.command.producer.CommandProducerActionFactory;
|
||||
import org.eclipse.che.ide.command.producer.CommandProducerActionManager;
|
||||
import org.eclipse.che.ide.command.toolbar.CommandToolbarView;
|
||||
import org.eclipse.che.ide.command.toolbar.CommandToolbarViewImpl;
|
||||
import org.eclipse.che.ide.command.toolbar.ToolbarButtonsFactory;
|
||||
import org.eclipse.che.ide.command.toolbar.commands.ExecuteCommandView;
|
||||
import org.eclipse.che.ide.command.toolbar.commands.ExecuteCommandViewImpl;
|
||||
import org.eclipse.che.ide.command.toolbar.commands.button.PopupItemFactory;
|
||||
import org.eclipse.che.ide.command.toolbar.previews.PreviewsView;
|
||||
import org.eclipse.che.ide.command.toolbar.previews.PreviewsViewImpl;
|
||||
import org.eclipse.che.ide.command.toolbar.processes.ProcessesListView;
|
||||
import org.eclipse.che.ide.command.toolbar.processes.ProcessesListViewImpl;
|
||||
import org.eclipse.che.ide.command.type.CommandTypeRegistryImpl;
|
||||
import org.eclipse.che.ide.command.type.chooser.CommandTypeChooserView;
|
||||
import org.eclipse.che.ide.command.type.chooser.CommandTypeChooserViewImpl;
|
||||
|
||||
import static org.eclipse.che.ide.command.node.CommandFileNode.FILE_TYPE_EXT;
|
||||
|
||||
/**
|
||||
* GIN module for configuring Command API components.
|
||||
|
|
@ -27,11 +80,67 @@ public class CommandApiModule extends AbstractGinModule {
|
|||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(CommandTypeRegistry.class).to(CommandTypeRegistryImpl.class).in(Singleton.class);
|
||||
GinMultibinder.newSetBinder(binder(), CommandType.class);
|
||||
|
||||
// predefined goals
|
||||
GinMultibinder<CommandGoal> goalBinder = GinMultibinder.newSetBinder(binder(), CommandGoal.class);
|
||||
goalBinder.addBinding().to(BuildGoal.class);
|
||||
goalBinder.addBinding().to(TestGoal.class);
|
||||
goalBinder.addBinding().to(RunGoal.class);
|
||||
goalBinder.addBinding().to(DebugGoal.class);
|
||||
goalBinder.addBinding().to(DeployGoal.class);
|
||||
goalBinder.addBinding().to(CommonGoal.class);
|
||||
|
||||
bind(CommandTypeRegistry.class).to(CommandTypeRegistryImpl.class).in(Singleton.class);
|
||||
bind(CommandGoalRegistry.class).to(CommandGoalRegistryImpl.class).in(Singleton.class);
|
||||
|
||||
bind(CommandManager.class).to(CommandManagerImpl.class).in(Singleton.class);
|
||||
|
||||
// start-up components
|
||||
GinMapBinder<String, Component> componentBinder = GinMapBinder.newMapBinder(binder(), String.class, Component.class);
|
||||
componentBinder.addBinding("CommandManagerImpl").to(CommandManagerImpl.class);
|
||||
componentBinder.addBinding("CommandsExplorerPresenter").to(CommandsExplorerPresenter.class);
|
||||
componentBinder.addBinding("CommandProducerActionManager").to(CommandProducerActionManager.class);
|
||||
componentBinder.addBinding("ExecuteCommandActionManager").to(ExecuteCommandActionManager.class);
|
||||
|
||||
install(new GinFactoryModuleBuilder().build(ExecuteCommandActionFactory.class));
|
||||
install(new GinFactoryModuleBuilder().build(GoalPopUpGroupFactory.class));
|
||||
install(new GinFactoryModuleBuilder().build(NodeFactory.class));
|
||||
install(new GinFactoryModuleBuilder().build(CommandProducerActionFactory.class));
|
||||
|
||||
GinMapBinder<String, Component> componentsBinder = GinMapBinder.newMapBinder(binder(), String.class, Component.class);
|
||||
componentsBinder.addBinding("CommandProducerActionManager").to(CommandProducerActionManager.class);
|
||||
bind(CommandsExplorerView.class).to(CommandsExplorerViewImpl.class).in(Singleton.class);
|
||||
bind(CommandTypeChooserView.class).to(CommandTypeChooserViewImpl.class);
|
||||
bind(CommandsPaletteView.class).to(CommandsPaletteViewImpl.class).in(Singleton.class);
|
||||
|
||||
// command editor
|
||||
bind(CommandEditorView.class).to(CommandEditorViewImpl.class);
|
||||
bind(NamePageView.class).to(NamePageViewImpl.class);
|
||||
bind(GoalPageView.class).to(GoalPageViewImpl.class);
|
||||
bind(ProjectsPageView.class).to(ProjectsPageViewImpl.class);
|
||||
bind(PageWithTextEditorView.class).to(PageWithTextEditorViewImpl.class);
|
||||
|
||||
// toolbar
|
||||
bind(CommandToolbarView.class).to(CommandToolbarViewImpl.class).in(Singleton.class);
|
||||
bind(ExecuteCommandView.class).to(ExecuteCommandViewImpl.class).in(Singleton.class);
|
||||
bind(ProcessesListView.class).to(ProcessesListViewImpl.class).in(Singleton.class);
|
||||
bind(PreviewsView.class).to(PreviewsViewImpl.class).in(Singleton.class);
|
||||
|
||||
install(new GinFactoryModuleBuilder().build(ToolbarButtonsFactory.class));
|
||||
install(new GinFactoryModuleBuilder().build(PopupItemFactory.class));
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("CommandFileType")
|
||||
protected FileType provideCommandFileType(Resources resources) {
|
||||
return new FileType(resources.defaultImage(), FILE_TYPE_EXT);
|
||||
}
|
||||
|
||||
/** Provides the goal which is used for grouping commands which doesn't belong to any goal. */
|
||||
@Provides
|
||||
@Named("default")
|
||||
@Singleton
|
||||
protected CommandGoal provideDefaultGoal(CommonGoal commonGoal) {
|
||||
return commonGoal;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
/*******************************************************************************
|
||||
* 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.command;
|
||||
|
||||
import com.google.gwt.resources.client.ClientBundle;
|
||||
import com.google.gwt.resources.client.CssResource;
|
||||
import com.google.gwt.resources.client.DataResource;
|
||||
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
/**
|
||||
* Client bundle for Command related resources.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface CommandResources extends ClientBundle {
|
||||
|
||||
/** Resource is used as CSS constant's value for setting 'background-image' property. */
|
||||
@DataResource.MimeType("image/svg+xml")
|
||||
@Source("magnifier.svg")
|
||||
DataResource magnifier();
|
||||
|
||||
@Source("explorer/explorer-part.svg")
|
||||
SVGResource explorerPart();
|
||||
|
||||
@Source("explorer/add-command-button.svg")
|
||||
SVGResource addCommand();
|
||||
|
||||
@Source("explorer/duplicate-command-button.svg")
|
||||
SVGResource duplicateCommand();
|
||||
|
||||
@Source("explorer/remove-command-button.svg")
|
||||
SVGResource removeCommand();
|
||||
|
||||
@Source({"explorer/styles.css", "org/eclipse/che/ide/api/ui/style.css"})
|
||||
ExplorerCSS commandsExplorerCss();
|
||||
|
||||
@Source({"palette/styles.css", "org/eclipse/che/ide/api/ui/style.css"})
|
||||
PaletteCSS commandsPaletteCss();
|
||||
|
||||
@Source({"toolbar/processes/styles.css", "org/eclipse/che/ide/api/ui/style.css"})
|
||||
ToolbarCSS commandToolbarCss();
|
||||
|
||||
@Source({"editor/styles.css", "org/eclipse/che/ide/api/ui/style.css"})
|
||||
EditorCSS editorCss();
|
||||
|
||||
@Source({"type/styles.css", "org/eclipse/che/ide/api/ui/style.css"})
|
||||
CommandTypeChooserCSS commandTypeChooserCss();
|
||||
|
||||
interface ExplorerCSS extends CssResource {
|
||||
String commandGoalNode();
|
||||
|
||||
String commandNode();
|
||||
|
||||
String commandNodeText();
|
||||
|
||||
String commandNodeButtonsPanel();
|
||||
}
|
||||
|
||||
interface PaletteCSS extends CssResource {
|
||||
String filterField();
|
||||
}
|
||||
|
||||
interface ToolbarCSS extends CssResource {
|
||||
String toolbarButton();
|
||||
|
||||
String processesListLabel();
|
||||
|
||||
String processWidgetText();
|
||||
|
||||
String processWidgetMachineNameLabel();
|
||||
|
||||
String processWidgetCommandNameLabel();
|
||||
|
||||
String processWidgetPidLabel();
|
||||
|
||||
String processWidgetActionButton();
|
||||
|
||||
String previewUrlWidget();
|
||||
}
|
||||
|
||||
interface EditorCSS extends CssResource {
|
||||
String sectionLabel();
|
||||
|
||||
String section();
|
||||
}
|
||||
|
||||
interface CommandTypeChooserCSS extends CssResource {
|
||||
String chooserPopup();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*******************************************************************************
|
||||
* 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.command;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandType;
|
||||
import org.eclipse.che.ide.api.command.CommandTypeRegistry;
|
||||
import org.eclipse.che.ide.api.command.CommandGoalRegistry;
|
||||
import org.eclipse.che.ide.api.icon.Icon;
|
||||
import org.eclipse.che.ide.api.icon.IconRegistry;
|
||||
import org.vectomatic.dom.svg.ui.SVGImage;
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A smattering of useful methods to work with commands.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
@Singleton
|
||||
public class CommandUtils {
|
||||
|
||||
private final CommandGoalRegistry goalRegistry;
|
||||
private final CommandTypeRegistry commandTypeRegistry;
|
||||
private final IconRegistry iconRegistry;
|
||||
|
||||
@Inject
|
||||
public CommandUtils(CommandGoalRegistry commandGoalRegistry,
|
||||
CommandTypeRegistry commandTypeRegistry,
|
||||
IconRegistry iconRegistry) {
|
||||
this.goalRegistry = commandGoalRegistry;
|
||||
this.commandTypeRegistry = commandTypeRegistry;
|
||||
this.iconRegistry = iconRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups the given {@code commands} by its goal.
|
||||
*
|
||||
* @return map that contains the given {@code commands} grouped by its goal
|
||||
*/
|
||||
public Map<CommandGoal, List<CommandImpl>> groupCommandsByGoal(List<CommandImpl> commands) {
|
||||
final Map<CommandGoal, List<CommandImpl>> commandsByGoal = new HashMap<>();
|
||||
|
||||
for (CommandImpl command : commands) {
|
||||
final String goalId = command.getGoal();
|
||||
final CommandGoal commandGoal = goalRegistry.getGoalForId(goalId);
|
||||
|
||||
commandsByGoal.computeIfAbsent(commandGoal, key -> new ArrayList<>())
|
||||
.add(command);
|
||||
}
|
||||
|
||||
return commandsByGoal;
|
||||
}
|
||||
|
||||
/** Returns the icon for the given command type ID or {@code null} if none. */
|
||||
@Nullable
|
||||
public SVGResource getCommandTypeIcon(String typeId) {
|
||||
final CommandType commandType = commandTypeRegistry.getCommandTypeById(typeId);
|
||||
|
||||
if (commandType != null) {
|
||||
final Icon icon = iconRegistry.getIconIfExist("command.type." + commandType.getId());
|
||||
|
||||
if (icon != null) {
|
||||
final SVGImage svgImage = icon.getSVGImage();
|
||||
|
||||
if (svgImage != null) {
|
||||
return icon.getSVGResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Returns the icon for the given command goal ID or {@code null} if none. */
|
||||
@Nullable
|
||||
public SVGResource getCommandGoalIcon(String goalId) {
|
||||
final Optional<CommandGoal> goalOptional = goalRegistry.getPredefinedGoalById(goalId);
|
||||
|
||||
if (goalOptional.isPresent()) {
|
||||
final Icon icon = iconRegistry.getIconIfExist("command.goal." + goalOptional.get().getId());
|
||||
|
||||
if (icon != null) {
|
||||
final SVGImage svgImage = icon.getSVGImage();
|
||||
|
||||
if (svgImage != null) {
|
||||
return icon.getSVGResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,305 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.AcceptsOneWidget;
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.CoreLocalizationConstant;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
import org.eclipse.che.ide.api.command.CommandManager.CommandChangedListener;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.api.editor.AbstractEditorPresenter;
|
||||
import org.eclipse.che.ide.api.editor.EditorAgent;
|
||||
import org.eclipse.che.ide.api.editor.EditorInput;
|
||||
import org.eclipse.che.ide.api.icon.Icon;
|
||||
import org.eclipse.che.ide.api.icon.IconRegistry;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.parts.WorkspaceAgent;
|
||||
import org.eclipse.che.ide.api.resources.VirtualFile;
|
||||
import org.eclipse.che.ide.command.editor.page.CommandEditorPage;
|
||||
import org.eclipse.che.ide.command.editor.page.commandline.CommandLinePage;
|
||||
import org.eclipse.che.ide.command.editor.page.goal.GoalPage;
|
||||
import org.eclipse.che.ide.command.editor.page.name.NamePage;
|
||||
import org.eclipse.che.ide.command.editor.page.previewurl.PreviewUrlPage;
|
||||
import org.eclipse.che.ide.command.editor.page.project.ProjectsPage;
|
||||
import org.eclipse.che.ide.command.node.CommandFileNode;
|
||||
import org.eclipse.che.ide.command.node.NodeFactory;
|
||||
import org.vectomatic.dom.svg.ui.SVGImage;
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.EMERGE_MODE;
|
||||
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.WARNING;
|
||||
|
||||
/** Presenter for command editor. */
|
||||
public class CommandEditor extends AbstractEditorPresenter implements CommandEditorView.ActionDelegate,
|
||||
CommandChangedListener {
|
||||
|
||||
private final CommandEditorView view;
|
||||
private final WorkspaceAgent workspaceAgent;
|
||||
private final IconRegistry iconRegistry;
|
||||
private final CommandManager commandManager;
|
||||
private final NotificationManager notificationManager;
|
||||
private final DialogFactory dialogFactory;
|
||||
private final EditorAgent editorAgent;
|
||||
private final CoreLocalizationConstant coreMessages;
|
||||
private final EditorMessages messages;
|
||||
private final NodeFactory nodeFactory;
|
||||
|
||||
private final List<CommandEditorPage> pages;
|
||||
|
||||
/** Edited command. */
|
||||
@VisibleForTesting
|
||||
protected CommandImpl editedCommand;
|
||||
/** Initial (before any modification) name of the edited command. */
|
||||
private String commandNameInitial;
|
||||
|
||||
@Inject
|
||||
public CommandEditor(CommandEditorView view,
|
||||
WorkspaceAgent workspaceAgent,
|
||||
IconRegistry iconRegistry,
|
||||
CommandManager commandManager,
|
||||
NamePage namePage,
|
||||
ProjectsPage projectsPage,
|
||||
CommandLinePage commandLinePage,
|
||||
GoalPage goalPage,
|
||||
PreviewUrlPage previewUrlPage,
|
||||
NotificationManager notificationManager,
|
||||
DialogFactory dialogFactory,
|
||||
EditorAgent editorAgent,
|
||||
CoreLocalizationConstant coreMessages,
|
||||
EditorMessages messages,
|
||||
NodeFactory nodeFactory) {
|
||||
this.view = view;
|
||||
this.workspaceAgent = workspaceAgent;
|
||||
this.iconRegistry = iconRegistry;
|
||||
this.commandManager = commandManager;
|
||||
this.notificationManager = notificationManager;
|
||||
this.dialogFactory = dialogFactory;
|
||||
this.editorAgent = editorAgent;
|
||||
this.coreMessages = coreMessages;
|
||||
this.messages = messages;
|
||||
this.nodeFactory = nodeFactory;
|
||||
|
||||
view.setDelegate(this);
|
||||
|
||||
commandManager.addCommandChangedListener(this);
|
||||
|
||||
pages = new LinkedList<>();
|
||||
pages.add(previewUrlPage);
|
||||
pages.add(projectsPage);
|
||||
pages.add(goalPage);
|
||||
pages.add(commandLinePage);
|
||||
pages.add(namePage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void go(AcceptsOneWidget container) {
|
||||
container.setWidget(getView());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeEditor(EditorAgent.OpenEditorCallback callback) {
|
||||
final VirtualFile file = getEditorInput().getFile();
|
||||
|
||||
if (file instanceof CommandFileNode) {
|
||||
// make a copy of the given command to avoid modifying of the provided command
|
||||
editedCommand = new CommandImpl(((CommandFileNode)file).getData());
|
||||
|
||||
initializePages();
|
||||
|
||||
pages.forEach(page -> view.addPage(page.getView(), page.getTitle()));
|
||||
} else {
|
||||
callback.onInitializationFailed();
|
||||
}
|
||||
}
|
||||
|
||||
/** Initialize editor's pages with the edited command. */
|
||||
private void initializePages() {
|
||||
commandNameInitial = editedCommand.getName();
|
||||
|
||||
pages.forEach(page -> {
|
||||
page.edit(editedCommand);
|
||||
page.setDirtyStateListener(() -> {
|
||||
updateDirtyState(isDirtyPage());
|
||||
view.setSaveEnabled(isDirtyPage());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** Checks whether any page is dirty. */
|
||||
private boolean isDirtyPage() {
|
||||
for (CommandEditorPage page : pages) {
|
||||
if (page.isDirty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SVGResource getTitleImage() {
|
||||
final VirtualFile file = getEditorInput().getFile();
|
||||
|
||||
if (file instanceof CommandFileNode) {
|
||||
final CommandImpl command = ((CommandFileNode)file).getData();
|
||||
final Icon icon = iconRegistry.getIconIfExist("command.type." + command.getType());
|
||||
|
||||
if (icon != null) {
|
||||
final SVGImage svgImage = icon.getSVGImage();
|
||||
|
||||
if (svgImage != null) {
|
||||
return icon.getSVGResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return input.getSVGResource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return (isDirty() ? "* " : "") + input.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IsWidget getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getTitleToolTip() {
|
||||
return input.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSave() {
|
||||
doSave(new AsyncCallback<EditorInput>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(EditorInput result) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSave(AsyncCallback<EditorInput> callback) {
|
||||
commandManager.updateCommand(commandNameInitial, editedCommand).then(arg -> {
|
||||
updateDirtyState(false);
|
||||
|
||||
// according to the CommandManager#updateCommand contract
|
||||
// command's name after updating may differ from the proposed name
|
||||
// in order to prevent name duplication
|
||||
editedCommand.setName(arg.getName());
|
||||
|
||||
if (!commandNameInitial.equals(editedCommand.getName())) {
|
||||
input.setFile(nodeFactory.newCommandFileNode(editedCommand));
|
||||
}
|
||||
|
||||
initializePages();
|
||||
|
||||
callback.onSuccess(getEditorInput());
|
||||
}).catchError((Operation<PromiseError>)arg -> {
|
||||
notificationManager.notify(messages.editorMessageUnableToSave(),
|
||||
arg.getMessage(),
|
||||
WARNING,
|
||||
EMERGE_MODE);
|
||||
|
||||
callback.onFailure(arg.getCause());
|
||||
|
||||
throw new OperationException(arg.getMessage());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSaveAs() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(boolean save) {
|
||||
workspaceAgent.removePart(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosing(AsyncCallback<Void> callback) {
|
||||
if (!isDirty()) {
|
||||
callback.onSuccess(null);
|
||||
} else {
|
||||
dialogFactory.createChoiceDialog(
|
||||
coreMessages.askWindowCloseTitle(),
|
||||
coreMessages.messagesSaveChanges(getEditorInput().getName()),
|
||||
coreMessages.yesButtonTitle(),
|
||||
coreMessages.noButtonTitle(),
|
||||
coreMessages.cancelButton(),
|
||||
() -> doSave(new AsyncCallback<EditorInput>() {
|
||||
@Override
|
||||
public void onSuccess(EditorInput result) {
|
||||
callback.onSuccess(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
callback.onFailure(null);
|
||||
}
|
||||
}),
|
||||
() -> callback.onSuccess(null),
|
||||
() -> callback.onFailure(null)).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandCancel() {
|
||||
close(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandSave() {
|
||||
doSave();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandAdded(CommandImpl command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandUpdated(CommandImpl previousCommand, CommandImpl command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandRemoved(CommandImpl command) {
|
||||
if (command.getName().equals(editedCommand.getName())) {
|
||||
editorAgent.closeEditor(this);
|
||||
Scheduler.get().scheduleDeferred(() -> commandManager.removeCommandChangedListener(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.eclipse.che.ide.api.editor.EditorPartPresenter;
|
||||
import org.eclipse.che.ide.api.editor.EditorProvider;
|
||||
|
||||
/**
|
||||
* Provides {@link CommandEditor} instances.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class CommandEditorProvider implements EditorProvider {
|
||||
|
||||
private final Provider<CommandEditor> editorProvider;
|
||||
private final EditorMessages editorMessages;
|
||||
|
||||
@Inject
|
||||
public CommandEditorProvider(Provider<CommandEditor> editorProvider, EditorMessages editorMessages) {
|
||||
this.editorProvider = editorProvider;
|
||||
this.editorMessages = editorMessages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "che_command_editor";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return editorMessages.editorDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditorPartPresenter getEditor() {
|
||||
return editorProvider.get();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor;
|
||||
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
|
||||
import org.eclipse.che.ide.api.mvp.View;
|
||||
|
||||
/**
|
||||
* The view for {@link CommandEditor}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface CommandEditorView extends View<CommandEditorView.ActionDelegate> {
|
||||
|
||||
/**
|
||||
* Add page to the view. New page will be added to the top.
|
||||
*
|
||||
* @param page
|
||||
* page to add
|
||||
* @param title
|
||||
* text that should be used as page's title
|
||||
*/
|
||||
void addPage(IsWidget page, String title);
|
||||
|
||||
/**
|
||||
* Set whether saving command is enabled or not.
|
||||
*
|
||||
* @param enable
|
||||
* {@code true} if command saving is enabled and {@code false} otherwise
|
||||
*/
|
||||
void setSaveEnabled(boolean enable);
|
||||
|
||||
/** The action delegate for this view. */
|
||||
interface ActionDelegate {
|
||||
|
||||
/** Called when reverting command changes is requested. */
|
||||
void onCommandCancel();
|
||||
|
||||
/** Called when saving command is requested. */
|
||||
void onCommandSave();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.uibinder.client.UiHandler;
|
||||
import com.google.gwt.user.client.Timer;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ScrollPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.command.CommandResources;
|
||||
import org.eclipse.che.ide.ui.window.Window;
|
||||
|
||||
/**
|
||||
* Implementation of {@link CommandEditorView}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class CommandEditorViewImpl extends Composite implements CommandEditorView {
|
||||
|
||||
private static final CommandEditorViewImplUiBinder UI_BINDER = GWT.create(CommandEditorViewImplUiBinder.class);
|
||||
private static final Window.Resources WINDOW_RESOURCES = GWT.create(Window.Resources.class);
|
||||
|
||||
private final CommandResources resources;
|
||||
|
||||
@UiField
|
||||
Button cancelButton;
|
||||
|
||||
@UiField
|
||||
Button saveButton;
|
||||
|
||||
@UiField
|
||||
ScrollPanel scrollPanel;
|
||||
|
||||
@UiField
|
||||
FlowPanel pagesPanel;
|
||||
|
||||
/** The delegate to receive events from this view. */
|
||||
private ActionDelegate delegate;
|
||||
|
||||
@Inject
|
||||
public CommandEditorViewImpl(CommandResources resources) {
|
||||
this.resources = resources;
|
||||
|
||||
initWidget(UI_BINDER.createAndBindUi(this));
|
||||
setSaveEnabled(false);
|
||||
saveButton.addStyleName(WINDOW_RESOURCES.windowCss().primaryButton());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPage(IsWidget page, String title) {
|
||||
page.asWidget().addStyleName(resources.editorCss().section());
|
||||
pagesPanel.insert(page, 0);
|
||||
|
||||
if (!title.isEmpty()) {
|
||||
Label label = new Label(title);
|
||||
label.addStyleName(resources.editorCss().sectionLabel());
|
||||
pagesPanel.insert(label, 0);
|
||||
}
|
||||
|
||||
// editor must be scrolled to the top immediately after opening
|
||||
new Timer() {
|
||||
@Override
|
||||
public void run() {
|
||||
scrollPanel.scrollToTop();
|
||||
}
|
||||
}.schedule(1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSaveEnabled(boolean enable) {
|
||||
saveButton.setEnabled(enable);
|
||||
}
|
||||
|
||||
@UiHandler("cancelButton")
|
||||
public void handleCancelButton(ClickEvent clickEvent) {
|
||||
delegate.onCommandCancel();
|
||||
}
|
||||
|
||||
@UiHandler("saveButton")
|
||||
public void handleSaveButton(ClickEvent clickEvent) {
|
||||
delegate.onCommandSave();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDelegate(ActionDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
interface CommandEditorViewImplUiBinder extends UiBinder<Widget, CommandEditorViewImpl> {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
|
||||
<ui:with field='messages' type='org.eclipse.che.ide.command.editor.EditorMessages'/>
|
||||
<ui:style>
|
||||
@eval partBackground org.eclipse.che.ide.api.theme.Style.theme.partBackground();
|
||||
@eval tabsPanelBackground org.eclipse.che.ide.api.theme.Style.theme.tabsPanelBackground();
|
||||
|
||||
.mainPanel {
|
||||
background-color: partBackground;
|
||||
}
|
||||
|
||||
.header {
|
||||
height: 38px;
|
||||
padding-top: 5px;
|
||||
background-color: tabsPanelBackground;
|
||||
}
|
||||
|
||||
.button {
|
||||
float: right;
|
||||
margin: 5px 0 0 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
</ui:style>
|
||||
|
||||
<g:DockLayoutPanel addStyleNames="{style.mainPanel}">
|
||||
<g:center>
|
||||
<g:ScrollPanel ui:field="scrollPanel">
|
||||
<g:FlowPanel width="700px" ui:field="pagesPanel"/>
|
||||
</g:ScrollPanel>
|
||||
</g:center>
|
||||
<g:south size="44">
|
||||
<g:FlowPanel addStyleNames="{style.header}">
|
||||
<g:Button ui:field="cancelButton"
|
||||
text="{messages.buttonCancelText}"
|
||||
addStyleNames="{style.button}"
|
||||
debugId="command-editor-button-cancel"/>
|
||||
<g:Button ui:field="saveButton"
|
||||
text="{messages.buttonSaveText}"
|
||||
addStyleNames="{style.button}"
|
||||
debugId="command-editor-button-save"/>
|
||||
</g:FlowPanel>
|
||||
</g:south>
|
||||
</g:DockLayoutPanel>
|
||||
</ui:UiBinder>
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor;
|
||||
|
||||
import com.google.gwt.i18n.client.Messages;
|
||||
|
||||
/**
|
||||
* I18n messages for the Command Editor.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface EditorMessages extends Messages {
|
||||
|
||||
@Key("editor.description")
|
||||
String editorDescription();
|
||||
|
||||
@Key("editor.message.unable_save")
|
||||
String editorMessageUnableToSave();
|
||||
|
||||
@Key("button.test.text")
|
||||
String buttonRunText();
|
||||
|
||||
@Key("button.save.text")
|
||||
String buttonSaveText();
|
||||
|
||||
@Key("button.cancel.text")
|
||||
String buttonCancelText();
|
||||
|
||||
@Key("page.name.title")
|
||||
String pageNameTitle();
|
||||
|
||||
@Key("page.command_line.title")
|
||||
String pageCommandLineTitle();
|
||||
|
||||
@Key("page.goal.title")
|
||||
String pageGoalTitle();
|
||||
|
||||
@Key("page.projects.title")
|
||||
String pageProjectsTitle();
|
||||
|
||||
@Key("page.projects.table.header.project.label")
|
||||
String pageProjectsTableHeaderProjectLabel();
|
||||
|
||||
@Key("page.projects.table.header.applicable.label")
|
||||
String pageProjectsTableHeaderApplicableLabel();
|
||||
|
||||
@Key("page.with_text_editor.macros")
|
||||
String pageWithTextEditorMacros();
|
||||
|
||||
@Key("page.preview_url.title")
|
||||
String pagePreviewUrlTitle();
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page;
|
||||
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
|
||||
/**
|
||||
* Abstract {@link CommandEditorPage} that provides basic functionality.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public abstract class AbstractCommandEditorPage implements CommandEditorPage {
|
||||
|
||||
private final String title;
|
||||
|
||||
protected CommandImpl editedCommand;
|
||||
|
||||
private DirtyStateListener listener;
|
||||
|
||||
/** Creates new page with the given title and tooltip. */
|
||||
protected AbstractCommandEditorPage(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void edit(CommandImpl command) {
|
||||
editedCommand = command;
|
||||
|
||||
initialize();
|
||||
notifyDirtyStateChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called every time when command is opening in the editor.
|
||||
* Typically, implementor should do initial setup of the page with the {@link #editedCommand}.
|
||||
*/
|
||||
protected abstract void initialize();
|
||||
|
||||
@Override
|
||||
public void setDirtyStateListener(DirtyStateListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called by page every time when any command
|
||||
* modifications on the page have been performed.
|
||||
*/
|
||||
protected void notifyDirtyStateChanged() {
|
||||
if (listener != null) {
|
||||
listener.onDirtyStateChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page;
|
||||
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.command.editor.CommandEditor;
|
||||
|
||||
/**
|
||||
* Defines the requirements for the page for {@link CommandEditor}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
* @see CommandEditor
|
||||
*/
|
||||
public interface CommandEditorPage {
|
||||
|
||||
/** Returns page's title. */
|
||||
String getTitle();
|
||||
|
||||
/** Returns page's view. */
|
||||
IsWidget getView();
|
||||
|
||||
/**
|
||||
* This method is called every time when command is opening in the editor.
|
||||
* Typically, implementor should hold the given {@code command}
|
||||
* instance for subsequent modifying it directly and do pages's initial setup.
|
||||
*/
|
||||
void edit(CommandImpl command);
|
||||
|
||||
/**
|
||||
* Whether the page has been modified or not?
|
||||
*
|
||||
* @return {@code true} if page is modified, and {@code false} - otherwise
|
||||
*/
|
||||
boolean isDirty();
|
||||
|
||||
/** Sets {@link DirtyStateListener}. */
|
||||
void setDirtyStateListener(DirtyStateListener listener);
|
||||
|
||||
/**
|
||||
* Listener that should be called by page every time when
|
||||
* any command modifications on the page have been performed.
|
||||
*/
|
||||
interface DirtyStateListener {
|
||||
void onDirtyStateChanged();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.commandline;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.editor.defaulteditor.EditorBuilder;
|
||||
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry;
|
||||
import org.eclipse.che.ide.command.editor.EditorMessages;
|
||||
import org.eclipse.che.ide.command.editor.page.CommandEditorPage;
|
||||
import org.eclipse.che.ide.command.editor.page.text.AbstractPageWithTextEditor;
|
||||
import org.eclipse.che.ide.command.editor.page.text.MacroEditorConfiguration;
|
||||
import org.eclipse.che.ide.command.editor.page.text.PageWithTextEditorView;
|
||||
import org.eclipse.che.ide.macro.chooser.MacroChooser;
|
||||
|
||||
/**
|
||||
* Presenter for {@link CommandEditorPage} which allows to edit command line.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class CommandLinePage extends AbstractPageWithTextEditor {
|
||||
|
||||
@Inject
|
||||
public CommandLinePage(PageWithTextEditorView view,
|
||||
EditorBuilder editorBuilder,
|
||||
FileTypeRegistry fileTypeRegistry,
|
||||
MacroChooser macroChooser,
|
||||
EditorMessages messages,
|
||||
MacroEditorConfiguration editorConfiguration) {
|
||||
super(view,
|
||||
editorBuilder,
|
||||
fileTypeRegistry,
|
||||
macroChooser,
|
||||
messages.pageCommandLineTitle(),
|
||||
editorConfiguration);
|
||||
|
||||
view.asWidget().getElement().setId("command_editor-command_line");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCommandPropertyValue() {
|
||||
return editedCommand.getCommandLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateCommandPropertyValue(String content) {
|
||||
editedCommand.setCommandLine(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getType() {
|
||||
return ".sh";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.goal;
|
||||
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.command.BaseCommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
import org.eclipse.che.ide.api.command.CommandGoalRegistry;
|
||||
import org.eclipse.che.ide.command.editor.EditorMessages;
|
||||
import org.eclipse.che.ide.command.editor.page.AbstractCommandEditorPage;
|
||||
import org.eclipse.che.ide.command.editor.page.CommandEditorPage;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
|
||||
/**
|
||||
* {@link CommandEditorPage} which allows to edit command's goal.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class GoalPage extends AbstractCommandEditorPage implements GoalPageView.ActionDelegate {
|
||||
|
||||
private final GoalPageView view;
|
||||
private final CommandGoalRegistry goalRegistry;
|
||||
private final CommandManager commandManager;
|
||||
|
||||
/** Initial value of the command's goal. */
|
||||
private String goalInitial;
|
||||
|
||||
@Inject
|
||||
public GoalPage(GoalPageView view,
|
||||
CommandGoalRegistry commandGoalRegistry,
|
||||
CommandManager commandManager,
|
||||
EditorMessages messages) {
|
||||
super(messages.pageGoalTitle());
|
||||
|
||||
this.view = view;
|
||||
this.goalRegistry = commandGoalRegistry;
|
||||
this.commandManager = commandManager;
|
||||
|
||||
view.setDelegate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IsWidget getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
final String goalId = editedCommand.getGoal();
|
||||
final CommandGoal commandGoal = goalRegistry.getGoalForId(goalId);
|
||||
|
||||
goalInitial = commandGoal.getId();
|
||||
|
||||
final Set<CommandGoal> goals = new HashSet<>();
|
||||
goals.addAll(goalRegistry.getAllPredefinedGoals());
|
||||
goals.addAll(getCustomGoals());
|
||||
|
||||
view.setAvailableGoals(goals);
|
||||
view.setGoal(commandGoal.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty() {
|
||||
if (editedCommand == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final CommandGoal commandGoal = goalRegistry.getGoalForId(editedCommand.getGoal());
|
||||
|
||||
return !(goalInitial.equals(commandGoal.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGoalChanged(String goalId) {
|
||||
editedCommand.setGoal(goalId);
|
||||
|
||||
notifyDirtyStateChanged();
|
||||
}
|
||||
|
||||
/** Returns all custom (non-predefined) command goals. */
|
||||
private Set<CommandGoal> getCustomGoals() {
|
||||
final Set<CommandGoal> list = new HashSet<>();
|
||||
|
||||
for (CommandImpl command : commandManager.getCommands()) {
|
||||
final String goalId = command.getGoal();
|
||||
|
||||
final Optional<CommandGoal> goalOptional = goalRegistry.getPredefinedGoalById(goalId);
|
||||
if (!goalOptional.isPresent() && !isNullOrEmpty(goalId)) {
|
||||
list.add(new BaseCommandGoal(goalId));
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.goal;
|
||||
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.mvp.View;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The view of {@link GoalPage}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface GoalPageView extends View<GoalPageView.ActionDelegate> {
|
||||
|
||||
/** Set the list of goals which are available to set for command. */
|
||||
void setAvailableGoals(Set<CommandGoal> goals);
|
||||
|
||||
/** Sets the command's goal value. */
|
||||
void setGoal(String goalId);
|
||||
|
||||
/** The action delegate for this view. */
|
||||
interface ActionDelegate {
|
||||
|
||||
/**
|
||||
* Called when command goal has been changed.
|
||||
*
|
||||
* @param goalId
|
||||
* new value of the command goal
|
||||
*/
|
||||
void onGoalChanged(String goalId);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.goal;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.KeyUpEvent;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.uibinder.client.UiHandler;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.ui.listbox.CustomComboBox;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Implementation of {@link GoalPageView}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class GoalPageViewImpl extends Composite implements GoalPageView {
|
||||
|
||||
private static final GoalPageViewImplUiBinder UI_BINDER = GWT.create(GoalPageViewImplUiBinder.class);
|
||||
|
||||
@UiField
|
||||
CustomComboBox goalComboBox;
|
||||
|
||||
private ActionDelegate delegate;
|
||||
|
||||
@Inject
|
||||
public GoalPageViewImpl() {
|
||||
initWidget(UI_BINDER.createAndBindUi(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAvailableGoals(Set<CommandGoal> goals) {
|
||||
goalComboBox.clear();
|
||||
goals.forEach(g -> goalComboBox.addItem(g.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGoal(String goalId) {
|
||||
goalComboBox.setValue(goalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDelegate(ActionDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@UiHandler({"goalComboBox"})
|
||||
void onGoalKeyUp(KeyUpEvent event) {
|
||||
delegate.onGoalChanged(goalComboBox.getValue());
|
||||
}
|
||||
|
||||
@UiHandler({"goalComboBox"})
|
||||
void onGoalChanged(ChangeEvent event) {
|
||||
delegate.onGoalChanged(goalComboBox.getValue());
|
||||
}
|
||||
|
||||
interface GoalPageViewImplUiBinder extends UiBinder<Widget, GoalPageViewImpl> {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:che='urn:import:org.eclipse.che.ide.ui.listbox'>
|
||||
<ui:style>
|
||||
.combo-box {
|
||||
display: block;
|
||||
}
|
||||
</ui:style>
|
||||
<che:CustomComboBox ui:field="goalComboBox" width="100%" addStyleNames="{style.combo-box}" debugId="command_editor-goal"/>
|
||||
</ui:UiBinder>
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.name;
|
||||
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.command.CommandExecutor;
|
||||
import org.eclipse.che.ide.command.editor.EditorMessages;
|
||||
import org.eclipse.che.ide.command.editor.page.AbstractCommandEditorPage;
|
||||
import org.eclipse.che.ide.command.editor.page.CommandEditorPage;
|
||||
|
||||
/**
|
||||
* Presenter for {@link CommandEditorPage} which allows to edit command's name.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class NamePage extends AbstractCommandEditorPage implements NamePageView.ActionDelegate {
|
||||
|
||||
private final NamePageView view;
|
||||
private final CommandExecutor commandExecutor;
|
||||
|
||||
/** Initial value of the command's name. */
|
||||
private String commandNameInitial;
|
||||
|
||||
@Inject
|
||||
public NamePage(NamePageView view, EditorMessages messages, CommandExecutor commandExecutor) {
|
||||
super(messages.pageNameTitle());
|
||||
|
||||
this.view = view;
|
||||
this.commandExecutor = commandExecutor;
|
||||
|
||||
view.setDelegate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IsWidget getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
commandNameInitial = editedCommand.getName();
|
||||
|
||||
view.setCommandName(editedCommand.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty() {
|
||||
if (editedCommand == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !(commandNameInitial.equals(editedCommand.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNameChanged(String name) {
|
||||
editedCommand.setName(name);
|
||||
|
||||
notifyDirtyStateChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandRun() {
|
||||
commandExecutor.executeCommand(editedCommand);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.name;
|
||||
|
||||
import org.eclipse.che.ide.api.mvp.View;
|
||||
|
||||
/**
|
||||
* The view for {@link NamePage}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface NamePageView extends View<NamePageView.ActionDelegate> {
|
||||
|
||||
/** Sets the command's name value. */
|
||||
void setCommandName(String name);
|
||||
|
||||
/** The action delegate for this view. */
|
||||
interface ActionDelegate {
|
||||
|
||||
/**
|
||||
* Called when command's name has been changed.
|
||||
*
|
||||
* @param name
|
||||
* changed value of the command's name
|
||||
*/
|
||||
void onNameChanged(String name);
|
||||
|
||||
/** Called when executing command is requested. */
|
||||
void onCommandRun();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.name;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.KeyUpEvent;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.uibinder.client.UiHandler;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Implementation of {@link NamePageView}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class NamePageViewImpl extends Composite implements NamePageView {
|
||||
|
||||
private static final NamePageViewImplUiBinder UI_BINDER = GWT.create(NamePageViewImplUiBinder.class);
|
||||
|
||||
@UiField
|
||||
TextBox commandName;
|
||||
|
||||
@UiField
|
||||
Button runButton;
|
||||
|
||||
private ActionDelegate delegate;
|
||||
|
||||
@Inject
|
||||
public NamePageViewImpl() {
|
||||
initWidget(UI_BINDER.createAndBindUi(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCommandName(String name) {
|
||||
commandName.setValue(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDelegate(ActionDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@UiHandler({"commandName"})
|
||||
void onNameChanged(KeyUpEvent event) {
|
||||
delegate.onNameChanged(commandName.getValue());
|
||||
}
|
||||
|
||||
@UiHandler("runButton")
|
||||
public void handleRunButton(ClickEvent clickEvent) {
|
||||
delegate.onCommandRun();
|
||||
}
|
||||
|
||||
interface NamePageViewImplUiBinder extends UiBinder<Widget, NamePageViewImpl> {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
|
||||
<ui:with field='messages' type='org.eclipse.che.ide.command.editor.EditorMessages'/>
|
||||
<ui:style>
|
||||
.button {
|
||||
float: right;
|
||||
margin-top: 1px;
|
||||
font-weight: bold;
|
||||
background: #51b200;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background: #51b200;
|
||||
}
|
||||
</ui:style>
|
||||
|
||||
<g:FlowPanel width="100%">
|
||||
<g:Button ui:field="runButton"
|
||||
text="{messages.buttonRunText}"
|
||||
addStyleNames="{style.button}"
|
||||
debugId="command-editor-button-run"/>
|
||||
<g:TextBox ui:field="commandName" width="88%"/>
|
||||
</g:FlowPanel>
|
||||
</ui:UiBinder>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.previewurl;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.editor.defaulteditor.EditorBuilder;
|
||||
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry;
|
||||
import org.eclipse.che.ide.command.editor.EditorMessages;
|
||||
import org.eclipse.che.ide.command.editor.page.CommandEditorPage;
|
||||
import org.eclipse.che.ide.command.editor.page.text.AbstractPageWithTextEditor;
|
||||
import org.eclipse.che.ide.command.editor.page.text.MacroEditorConfiguration;
|
||||
import org.eclipse.che.ide.command.editor.page.text.PageWithTextEditorView;
|
||||
import org.eclipse.che.ide.macro.chooser.MacroChooser;
|
||||
|
||||
import static org.eclipse.che.api.workspace.shared.Constants.COMMAND_PREVIEW_URL_ATTRIBUTE_NAME;
|
||||
|
||||
/**
|
||||
* Presenter for {@link CommandEditorPage} which allows to edit command's preview URL.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class PreviewUrlPage extends AbstractPageWithTextEditor {
|
||||
|
||||
@Inject
|
||||
public PreviewUrlPage(PageWithTextEditorView view,
|
||||
EditorBuilder editorBuilder,
|
||||
FileTypeRegistry fileTypeRegistry,
|
||||
MacroChooser macroChooser,
|
||||
EditorMessages messages,
|
||||
MacroEditorConfiguration editorConfiguration) {
|
||||
super(view,
|
||||
editorBuilder,
|
||||
fileTypeRegistry,
|
||||
macroChooser,
|
||||
messages.pagePreviewUrlTitle(),
|
||||
editorConfiguration);
|
||||
|
||||
view.asWidget().getElement().setId("command_editor-preview_url");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCommandPropertyValue() {
|
||||
final String previewUrl = editedCommand.getAttributes().get(COMMAND_PREVIEW_URL_ATTRIBUTE_NAME);
|
||||
|
||||
return previewUrl != null ? previewUrl : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateCommandPropertyValue(String content) {
|
||||
editedCommand.getAttributes().put(COMMAND_PREVIEW_URL_ATTRIBUTE_NAME, content);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.project;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeHandler;
|
||||
import com.google.gwt.event.shared.HandlerRegistration;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.HasValue;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
|
||||
import org.eclipse.che.ide.ui.switcher.Switcher;
|
||||
|
||||
/**
|
||||
* Switcher widget which is associated with some project name.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class ProjectSwitcher extends Composite implements HasValue<Boolean> {
|
||||
|
||||
private static final ProjectSwitcherUiBinder UI_BINDER = GWT.create(ProjectSwitcherUiBinder.class);
|
||||
|
||||
@UiField
|
||||
Label label;
|
||||
|
||||
@UiField
|
||||
Switcher switcher;
|
||||
|
||||
ProjectSwitcher(String projectName) {
|
||||
initWidget(UI_BINDER.createAndBindUi(this));
|
||||
|
||||
label.setText(projectName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getValue() {
|
||||
return switcher.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Boolean value) {
|
||||
switcher.setValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Boolean value, boolean fireEvents) {
|
||||
switcher.setValue(value, fireEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Boolean> handler) {
|
||||
return switcher.addValueChangeHandler(handler);
|
||||
}
|
||||
|
||||
interface ProjectSwitcherUiBinder extends UiBinder<Widget, ProjectSwitcher> {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:g='urn:import:com.google.gwt.user.client.ui'
|
||||
xmlns:che='urn:import:org.eclipse.che.ide.ui.switcher'>
|
||||
|
||||
<ui:style>
|
||||
.panel {
|
||||
background-color: #3D4650;
|
||||
padding: 5px 0 5px 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
display: inline-block;
|
||||
width: 150px;
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
|
||||
.switcher {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</ui:style>
|
||||
|
||||
<g:FlowPanel addStyleNames="{style.panel}">
|
||||
<g:Label ui:field="label" addStyleNames="{style.label}"/>
|
||||
<che:Switcher ui:field="switcher" addStyleNames="{style.switcher}"/>
|
||||
</g:FlowPanel>
|
||||
</ui:UiBinder>
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.project;
|
||||
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.web.bindery.event.shared.EventBus;
|
||||
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl.ApplicableContext;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
import org.eclipse.che.ide.api.resources.Resource;
|
||||
import org.eclipse.che.ide.api.resources.ResourceChangedEvent;
|
||||
import org.eclipse.che.ide.api.resources.ResourceChangedEvent.ResourceChangedHandler;
|
||||
import org.eclipse.che.ide.api.resources.ResourceDelta;
|
||||
import org.eclipse.che.ide.command.editor.EditorMessages;
|
||||
import org.eclipse.che.ide.command.editor.page.AbstractCommandEditorPage;
|
||||
import org.eclipse.che.ide.command.editor.page.CommandEditorPage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** Presenter for {@link CommandEditorPage} which allows to edit command's applicable projects. */
|
||||
public class ProjectsPage extends AbstractCommandEditorPage implements ProjectsPageView.ActionDelegate,
|
||||
ResourceChangedHandler {
|
||||
|
||||
private final ProjectsPageView view;
|
||||
private final AppContext appContext;
|
||||
|
||||
/** Initial value of the applicable projects list. */
|
||||
private List<String> applicableProjectsInitial;
|
||||
|
||||
@Inject
|
||||
public ProjectsPage(ProjectsPageView view,
|
||||
AppContext appContext,
|
||||
EditorMessages messages,
|
||||
EventBus eventBus) {
|
||||
super(messages.pageProjectsTitle());
|
||||
|
||||
this.view = view;
|
||||
this.appContext = appContext;
|
||||
|
||||
eventBus.addHandler(ResourceChangedEvent.getType(), this);
|
||||
|
||||
view.setDelegate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IsWidget getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
final ApplicableContext context = editedCommand.getApplicableContext();
|
||||
|
||||
applicableProjectsInitial = new ArrayList<>(context.getApplicableProjects());
|
||||
|
||||
refreshProjects();
|
||||
}
|
||||
|
||||
/** Refresh 'Projects' section in the view. */
|
||||
private void refreshProjects() {
|
||||
final Map<Project, Boolean> projectsState = new HashMap<>();
|
||||
|
||||
for (Project project : appContext.getProjects()) {
|
||||
ApplicableContext context = editedCommand.getApplicableContext();
|
||||
boolean applicable = context.getApplicableProjects().contains(project.getPath());
|
||||
|
||||
projectsState.put(project, applicable);
|
||||
}
|
||||
|
||||
view.setProjects(projectsState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty() {
|
||||
if (editedCommand == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ApplicableContext context = editedCommand.getApplicableContext();
|
||||
|
||||
return !(applicableProjectsInitial.equals(context.getApplicableProjects()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicableProjectChanged(Project project, boolean applicable) {
|
||||
final ApplicableContext context = editedCommand.getApplicableContext();
|
||||
|
||||
if (applicable) {
|
||||
// if command is bound with one project at least
|
||||
// then remove command from the workspace
|
||||
if (context.getApplicableProjects().isEmpty()) {
|
||||
context.setWorkspaceApplicable(false);
|
||||
}
|
||||
|
||||
context.addProject(project.getPath());
|
||||
} else {
|
||||
context.removeProject(project.getPath());
|
||||
|
||||
// if command isn't bound to any project
|
||||
// then save it to the workspace
|
||||
if (context.getApplicableProjects().isEmpty()) {
|
||||
context.setWorkspaceApplicable(true);
|
||||
}
|
||||
}
|
||||
|
||||
notifyDirtyStateChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResourceChanged(ResourceChangedEvent event) {
|
||||
final ResourceDelta delta = event.getDelta();
|
||||
final Resource resource = delta.getResource();
|
||||
|
||||
if (resource.isProject()) {
|
||||
// defer refreshing the projects section since appContext#getProjects may return old data
|
||||
Scheduler.get().scheduleDeferred(this::refreshProjects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.project;
|
||||
|
||||
import org.eclipse.che.ide.api.mvp.View;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The view for {@link ProjectsPage}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface ProjectsPageView extends View<ProjectsPageView.ActionDelegate> {
|
||||
|
||||
/** Sets the applicable projects. */
|
||||
void setProjects(Map<Project, Boolean> projects);
|
||||
|
||||
/** The action delegate for this view. */
|
||||
interface ActionDelegate {
|
||||
|
||||
/** Called when applicable project has been changed. */
|
||||
void onApplicableProjectChanged(Project project, boolean applicable);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.project;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Implementation of {@link ProjectsPageView}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class ProjectsPageViewImpl extends Composite implements ProjectsPageView {
|
||||
|
||||
private static final ProjectsPageViewImplUiBinder UI_BINDER = GWT.create(ProjectsPageViewImplUiBinder.class);
|
||||
|
||||
@UiField
|
||||
FlowPanel mainPanel;
|
||||
|
||||
@UiField
|
||||
FlowPanel projectsPanel;
|
||||
|
||||
private ActionDelegate delegate;
|
||||
|
||||
@Inject
|
||||
public ProjectsPageViewImpl() {
|
||||
initWidget(UI_BINDER.createAndBindUi(this));
|
||||
|
||||
mainPanel.setVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProjects(Map<Project, Boolean> projects) {
|
||||
projectsPanel.clear();
|
||||
mainPanel.setVisible(!projects.isEmpty());
|
||||
|
||||
projects.entrySet().forEach(entry -> addProjectSwitcherToPanel(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
|
||||
private void addProjectSwitcherToPanel(Project project, boolean applicable) {
|
||||
final ProjectSwitcher switcher = new ProjectSwitcher(project.getName());
|
||||
switcher.setValue(applicable);
|
||||
switcher.addValueChangeHandler(event -> delegate.onApplicableProjectChanged(project, event.getValue()));
|
||||
|
||||
projectsPanel.add(switcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDelegate(ActionDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
interface ProjectsPageViewImplUiBinder extends UiBinder<Widget, ProjectsPageViewImpl> {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
|
||||
<ui:with field='messages' type='org.eclipse.che.ide.command.editor.EditorMessages'/>
|
||||
<ui:style>
|
||||
@eval textFieldBorderColor org.eclipse.che.ide.api.theme.Style.theme.toolButtonActiveBorder();
|
||||
|
||||
.table {
|
||||
border: textFieldBorderColor;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background-color: #2E353B;
|
||||
}
|
||||
|
||||
.column-header {
|
||||
display: inline-block;
|
||||
width: 150px;
|
||||
margin-left: 10px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
</ui:style>
|
||||
|
||||
<g:FlowPanel width="100%" ui:field="mainPanel" addStyleNames="{style.table}" debugId="command_editor-projects">
|
||||
<g:FlowPanel addStyleNames="{style.table-header}">
|
||||
<g:Label text="{messages.pageProjectsTableHeaderProjectLabel}" addStyleNames="{style.column-header}"/>
|
||||
<g:Label text="{messages.pageProjectsTableHeaderApplicableLabel}" addStyleNames="{style.column-header}"/>
|
||||
</g:FlowPanel>
|
||||
<g:FlowPanel ui:field="projectsPanel"/>
|
||||
</g:FlowPanel>
|
||||
</ui:UiBinder>
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.text;
|
||||
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
|
||||
import org.eclipse.che.ide.api.editor.OpenEditorCallbackImpl;
|
||||
import org.eclipse.che.ide.api.editor.defaulteditor.EditorBuilder;
|
||||
import org.eclipse.che.ide.api.editor.document.Document;
|
||||
import org.eclipse.che.ide.api.editor.editorconfig.TextEditorConfiguration;
|
||||
import org.eclipse.che.ide.api.editor.texteditor.TextEditor;
|
||||
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry;
|
||||
import org.eclipse.che.ide.api.resources.SyntheticFile;
|
||||
import org.eclipse.che.ide.api.resources.VirtualFile;
|
||||
import org.eclipse.che.ide.command.editor.page.AbstractCommandEditorPage;
|
||||
import org.eclipse.che.ide.command.editor.page.CommandEditorPage;
|
||||
import org.eclipse.che.ide.macro.chooser.MacroChooser;
|
||||
|
||||
import static org.eclipse.che.ide.api.editor.EditorPartPresenter.PROP_DIRTY;
|
||||
import static org.eclipse.che.ide.api.editor.EditorPartPresenter.PROP_INPUT;
|
||||
|
||||
/**
|
||||
* Abstract {@link CommandEditorPage} which allows to edit a command's property
|
||||
* with a text editor that provides autocompletion for macros names.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public abstract class AbstractPageWithTextEditor extends AbstractCommandEditorPage implements PageWithTextEditorView.ActionDelegate {
|
||||
|
||||
private final PageWithTextEditorView view;
|
||||
private final FileTypeRegistry fileTypeRegistry;
|
||||
private final MacroChooser macroChooser;
|
||||
private final TextEditorConfiguration editorConfiguration;
|
||||
|
||||
private TextEditor editor;
|
||||
|
||||
/** Initial value of the edited command's property. */
|
||||
private String initialValue;
|
||||
|
||||
protected AbstractPageWithTextEditor(PageWithTextEditorView view,
|
||||
EditorBuilder editorBuilder,
|
||||
FileTypeRegistry fileTypeRegistry,
|
||||
MacroChooser macroChooser,
|
||||
String title,
|
||||
TextEditorConfiguration editorConfiguration) {
|
||||
super("");
|
||||
|
||||
this.view = view;
|
||||
this.fileTypeRegistry = fileTypeRegistry;
|
||||
this.macroChooser = macroChooser;
|
||||
this.editorConfiguration = editorConfiguration;
|
||||
|
||||
view.setDelegate(this);
|
||||
view.setHeight(getHeight());
|
||||
view.setEditorTitle(title);
|
||||
|
||||
initializeEditor(editorBuilder);
|
||||
}
|
||||
|
||||
private void initializeEditor(EditorBuilder editorBuilder) {
|
||||
editor = editorBuilder.buildEditor();
|
||||
editor.initialize(editorConfiguration);
|
||||
editor.activate();
|
||||
|
||||
editor.addPropertyListener((source, propId) -> {
|
||||
switch (propId) {
|
||||
case PROP_INPUT:
|
||||
editor.go(view.getEditorContainer());
|
||||
|
||||
editor.getEditorWidget().setAnnotationRulerVisible(false);
|
||||
editor.getEditorWidget().setFoldingRulerVisible(false);
|
||||
editor.getEditorWidget().setZoomRulerVisible(false);
|
||||
editor.getEditorWidget().setOverviewRulerVisible(false);
|
||||
|
||||
break;
|
||||
case PROP_DIRTY:
|
||||
updateCommandPropertyValue(editor.getDocument().getContents());
|
||||
notifyDirtyStateChanged();
|
||||
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public IsWidget getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
initialValue = getCommandPropertyValue();
|
||||
|
||||
setContent(initialValue);
|
||||
}
|
||||
|
||||
/** Sets editor's content. */
|
||||
private void setContent(String content) {
|
||||
VirtualFile file = new SyntheticFile(editedCommand.getName() + getType(), content);
|
||||
|
||||
editor.init(new EditorInputImpl(fileTypeRegistry.getFileTypeByFile(file), file), new OpenEditorCallbackImpl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty() {
|
||||
if (editedCommand == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !initialValue.equals(getCommandPropertyValue());
|
||||
}
|
||||
|
||||
/** Returns the current value of the edited command's property. */
|
||||
protected abstract String getCommandPropertyValue();
|
||||
|
||||
/**
|
||||
* Updates the value of the edited command's property.
|
||||
*
|
||||
* @param newValue
|
||||
* new value of the edited command's property
|
||||
*/
|
||||
protected abstract void updateCommandPropertyValue(String newValue);
|
||||
|
||||
/** Returns height of the page in pixels. Default height is 150 px. */
|
||||
protected int getHeight() {
|
||||
return 150;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns type of the edited content.
|
||||
* Type must be specified as file's extension e.g.: .sh, .css.
|
||||
* Default type is text/plain.
|
||||
*/
|
||||
protected String getType() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExploreMacros() {
|
||||
macroChooser.show(macro -> {
|
||||
Document document = editor.getDocument();
|
||||
document.replace(document.getCursorOffset(), 0, macro.getName());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.text;
|
||||
|
||||
import org.eclipse.che.ide.api.editor.EditorInput;
|
||||
import org.eclipse.che.ide.api.filetypes.FileType;
|
||||
import org.eclipse.che.ide.api.resources.VirtualFile;
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
class EditorInputImpl implements EditorInput {
|
||||
|
||||
private VirtualFile file;
|
||||
private FileType fileType;
|
||||
|
||||
EditorInputImpl(FileType fileType, VirtualFile file) {
|
||||
this.fileType = fileType;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolTipText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return file.getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SVGResource getSVGResource() {
|
||||
return fileType.getImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFile(VirtualFile file) {
|
||||
this.file = file;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.text;
|
||||
|
||||
import org.eclipse.che.ide.Resources;
|
||||
import org.eclipse.che.ide.api.editor.codeassist.CodeAssistCallback;
|
||||
import org.eclipse.che.ide.api.editor.codeassist.CodeAssistProcessor;
|
||||
import org.eclipse.che.ide.api.editor.codeassist.CompletionProposal;
|
||||
import org.eclipse.che.ide.api.editor.document.Document;
|
||||
import org.eclipse.che.ide.api.editor.text.TextPosition;
|
||||
import org.eclipse.che.ide.api.editor.texteditor.TextEditor;
|
||||
import org.eclipse.che.ide.api.macro.Macro;
|
||||
import org.eclipse.che.ide.api.macro.MacroRegistry;
|
||||
import org.eclipse.che.ide.filters.FuzzyMatches;
|
||||
import org.eclipse.che.ide.filters.Match;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Code assist processor for macro names. */
|
||||
public class MacroCodeAssistProcessor implements CodeAssistProcessor {
|
||||
|
||||
private MacroRegistry registry;
|
||||
private FuzzyMatches fuzzyMatches;
|
||||
private Resources resources;
|
||||
private LastCompletion lastCompletion;
|
||||
|
||||
@Inject
|
||||
public MacroCodeAssistProcessor(MacroRegistry registry, FuzzyMatches fuzzyMatches, Resources resources) {
|
||||
this.registry = registry;
|
||||
this.fuzzyMatches = fuzzyMatches;
|
||||
this.resources = resources;
|
||||
lastCompletion = new LastCompletion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computeCompletionProposals(TextEditor editor, int offset, boolean triggered, CodeAssistCallback callback) {
|
||||
Document document = editor.getDocument();
|
||||
TextPosition position = document.getPositionFromIndex(offset);
|
||||
|
||||
String currentLine = editor.getDocument().getLineContent(position.getLine());
|
||||
final String currentWord = getCurrentWord(currentLine, position.getCharacter());
|
||||
|
||||
List<CompletionProposal> result = new ArrayList<>();
|
||||
if (triggered && !lastCompletion.isGoodFor(currentWord, offset)) {
|
||||
lastCompletion.offset = offset;
|
||||
lastCompletion.wordStartOffset = offset - currentWord.length(); // start completion word
|
||||
lastCompletion.word = currentWord;
|
||||
}
|
||||
|
||||
List<Macro> macros = registry.getMacros();
|
||||
for (Macro macro : macros) {
|
||||
List<Match> matches = fuzzyMatches.fuzzyMatch(currentWord, macro.getName());
|
||||
if (matches != null) {
|
||||
MacroCompletionProposal proposal = new MacroCompletionProposal(macro,
|
||||
matches,
|
||||
resources,
|
||||
lastCompletion.wordStartOffset,
|
||||
currentWord.length());
|
||||
result.add(proposal);
|
||||
}
|
||||
}
|
||||
|
||||
result.sort((o1, o2) -> {
|
||||
MacroCompletionProposal p1 = ((MacroCompletionProposal)o1);
|
||||
MacroCompletionProposal p2 = ((MacroCompletionProposal)o2);
|
||||
|
||||
return p1.getMacro().getName().compareTo(p2.getMacro().getName());
|
||||
});
|
||||
|
||||
callback.proposalComputed(result);
|
||||
}
|
||||
|
||||
private String getCurrentWord(String text, int offset) {
|
||||
int i = offset - 1;
|
||||
while (i >= 0 && isWordChar(text.charAt(i))) {
|
||||
i--;
|
||||
}
|
||||
return text.substring(i + 1, offset);
|
||||
}
|
||||
|
||||
private boolean isWordChar(char c) {
|
||||
return c >= 'a' && c <= 'z' ||
|
||||
c >= 'A' && c <= 'Z' ||
|
||||
c >= '0' && c <= '9' ||
|
||||
c >= '\u007f' && c <= '\u00ff' ||
|
||||
c == '$' ||
|
||||
c == '{' ||
|
||||
c == '.' ||
|
||||
c == '_' ||
|
||||
c == '-';
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getErrorMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private class LastCompletion {
|
||||
String word = "";
|
||||
int wordStartOffset;
|
||||
int offset;
|
||||
|
||||
boolean isGoodFor(String currentWord, int offset) {
|
||||
return currentWord.startsWith(word) &&
|
||||
offset - this.offset == currentWord.length() - word.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.text;
|
||||
|
||||
import com.google.gwt.dom.client.Style;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import org.eclipse.che.ide.Resources;
|
||||
import org.eclipse.che.ide.api.editor.codeassist.Completion;
|
||||
import org.eclipse.che.ide.api.editor.codeassist.CompletionProposal;
|
||||
import org.eclipse.che.ide.api.editor.document.Document;
|
||||
import org.eclipse.che.ide.api.editor.text.LinearRange;
|
||||
import org.eclipse.che.ide.api.icon.Icon;
|
||||
import org.eclipse.che.ide.api.macro.Macro;
|
||||
import org.eclipse.che.ide.filters.Match;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Completion proposal for {@link Macro} that will insert {@link Macro#getName()} value. */
|
||||
class MacroCompletionProposal implements CompletionProposal {
|
||||
|
||||
private final Macro macro;
|
||||
private final List<Match> matches;
|
||||
private Resources resources;
|
||||
private int offset;
|
||||
private int length;
|
||||
|
||||
MacroCompletionProposal(Macro macro, List<Match> matches, Resources resources, int offset, int length) {
|
||||
this.macro = macro;
|
||||
this.matches = matches;
|
||||
this.resources = resources;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAdditionalProposalInfo(AsyncCallback<Widget> callback) {
|
||||
String documentation = macro.getDescription();
|
||||
if (documentation == null || documentation.trim().isEmpty()) {
|
||||
documentation = "No documentation found.";
|
||||
}
|
||||
|
||||
Label label = new Label(documentation);
|
||||
label.setWordWrap(true);
|
||||
label.getElement().getStyle().setFontSize(13, Style.Unit.PX);
|
||||
label.getElement().getStyle().setMarginLeft(4, Style.Unit.PX);
|
||||
label.setSize("100%", "100%");
|
||||
callback.onSuccess(label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayString() {
|
||||
SafeHtmlBuilder builder = new SafeHtmlBuilder();
|
||||
|
||||
String label = macro.getName();
|
||||
int pos = 0;
|
||||
for (Match highlight : matches) {
|
||||
if (highlight.getStart() == highlight.getEnd()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pos < highlight.getStart()) {
|
||||
appendPlain(builder, label.substring(pos, highlight.getStart()));
|
||||
}
|
||||
|
||||
appendHighlighted(builder, label.substring(highlight.getStart(), highlight.getEnd()));
|
||||
pos = highlight.getEnd();
|
||||
}
|
||||
|
||||
if (pos < label.length()) {
|
||||
appendPlain(builder, label.substring(pos));
|
||||
}
|
||||
|
||||
return builder.toSafeHtml().asString();
|
||||
}
|
||||
|
||||
private void appendPlain(SafeHtmlBuilder builder, String text) {
|
||||
builder.appendEscaped(text);
|
||||
}
|
||||
|
||||
private void appendHighlighted(SafeHtmlBuilder builder, String text) {
|
||||
builder.appendHtmlConstant("<span class=\"" + resources.coreCss().codeassistantHighlight() + "\">");
|
||||
builder.appendEscaped(text);
|
||||
builder.appendHtmlConstant("</span>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCompletion(final CompletionCallback callback) {
|
||||
callback.onCompletion(new Completion() {
|
||||
@Override
|
||||
public void apply(Document document) {
|
||||
document.replace(offset, length, macro.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearRange getSelection(Document document) {
|
||||
LinearRange.PartialLinearRange start = LinearRange.createWithStart(offset + macro.getName().length());
|
||||
return start.andLength(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Macro getMacro() {
|
||||
return macro;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.text;
|
||||
|
||||
import org.eclipse.che.ide.api.editor.codeassist.CodeAssistProcessor;
|
||||
import org.eclipse.che.ide.api.editor.editorconfig.DefaultTextEditorConfiguration;
|
||||
import org.eclipse.che.ide.api.editor.editorconfig.TextEditorConfiguration;
|
||||
import org.eclipse.che.ide.api.editor.partition.DocumentPartitioner;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link TextEditorConfiguration} which provides {@link CodeAssistProcessor} for macros names.
|
||||
*/
|
||||
public class MacroEditorConfiguration extends DefaultTextEditorConfiguration {
|
||||
|
||||
private MacroCodeAssistProcessor codeAssistProcessor;
|
||||
|
||||
@Inject
|
||||
public MacroEditorConfiguration(MacroCodeAssistProcessor codeAssistProcessor) {
|
||||
this.codeAssistProcessor = codeAssistProcessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, CodeAssistProcessor> getContentAssistantProcessors() {
|
||||
Map<String, CodeAssistProcessor> map = new HashMap<>();
|
||||
map.put(DocumentPartitioner.DEFAULT_CONTENT_TYPE, codeAssistProcessor);
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.text;
|
||||
|
||||
import com.google.gwt.user.client.ui.SimpleLayoutPanel;
|
||||
|
||||
import org.eclipse.che.ide.api.mvp.View;
|
||||
|
||||
/**
|
||||
* View for {@link AbstractPageWithTextEditor}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface PageWithTextEditorView extends View<PageWithTextEditorView.ActionDelegate> {
|
||||
|
||||
/** Returns the container where the editor should be placed. */
|
||||
SimpleLayoutPanel getEditorContainer();
|
||||
|
||||
/** Sets height of the view. */
|
||||
void setHeight(int height);
|
||||
|
||||
/** Sets title for the editor. */
|
||||
void setEditorTitle(String title);
|
||||
|
||||
/** The action delegate for this view. */
|
||||
interface ActionDelegate {
|
||||
|
||||
/** Called when exploring macros is requested. */
|
||||
void onExploreMacros();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.editor.page.text;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.uibinder.client.UiHandler;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.DockLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.Hyperlink;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.SimpleLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Implementation of {@link PageWithTextEditorView}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class PageWithTextEditorViewImpl extends Composite implements PageWithTextEditorView {
|
||||
|
||||
private static final PageWithTextEditorViewImplUiBinder UI_BINDER = GWT.create(PageWithTextEditorViewImplUiBinder.class);
|
||||
|
||||
@UiField
|
||||
DockLayoutPanel mainPanel;
|
||||
|
||||
@UiField
|
||||
Label title;
|
||||
|
||||
@UiField
|
||||
Hyperlink exploreMacrosLink;
|
||||
|
||||
@UiField
|
||||
SimpleLayoutPanel editorPanel;
|
||||
|
||||
/** The delegate to receive events from this view. */
|
||||
private ActionDelegate delegate;
|
||||
|
||||
@Inject
|
||||
public PageWithTextEditorViewImpl() {
|
||||
initWidget(UI_BINDER.createAndBindUi(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDelegate(ActionDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimpleLayoutPanel getEditorContainer() {
|
||||
return editorPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeight(int height) {
|
||||
mainPanel.setHeight(height + "px");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEditorTitle(String title) {
|
||||
this.title.setText(title);
|
||||
}
|
||||
|
||||
@UiHandler("exploreMacrosLink")
|
||||
public void handleExploreMacrosLinkClick(ClickEvent event) {
|
||||
delegate.onExploreMacros();
|
||||
}
|
||||
|
||||
interface PageWithTextEditorViewImplUiBinder extends UiBinder<Widget, PageWithTextEditorViewImpl> {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
|
||||
<ui:with field='messages' type='org.eclipse.che.ide.command.editor.EditorMessages'/>
|
||||
<ui:with field='resources' type='org.eclipse.che.ide.command.CommandResources'/>
|
||||
<ui:style>
|
||||
@eval textFieldBorderColor org.eclipse.che.ide.api.theme.Style.theme.toolButtonActiveBorder();
|
||||
|
||||
.editor {
|
||||
border: textFieldBorderColor;
|
||||
}
|
||||
|
||||
.title {
|
||||
float: left;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.link a, a:visited {
|
||||
float: right;
|
||||
margin: 8px 10px 8px 0;
|
||||
color: #4990E2;
|
||||
font-size: 11px;
|
||||
}
|
||||
</ui:style>
|
||||
<g:DockLayoutPanel ui:field="mainPanel" width="100%">
|
||||
<g:north size="30">
|
||||
<g:FlowPanel>
|
||||
<g:Label ui:field="title" addStyleNames="{resources.editorCss.sectionLabel} {style.title}"/>
|
||||
<g:Hyperlink ui:field="exploreMacrosLink"
|
||||
text="{messages.pageWithTextEditorMacros}"
|
||||
addStyleNames="{style.link}"
|
||||
debugId="link-explore_macros"/>
|
||||
</g:FlowPanel>
|
||||
</g:north>
|
||||
<g:center>
|
||||
<g:SimpleLayoutPanel ui:field="editorPanel" addStyleNames="{style.editor}"/>
|
||||
</g:center>
|
||||
</g:DockLayoutPanel>
|
||||
</ui:UiBinder>
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.execute;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.model.machine.Machine;
|
||||
import org.eclipse.che.ide.api.action.ActionEvent;
|
||||
import org.eclipse.che.ide.api.action.ActionManager;
|
||||
import org.eclipse.che.ide.api.action.DefaultActionGroup;
|
||||
import org.eclipse.che.ide.api.resources.Resource;
|
||||
import org.eclipse.che.ide.api.selection.Selection;
|
||||
import org.eclipse.che.ide.api.selection.SelectionAgent;
|
||||
import org.eclipse.che.ide.resources.tree.ResourceNode;
|
||||
|
||||
/**
|
||||
* Action group that contains all actions for executing commands.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
@Singleton
|
||||
public class CommandsActionGroup extends DefaultActionGroup {
|
||||
|
||||
private final SelectionAgent selectionAgent;
|
||||
|
||||
@Inject
|
||||
public CommandsActionGroup(ActionManager actionManager,
|
||||
SelectionAgent selectionAgent,
|
||||
ExecMessages messages) {
|
||||
super(messages.actionCommandsTitle(), true, actionManager);
|
||||
|
||||
this.selectionAgent = selectionAgent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(ActionEvent e) {
|
||||
e.getPresentation().setEnabledAndVisible(false);
|
||||
|
||||
// action group should be visible when current selection is machine or project
|
||||
|
||||
final Selection<?> selection = selectionAgent.getSelection();
|
||||
|
||||
if (selection != null && !selection.isEmpty() && selection.isSingleSelection()) {
|
||||
final Object possibleNode = selection.getHeadElement();
|
||||
|
||||
if (possibleNode instanceof Machine) {
|
||||
e.getPresentation().setEnabledAndVisible(true);
|
||||
} else if (possibleNode instanceof ResourceNode) {
|
||||
final Resource selectedResource = ((ResourceNode)possibleNode).getData();
|
||||
|
||||
e.getPresentation().setEnabledAndVisible(selectedResource.isProject());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.execute;
|
||||
|
||||
import com.google.gwt.i18n.client.Messages;
|
||||
|
||||
/**
|
||||
* I18n messages relate to the command execution.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface ExecMessages extends Messages {
|
||||
|
||||
@Key("action.commands.title")
|
||||
String actionCommandsTitle();
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.execute;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import org.eclipse.che.ide.api.action.Action;
|
||||
import org.eclipse.che.ide.api.action.ActionEvent;
|
||||
import org.eclipse.che.ide.api.command.CommandExecutor;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
import org.eclipse.che.ide.command.CommandUtils;
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
/** Action for executing a {@link CommandImpl}. */
|
||||
class ExecuteCommandAction extends Action {
|
||||
|
||||
private final CommandImpl command;
|
||||
private final CommandExecutor commandExecutor;
|
||||
private final CommandManager commandManager;
|
||||
|
||||
@Inject
|
||||
ExecuteCommandAction(@Assisted CommandImpl command,
|
||||
CommandUtils commandUtils,
|
||||
CommandExecutor commandExecutor,
|
||||
CommandManager commandManager) {
|
||||
super(command.getName());
|
||||
|
||||
this.command = command;
|
||||
this.commandExecutor = commandExecutor;
|
||||
this.commandManager = commandManager;
|
||||
|
||||
final SVGResource commandIcon = commandUtils.getCommandTypeIcon(command.getType());
|
||||
if (commandIcon != null) {
|
||||
getTemplatePresentation().setSVGResource(commandIcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(ActionEvent e) {
|
||||
e.getPresentation().setEnabledAndVisible(commandManager.isCommandApplicable(command));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
commandExecutor.executeCommand(command);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.execute;
|
||||
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
|
||||
/**
|
||||
* Factory for creating {@link ExecuteCommandAction} instances.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface ExecuteCommandActionFactory {
|
||||
|
||||
/** Creates new instance of {@link ExecuteCommandAction} for executing the specified {@code command}. */
|
||||
ExecuteCommandAction create(CommandImpl command);
|
||||
}
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.execute;
|
||||
|
||||
import com.google.gwt.core.client.Callback;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.ide.api.action.Action;
|
||||
import org.eclipse.che.ide.api.action.ActionManager;
|
||||
import org.eclipse.che.ide.api.action.DefaultActionGroup;
|
||||
import org.eclipse.che.ide.api.command.CommandGoalRegistry;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
import org.eclipse.che.ide.api.command.CommandManager.CommandChangedListener;
|
||||
import org.eclipse.che.ide.api.command.CommandManager.CommandLoadedListener;
|
||||
import org.eclipse.che.ide.api.component.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static org.eclipse.che.ide.api.action.IdeActions.GROUP_CONSOLES_TREE_CONTEXT_MENU;
|
||||
import static org.eclipse.che.ide.api.action.IdeActions.GROUP_EDITOR_TAB_CONTEXT_MENU;
|
||||
import static org.eclipse.che.ide.api.action.IdeActions.GROUP_MAIN_CONTEXT_MENU;
|
||||
|
||||
/**
|
||||
* Manager listens for creating/removing commands and adds/removes
|
||||
* related {@link ExecuteCommandAction}s in the context menus.
|
||||
*/
|
||||
@Singleton
|
||||
public class ExecuteCommandActionManager implements Component, CommandLoadedListener, CommandChangedListener {
|
||||
|
||||
private static final String COMMANDS_ACTION_GROUP_ID_PREFIX = "commandsActionGroup";
|
||||
private static final String COMMAND_ACTION_ID_PREFIX = "command_";
|
||||
private static final String GOAL_ACTION_GROUP_ID_PREFIX = "goal_";
|
||||
|
||||
private final CommandManager commandManager;
|
||||
private final ActionManager actionManager;
|
||||
private final CommandsActionGroup commandsActionGroup;
|
||||
private final GoalPopUpGroupFactory goalPopUpGroupFactory;
|
||||
private final ExecuteCommandActionFactory commandActionFactory;
|
||||
private final CommandGoalRegistry goalRegistry;
|
||||
|
||||
/** Map of command's name to an appropriate {@link ExecuteCommandAction}. */
|
||||
private final Map<String, Action> commandActions;
|
||||
/** Map of command goal's ID to an appropriate action group. */
|
||||
private final Map<String, DefaultActionGroup> goalPopUpGroups;
|
||||
|
||||
@Inject
|
||||
public ExecuteCommandActionManager(CommandManager commandManager,
|
||||
ActionManager actionManager,
|
||||
CommandsActionGroup commandsActionGroup,
|
||||
GoalPopUpGroupFactory goalPopUpGroupFactory,
|
||||
ExecuteCommandActionFactory commandActionFactory,
|
||||
CommandGoalRegistry goalRegistry) {
|
||||
this.commandManager = commandManager;
|
||||
this.actionManager = actionManager;
|
||||
this.commandsActionGroup = commandsActionGroup;
|
||||
this.goalPopUpGroupFactory = goalPopUpGroupFactory;
|
||||
this.commandActionFactory = commandActionFactory;
|
||||
this.goalRegistry = goalRegistry;
|
||||
|
||||
commandActions = new HashMap<>();
|
||||
goalPopUpGroups = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Callback<Component, Exception> callback) {
|
||||
callback.onSuccess(this);
|
||||
|
||||
commandManager.addCommandLoadedListener(this);
|
||||
commandManager.addCommandChangedListener(this);
|
||||
|
||||
actionManager.registerAction(COMMANDS_ACTION_GROUP_ID_PREFIX, commandsActionGroup);
|
||||
|
||||
// inject 'Commands' menu into context menus
|
||||
((DefaultActionGroup)actionManager.getAction(GROUP_MAIN_CONTEXT_MENU)).add(commandsActionGroup);
|
||||
((DefaultActionGroup)actionManager.getAction(GROUP_EDITOR_TAB_CONTEXT_MENU)).add(commandsActionGroup);
|
||||
((DefaultActionGroup)actionManager.getAction(GROUP_CONSOLES_TREE_CONTEXT_MENU)).add(commandsActionGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandsLoaded() {
|
||||
commandManager.getCommands().forEach(this::addAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandAdded(CommandImpl command) {
|
||||
addAction(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates action for executing the given command and
|
||||
* adds created action to the appropriate action group.
|
||||
*/
|
||||
private void addAction(CommandImpl command) {
|
||||
final ExecuteCommandAction action = commandActionFactory.create(command);
|
||||
|
||||
actionManager.registerAction(COMMAND_ACTION_ID_PREFIX + command.getName(), action);
|
||||
commandActions.put(command.getName(), action);
|
||||
|
||||
getActionGroupForCommand(command).add(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the action group which is appropriate for placing the action for executing the given command.
|
||||
* If appropriate action group doesn't exist it will be created and added to the right place.
|
||||
*/
|
||||
private DefaultActionGroup getActionGroupForCommand(CommandImpl command) {
|
||||
String goalId = command.getGoal();
|
||||
|
||||
if (isNullOrEmpty(goalId)) {
|
||||
goalId = goalRegistry.getDefaultGoal().getId();
|
||||
}
|
||||
|
||||
DefaultActionGroup commandGoalPopUpGroup = goalPopUpGroups.get(goalId);
|
||||
|
||||
if (commandGoalPopUpGroup == null) {
|
||||
commandGoalPopUpGroup = goalPopUpGroupFactory.create(goalId);
|
||||
|
||||
actionManager.registerAction(GOAL_ACTION_GROUP_ID_PREFIX + goalId, commandGoalPopUpGroup);
|
||||
goalPopUpGroups.put(goalId, commandGoalPopUpGroup);
|
||||
|
||||
commandsActionGroup.add(commandGoalPopUpGroup);
|
||||
}
|
||||
|
||||
return commandGoalPopUpGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandUpdated(CommandImpl previousCommand, CommandImpl command) {
|
||||
removeAction(previousCommand);
|
||||
addAction(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandRemoved(CommandImpl command) {
|
||||
removeAction(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes action for executing the given command and
|
||||
* removes the appropriate action group in case it's empty.
|
||||
*/
|
||||
private void removeAction(CommandImpl command) {
|
||||
final Action commandAction = commandActions.remove(command.getName());
|
||||
|
||||
if (commandAction != null) {
|
||||
final String commandActionId = actionManager.getId(commandAction);
|
||||
if (commandActionId != null) {
|
||||
actionManager.unregisterAction(commandActionId);
|
||||
}
|
||||
|
||||
// remove action from it's action group
|
||||
String goalId = command.getGoal();
|
||||
if (isNullOrEmpty(goalId)) {
|
||||
goalId = goalRegistry.getDefaultGoal().getId();
|
||||
}
|
||||
|
||||
// remove action group if it's empty
|
||||
final DefaultActionGroup goalPopUpGroup = goalPopUpGroups.remove(goalId);
|
||||
|
||||
if (goalPopUpGroup != null) {
|
||||
goalPopUpGroup.remove(commandAction);
|
||||
|
||||
if (goalPopUpGroup.getChildrenCount() == 0) {
|
||||
final String goalActionId = actionManager.getId(goalPopUpGroup);
|
||||
if (goalActionId != null) {
|
||||
actionManager.unregisterAction(goalActionId);
|
||||
}
|
||||
commandsActionGroup.remove(goalPopUpGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.execute;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import org.eclipse.che.ide.api.action.ActionEvent;
|
||||
import org.eclipse.che.ide.api.action.ActionManager;
|
||||
import org.eclipse.che.ide.api.action.DefaultActionGroup;
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandGoalRegistry;
|
||||
import org.eclipse.che.ide.api.icon.Icon;
|
||||
import org.eclipse.che.ide.api.icon.IconRegistry;
|
||||
import org.vectomatic.dom.svg.ui.SVGImage;
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
/**
|
||||
* Action group that represents command goal.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
class GoalPopUpGroup extends DefaultActionGroup {
|
||||
|
||||
private final CommandGoal commandGoal;
|
||||
private final IconRegistry iconRegistry;
|
||||
|
||||
@Inject
|
||||
GoalPopUpGroup(@Assisted String goalId,
|
||||
ActionManager actionManager,
|
||||
CommandGoalRegistry goalRegistry,
|
||||
IconRegistry iconRegistry) {
|
||||
super(actionManager);
|
||||
|
||||
this.iconRegistry = iconRegistry;
|
||||
commandGoal = goalRegistry.getGoalForId(goalId);
|
||||
|
||||
setPopup(true);
|
||||
|
||||
// set icon
|
||||
final SVGResource commandTypeIcon = getCommandGoalIcon();
|
||||
if (commandTypeIcon != null) {
|
||||
getTemplatePresentation().setSVGResource(commandTypeIcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(ActionEvent e) {
|
||||
e.getPresentation().setText(commandGoal.getId() + " (" + getChildrenCount() + ")");
|
||||
}
|
||||
|
||||
private SVGResource getCommandGoalIcon() {
|
||||
final String goalId = commandGoal.getId();
|
||||
|
||||
final Icon icon = iconRegistry.getIconIfExist("command.goal." + goalId);
|
||||
|
||||
if (icon != null) {
|
||||
final SVGImage svgImage = icon.getSVGImage();
|
||||
|
||||
if (svgImage != null) {
|
||||
return icon.getSVGResource();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.execute;
|
||||
|
||||
/**
|
||||
* Factory for creating {@link GoalPopUpGroup} instances.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface GoalPopUpGroupFactory {
|
||||
|
||||
/** Creates new {@link GoalPopUpGroup} for the command goal with the given {@code id}. */
|
||||
GoalPopUpGroup create(String id);
|
||||
}
|
||||
|
|
@ -0,0 +1,305 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.explorer;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.gwt.core.client.Callback;
|
||||
import com.google.gwt.user.client.Timer;
|
||||
import com.google.gwt.user.client.ui.AcceptsOneWidget;
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.DelayedTask;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandGoalRegistry;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl.ApplicableContext;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
import org.eclipse.che.ide.api.command.CommandManager.CommandChangedListener;
|
||||
import org.eclipse.che.ide.api.command.CommandManager.CommandLoadedListener;
|
||||
import org.eclipse.che.ide.api.command.CommandType;
|
||||
import org.eclipse.che.ide.api.component.Component;
|
||||
import org.eclipse.che.ide.api.constraints.Constraints;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.api.editor.EditorAgent;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.parts.WorkspaceAgent;
|
||||
import org.eclipse.che.ide.api.parts.base.BasePresenter;
|
||||
import org.eclipse.che.ide.command.CommandResources;
|
||||
import org.eclipse.che.ide.command.CommandUtils;
|
||||
import org.eclipse.che.ide.command.node.NodeFactory;
|
||||
import org.eclipse.che.ide.command.type.chooser.CommandTypeChooser;
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.EMERGE_MODE;
|
||||
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL;
|
||||
import static org.eclipse.che.ide.api.parts.PartStackType.NAVIGATION;
|
||||
|
||||
/** Presenter for Commands Explorer. */
|
||||
@Singleton
|
||||
public class CommandsExplorerPresenter extends BasePresenter implements CommandsExplorerView.ActionDelegate,
|
||||
Component,
|
||||
CommandChangedListener,
|
||||
CommandLoadedListener {
|
||||
|
||||
private final CommandsExplorerView view;
|
||||
private final CommandResources resources;
|
||||
private final WorkspaceAgent workspaceAgent;
|
||||
private final CommandManager commandManager;
|
||||
private final NotificationManager notificationManager;
|
||||
private final CommandTypeChooser commandTypeChooser;
|
||||
private final ExplorerMessages messages;
|
||||
private final RefreshViewTask refreshViewTask;
|
||||
private final DialogFactory dialogFactory;
|
||||
private final NodeFactory nodeFactory;
|
||||
private final EditorAgent editorAgent;
|
||||
private final AppContext appContext;
|
||||
|
||||
@Inject
|
||||
public CommandsExplorerPresenter(CommandsExplorerView view,
|
||||
CommandResources commandResources,
|
||||
WorkspaceAgent workspaceAgent,
|
||||
CommandManager commandManager,
|
||||
NotificationManager notificationManager,
|
||||
CommandTypeChooser commandTypeChooser,
|
||||
ExplorerMessages messages,
|
||||
RefreshViewTask refreshViewTask,
|
||||
DialogFactory dialogFactory,
|
||||
NodeFactory nodeFactory,
|
||||
EditorAgent editorAgent,
|
||||
AppContext appContext) {
|
||||
this.view = view;
|
||||
this.resources = commandResources;
|
||||
this.workspaceAgent = workspaceAgent;
|
||||
this.commandManager = commandManager;
|
||||
this.notificationManager = notificationManager;
|
||||
this.commandTypeChooser = commandTypeChooser;
|
||||
this.messages = messages;
|
||||
this.refreshViewTask = refreshViewTask;
|
||||
this.dialogFactory = dialogFactory;
|
||||
this.nodeFactory = nodeFactory;
|
||||
this.editorAgent = editorAgent;
|
||||
this.appContext = appContext;
|
||||
|
||||
view.setDelegate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Callback<Component, Exception> callback) {
|
||||
workspaceAgent.openPart(this, NAVIGATION, Constraints.LAST);
|
||||
|
||||
commandManager.addCommandLoadedListener(this);
|
||||
commandManager.addCommandChangedListener(this);
|
||||
|
||||
callback.onSuccess(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void go(AcceptsOneWidget container) {
|
||||
refreshView();
|
||||
|
||||
container.setWidget(getView());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return messages.partTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IsWidget getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getTitleToolTip() {
|
||||
return messages.partTooltip();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SVGResource getTitleImage() {
|
||||
return resources.explorerPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandAdd(int left, int top) {
|
||||
commandTypeChooser.show(left, top).then(createCommand(getDefaultContext()));
|
||||
}
|
||||
|
||||
/** Returns the default {@link ApplicableContext} for the new command. */
|
||||
private ApplicableContext getDefaultContext() {
|
||||
final ApplicableContext context = new ApplicableContext();
|
||||
|
||||
if (appContext.getProjects().length > 0) {
|
||||
context.setWorkspaceApplicable(false);
|
||||
|
||||
Arrays.stream(appContext.getProjects())
|
||||
.forEach(p -> context.addProject(p.getPath()));
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
/** Returns an operation which creates a command with the given context. */
|
||||
private Operation<CommandType> createCommand(ApplicableContext context) {
|
||||
return selectedCommandType -> {
|
||||
final CommandGoal selectedGoal = view.getSelectedGoal();
|
||||
|
||||
if (selectedGoal == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
commandManager.createCommand(selectedGoal.getId(), selectedCommandType.getId(), context)
|
||||
.then(command -> {
|
||||
refreshViewAndSelectCommand(command);
|
||||
editorAgent.openEditor(nodeFactory.newCommandFileNode(command));
|
||||
})
|
||||
.catchError(showErrorNotification(messages.unableCreate()));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandDuplicate(CommandImpl command) {
|
||||
commandManager.createCommand(command)
|
||||
.then(this::refreshViewAndSelectCommand)
|
||||
.catchError(showErrorNotification(messages.unableDuplicate()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandRemove(CommandImpl command) {
|
||||
dialogFactory.createConfirmDialog(messages.removeCommandConfirmationTitle(),
|
||||
messages.removeCommandConfirmationMessage(command.getName()),
|
||||
() -> commandManager.removeCommand(command.getName())
|
||||
.catchError(showErrorNotification(messages.unableRemove())),
|
||||
null).show();
|
||||
}
|
||||
|
||||
/** Returns an operation which shows an error notification with the given title. */
|
||||
private Operation<PromiseError> showErrorNotification(String title) {
|
||||
return err -> {
|
||||
notificationManager.notify(title, err.getMessage(), FAIL, EMERGE_MODE);
|
||||
throw new OperationException(err.getMessage());
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandsLoaded() {
|
||||
refreshView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandAdded(CommandImpl command) {
|
||||
refreshView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandUpdated(CommandImpl previousCommand, CommandImpl command) {
|
||||
refreshView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandRemoved(CommandImpl command) {
|
||||
refreshView();
|
||||
}
|
||||
|
||||
/** Refresh view and preserve current selection. */
|
||||
private void refreshView() {
|
||||
refreshViewAndSelectCommand(null);
|
||||
}
|
||||
|
||||
private void refreshViewAndSelectCommand(CommandImpl command) {
|
||||
refreshViewTask.delayAndSelectCommand(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link DelayedTask} for refreshing the view and optionally selecting the specified command.
|
||||
* <p>Tree widget in the view works asynchronously using events
|
||||
* and it needs some time to be fully rendered.
|
||||
* So successive refreshing view must be called with some delay.
|
||||
*/
|
||||
// since GIN can't instantiate inner classes
|
||||
// made it nested in order to allow injection
|
||||
@VisibleForTesting
|
||||
static class RefreshViewTask extends DelayedTask {
|
||||
|
||||
// 300 milliseconds should be enough to fully refreshing the tree
|
||||
private static final int DELAY_MILLIS = 300;
|
||||
|
||||
private final CommandsExplorerView view;
|
||||
private final CommandGoalRegistry goalRegistry;
|
||||
private final CommandManager commandManager;
|
||||
private final CommandUtils commandUtils;
|
||||
|
||||
private CommandImpl commandToSelect;
|
||||
|
||||
@Inject
|
||||
public RefreshViewTask(CommandsExplorerView view,
|
||||
CommandGoalRegistry goalRegistry,
|
||||
CommandManager commandManager,
|
||||
CommandUtils commandUtils) {
|
||||
this.view = view;
|
||||
this.goalRegistry = goalRegistry;
|
||||
this.commandManager = commandManager;
|
||||
this.commandUtils = commandUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExecute() {
|
||||
refreshView();
|
||||
|
||||
if (commandToSelect != null) {
|
||||
// wait some time while tree in the view will be fully refreshed
|
||||
new Timer() {
|
||||
@Override
|
||||
public void run() {
|
||||
view.selectCommand(commandToSelect);
|
||||
}
|
||||
}.schedule(DELAY_MILLIS);
|
||||
}
|
||||
}
|
||||
|
||||
void delayAndSelectCommand(@Nullable CommandImpl command) {
|
||||
if (command != null) {
|
||||
commandToSelect = command;
|
||||
}
|
||||
|
||||
delay(DELAY_MILLIS);
|
||||
}
|
||||
|
||||
private void refreshView() {
|
||||
final Map<CommandGoal, List<CommandImpl>> commandsByGoals = new HashMap<>();
|
||||
|
||||
// all predefined commandToSelect goals must be shown in the view
|
||||
// so populate map by all registered commandToSelect goals
|
||||
for (CommandGoal goal : goalRegistry.getAllPredefinedGoals()) {
|
||||
commandsByGoals.put(goal, new ArrayList<>());
|
||||
}
|
||||
|
||||
commandsByGoals.putAll(commandUtils.groupCommandsByGoal(commandManager.getCommands()));
|
||||
|
||||
view.setCommands(commandsByGoals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.explorer;
|
||||
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.mvp.View;
|
||||
import org.eclipse.che.ide.api.parts.base.BaseActionDelegate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The view for {@link CommandsExplorerPresenter}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface CommandsExplorerView extends View<CommandsExplorerView.ActionDelegate> {
|
||||
|
||||
/**
|
||||
* Sets the commands to display in the view.
|
||||
*
|
||||
* @param commands
|
||||
* commands grouped by its type
|
||||
*/
|
||||
void setCommands(Map<CommandGoal, List<CommandImpl>> commands);
|
||||
|
||||
/** Returns the currently selected command goal or {@code null} if none. */
|
||||
@Nullable
|
||||
CommandGoal getSelectedGoal();
|
||||
|
||||
/** Returns the currently selected command or {@code null} if none. */
|
||||
@Nullable
|
||||
CommandImpl getSelectedCommand();
|
||||
|
||||
/** Select the given {@code command}. */
|
||||
void selectCommand(CommandImpl command);
|
||||
|
||||
/** The action delegate for this view. */
|
||||
interface ActionDelegate extends BaseActionDelegate {
|
||||
|
||||
/** Called when adding new command is requested. */
|
||||
void onCommandAdd(int left, int top);
|
||||
|
||||
/**
|
||||
* Called when duplicating command is requested.
|
||||
*
|
||||
* @param command
|
||||
* command duplication of which is requested
|
||||
*/
|
||||
void onCommandDuplicate(CommandImpl command);
|
||||
|
||||
/**
|
||||
* Called when removing command is requested.
|
||||
*
|
||||
* @param command
|
||||
* command removing of which is requested
|
||||
*/
|
||||
void onCommandRemove(CommandImpl command);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.explorer;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.Resources;
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.data.tree.Node;
|
||||
import org.eclipse.che.ide.api.parts.base.BaseView;
|
||||
import org.eclipse.che.ide.command.CommandResources;
|
||||
import org.eclipse.che.ide.command.node.CommandFileNode;
|
||||
import org.eclipse.che.ide.command.node.CommandGoalNode;
|
||||
import org.eclipse.che.ide.command.node.NodeFactory;
|
||||
import org.eclipse.che.ide.ui.smartTree.NodeLoader;
|
||||
import org.eclipse.che.ide.ui.smartTree.NodeStorage;
|
||||
import org.eclipse.che.ide.ui.smartTree.Tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.eclipse.che.ide.ui.smartTree.SelectionModel.Mode.SINGLE;
|
||||
|
||||
/**
|
||||
* Implementation of {@link CommandsExplorerView}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
@Singleton
|
||||
public class CommandsExplorerViewImpl extends BaseView<CommandsExplorerView.ActionDelegate> implements CommandsExplorerView {
|
||||
|
||||
private static final CommandsExplorerViewImplUiBinder UI_BINDER = GWT.create(CommandsExplorerViewImplUiBinder.class);
|
||||
|
||||
private final CommandsTreeRenderer treeRenderer;
|
||||
private final NodeFactory nodeFactory;
|
||||
/** Mapping of the commands to the rendered tree nodes. */
|
||||
private final Map<CommandImpl, CommandFileNode> commandNodes;
|
||||
|
||||
@UiField(provided = true)
|
||||
Tree tree;
|
||||
|
||||
@Inject
|
||||
public CommandsExplorerViewImpl(Resources coreResources,
|
||||
ExplorerMessages messages,
|
||||
CommandResources resources,
|
||||
NodeFactory nodeFactory) {
|
||||
super(coreResources);
|
||||
|
||||
this.nodeFactory = nodeFactory;
|
||||
commandNodes = new HashMap<>();
|
||||
|
||||
setTitle(messages.viewTitle());
|
||||
|
||||
tree = new Tree(new NodeStorage(), new NodeLoader());
|
||||
tree.ensureDebugId("commands-explorer");
|
||||
|
||||
treeRenderer = new CommandsTreeRenderer(tree.getTreeStyles(), resources, delegate);
|
||||
|
||||
tree.setPresentationRenderer(treeRenderer);
|
||||
tree.getSelectionModel().setSelectionMode(SINGLE);
|
||||
|
||||
tree.getSelectionModel().addSelectionHandler(event -> {
|
||||
for (Node node : tree.getNodeStorage().getAll()) {
|
||||
final Element nodeContainerElement = tree.getNodeDescriptor(node).getNodeContainerElement();
|
||||
|
||||
if (nodeContainerElement != null) {
|
||||
nodeContainerElement.removeAttribute("selected");
|
||||
}
|
||||
}
|
||||
|
||||
tree.getNodeDescriptor(event.getSelectedItem())
|
||||
.getNodeContainerElement()
|
||||
.setAttribute("selected", "selected");
|
||||
});
|
||||
|
||||
setContentWidget(UI_BINDER.createAndBindUi(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void focusView() {
|
||||
tree.setFocus(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCommands(Map<CommandGoal, List<CommandImpl>> commands) {
|
||||
treeRenderer.setDelegate(delegate);
|
||||
|
||||
renderCommands(commands);
|
||||
}
|
||||
|
||||
private void renderCommands(Map<CommandGoal, List<CommandImpl>> commands) {
|
||||
commandNodes.clear();
|
||||
tree.getNodeStorage().clear();
|
||||
|
||||
for (Entry<CommandGoal, List<CommandImpl>> entry : commands.entrySet()) {
|
||||
List<CommandFileNode> commandNodes = new ArrayList<>(entry.getValue().size());
|
||||
for (CommandImpl command : entry.getValue()) {
|
||||
final CommandFileNode commandFileNode = nodeFactory.newCommandFileNode(command);
|
||||
commandNodes.add(commandFileNode);
|
||||
|
||||
this.commandNodes.put(command, commandFileNode);
|
||||
}
|
||||
|
||||
final CommandGoalNode commandGoalNode = nodeFactory.newCommandGoalNode(entry.getKey(), commandNodes);
|
||||
tree.getNodeStorage().add(commandGoalNode);
|
||||
}
|
||||
|
||||
tree.expandAll();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CommandGoal getSelectedGoal() {
|
||||
final List<Node> selectedNodes = tree.getSelectionModel().getSelectedNodes();
|
||||
|
||||
if (!selectedNodes.isEmpty()) {
|
||||
final Node selectedNode = selectedNodes.get(0);
|
||||
|
||||
if (selectedNode instanceof CommandGoalNode) {
|
||||
return ((CommandGoalNode)selectedNode).getData();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CommandImpl getSelectedCommand() {
|
||||
final List<Node> selectedNodes = tree.getSelectionModel().getSelectedNodes();
|
||||
|
||||
if (!selectedNodes.isEmpty()) {
|
||||
final Node selectedNode = selectedNodes.get(0);
|
||||
|
||||
if (selectedNode instanceof CommandFileNode) {
|
||||
return ((CommandFileNode)selectedNode).getData();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCommand(CommandImpl command) {
|
||||
tree.getSelectionModel().setSelection(singletonList(commandNodes.get(command)));
|
||||
}
|
||||
|
||||
interface CommandsExplorerViewImplUiBinder extends UiBinder<Widget, CommandsExplorerViewImpl> {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:che='urn:import:org.eclipse.che.ide.ui'>
|
||||
<che:smartTree.Tree ui:field="tree"/>
|
||||
</ui:UiBinder>
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.explorer;
|
||||
|
||||
import com.google.gwt.dom.client.Document;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.user.client.Event;
|
||||
|
||||
import org.eclipse.che.ide.api.data.tree.Node;
|
||||
import org.eclipse.che.ide.command.CommandResources;
|
||||
import org.eclipse.che.ide.command.explorer.CommandsExplorerView.ActionDelegate;
|
||||
import org.eclipse.che.ide.command.node.CommandFileNode;
|
||||
import org.eclipse.che.ide.command.node.CommandGoalNode;
|
||||
import org.eclipse.che.ide.ui.smartTree.Tree;
|
||||
import org.eclipse.che.ide.ui.smartTree.TreeStyles;
|
||||
import org.eclipse.che.ide.ui.smartTree.presentation.DefaultPresentationRenderer;
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
import static com.google.gwt.user.client.Event.ONCLICK;
|
||||
|
||||
/**
|
||||
* Renderer for the commands tree.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
class CommandsTreeRenderer extends DefaultPresentationRenderer<Node> {
|
||||
|
||||
private final CommandResources resources;
|
||||
|
||||
private ActionDelegate delegate;
|
||||
|
||||
CommandsTreeRenderer(TreeStyles treeStyles, CommandResources resources, ActionDelegate delegate) {
|
||||
super(treeStyles);
|
||||
|
||||
this.resources = resources;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/** Sets the delegate that will handle events from the rendered DOM elements. */
|
||||
void setDelegate(ActionDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element getPresentableTextContainer(Element content) {
|
||||
final Element presentableTextContainer = super.getPresentableTextContainer(content);
|
||||
presentableTextContainer.addClassName(resources.commandsExplorerCss().commandNodeText());
|
||||
|
||||
return presentableTextContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element render(Node node, String domID, Tree.Joint joint, int depth) {
|
||||
final Element element = super.render(node, domID, joint, depth);
|
||||
final Element nodeContainerElement = element.getFirstChildElement();
|
||||
|
||||
if (node instanceof CommandFileNode) {
|
||||
CommandFileNode commandNode = (CommandFileNode)node;
|
||||
|
||||
nodeContainerElement.setId("command_" + commandNode.getDisplayName());
|
||||
|
||||
renderCommandNode(commandNode, nodeContainerElement);
|
||||
} else if (node instanceof CommandGoalNode) {
|
||||
CommandGoalNode goalNode = (CommandGoalNode)node;
|
||||
|
||||
nodeContainerElement.setId("goal_" + goalNode.getName());
|
||||
|
||||
renderCommandGoalNode(nodeContainerElement);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
private void renderCommandNode(CommandFileNode node, Element nodeContainerElement) {
|
||||
nodeContainerElement.addClassName(resources.commandsExplorerCss().commandNode());
|
||||
|
||||
final Element removeCommandButton = createButton(resources.removeCommand());
|
||||
Event.setEventListener(removeCommandButton, event -> {
|
||||
if (ONCLICK == event.getTypeInt()) {
|
||||
event.stopPropagation();
|
||||
delegate.onCommandRemove(node.getData());
|
||||
}
|
||||
});
|
||||
|
||||
final Element duplicateCommandButton = createButton(resources.duplicateCommand());
|
||||
Event.setEventListener(duplicateCommandButton, event -> {
|
||||
if (ONCLICK == event.getTypeInt()) {
|
||||
event.stopPropagation();
|
||||
delegate.onCommandDuplicate(node.getData());
|
||||
}
|
||||
});
|
||||
|
||||
final Element buttonsPanel = Document.get().createSpanElement();
|
||||
buttonsPanel.setClassName(resources.commandsExplorerCss().commandNodeButtonsPanel());
|
||||
buttonsPanel.appendChild(removeCommandButton);
|
||||
buttonsPanel.appendChild(duplicateCommandButton);
|
||||
|
||||
nodeContainerElement.appendChild(buttonsPanel);
|
||||
|
||||
removeCommandButton.setId("commands_tree-button-remove");
|
||||
duplicateCommandButton.setId("commands_tree-button-duplicate");
|
||||
}
|
||||
|
||||
private void renderCommandGoalNode(Element nodeContainerElement) {
|
||||
nodeContainerElement.addClassName(resources.commandsExplorerCss().commandGoalNode());
|
||||
|
||||
final Element addCommandButton = createButton(resources.addCommand());
|
||||
|
||||
Event.setEventListener(addCommandButton, event -> {
|
||||
if (ONCLICK == event.getTypeInt()) {
|
||||
event.stopPropagation();
|
||||
delegate.onCommandAdd(addCommandButton.getAbsoluteLeft(), addCommandButton.getAbsoluteTop());
|
||||
}
|
||||
});
|
||||
|
||||
nodeContainerElement.appendChild(addCommandButton);
|
||||
|
||||
addCommandButton.setId("commands_tree-button-add");
|
||||
}
|
||||
|
||||
private Element createButton(SVGResource icon) {
|
||||
final Element button = Document.get().createSpanElement();
|
||||
button.appendChild(icon.getSvg().getElement());
|
||||
|
||||
Event.sinkEvents(button, ONCLICK);
|
||||
|
||||
return button;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.explorer;
|
||||
|
||||
import com.google.gwt.i18n.client.Messages;
|
||||
|
||||
/**
|
||||
* I18n messages for the Command Explorer.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface ExplorerMessages extends Messages {
|
||||
|
||||
@Key("explorer.part.title")
|
||||
String partTitle();
|
||||
|
||||
@Key("explorer.part.tooltip")
|
||||
String partTooltip();
|
||||
|
||||
@Key("explorer.view.title")
|
||||
String viewTitle();
|
||||
|
||||
@Key("explorer.message.unable_create")
|
||||
String unableCreate();
|
||||
|
||||
@Key("explorer.message.unable_duplicate")
|
||||
String unableDuplicate();
|
||||
|
||||
@Key("explorer.message.unable_remove")
|
||||
String unableRemove();
|
||||
|
||||
@Key("explorer.remove_confirmation.title")
|
||||
String removeCommandConfirmationTitle();
|
||||
|
||||
@Key("explorer.remove_confirmation.message")
|
||||
String removeCommandConfirmationMessage(String commandName);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.goal;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.command.BaseCommandGoal;
|
||||
|
||||
/**
|
||||
* Represents predefined 'Build' goal.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class BuildGoal extends BaseCommandGoal {
|
||||
|
||||
@Inject
|
||||
public BuildGoal() {
|
||||
super("Build");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.goal;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.api.command.BaseCommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandGoalRegistry;
|
||||
import org.eclipse.che.ide.util.loging.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
/**
|
||||
* Implementation of {@link CommandGoalRegistry}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
@Singleton
|
||||
public class CommandGoalRegistryImpl implements CommandGoalRegistry {
|
||||
|
||||
private final CommandGoal defaultGoal;
|
||||
private final GoalMessages messages;
|
||||
private final Map<String, CommandGoal> commandGoals;
|
||||
|
||||
@Inject
|
||||
public CommandGoalRegistryImpl(@Named("default") CommandGoal defaultCommandGoal, GoalMessages messages) {
|
||||
defaultGoal = defaultCommandGoal;
|
||||
this.messages = messages;
|
||||
|
||||
commandGoals = new HashMap<>();
|
||||
}
|
||||
|
||||
@Inject(optional = true)
|
||||
private void register(Set<CommandGoal> goals) {
|
||||
for (CommandGoal type : goals) {
|
||||
final String id = type.getId();
|
||||
|
||||
if (commandGoals.containsKey(id)) {
|
||||
Log.warn(getClass(), messages.messageGoalAlreadyRegistered(id));
|
||||
} else {
|
||||
commandGoals.put(id, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommandGoal> getAllPredefinedGoals() {
|
||||
return unmodifiableList(new ArrayList<>(commandGoals.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandGoal getDefaultGoal() {
|
||||
return defaultGoal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CommandGoal> getPredefinedGoalById(String id) {
|
||||
return ofNullable(commandGoals.get(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandGoal getGoalForId(@Nullable String id) {
|
||||
if (isNullOrEmpty(id)) {
|
||||
return getDefaultGoal();
|
||||
}
|
||||
|
||||
return getPredefinedGoalById(id).orElse(new BaseCommandGoal(id));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.goal;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.command.BaseCommandGoal;
|
||||
|
||||
/**
|
||||
* Represents predefined 'Common' goal.
|
||||
* By default it's used for grouping commands which doesn't belong to any goal.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class CommonGoal extends BaseCommandGoal {
|
||||
|
||||
@Inject
|
||||
public CommonGoal() {
|
||||
super("Common");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.goal;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.command.BaseCommandGoal;
|
||||
|
||||
/**
|
||||
* Represents predefined 'Debug' goal.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class DebugGoal extends BaseCommandGoal {
|
||||
|
||||
@Inject
|
||||
public DebugGoal() {
|
||||
super("Debug");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.goal;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.command.BaseCommandGoal;
|
||||
|
||||
/**
|
||||
* Represents predefined 'Deploy' goal.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class DeployGoal extends BaseCommandGoal {
|
||||
|
||||
@Inject
|
||||
public DeployGoal() {
|
||||
super("Deploy");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.goal;
|
||||
|
||||
import com.google.gwt.i18n.client.Messages;
|
||||
|
||||
/**
|
||||
* I18n messages relate to the command goals.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface GoalMessages extends Messages {
|
||||
|
||||
@Key("message.goal_already_registered")
|
||||
String messageGoalAlreadyRegistered(String goalId);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.goal;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.command.BaseCommandGoal;
|
||||
|
||||
/**
|
||||
* Represents predefined 'Run' goal.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class RunGoal extends BaseCommandGoal {
|
||||
|
||||
@Inject
|
||||
public RunGoal() {
|
||||
super("Run");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.goal;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.ide.api.command.BaseCommandGoal;
|
||||
|
||||
/**
|
||||
* Represents predefined 'Test' goal.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public class TestGoal extends BaseCommandGoal {
|
||||
|
||||
@Inject
|
||||
public TestGoal() {
|
||||
super("Test");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,456 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.manager;
|
||||
|
||||
import elemental.util.ArrayOf;
|
||||
import elemental.util.Collections;
|
||||
|
||||
import com.google.gwt.core.client.Callback;
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.web.bindery.event.shared.EventBus;
|
||||
|
||||
import org.eclipse.che.api.core.model.machine.Machine;
|
||||
import org.eclipse.che.api.promises.client.Function;
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.api.promises.client.PromiseProvider;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl.ApplicableContext;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
import org.eclipse.che.ide.api.command.CommandType;
|
||||
import org.eclipse.che.ide.api.command.CommandTypeRegistry;
|
||||
import org.eclipse.che.ide.api.component.Component;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
import org.eclipse.che.ide.api.resources.Resource;
|
||||
import org.eclipse.che.ide.api.selection.Selection;
|
||||
import org.eclipse.che.ide.api.selection.SelectionAgent;
|
||||
import org.eclipse.che.ide.api.workspace.WorkspaceReadyEvent;
|
||||
import org.eclipse.che.ide.api.workspace.WorkspaceReadyEvent.WorkspaceReadyHandler;
|
||||
import org.eclipse.che.ide.util.loging.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.eclipse.che.api.workspace.shared.Constants.COMMAND_GOAL_ATTRIBUTE_NAME;
|
||||
import static org.eclipse.che.api.workspace.shared.Constants.COMMAND_PREVIEW_URL_ATTRIBUTE_NAME;
|
||||
|
||||
/** Implementation of {@link CommandManager}. */
|
||||
@Singleton
|
||||
public class CommandManagerImpl implements CommandManager, Component, WorkspaceReadyHandler {
|
||||
|
||||
private final AppContext appContext;
|
||||
private final PromiseProvider promiseProvider;
|
||||
private final CommandTypeRegistry commandTypeRegistry;
|
||||
private final ProjectCommandManagerDelegate projectCommandManager;
|
||||
private final WorkspaceCommandManagerDelegate workspaceCommandManager;
|
||||
private final EventBus eventBus;
|
||||
private final SelectionAgent selectionAgent;
|
||||
|
||||
/** Map of the commands' names to the commands. */
|
||||
private final Map<String, CommandImpl> commands;
|
||||
private final Set<CommandLoadedListener> commandLoadedListeners;
|
||||
private final Set<CommandChangedListener> commandChangedListeners;
|
||||
|
||||
@Inject
|
||||
public CommandManagerImpl(AppContext appContext,
|
||||
PromiseProvider promiseProvider,
|
||||
CommandTypeRegistry commandTypeRegistry,
|
||||
ProjectCommandManagerDelegate projectCommandManagerDelegate,
|
||||
WorkspaceCommandManagerDelegate workspaceCommandManagerDelegate,
|
||||
EventBus eventBus,
|
||||
SelectionAgent selectionAgent) {
|
||||
this.appContext = appContext;
|
||||
this.promiseProvider = promiseProvider;
|
||||
this.commandTypeRegistry = commandTypeRegistry;
|
||||
this.projectCommandManager = projectCommandManagerDelegate;
|
||||
this.workspaceCommandManager = workspaceCommandManagerDelegate;
|
||||
this.eventBus = eventBus;
|
||||
this.selectionAgent = selectionAgent;
|
||||
|
||||
commands = new HashMap<>();
|
||||
commandLoadedListeners = new HashSet<>();
|
||||
commandChangedListeners = new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Callback<Component, Exception> callback) {
|
||||
eventBus.addHandler(WorkspaceReadyEvent.getType(), this);
|
||||
|
||||
callback.onSuccess(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorkspaceReady(WorkspaceReadyEvent event) {
|
||||
fetchCommands();
|
||||
}
|
||||
|
||||
private void fetchCommands() {
|
||||
// get all commands related to the workspace
|
||||
workspaceCommandManager.getCommands(appContext.getWorkspaceId()).then(workspaceCommands -> {
|
||||
workspaceCommands.forEach(workspaceCommand -> commands.put(workspaceCommand.getName(),
|
||||
new CommandImpl(workspaceCommand, new ApplicableContext())));
|
||||
|
||||
// get all commands related to the projects
|
||||
Arrays.stream(appContext.getProjects())
|
||||
.forEach(project -> projectCommandManager.getCommands(project).forEach(projectCommand -> {
|
||||
final CommandImpl existedCommand = commands.get(projectCommand.getName());
|
||||
|
||||
if (existedCommand == null) {
|
||||
commands.put(projectCommand.getName(),
|
||||
new CommandImpl(projectCommand, new ApplicableContext(project.getPath())));
|
||||
} else {
|
||||
if (projectCommand.equalsIgnoreContext(existedCommand)) {
|
||||
existedCommand.getApplicableContext().addProject(project.getPath());
|
||||
} else {
|
||||
// normally, should never happen
|
||||
Log.error(CommandManagerImpl.this.getClass(), "Different commands with the same names found");
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
notifyCommandsLoaded();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommandImpl> getCommands() {
|
||||
return commands.values()
|
||||
.stream()
|
||||
.map(CommandImpl::new)
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.Optional<CommandImpl> getCommand(String name) {
|
||||
return commands.values()
|
||||
.stream()
|
||||
.filter(command -> name.equals(command.getName()))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommandImpl> getApplicableCommands() {
|
||||
return commands.values()
|
||||
.stream()
|
||||
.filter(this::isCommandApplicable)
|
||||
.map(CommandImpl::new)
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCommandApplicable(CommandImpl command) {
|
||||
return isMachineSelected() || isCommandApplicableToCurrentProject(command);
|
||||
|
||||
}
|
||||
|
||||
/** Checks whether the machine is currently selected. */
|
||||
private boolean isMachineSelected() {
|
||||
final Selection<?> selection = selectionAgent.getSelection();
|
||||
|
||||
if (selection != null && !selection.isEmpty() && selection.isSingleSelection()) {
|
||||
return selection.getHeadElement() instanceof Machine;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Checks whether the given command is applicable to the current project. */
|
||||
private boolean isCommandApplicableToCurrentProject(CommandImpl command) {
|
||||
final List<String> applicableProjects = command.getApplicableContext().getApplicableProjects();
|
||||
|
||||
if (applicableProjects.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Resource currentResource = appContext.getResource();
|
||||
if (currentResource != null) {
|
||||
final Project currentProject = currentResource.getProject();
|
||||
if (currentProject != null) {
|
||||
return applicableProjects.contains(currentProject.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<CommandImpl> createCommand(String goalId, String typeId) {
|
||||
return createCommand(goalId,
|
||||
typeId,
|
||||
null,
|
||||
null,
|
||||
new HashMap<>(),
|
||||
new ApplicableContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<CommandImpl> createCommand(String goalId, String typeId, ApplicableContext context) {
|
||||
return createCommand(goalId, typeId, null, null, new HashMap<>(), context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<CommandImpl> createCommand(String goalId,
|
||||
String typeId,
|
||||
String name,
|
||||
String commandLine,
|
||||
Map<String, String> attributes) {
|
||||
return createCommand(goalId, typeId, name, commandLine, attributes, new ApplicableContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<CommandImpl> createCommand(String goalId,
|
||||
String typeId,
|
||||
@Nullable String name,
|
||||
@Nullable String commandLine,
|
||||
Map<String, String> attributes,
|
||||
ApplicableContext context) {
|
||||
final CommandType commandType = commandTypeRegistry.getCommandTypeById(typeId);
|
||||
|
||||
if (commandType == null) {
|
||||
return promiseProvider.reject(new Exception("Unknown command type: '" + typeId + "'"));
|
||||
}
|
||||
|
||||
final Map<String, String> attr = new HashMap<>(attributes);
|
||||
attr.put(COMMAND_PREVIEW_URL_ATTRIBUTE_NAME, commandType.getPreviewUrlTemplate());
|
||||
attr.put(COMMAND_GOAL_ATTRIBUTE_NAME, goalId);
|
||||
|
||||
return createCommand(new CommandImpl(getUniqueCommandName(typeId, name),
|
||||
commandLine != null ? commandLine : commandType.getCommandLineTemplate(),
|
||||
typeId,
|
||||
attr,
|
||||
context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<CommandImpl> createCommand(CommandImpl command) {
|
||||
return doCreateCommand(command).then((Function<CommandImpl, CommandImpl>)newCommand -> {
|
||||
// postpone the notification because
|
||||
// listeners should be notified after returning from #createCommand method
|
||||
Scheduler.get().scheduleDeferred(() -> notifyCommandAdded(newCommand));
|
||||
|
||||
return newCommand;
|
||||
});
|
||||
}
|
||||
|
||||
/** Does the actual work for command creation. Doesn't notify listeners. */
|
||||
private Promise<CommandImpl> doCreateCommand(CommandImpl command) {
|
||||
final ApplicableContext context = command.getApplicableContext();
|
||||
if (!context.isWorkspaceApplicable() && context.getApplicableProjects().isEmpty()) {
|
||||
return promiseProvider.reject(new Exception("Command has to be applicable to the workspace or at least one project"));
|
||||
}
|
||||
|
||||
final CommandType commandType = commandTypeRegistry.getCommandTypeById(command.getType());
|
||||
if (commandType == null) {
|
||||
return promiseProvider.reject(new Exception("Unknown command type: '" + command.getType() + "'"));
|
||||
}
|
||||
|
||||
final CommandImpl newCommand = new CommandImpl(command);
|
||||
newCommand.setName(getUniqueCommandName(command.getType(), command.getName()));
|
||||
|
||||
final ArrayOf<Promise<?>> commandPromises = Collections.arrayOf();
|
||||
|
||||
if (context.isWorkspaceApplicable()) {
|
||||
Promise<CommandImpl> p = workspaceCommandManager.createCommand(newCommand)
|
||||
.then((Function<CommandImpl, CommandImpl>)arg -> {
|
||||
newCommand.getApplicableContext().setWorkspaceApplicable(true);
|
||||
return newCommand;
|
||||
});
|
||||
|
||||
commandPromises.push(p);
|
||||
}
|
||||
|
||||
for (final String projectPath : context.getApplicableProjects()) {
|
||||
final Project project = getProjectByPath(projectPath);
|
||||
|
||||
if (project == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Promise<CommandImpl> p = projectCommandManager.createCommand(project, newCommand)
|
||||
.then((Function<CommandImpl, CommandImpl>)arg -> {
|
||||
newCommand.getApplicableContext().addProject(projectPath);
|
||||
return newCommand;
|
||||
});
|
||||
|
||||
commandPromises.push(p);
|
||||
}
|
||||
|
||||
return promiseProvider.all2(commandPromises)
|
||||
.then((Function<ArrayOf<?>, CommandImpl>)ignore -> {
|
||||
commands.put(newCommand.getName(), newCommand);
|
||||
return newCommand;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<CommandImpl> updateCommand(String name, CommandImpl commandToUpdate) {
|
||||
final CommandImpl existedCommand = commands.get(name);
|
||||
|
||||
if (existedCommand == null) {
|
||||
return promiseProvider.reject(new Exception("Command '" + name + "' does not exist."));
|
||||
}
|
||||
|
||||
return doRemoveCommand(name).thenPromise(aVoid -> doCreateCommand(commandToUpdate)
|
||||
.then((Function<CommandImpl, CommandImpl>)updatedCommand -> {
|
||||
// listeners should be notified after returning from #updateCommand method
|
||||
// so let's postpone notification
|
||||
Scheduler.get().scheduleDeferred(() -> notifyCommandUpdated(existedCommand, updatedCommand));
|
||||
|
||||
return updatedCommand;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<Void> removeCommand(String name) {
|
||||
final CommandImpl command = commands.get(name);
|
||||
|
||||
if (command == null) {
|
||||
return promiseProvider.reject(new Exception("Command '" + name + "' does not exist."));
|
||||
}
|
||||
|
||||
return doRemoveCommand(name).then(aVoid -> {
|
||||
// listeners should be notified after returning from #removeCommand method
|
||||
// so let's postpone notification
|
||||
Scheduler.get().scheduleDeferred(() -> notifyCommandRemoved(command));
|
||||
});
|
||||
}
|
||||
|
||||
/** Removes the command without notifying listeners. */
|
||||
private Promise<Void> doRemoveCommand(String name) {
|
||||
final CommandImpl command = commands.get(name);
|
||||
|
||||
if (command == null) {
|
||||
return promiseProvider.reject(new Exception("Command '" + name + "' does not exist."));
|
||||
}
|
||||
|
||||
final ApplicableContext context = command.getApplicableContext();
|
||||
|
||||
final ArrayOf<Promise<?>> commandPromises = Collections.arrayOf();
|
||||
|
||||
if (context.isWorkspaceApplicable()) {
|
||||
final Promise<Void> p = workspaceCommandManager.removeCommand(name).then((Function<Void, Void>)aVoid -> {
|
||||
command.getApplicableContext().setWorkspaceApplicable(false);
|
||||
return null;
|
||||
});
|
||||
|
||||
commandPromises.push(p);
|
||||
}
|
||||
|
||||
for (final String projectPath : context.getApplicableProjects()) {
|
||||
final Project project = getProjectByPath(projectPath);
|
||||
|
||||
if (project == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final Promise<Void> p = projectCommandManager.removeCommand(project, name).then((Function<Void, Void>)aVoid -> {
|
||||
command.getApplicableContext().removeProject(projectPath);
|
||||
return null;
|
||||
});
|
||||
|
||||
commandPromises.push(p);
|
||||
}
|
||||
|
||||
return promiseProvider.all2(commandPromises)
|
||||
.then((Function<ArrayOf<?>, Void>)arg -> {
|
||||
commands.remove(command.getName());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Project getProjectByPath(String path) {
|
||||
for (Project project : appContext.getProjects()) {
|
||||
if (path.equals(project.getPath())) {
|
||||
return project;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCommandLoadedListener(CommandLoadedListener listener) {
|
||||
commandLoadedListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCommandLoadedListener(CommandLoadedListener listener) {
|
||||
commandLoadedListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCommandChangedListener(CommandChangedListener listener) {
|
||||
commandChangedListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCommandChangedListener(CommandChangedListener listener) {
|
||||
commandChangedListeners.remove(listener);
|
||||
}
|
||||
|
||||
private void notifyCommandsLoaded() {
|
||||
commandLoadedListeners.forEach(CommandLoadedListener::onCommandsLoaded);
|
||||
}
|
||||
|
||||
private void notifyCommandAdded(CommandImpl command) {
|
||||
commandChangedListeners.forEach(listener -> listener.onCommandAdded(command));
|
||||
}
|
||||
|
||||
private void notifyCommandRemoved(CommandImpl command) {
|
||||
commandChangedListeners.forEach(listener -> listener.onCommandRemoved(command));
|
||||
}
|
||||
|
||||
private void notifyCommandUpdated(CommandImpl prevCommand, CommandImpl command) {
|
||||
commandChangedListeners.forEach(listener -> listener.onCommandUpdated(prevCommand, command));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code customName} if it's unique within the given {@code commandTypeId}
|
||||
* or newly generated name if it isn't unique within the given {@code commandTypeId}.
|
||||
*/
|
||||
private String getUniqueCommandName(String commandTypeId, @Nullable String customName) {
|
||||
final CommandType commandType = commandTypeRegistry.getCommandTypeById(commandTypeId);
|
||||
final Set<String> commandNames = commands.keySet();
|
||||
|
||||
final String newCommandName;
|
||||
|
||||
if (isNullOrEmpty(customName)) {
|
||||
newCommandName = "new" + commandType.getDisplayName();
|
||||
} else {
|
||||
if (!commandNames.contains(customName)) {
|
||||
return customName;
|
||||
}
|
||||
newCommandName = customName + " copy";
|
||||
}
|
||||
|
||||
if (!commandNames.contains(newCommandName)) {
|
||||
return newCommandName;
|
||||
}
|
||||
|
||||
for (int count = 1; count < 1000; count++) {
|
||||
if (!commandNames.contains(newCommandName + "-" + count)) {
|
||||
return newCommandName + "-" + count;
|
||||
}
|
||||
}
|
||||
|
||||
return newCommandName;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.manager;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.machine.shared.dto.CommandDto;
|
||||
import org.eclipse.che.api.promises.client.Function;
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.api.promises.client.PromiseProvider;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
import org.eclipse.che.ide.api.command.CommandType;
|
||||
import org.eclipse.che.ide.api.project.MutableProjectConfig;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
import org.eclipse.che.ide.dto.DtoFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.eclipse.che.api.project.shared.Constants.COMMANDS_ATTRIBUTE_NAME;
|
||||
|
||||
/** Responsible for managing the commands which are stored with projects. */
|
||||
@Singleton
|
||||
class ProjectCommandManagerDelegate {
|
||||
|
||||
private final DtoFactory dtoFactory;
|
||||
private final PromiseProvider promiseProvider;
|
||||
|
||||
@Inject
|
||||
ProjectCommandManagerDelegate(DtoFactory dtoFactory, PromiseProvider promiseProvider) {
|
||||
this.dtoFactory = dtoFactory;
|
||||
this.promiseProvider = promiseProvider;
|
||||
}
|
||||
|
||||
/** Returns commands for the specified {@code project}. */
|
||||
List<CommandImpl> getCommands(Project project) {
|
||||
List<String> attrValues = project.getAttributes(COMMANDS_ATTRIBUTE_NAME);
|
||||
if (attrValues == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
Map<String, CommandImpl> commands = new HashMap<>(attrValues.size());
|
||||
for (String commandJson : attrValues) {
|
||||
CommandDto command = dtoFactory.createDtoFromJson(commandJson, CommandDto.class);
|
||||
commands.put(command.getName(), new CommandImpl(command));
|
||||
}
|
||||
|
||||
return new ArrayList<>(commands.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new command of the specified type.
|
||||
* <p><b>Note</b> that command's name will be generated by {@link CommandManager}
|
||||
* and command line will be provided by an appropriate {@link CommandType}.
|
||||
*/
|
||||
Promise<CommandImpl> createCommand(Project project, final CommandImpl newCommand) {
|
||||
final List<CommandImpl> commands = getCommands(project);
|
||||
|
||||
for (CommandImpl projectCommand : commands) {
|
||||
if (projectCommand.getName().equals(newCommand.getName())) {
|
||||
return promiseProvider.reject(new Exception("Command '" + newCommand.getName() +
|
||||
"' is already associated to the project '" + project.getName() + "'"));
|
||||
}
|
||||
}
|
||||
|
||||
commands.add(newCommand);
|
||||
|
||||
return updateProject(project, commands).then((Function<Void, CommandImpl>)arg -> newCommand);
|
||||
}
|
||||
|
||||
/** Updates the specified {@code project} with the given {@code commands}. */
|
||||
private Promise<Void> updateProject(Project project, List<CommandImpl> commands) {
|
||||
MutableProjectConfig config = new MutableProjectConfig(project);
|
||||
Map<String, List<String>> attributes = config.getAttributes();
|
||||
|
||||
List<String> attrValue = new ArrayList<>(attributes.size());
|
||||
for (CommandImpl command : commands) {
|
||||
CommandDto commandDto = dtoFactory.createDto(CommandDto.class)
|
||||
.withName(command.getName())
|
||||
.withType(command.getType())
|
||||
.withCommandLine(command.getCommandLine())
|
||||
.withAttributes(command.getAttributes());
|
||||
attrValue.add(dtoFactory.toJson(commandDto));
|
||||
}
|
||||
|
||||
attributes.put(COMMANDS_ATTRIBUTE_NAME, attrValue);
|
||||
|
||||
return project.update()
|
||||
.withBody(config)
|
||||
.send()
|
||||
.then((Function<Project, Void>)arg -> null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the command with the specified {@code name} by replacing it with the given {@code command}.
|
||||
* <p><b>Note</b> that name of the updated command may differ from the name provided by the given {@code command}
|
||||
* in order to prevent name duplication.
|
||||
*/
|
||||
Promise<CommandImpl> updateCommand(Project project, final CommandImpl command) {
|
||||
final List<CommandImpl> projectCommands = getCommands(project);
|
||||
|
||||
if (projectCommands.isEmpty()) {
|
||||
return promiseProvider.reject(new Exception("Command '" + command.getName() + "' is not associated with the project '" +
|
||||
project.getName() + "'"));
|
||||
}
|
||||
|
||||
final List<CommandImpl> commandsToUpdate = new ArrayList<>();
|
||||
for (CommandImpl projectCommand : projectCommands) {
|
||||
// skip existed command with the same name
|
||||
if (!command.getName().equals(projectCommand.getName())) {
|
||||
commandsToUpdate.add(projectCommand);
|
||||
}
|
||||
}
|
||||
|
||||
commandsToUpdate.add(command);
|
||||
|
||||
return updateProject(project, new ArrayList<>(commandsToUpdate))
|
||||
.then((Function<Void, CommandImpl>)arg -> command);
|
||||
}
|
||||
|
||||
/** Removes the command with the specified {@code commandName}. */
|
||||
Promise<Void> removeCommand(Project project, String commandName) {
|
||||
final List<CommandImpl> commands = getCommands(project);
|
||||
|
||||
if (commands.isEmpty()) {
|
||||
return promiseProvider.reject(new Exception("Command '" + commandName + "' is not associated with the project '" +
|
||||
project.getName() + "'"));
|
||||
}
|
||||
|
||||
final List<CommandImpl> commandsToUpdate = new ArrayList<>();
|
||||
for (CommandImpl projectCommand : commands) {
|
||||
if (!commandName.equals(projectCommand.getName())) {
|
||||
commandsToUpdate.add(projectCommand);
|
||||
}
|
||||
}
|
||||
|
||||
return updateProject(project, new ArrayList<>(commandsToUpdate));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.manager;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.machine.shared.dto.CommandDto;
|
||||
import org.eclipse.che.api.promises.client.Function;
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
import org.eclipse.che.ide.api.command.CommandType;
|
||||
import org.eclipse.che.ide.api.workspace.WorkspaceServiceClient;
|
||||
import org.eclipse.che.ide.dto.DtoFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/** Responsible for managing the commands which are stored with workspace. */
|
||||
@Singleton
|
||||
class WorkspaceCommandManagerDelegate {
|
||||
|
||||
private final DtoFactory dtoFactory;
|
||||
private final WorkspaceServiceClient workspaceServiceClient;
|
||||
private final AppContext appContext;
|
||||
|
||||
@Inject
|
||||
WorkspaceCommandManagerDelegate(DtoFactory dtoFactory,
|
||||
WorkspaceServiceClient workspaceServiceClient,
|
||||
AppContext appContext) {
|
||||
this.dtoFactory = dtoFactory;
|
||||
this.workspaceServiceClient = workspaceServiceClient;
|
||||
this.appContext = appContext;
|
||||
}
|
||||
|
||||
/** Returns commands which are stored in the workspace with the specified {@code workspaceId}. */
|
||||
Promise<List<CommandImpl>> getCommands(String workspaceId) {
|
||||
return workspaceServiceClient.getCommands(workspaceId)
|
||||
.then((Function<List<CommandDto>,
|
||||
List<CommandImpl>>)commands -> commands.stream()
|
||||
.map(CommandImpl::new)
|
||||
.collect(toList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new command of the specified type.
|
||||
* <p><b>Note</b> that command's name will be generated by {@link CommandManager}
|
||||
* and command line will be provided by an appropriate {@link CommandType}.
|
||||
*/
|
||||
Promise<CommandImpl> createCommand(final CommandImpl command) {
|
||||
final CommandDto commandDto = dtoFactory.createDto(CommandDto.class)
|
||||
.withName(command.getName())
|
||||
.withCommandLine(command.getCommandLine())
|
||||
.withType(command.getType())
|
||||
.withAttributes(command.getAttributes());
|
||||
|
||||
return workspaceServiceClient.addCommand(appContext.getWorkspaceId(), commandDto)
|
||||
.then((Function<WorkspaceDto, CommandImpl>)arg -> command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the command with the specified {@code name} by replacing it with the given {@code command}.
|
||||
* <p><b>Note</b> that name of the updated command may differ from the name provided by the given {@code command}
|
||||
* in order to prevent name duplication.
|
||||
*/
|
||||
Promise<CommandImpl> updateCommand(final CommandImpl command) {
|
||||
final CommandDto commandDto = dtoFactory.createDto(CommandDto.class)
|
||||
.withName(command.getName())
|
||||
.withCommandLine(command.getCommandLine())
|
||||
.withType(command.getType())
|
||||
.withAttributes(command.getAttributes());
|
||||
|
||||
return workspaceServiceClient.updateCommand(appContext.getWorkspaceId(), command.getName(), commandDto)
|
||||
.then((Function<WorkspaceDto, CommandImpl>)arg -> command);
|
||||
}
|
||||
|
||||
/** Removes the command with the specified {@code commandName}. */
|
||||
Promise<Void> removeCommand(String commandName) {
|
||||
return workspaceServiceClient.deleteCommand(appContext.getWorkspaceId(), commandName)
|
||||
.then((Function<WorkspaceDto, Void>)arg -> null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.node;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.data.tree.Node;
|
||||
import org.eclipse.che.ide.api.data.tree.settings.NodeSettings;
|
||||
import org.eclipse.che.ide.command.CommandUtils;
|
||||
import org.eclipse.che.ide.project.node.SyntheticNode;
|
||||
import org.eclipse.che.ide.ui.smartTree.presentation.NodePresentation;
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Abstract tree node that represents {@link CommandImpl}. */
|
||||
class AbstractCommandNode extends SyntheticNode<CommandImpl> {
|
||||
|
||||
private final CommandUtils commandUtils;
|
||||
|
||||
AbstractCommandNode(CommandImpl data, NodeSettings nodeSettings, CommandUtils commandUtils) {
|
||||
super(data, nodeSettings);
|
||||
|
||||
this.commandUtils = commandUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePresentation(NodePresentation presentation) {
|
||||
presentation.setPresentableText(getName());
|
||||
|
||||
final SVGResource commandTypeIcon = commandUtils.getCommandTypeIcon(getData().getType());
|
||||
|
||||
if (commandTypeIcon != null) {
|
||||
presentation.setPresentableIcon(commandTypeIcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getData().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Promise<List<Node>> getChildrenImpl() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.node;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.data.tree.HasAction;
|
||||
import org.eclipse.che.ide.api.editor.EditorAgent;
|
||||
import org.eclipse.che.ide.api.resources.VirtualFile;
|
||||
import org.eclipse.che.ide.command.CommandUtils;
|
||||
import org.eclipse.che.ide.resource.Path;
|
||||
import org.eclipse.che.ide.ui.smartTree.presentation.NodePresentation;
|
||||
|
||||
/** Extension of {@link AbstractCommandNode} that also acts as a {@link VirtualFile} for using it in editor. */
|
||||
public class CommandFileNode extends AbstractCommandNode implements HasAction, VirtualFile {
|
||||
|
||||
/** Extension for the file type that represents a command. */
|
||||
public static final String FILE_TYPE_EXT = "che_command_internal";
|
||||
|
||||
private final EditorAgent editorAgent;
|
||||
|
||||
@Inject
|
||||
public CommandFileNode(@Assisted CommandImpl data,
|
||||
CommandUtils commandUtils,
|
||||
EditorAgent editorAgent) {
|
||||
super(data, null, commandUtils);
|
||||
|
||||
this.editorAgent = editorAgent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePresentation(NodePresentation presentation) {
|
||||
super.updatePresentation(presentation);
|
||||
|
||||
presentation.setPresentableText(getDisplayName());
|
||||
presentation.setPresentableTextCss("overflow: hidden; text-overflow: ellipsis;");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed() {
|
||||
editorAgent.openEditor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getLocation() {
|
||||
return Path.valueOf("commands/" + getData().getType() + "/" + getData().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getData().getName() + "." + FILE_TYPE_EXT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return getData().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentUrl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<String> getContent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<Void> updateContent(String content) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.node;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.api.promises.client.PromiseProvider;
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.data.tree.Node;
|
||||
import org.eclipse.che.ide.command.CommandUtils;
|
||||
import org.eclipse.che.ide.project.node.SyntheticNode;
|
||||
import org.eclipse.che.ide.ui.smartTree.presentation.NodePresentation;
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Tree node that represents {@link CommandGoal}. */
|
||||
public class CommandGoalNode extends SyntheticNode<CommandGoal> {
|
||||
|
||||
private final List<? extends AbstractCommandNode> commands;
|
||||
private final PromiseProvider promiseProvider;
|
||||
private final CommandUtils commandUtils;
|
||||
|
||||
@Inject
|
||||
public CommandGoalNode(@Assisted CommandGoal data,
|
||||
@Assisted List<? extends AbstractCommandNode> commands,
|
||||
PromiseProvider promiseProvider,
|
||||
CommandUtils commandUtils) {
|
||||
super(data, null);
|
||||
|
||||
this.commands = commands;
|
||||
this.promiseProvider = promiseProvider;
|
||||
this.commandUtils = commandUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePresentation(NodePresentation presentation) {
|
||||
presentation.setPresentableText(getName().toUpperCase() + " (" + commands.size() + ")");
|
||||
presentation.setPresentableTextCss("font-weight: bold;");
|
||||
|
||||
final SVGResource goalIcon = commandUtils.getCommandGoalIcon(getData().getId());
|
||||
if (goalIcon != null) {
|
||||
presentation.setPresentableIcon(goalIcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getData().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Promise<List<Node>> getChildrenImpl() {
|
||||
List<Node> children = new ArrayList<>();
|
||||
children.addAll(commands);
|
||||
|
||||
return promiseProvider.resolve(children);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.node;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.data.tree.HasAction;
|
||||
import org.eclipse.che.ide.command.CommandUtils;
|
||||
|
||||
/**
|
||||
* Extension of {@link AbstractCommandNode} that can execute
|
||||
* a command when performing an action is requested.
|
||||
*/
|
||||
public class ExecutableCommandNode extends AbstractCommandNode implements HasAction {
|
||||
|
||||
private final ActionDelegate actionDelegate;
|
||||
|
||||
@Inject
|
||||
public ExecutableCommandNode(@Assisted CommandImpl data,
|
||||
@Assisted ActionDelegate actionDelegate,
|
||||
CommandUtils commandUtils) {
|
||||
super(data, null, commandUtils);
|
||||
|
||||
this.actionDelegate = actionDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed() {
|
||||
actionDelegate.actionPerformed();
|
||||
}
|
||||
|
||||
/** Interface for delegating performing action on node. */
|
||||
public interface ActionDelegate {
|
||||
void actionPerformed();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.node;
|
||||
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Factory for different command tree nodes. */
|
||||
public interface NodeFactory {
|
||||
|
||||
CommandGoalNode newCommandGoalNode(CommandGoal data, List<? extends AbstractCommandNode> commands);
|
||||
|
||||
ExecutableCommandNode newExecutableCommandNode(CommandImpl command, ExecutableCommandNode.ActionDelegate actionDelegate);
|
||||
|
||||
CommandFileNode newCommandFileNode(CommandImpl data);
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.palette;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.model.machine.Machine;
|
||||
import org.eclipse.che.api.core.model.workspace.WorkspaceRuntime;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.command.CommandExecutor;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.command.CommandUtils;
|
||||
import org.eclipse.che.ide.machine.chooser.MachineChooser;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.eclipse.che.ide.util.StringUtils.containsIgnoreCase;
|
||||
|
||||
/**
|
||||
* Presenter for Commands Palette.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
@Singleton
|
||||
public class CommandsPalettePresenter implements CommandsPaletteView.ActionDelegate {
|
||||
|
||||
private final CommandsPaletteView view;
|
||||
private final CommandManager commandManager;
|
||||
private final CommandExecutor commandExecutor;
|
||||
private final DialogFactory dialogFactory;
|
||||
private final AppContext appContext;
|
||||
private final MachineChooser machineChooser;
|
||||
private final CommandUtils commandUtils;
|
||||
private final PaletteMessages messages;
|
||||
|
||||
@Inject
|
||||
public CommandsPalettePresenter(CommandsPaletteView view,
|
||||
CommandManager commandManager,
|
||||
CommandExecutor commandExecutor,
|
||||
DialogFactory dialogFactory,
|
||||
AppContext appContext,
|
||||
MachineChooser machineChooser,
|
||||
CommandUtils commandUtils,
|
||||
PaletteMessages messages) {
|
||||
this.view = view;
|
||||
this.commandManager = commandManager;
|
||||
this.commandExecutor = commandExecutor;
|
||||
this.dialogFactory = dialogFactory;
|
||||
this.appContext = appContext;
|
||||
this.machineChooser = machineChooser;
|
||||
this.commandUtils = commandUtils;
|
||||
this.messages = messages;
|
||||
|
||||
view.setDelegate(this);
|
||||
}
|
||||
|
||||
public void showDialog() {
|
||||
view.show();
|
||||
view.setCommands(commandUtils.groupCommandsByGoal(commandManager.getCommands()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFilterChanged(String filterValue) {
|
||||
final List<CommandImpl> filteredCommands = commandManager.getCommands();
|
||||
|
||||
if (!filterValue.isEmpty()) {
|
||||
final ListIterator<CommandImpl> it = filteredCommands.listIterator();
|
||||
|
||||
while (it.hasNext()) {
|
||||
final CommandImpl command = it.next();
|
||||
|
||||
if (!containsIgnoreCase(command.getName(), filterValue)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
view.setCommands(commandUtils.groupCommandsByGoal(filteredCommands));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandExecute(CommandImpl command) {
|
||||
view.close();
|
||||
|
||||
if (getMachines().isEmpty()) {
|
||||
// should not happen, but let's play safe
|
||||
dialogFactory.createMessageDialog("", messages.messageNoMachine(), null).show();
|
||||
} else {
|
||||
machineChooser.show().then(machine -> {
|
||||
commandExecutor.executeCommand(command, machine);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private List<? extends Machine> getMachines() {
|
||||
final WorkspaceRuntime runtime = appContext.getWorkspace().getRuntime();
|
||||
|
||||
if (runtime != null) {
|
||||
return runtime.getMachines();
|
||||
}
|
||||
|
||||
return emptyList();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.palette;
|
||||
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.mvp.View;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The view for {@link CommandsPalettePresenter}.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface CommandsPaletteView extends View<CommandsPaletteView.ActionDelegate> {
|
||||
|
||||
/** Show the view. */
|
||||
void show();
|
||||
|
||||
/** Close the view. */
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Sets the commands to display in the view.
|
||||
*
|
||||
* @param commands
|
||||
* commands grouped by type
|
||||
*/
|
||||
void setCommands(Map<CommandGoal, List<CommandImpl>> commands);
|
||||
|
||||
/** The action delegate for this view. */
|
||||
interface ActionDelegate {
|
||||
|
||||
/** Called when filtering commands is requested. */
|
||||
void onFilterChanged(String filterValue);
|
||||
|
||||
/** Called when command execution is requested. */
|
||||
void onCommandExecute(CommandImpl command);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.palette;
|
||||
|
||||
import elemental.html.DivElement;
|
||||
import elemental.html.SpanElement;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.event.dom.client.KeyUpEvent;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.uibinder.client.UiHandler;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.ide.FontAwesome;
|
||||
import org.eclipse.che.ide.api.command.CommandGoal;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.data.tree.Node;
|
||||
import org.eclipse.che.ide.command.node.CommandGoalNode;
|
||||
import org.eclipse.che.ide.command.node.ExecutableCommandNode;
|
||||
import org.eclipse.che.ide.command.node.NodeFactory;
|
||||
import org.eclipse.che.ide.ui.smartTree.NodeLoader;
|
||||
import org.eclipse.che.ide.ui.smartTree.NodeStorage;
|
||||
import org.eclipse.che.ide.ui.smartTree.Tree;
|
||||
import org.eclipse.che.ide.ui.window.Window;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import static com.google.gwt.event.dom.client.KeyCodes.KEY_DOWN;
|
||||
import static com.google.gwt.event.dom.client.KeyCodes.KEY_ENTER;
|
||||
import static com.google.gwt.event.dom.client.KeyCodes.KEY_UP;
|
||||
import static org.eclipse.che.ide.ui.smartTree.SelectionModel.Mode.SINGLE;
|
||||
import static org.eclipse.che.ide.util.dom.Elements.createDivElement;
|
||||
import static org.eclipse.che.ide.util.dom.Elements.createSpanElement;
|
||||
import static org.eclipse.che.ide.util.dom.Elements.createTextNode;
|
||||
|
||||
/** Implementation of {@link CommandsPaletteView}. */
|
||||
@Singleton
|
||||
public class CommandsPaletteViewImpl extends Window implements CommandsPaletteView {
|
||||
|
||||
private static final CommandsPaletteViewImplUiBinder UI_BINDER = GWT.create(CommandsPaletteViewImplUiBinder.class);
|
||||
|
||||
private final NodeFactory nodeFactory;
|
||||
|
||||
@UiField
|
||||
TextBox filterField;
|
||||
|
||||
@UiField(provided = true)
|
||||
Tree tree;
|
||||
|
||||
@UiField
|
||||
Label hintLabel;
|
||||
|
||||
private ActionDelegate delegate;
|
||||
|
||||
@Inject
|
||||
public CommandsPaletteViewImpl(NodeFactory nodeFactory, PaletteMessages messages) {
|
||||
this.nodeFactory = nodeFactory;
|
||||
|
||||
tree = new Tree(new NodeStorage(), new NodeLoader());
|
||||
tree.getSelectionModel().setSelectionMode(SINGLE);
|
||||
|
||||
setWidget(UI_BINDER.createAndBindUi(this));
|
||||
setTitle(messages.viewTitle());
|
||||
|
||||
filterField.getElement().setAttribute("placeholder", messages.filterPlaceholder());
|
||||
initHintLabel();
|
||||
getFooter().removeFromParent();
|
||||
}
|
||||
|
||||
private void initHintLabel() {
|
||||
final SpanElement upKeyLabel = createKeyLabel();
|
||||
upKeyLabel.setInnerHTML(FontAwesome.ARROW_UP);
|
||||
|
||||
final SpanElement downKeyLabel = createKeyLabel();
|
||||
downKeyLabel.setInnerHTML(FontAwesome.ARROW_DOWN);
|
||||
|
||||
final SpanElement enterKeyLabel = createKeyLabel();
|
||||
enterKeyLabel.getStyle().setPadding("0px 1px 1px 4px");
|
||||
enterKeyLabel.setInnerText(" Enter ");
|
||||
|
||||
final DivElement hintElement = createDivElement();
|
||||
hintElement.appendChild(upKeyLabel);
|
||||
hintElement.appendChild(downKeyLabel);
|
||||
hintElement.appendChild(createTextNode(" to select and "));
|
||||
hintElement.appendChild(enterKeyLabel);
|
||||
hintElement.appendChild(createTextNode(" to execute"));
|
||||
|
||||
hintLabel.getElement().appendChild((Element)hintElement);
|
||||
}
|
||||
|
||||
/** Creates an html element for displaying keyboard key. */
|
||||
private SpanElement createKeyLabel() {
|
||||
SpanElement element = createSpanElement();
|
||||
|
||||
element.getStyle().setFontWeight("bold");
|
||||
element.getStyle().setPadding("0 4px 1px 4px");
|
||||
element.getStyle().setMargin("0 3px");
|
||||
element.getStyle().setBorderWidth("1px");
|
||||
element.getStyle().setBorderStyle("solid");
|
||||
element.getStyle().setProperty("border-radius", "3px");
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
|
||||
filterField.setValue("");
|
||||
filterField.setFocus(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCommands(Map<CommandGoal, List<CommandImpl>> commands) {
|
||||
renderCommands(commands);
|
||||
}
|
||||
|
||||
/** Render commands grouped by goals. */
|
||||
private void renderCommands(Map<CommandGoal, List<CommandImpl>> commands) {
|
||||
tree.getNodeStorage().clear();
|
||||
|
||||
for (Entry<CommandGoal, List<CommandImpl>> entry : commands.entrySet()) {
|
||||
List<ExecutableCommandNode> commandNodes = new ArrayList<>(entry.getValue().size());
|
||||
|
||||
for (final CommandImpl command : entry.getValue()) {
|
||||
commandNodes.add(nodeFactory.newExecutableCommandNode(command, () -> delegate.onCommandExecute(command)));
|
||||
}
|
||||
|
||||
final CommandGoalNode commandGoalNode = nodeFactory.newCommandGoalNode(entry.getKey(), commandNodes);
|
||||
tree.getNodeStorage().add(commandGoalNode);
|
||||
}
|
||||
|
||||
tree.expandAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDelegate(ActionDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@UiHandler({"filterField"})
|
||||
void onFilterChanged(KeyUpEvent event) {
|
||||
switch (event.getNativeKeyCode()) {
|
||||
case KEY_UP:
|
||||
tree.getSelectionModel().selectPrevious();
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
tree.getSelectionModel().selectNext();
|
||||
break;
|
||||
case KEY_ENTER:
|
||||
final List<Node> selectedNodes = tree.getSelectionModel().getSelectedNodes();
|
||||
|
||||
if (!selectedNodes.isEmpty()) {
|
||||
final Node node = selectedNodes.get(0);
|
||||
|
||||
if (node instanceof ExecutableCommandNode) {
|
||||
delegate.onCommandExecute(((ExecutableCommandNode)node).getData());
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
delegate.onFilterChanged(filterField.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
interface CommandsPaletteViewImplUiBinder extends UiBinder<Widget, CommandsPaletteViewImpl> {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:g='urn:import:com.google.gwt.user.client.ui'
|
||||
xmlns:che='urn:import:org.eclipse.che.ide.ui'>
|
||||
<ui:with field='res' type='org.eclipse.che.ide.Resources'/>
|
||||
<ui:with field='messages' type='org.eclipse.che.ide.command.palette.PaletteMessages'/>
|
||||
|
||||
<ui:style>
|
||||
@eval partBackground org.eclipse.che.ide.api.theme.Style.theme.partBackground();
|
||||
@eval borderColor org.eclipse.che.ide.api.theme.Style.theme.getTextFieldBackgroundColor();
|
||||
|
||||
.tree {
|
||||
border: 1px solid;
|
||||
border-color: borderColor;
|
||||
background-color: partBackground;
|
||||
margin-top: 7px;
|
||||
min-width: 99%;
|
||||
}
|
||||
|
||||
.hint-label {
|
||||
margin: 7px auto;
|
||||
}
|
||||
</ui:style>
|
||||
|
||||
<g:DockLayoutPanel unit="PX" width="300px" height="300px" debugId="commands_palette">
|
||||
<g:north size="25">
|
||||
<g:TextBox width="87%"
|
||||
ui:field="filterField"
|
||||
addStyleNames="{res.commandsPaletteCss.filterField}"
|
||||
debugId="commands_palette-filter"/>
|
||||
</g:north>
|
||||
<g:center>
|
||||
<che:smartTree.Tree ui:field="tree" addStyleNames="{style.tree}"/>
|
||||
</g:center>
|
||||
<g:south size="50">
|
||||
<g:FlowPanel>
|
||||
<g:Label width="190px" text="{messages.viewHintText}" addStyleNames="{style.hint-label}"/>
|
||||
<g:Label width="230px" ui:field="hintLabel" addStyleNames="{style.hint-label}"/>
|
||||
</g:FlowPanel>
|
||||
</g:south>
|
||||
</g:DockLayoutPanel>
|
||||
</ui:UiBinder>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.palette;
|
||||
|
||||
import com.google.gwt.i18n.client.Messages;
|
||||
|
||||
/**
|
||||
* I18n messages for the Commands Palette.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
public interface PaletteMessages extends Messages {
|
||||
|
||||
@Key("action.show_palette.title")
|
||||
String actionShowPaletteTitle();
|
||||
|
||||
@Key("action.show_palette.description")
|
||||
String actionShowPaletteDescription();
|
||||
|
||||
@Key("view.title")
|
||||
String viewTitle();
|
||||
|
||||
@Key("view.filter.placeholder")
|
||||
String filterPlaceholder();
|
||||
|
||||
@Key("view.hint.text")
|
||||
String viewHintText();
|
||||
|
||||
@Key("message.no_machine")
|
||||
String messageNoMachine();
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*******************************************************************************
|
||||
* 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.command.palette;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.ide.api.action.Action;
|
||||
import org.eclipse.che.ide.api.action.ActionEvent;
|
||||
|
||||
/**
|
||||
* Action for opening Commands Palette.
|
||||
*
|
||||
* @author Artem Zatsarynnyi
|
||||
*/
|
||||
@Singleton
|
||||
public class ShowCommandsPaletteAction extends Action {
|
||||
|
||||
private final CommandsPalettePresenter presenter;
|
||||
|
||||
@Inject
|
||||
public ShowCommandsPaletteAction(PaletteMessages messages, CommandsPalettePresenter presenter) {
|
||||
super(messages.actionShowPaletteTitle(),
|
||||
messages.actionShowPaletteDescription(),
|
||||
null,
|
||||
null);
|
||||
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
presenter.showDialog();
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
* Contributors:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.command;
|
||||
package org.eclipse.che.ide.command.producer;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
|
@ -17,7 +17,7 @@ import org.eclipse.che.api.core.model.machine.Machine;
|
|||
import org.eclipse.che.ide.api.action.Action;
|
||||
import org.eclipse.che.ide.api.action.ActionEvent;
|
||||
import org.eclipse.che.ide.api.command.CommandImpl;
|
||||
import org.eclipse.che.ide.api.command.CommandManager;
|
||||
import org.eclipse.che.ide.api.command.CommandExecutor;
|
||||
import org.eclipse.che.ide.api.command.CommandProducer;
|
||||
|
||||
/**
|
||||
|
|
@ -30,18 +30,18 @@ public class CommandProducerAction extends Action {
|
|||
|
||||
private final CommandProducer commandProducer;
|
||||
private final Machine machine;
|
||||
private final CommandManager commandManager;
|
||||
private final CommandExecutor commandExecutor;
|
||||
|
||||
@Inject
|
||||
public CommandProducerAction(@Assisted String name,
|
||||
@Assisted CommandProducer commandProducer,
|
||||
@Assisted Machine machine,
|
||||
CommandManager commandManager) {
|
||||
CommandExecutor commandExecutor) {
|
||||
super(name);
|
||||
|
||||
this.commandProducer = commandProducer;
|
||||
this.machine = machine;
|
||||
this.commandManager = commandManager;
|
||||
this.commandExecutor = commandExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -52,6 +52,6 @@ public class CommandProducerAction extends Action {
|
|||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
CommandImpl command = commandProducer.createCommand(machine);
|
||||
commandManager.executeCommand(command, machine);
|
||||
commandExecutor.executeCommand(command, machine);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
* Contributors:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.command;
|
||||
package org.eclipse.che.ide.command.producer;
|
||||
|
||||
import org.eclipse.che.api.core.model.machine.Machine;
|
||||
import org.eclipse.che.ide.api.command.CommandProducer;
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
* Contributors:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.command;
|
||||
package org.eclipse.che.ide.command.producer;
|
||||
|
||||
import com.google.gwt.core.client.Callback;
|
||||
import com.google.inject.Inject;
|
||||
|
|
@ -43,7 +43,7 @@ import static org.eclipse.che.ide.api.action.IdeActions.GROUP_MAIN_TOOLBAR;
|
|||
import static org.eclipse.che.ide.api.constraints.Anchor.AFTER;
|
||||
|
||||
/**
|
||||
* Manages actions for the contextual commands.
|
||||
* Manages actions for the commands.
|
||||
* <p>Manager gets all registered {@link CommandProducer}s and creates related actions in context menus.
|
||||
* <p>Manager listens all machines's state (running/destroyed) in order to
|
||||
* create/remove actions for the related {@link CommandProducer}s in case
|
||||
|
|
@ -53,12 +53,15 @@ import static org.eclipse.che.ide.api.constraints.Anchor.AFTER;
|
|||
* @see CommandProducer
|
||||
*/
|
||||
@Singleton
|
||||
public class CommandProducerActionManager implements MachineStateEvent.Handler, WsAgentStateHandler, Component {
|
||||
public class CommandProducerActionManager implements MachineStateEvent.Handler,
|
||||
WsAgentStateHandler,
|
||||
Component {
|
||||
|
||||
private final ActionManager actionManager;
|
||||
private final CommandProducerActionFactory commandProducerActionFactory;
|
||||
private final AppContext appContext;
|
||||
private final Resources resources;
|
||||
private final ProducerMessages messages;
|
||||
|
||||
private final List<Machine> machines;
|
||||
private final Set<CommandProducer> commandProducers;
|
||||
|
|
@ -73,11 +76,13 @@ public class CommandProducerActionManager implements MachineStateEvent.Handler,
|
|||
ActionManager actionManager,
|
||||
CommandProducerActionFactory commandProducerActionFactory,
|
||||
AppContext appContext,
|
||||
Resources resources) {
|
||||
Resources resources,
|
||||
ProducerMessages messages) {
|
||||
this.actionManager = actionManager;
|
||||
this.commandProducerActionFactory = commandProducerActionFactory;
|
||||
this.appContext = appContext;
|
||||
this.resources = resources;
|
||||
this.messages = messages;
|
||||
|
||||
machines = new ArrayList<>();
|
||||
commandProducers = new HashSet<>();
|
||||
|
|
@ -93,10 +98,10 @@ public class CommandProducerActionManager implements MachineStateEvent.Handler,
|
|||
private void start(Set<CommandProducer> commandProducers) {
|
||||
this.commandProducers.addAll(commandProducers);
|
||||
|
||||
commandActionsPopUpGroup = new DefaultActionGroup("Commands", true, actionManager);
|
||||
commandActionsPopUpGroup = new DefaultActionGroup(messages.actionCommandsTitle(), true, actionManager);
|
||||
actionManager.registerAction("commandActionsPopUpGroup", commandActionsPopUpGroup);
|
||||
commandActionsPopUpGroup.getTemplatePresentation().setSVGResource(resources.compile());
|
||||
commandActionsPopUpGroup.getTemplatePresentation().setDescription("Execute command");
|
||||
commandActionsPopUpGroup.getTemplatePresentation().setDescription(messages.actionCommandsDescription());
|
||||
|
||||
DefaultActionGroup mainContextMenu = (DefaultActionGroup)actionManager.getAction(GROUP_MAIN_CONTEXT_MENU);
|
||||
mainContextMenu.add(commandActionsPopUpGroup);
|
||||
|
|
@ -183,11 +188,7 @@ public class CommandProducerActionManager implements MachineStateEvent.Handler,
|
|||
CommandProducerAction machineAction = commandProducerActionFactory.create(machine.getConfig().getName(),
|
||||
commandProducer,
|
||||
machine);
|
||||
List<Action> actionList = actionsByMachines.get(machine);
|
||||
if (actionList == null) {
|
||||
actionList = new ArrayList<>();
|
||||
actionsByMachines.put(machine, actionList);
|
||||
}
|
||||
final List<Action> actionList = actionsByMachines.computeIfAbsent(machine, key -> new ArrayList<>());
|
||||
actionList.add(machineAction);
|
||||
|
||||
actionManager.registerAction(machine.getConfig().getName(), machineAction);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue