Skip to content

Commit

Permalink
Improvements for intelligent commands - Phase 2 (#4611)
Browse files Browse the repository at this point in the history
Intelligent commands UX and UI improvements:
Changed flow of new command goal creation
Processes and Previews dropdown lists made fully clickable
Command editor made fullwidth
Command editors now are restorable as well as text editors
Added shortcuts for the default "Run" and "Debug" commands: Alt+R and Alt+D respectively
Added tooltip for process ID in commands toolbar
  • Loading branch information
azatsarynnyy committed Mar 29, 2017
1 parent 1648a3b commit 4a6d9cd
Show file tree
Hide file tree
Showing 46 changed files with 916 additions and 368 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

import org.eclipse.che.commons.annotation.Nullable;

import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
* Registry of command goals.
Expand All @@ -22,14 +22,17 @@
*/
public interface CommandGoalRegistry {

/** Returns all (predefined and created by user) {@link CommandGoal}s. */
Set<CommandGoal> getAllGoals();

/** Returns all registered predefined {@link CommandGoal}s. */
List<CommandGoal> getAllPredefinedGoals();
Set<CommandGoal> getAllPredefinedGoals();

/** Returns the default command goal which is used for grouping commands which doesn't belong to any goal. */
/** Returns the default command goal which is used for commands which actually doesn't belong to any goal. */
CommandGoal getDefaultGoal();

/**
* Returns an optional {@link CommandGoal} by the given ID
* Returns an {@code Optional} {@link CommandGoal} by the given ID
* or {@code Optional.absent()} if none was registered.
*
* @param id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
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.component.WsAgentComponent;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.command.editor.CommandEditorView;
import org.eclipse.che.ide.command.editor.CommandEditorViewImpl;
Expand Down Expand Up @@ -60,7 +61,7 @@
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.commands.button.MenuItemsFactory;
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;
Expand Down Expand Up @@ -98,10 +99,14 @@ protected void configure() {

// 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);

GinMapBinder<String, WsAgentComponent> wsAgentComponentBinder = GinMapBinder.newMapBinder(binder(),
String.class,
WsAgentComponent.class);
wsAgentComponentBinder.addBinding("Z CommandManagerImpl").to(CommandManagerImpl.class);
wsAgentComponentBinder.addBinding("Z CommandsExplorerPresenter").to(CommandsExplorerPresenter.class);
wsAgentComponentBinder.addBinding("Z ExecuteCommandActionManager").to(ExecuteCommandActionManager.class);

install(new GinFactoryModuleBuilder().build(ExecuteCommandActionFactory.class));
install(new GinFactoryModuleBuilder().build(GoalPopUpGroupFactory.class));
Expand All @@ -126,7 +131,7 @@ protected void configure() {
bind(PreviewsView.class).to(PreviewsViewImpl.class).in(Singleton.class);

install(new GinFactoryModuleBuilder().build(ToolbarButtonsFactory.class));
install(new GinFactoryModuleBuilder().build(PopupItemFactory.class));
install(new GinFactoryModuleBuilder().build(MenuItemsFactory.class));
}

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@
@eval partBackground org.eclipse.che.ide.api.theme.Style.theme.partBackground();
@eval tabsPanelBackground org.eclipse.che.ide.api.theme.Style.theme.tabsPanelBackground();

.mainPanel {
.main-panel {
background-color: partBackground;
}

.header {
.pages-panel {
width: literal("calc(100% - 40px)");
}

.buttons-panel {
height: 38px;
padding-top: 5px;
background-color: tabsPanelBackground;
Expand All @@ -36,14 +40,14 @@
}
</ui:style>

<g:DockLayoutPanel addStyleNames="{style.mainPanel}">
<g:DockLayoutPanel addStyleNames="{style.main-panel}">
<g:center>
<g:ScrollPanel ui:field="scrollPanel">
<g:FlowPanel width="700px" ui:field="pagesPanel"/>
<g:FlowPanel ui:field="pagesPanel" addStyleNames="{style.pages-panel}"/>
</g:ScrollPanel>
</g:center>
<g:south size="44">
<g:FlowPanel addStyleNames="{style.header}">
<g:FlowPanel addStyleNames="{style.buttons-panel}">
<g:Button ui:field="cancelButton"
text="{messages.buttonCancelText}"
addStyleNames="{style.button}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ public interface EditorMessages extends Messages {
@Key("page.goal.title")
String pageGoalTitle();

@Key("page.goal.new_goal.title")
String pageGoalNewGoalTitle();

@Key("page.goal.new_goal.label")
String pageGoalNewGoalLabel();

@Key("page.goal.new_goal.button.create")
String pageGoalNewGoalButtonCreate();

@Key("page.projects.title")
String pageProjectsTitle();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,16 @@
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.api.dialogs.DialogFactory;
import org.eclipse.che.ide.api.dialogs.InputCallback;
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.
*
Expand All @@ -37,21 +32,23 @@ public class GoalPage extends AbstractCommandEditorPage implements GoalPageView.

private final GoalPageView view;
private final CommandGoalRegistry goalRegistry;
private final CommandManager commandManager;
private final EditorMessages messages;
private final DialogFactory dialogFactory;

/** Initial value of the command's goal. */
private String goalInitial;

@Inject
public GoalPage(GoalPageView view,
CommandGoalRegistry commandGoalRegistry,
CommandManager commandManager,
EditorMessages messages) {
CommandGoalRegistry goalRegistry,
EditorMessages messages,
DialogFactory dialogFactory) {
super(messages.pageGoalTitle());

this.view = view;
this.goalRegistry = commandGoalRegistry;
this.commandManager = commandManager;
this.goalRegistry = goalRegistry;
this.messages = messages;
this.dialogFactory = dialogFactory;

view.setDelegate(this);
}
Expand All @@ -64,16 +61,12 @@ public IsWidget getView() {
@Override
protected void initialize() {
final String goalId = editedCommand.getGoal();
final CommandGoal commandGoal = goalRegistry.getGoalForId(goalId);

goalInitial = commandGoal.getId();
final CommandGoal goal = goalRegistry.getGoalForId(goalId);

final Set<CommandGoal> goals = new HashSet<>();
goals.addAll(goalRegistry.getAllPredefinedGoals());
goals.addAll(getCustomGoals());
goalInitial = goal.getId();

view.setAvailableGoals(goals);
view.setGoal(commandGoal.getId());
view.setAvailableGoals(goalRegistry.getAllGoals());
view.setGoal(goal.getId());
}

@Override
Expand All @@ -82,31 +75,37 @@ public boolean isDirty() {
return false;
}

final CommandGoal commandGoal = goalRegistry.getGoalForId(editedCommand.getGoal());
CommandGoal goal = goalRegistry.getGoalForId(editedCommand.getGoal());

return !(goalInitial.equals(commandGoal.getId()));
return !(goalInitial.equals(goal.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;
@Override
public void onCreateGoal() {
InputCallback inputCallback = value -> {
Set<CommandGoal> goals = goalRegistry.getAllGoals();
goals.add(goalRegistry.getGoalForId(value));

view.setAvailableGoals(goals);
view.setGoal(value);

editedCommand.setGoal(value);
notifyDirtyStateChanged();
};

dialogFactory.createInputDialog(messages.pageGoalNewGoalTitle(),
messages.pageGoalNewGoalLabel(),
"",
0,
0,
messages.pageGoalNewGoalButtonCreate(),
inputCallback,
null).show();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,8 @@ interface ActionDelegate {
* new value of the command goal
*/
void onGoalChanged(String goalId);

/** Called when creating new goal is requested. */
void onCreateGoal();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
*******************************************************************************/
package org.eclipse.che.ide.command.editor.page.goal;

import com.google.common.annotations.VisibleForTesting;
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;
Expand All @@ -21,7 +21,7 @@
import com.google.inject.Inject;

import org.eclipse.che.ide.api.command.CommandGoal;
import org.eclipse.che.ide.ui.listbox.CustomComboBox;
import org.eclipse.che.ide.ui.listbox.CustomListBox;

import java.util.Set;

Expand All @@ -32,42 +32,52 @@
*/
public class GoalPageViewImpl extends Composite implements GoalPageView {

@VisibleForTesting
static final String CREATE_GOAL_ITEM = "New Command Goal...";

private static final GoalPageViewImplUiBinder UI_BINDER = GWT.create(GoalPageViewImplUiBinder.class);

@UiField
CustomComboBox goalComboBox;
CustomListBox goalsList;

private ActionDelegate delegate;
private String lastValue;

@Inject
public GoalPageViewImpl() {
initWidget(UI_BINDER.createAndBindUi(this));
}

@Override
public void setAvailableGoals(Set<CommandGoal> goals) {
goalComboBox.clear();
goals.forEach(g -> goalComboBox.addItem(g.getId()));
public void setDelegate(ActionDelegate delegate) {
this.delegate = delegate;
}

@Override
public void setGoal(String goalId) {
goalComboBox.setValue(goalId);
}
public void setAvailableGoals(Set<CommandGoal> goals) {
goalsList.clear();
goals.forEach(g -> goalsList.addItem(g.getId()));

@Override
public void setDelegate(ActionDelegate delegate) {
this.delegate = delegate;
goalsList.addItem(CREATE_GOAL_ITEM);
}

@UiHandler({"goalComboBox"})
void onGoalKeyUp(KeyUpEvent event) {
delegate.onGoalChanged(goalComboBox.getValue());
@Override
public void setGoal(String goalId) {
goalsList.select(goalId);
lastValue = goalId;
}

@UiHandler({"goalComboBox"})
@UiHandler({"goalsList"})
void onGoalChanged(ChangeEvent event) {
delegate.onGoalChanged(goalComboBox.getValue());
String chosenValue = goalsList.getValue();

if (chosenValue.equals(CREATE_GOAL_ITEM)) {
goalsList.select(lastValue);
delegate.onCreateGoal();
} else {
lastValue = chosenValue;
delegate.onGoalChanged(lastValue);
}
}

interface GoalPageViewImplUiBinder extends UiBinder<Widget, GoalPageViewImpl> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
display: block;
}
</ui:style>
<che:CustomComboBox ui:field="goalComboBox" width="100%" addStyleNames="{style.combo-box}" debugId="command_editor-goal"/>
<che:CustomListBox ui:field="goalsList" width="100%" addStyleNames="{style.combo-box}" debugId="command_editor-goal"/>
</ui:UiBinder>
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ public NamePageViewImpl() {
}

@Override
public void setCommandName(String name) {
commandName.setValue(name);
public void setDelegate(ActionDelegate delegate) {
this.delegate = delegate;
}

@Override
public void setDelegate(ActionDelegate delegate) {
this.delegate = delegate;
public void setCommandName(String name) {
commandName.setValue(name);
}

@UiHandler({"commandName"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:with field='messages' type='org.eclipse.che.ide.command.editor.EditorMessages'/>
<ui:style>
.text-field {
width: literal("calc(100% - 80px)");
}

.button {
float: right;
margin-top: 1px;
Expand All @@ -33,6 +37,6 @@
text="{messages.buttonRunText}"
addStyleNames="{style.button}"
debugId="command-editor-button-run"/>
<g:TextBox ui:field="commandName" width="88%"/>
<g:TextBox ui:field="commandName" addStyleNames="{style.text-field}"/>
</g:FlowPanel>
</ui:UiBinder>
Loading

0 comments on commit 4a6d9cd

Please sign in to comment.