diff --git a/core/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/theme/Theme.java b/core/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/theme/Theme.java index 7d7da8bb35..8b706b0a5d 100644 --- a/core/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/theme/Theme.java +++ b/core/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/theme/Theme.java @@ -993,6 +993,48 @@ public interface Theme { */ String processTreeBackgroundColor(); + /** + * Background color for toolbar in consoles panel. + * + * @return color + */ + String consolesToolbarBackground(); + + /** + * Border color for consoles toolbar border. + * + * @return color + */ + String colsolesToolbarBorderColor(); + + /** + * Button color on consoles toolbar. + * + * @return color + */ + String consolesToolbarButtonColor(); + + /** + * Hovered button color on consoles toolbar. + * + * @return color + */ + String consolesToolbarHoveredButtonColor(); + + /** + * Disabled button on the consoles toolbar. + * + * @return color + */ + String consolesToolbarDisabledButtonColor(); + + /** + * Toggled button on the consoles toolbar. + * + * @return color + */ + String consolesToolbarToggledButtonColor(); + /** * Text color for DEV label in process tree. * diff --git a/core/ide/che-core-ide-api/src/main/resources/org/eclipse/che/ide/api/ui/style.css b/core/ide/che-core-ide-api/src/main/resources/org/eclipse/che/ide/api/ui/style.css index 02f47eedad..7fe01b8990 100644 --- a/core/ide/che-core-ide-api/src/main/resources/org/eclipse/che/ide/api/ui/style.css +++ b/core/ide/che-core-ide-api/src/main/resources/org/eclipse/che/ide/api/ui/style.css @@ -58,7 +58,15 @@ @eval partToolbarSeparatorTopColor org.eclipse.che.ide.api.theme.Style.theme.partToolbarSeparatorTopColor(); @eval partToolbarSeparatorBottomColor org.eclipse.che.ide.api.theme.Style.theme.partToolbarSeparatorBottomColor(); +@eval outputBackgroundColor org.eclipse.che.ide.api.theme.Style.theme.outputBackgroundColor(); + @eval consolePanelColor org.eclipse.che.ide.api.theme.Style.theme.consolePanelColor(); +@eval consolesToolbarBackground org.eclipse.che.ide.api.theme.Style.theme.consolesToolbarBackground(); +@eval colsolesToolbarBorderColor org.eclipse.che.ide.api.theme.Style.theme.colsolesToolbarBorderColor(); +@eval consolesToolbarButtonColor org.eclipse.che.ide.api.theme.Style.theme.consolesToolbarButtonColor(); +@eval consolesToolbarHoveredButtonColor org.eclipse.che.ide.api.theme.Style.theme.consolesToolbarHoveredButtonColor(); +@eval consolesToolbarDisabledButtonColor org.eclipse.che.ide.api.theme.Style.theme.consolesToolbarDisabledButtonColor(); +@eval consolesToolbarToggledButtonColor org.eclipse.che.ide.api.theme.Style.theme.consolesToolbarToggledButtonColor(); @eval tabBorderShadow org.eclipse.che.ide.api.theme.Style.theme.tabBorderShadow(); @@ -180,6 +188,9 @@ @def largeDropdownLabel 12px; @def buttonFontSize 11px; +@def consoleFontSize 11px; +@def consoleLineHeight 13px; + /* Fonts */ @def alternativeFontFamily "Helvetica Neue", "Myriad Pro","open sans", arial, sans-serif; @def fileTreeFontFamily "Helvetica Neue", "Myriad Pro","Lucida Grande", Verdana, Arial; diff --git a/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/theme/DarkTheme.java b/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/theme/DarkTheme.java index 97030b7eda..5cc7546420 100644 --- a/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/theme/DarkTheme.java +++ b/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/theme/DarkTheme.java @@ -766,6 +766,36 @@ public class DarkTheme implements Theme { return "#21252b"; } + @Override + public String consolesToolbarBackground() { + return "#21252B"; + } + + @Override + public String colsolesToolbarBorderColor() { + return "#121416"; + } + + @Override + public String consolesToolbarButtonColor() { + return "#aaaaaa"; + } + + @Override + public String consolesToolbarHoveredButtonColor() { + return "#e0e0e0"; + } + + @Override + public String consolesToolbarDisabledButtonColor() { + return "#777777"; + } + + @Override + public String consolesToolbarToggledButtonColor() { + return "rgba(0, 0, 0, 0.6)"; + } + @Override public String processTreeDevLabel() { return "white"; diff --git a/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/theme/LightTheme.java b/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/theme/LightTheme.java index 147ec49f42..0dc59ecc95 100644 --- a/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/theme/LightTheme.java +++ b/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/theme/LightTheme.java @@ -742,6 +742,36 @@ public class LightTheme implements Theme { return "white"; } + @Override + public String consolesToolbarBackground() { + return "#D6D6D9"; + } + + @Override + public String colsolesToolbarBorderColor() { + return "#8e8e8e"; + } + + @Override + public String consolesToolbarButtonColor() { + return "#aaaaaa"; + } + + @Override + public String consolesToolbarHoveredButtonColor() { + return "#e0e0e0"; + } + + @Override + public String consolesToolbarDisabledButtonColor() { + return "#777777"; + } + + @Override + public String consolesToolbarToggledButtonColor() { + return "rgba(0, 0, 0, 0.6)"; + } + @Override public String processTreeDevLabel() { return "white"; diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartView.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartView.java index 8f4fdffedf..d99c487555 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartView.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartView.java @@ -18,7 +18,8 @@ import org.eclipse.che.ide.api.mvp.View; * @author Andrey Plotnikov */ public interface GitOutputPartView extends View { - public interface ActionDelegate { + + interface ActionDelegate { /** * Handle user clicks on clear console button. */ diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartViewImpl.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartViewImpl.java index 6be5279aef..2029d5976d 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartViewImpl.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartViewImpl.java @@ -10,6 +10,9 @@ *******************************************************************************/ package org.eclipse.che.ide.ext.git.client.outputconsole; +import com.google.gwt.dom.client.Node; +import com.google.gwt.dom.client.PreElement; +import com.google.gwt.user.client.DOM; import org.eclipse.che.ide.api.parts.PartStackUIResources; import com.google.gwt.safehtml.shared.SimpleHtmlSanitizer; @@ -25,6 +28,7 @@ import com.google.inject.Inject; import org.eclipse.che.ide.ext.git.client.GitLocalizationConstant; import org.eclipse.che.ide.ui.button.ConsoleButton; import org.eclipse.che.ide.ui.button.ConsoleButtonFactory; +import org.eclipse.che.ide.util.loging.Log; import org.vectomatic.dom.svg.ui.SVGResource; import javax.validation.constraints.NotNull; @@ -49,10 +53,10 @@ public class GitOutputPartViewImpl extends Composite implements GitOutputPartVie FlowPanel buttons; @UiField - FlowPanel consoleArea; + ScrollPanel scrollPanel; @UiField - ScrollPanel scrollPanel; + FlowPanel consoleLines; @Inject public GitOutputPartViewImpl(GitLocalizationConstant constant, @@ -82,31 +86,29 @@ public class GitOutputPartViewImpl extends Composite implements GitOutputPartVie /** {@inheritDoc} */ @Override public void print(String text) { - String preStyle = " style='margin:0px; font-size: 12px;' "; - - HTML html = new HTML(); - html.setHTML("" + SimpleHtmlSanitizer.sanitizeHtml(text).asString() + ""); - html.getElement().setAttribute("style", "padding-left: 2px;"); - - consoleArea.add(html); + PreElement pre = DOM.createElement("pre").cast(); + pre.setInnerText(text.isEmpty() ? " " : text); + consoleLines.getElement().appendChild(pre); } @Override public void print(String text, String color) { - String preStyle = " style='margin:0px; font-size: 12px;' "; + PreElement pre = DOM.createElement("pre").cast(); + pre.setInnerText(text.isEmpty() ? " " : text); - HTML html = new HTML(); - html.setHTML("" + SimpleHtmlSanitizer.sanitizeHtml(text).asString() + ""); + try { + pre.getStyle().setColor(SimpleHtmlSanitizer.sanitizeHtml(color).asString()); + } catch (Exception e) { + Log.error(getClass(), "Unable to set color [" + color + "]", e); + } - html.getElement().setAttribute("style", "padding-left: 2px;"); - consoleArea.add(html); + consoleLines.getElement().appendChild(pre); } /** {@inheritDoc} */ @Override public void clear() { - consoleArea.clear(); + consoleLines.clear(); } /** {@inheritDoc} */ diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartViewImpl.ui.xml b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartViewImpl.ui.xml index 6d84297595..8e65a7e09e 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartViewImpl.ui.xml +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/outputconsole/GitOutputPartViewImpl.ui.xml @@ -14,26 +14,66 @@ - - .scrollPanel { - border: 1px solid #242424; - padding: 3px; + + + @eval outputBackgroundColor org.eclipse.che.ide.api.theme.Style.theme.outputBackgroundColor(); + + /** + * Toolbar on the left with buttons. + */ + .toolbar { + background-color: #373737; } - .backgroundColor { - background-color: #373737; + /** + * Console output area. + */ + .console { + background-color: outputBackgroundColor; + color: outputFontColor; + border-top: 1px solid separatorColor; + + -moz-user-select: text; + -webkit-user-select: text; + user-select: text; + outline: none; + + padding: 1px 3px 3px 3px; + margin-bottom: 0px; + } + + .console pre { + font-family: outputFontFamily; + font-size: consoleFontSize; + line-height: consoleLineHeight; + } + + .consoleLines { + width: 100%; + } + + .consoleLines > pre { + width: inherit; + padding: 0; + margin: 0; + } + + .consoleLines[wrap] > pre { + white-space: pre-wrap; + word-break: break-all; + word-wrap: break-word; } - + - - + + diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/MachineLocalizationConstant.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/MachineLocalizationConstant.java index 54b5bf3eb2..ead244c212 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/MachineLocalizationConstant.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/MachineLocalizationConstant.java @@ -248,7 +248,6 @@ public interface MachineLocalizationConstant extends Messages { @Key("view.targets.delete.error") String targetsViewDeleteError(String target); - @Key("process.active") String processActive(); @@ -381,6 +380,23 @@ public interface MachineLocalizationConstant extends Messages { @Key("view.consoles.title") String viewConsolesTitle(); + + @Key("consoles.reRunButton.tooltip") + String consolesReRunButtonTooltip(); + + @Key("consoles.stopButton.tooltip") + String consolesStopButtonTooltip(); + + @Key("consoles.clearOutputsButton.tooltip") + String consolesClearOutputsButtonTooltip(); + + @Key("consoles.wrapTextButton.tooltip") + String consolesWrapTextButtonTooltip(); + + @Key("consoles.autoScrollButton.tooltip") + String consolesAutoScrollButtonTooltip(); + + @Key("view.processes.tooltip") String viewProcessesTooltip(); diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/MachineResources.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/MachineResources.java index 6ff66a9ef7..a18850ee9f 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/MachineResources.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/MachineResources.java @@ -60,6 +60,21 @@ public interface MachineResources extends ClientBundle { @Source("images/process/add-terminal.svg") SVGResource addTerminalIcon(); + @Source("images/process/re-run.svg") + SVGResource reRunIcon(); + + @Source("images/process/stop.svg") + SVGResource stopIcon(); + + @Source("images/process/clear-outputs.svg") + SVGResource clearOutputsIcon(); + + @Source("images/process/scroll-to-bottom.svg") + SVGResource scrollToBottomIcon(); + + @Source("images/process/line-wrap.svg") + SVGResource lineWrapIcon(); + /** Returns the icon for 'Custom' command type. */ @Source("command/arbitrary/custom-command-type.svg") SVGResource customCommandType(); diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/CommandOutputConsolePresenter.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/CommandOutputConsolePresenter.java index d1b8fd552a..12da5a6761 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/CommandOutputConsolePresenter.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/CommandOutputConsolePresenter.java @@ -24,7 +24,7 @@ import org.eclipse.che.api.promises.client.OperationException; import org.eclipse.che.ide.extension.machine.client.MachineResources; import org.eclipse.che.ide.extension.machine.client.command.CommandConfiguration; import org.eclipse.che.ide.extension.machine.client.command.CommandManager; -import org.eclipse.che.ide.extension.machine.client.processes.event.ProcessFinishedEvent; +import org.eclipse.che.ide.extension.machine.client.processes.ProcessFinishedEvent; import org.eclipse.che.ide.rest.DtoUnmarshallerFactory; import org.eclipse.che.ide.util.loging.Log; import org.eclipse.che.ide.websocket.MessageBus; @@ -55,6 +55,7 @@ public class CommandOutputConsolePresenter implements CommandOutputConsole, Outp private final CommandConfiguration commandConfiguration; private final EventBus eventBus; private final String machineId; + private final CommandManager commandManager; private MessageBus messageBus; private int pid; @@ -62,6 +63,12 @@ public class CommandOutputConsolePresenter implements CommandOutputConsole, Outp private MessageHandler outputHandler; private boolean finished; + /** Wrap text or not */ + private boolean wrapText = false; + + /** Follow output when printing text */ + private boolean followOutput = true; + private List outputListenes = new ArrayList<>(); @Inject @@ -82,6 +89,7 @@ public class CommandOutputConsolePresenter implements CommandOutputConsole, Outp this.machineId = machineId; this.messageBus = messageBusProvider.getMessageBus(); this.eventBus = eventBus; + this.commandManager = commandManager; view.setDelegate(this); @@ -90,7 +98,7 @@ public class CommandOutputConsolePresenter implements CommandOutputConsole, Outp commandManager.substituteProperties(previewUrl).then(new Operation() { @Override public void apply(String arg) throws OperationException { - view.printPreviewUrl(arg); + view.showPreviewUrl(arg); } }); } else { @@ -120,6 +128,9 @@ public class CommandOutputConsolePresenter implements CommandOutputConsole, Outp @Override public void listenToOutput(String wsChannel) { + view.enableStopButton(true); + view.toggleScrollToEndButton(true); + outputChannel = wsChannel; outputHandler = new SubscriptionHandler(new OutputMessageUnmarshaller()) { @Override @@ -144,7 +155,7 @@ public class CommandOutputConsolePresenter implements CommandOutputConsole, Outp public void attachToProcess(final MachineProcessDto process) { this.pid = process.getPid(); - view.printCommandLine(process.getCommandLine()); + view.showCommandLine(process.getCommandLine()); final Unmarshallable unmarshaller = dtoUnmarshallerFactory.newWSUnmarshaller(MachineProcessEvent.class); final String processStateChannel = "machine:process:" + machineId; @@ -160,11 +171,14 @@ public class CommandOutputConsolePresenter implements CommandOutputConsole, Outp switch (result.getEventType()) { case STOPPED: finished = true; + view.enableStopButton(false); + eventBus.fireEvent(new ProcessFinishedEvent(null)); break; case ERROR: finished = true; + view.enableStopButton(false); eventBus.fireEvent(new ProcessFinishedEvent(null)); @@ -183,6 +197,8 @@ public class CommandOutputConsolePresenter implements CommandOutputConsole, Outp @Override protected void onErrorReceived(Throwable exception) { finished = true; + view.enableStopButton(false); + wsUnsubscribe(processStateChannel, this); wsUnsubscribe(outputChannel, outputHandler); } @@ -227,4 +243,49 @@ public class CommandOutputConsolePresenter implements CommandOutputConsole, Outp outputListenes.add(listener); } + @Override + public void reRunProcessButtonClicked() { + if (isFinished()) { + commandManager.execute(commandConfiguration); + } else { + machineServiceClient.stopProcess(machineId, pid).then(new Operation() { + @Override + public void apply(Void arg) throws OperationException { + commandManager.execute(commandConfiguration); + } + }); + } + } + + @Override + public void stopProcessButtonClicked() { + stop(); + } + + @Override + public void clearOutputsButtonClicked() { + view.clearConsole(); + } + + @Override + public void wrapTextButtonClicked() { + wrapText = !wrapText; + view.wrapText(wrapText); + view.toggleWrapTextButton(wrapText); + } + + @Override + public void scrollToBottomButtonClicked() { + followOutput = !followOutput; + + view.toggleScrollToEndButton(followOutput); + view.enableAutoScroll(followOutput); + } + + @Override + public void onOutputScrolled(boolean bottomReached) { + followOutput = bottomReached; + view.toggleScrollToEndButton(bottomReached); + } + } diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleView.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleView.java index 56396694e5..73312c00a6 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleView.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleView.java @@ -19,31 +19,106 @@ import org.eclipse.che.ide.api.mvp.View; */ public interface OutputConsoleView extends View { - /** Print the command line to the console. */ - void printCommandLine(String commandLine); - - /** Print the command preview Url. */ - void printPreviewUrl(String previewUrl); + /** + * Shows the command line to the console. + * + * @param commandLine + * command line + */ + void showCommandLine(String commandLine); /** - * Print the message. + * Shows the command preview URL. * - * @param message + * @param previewUrl + * preview URL + */ + void showPreviewUrl(String previewUrl); + + /** + * Prints text. + * + * @param text * text to print * @param cr * if {@code true} - next message should replace the current one, * if {@code false} - next message will be printed in a new line */ - void print(String message, boolean cr); + void print(String text, boolean cr); - /** Hides command title and command label */ + /** + * Hides command title and command label. + */ void hideCommand(); - /** Hides preview title and preview label */ + /** + * Hides preview title and preview label. + */ void hidePreview(); + /** + * Wraps text in the console. + * + * @param wrap + * set true to wrap the text + */ + void wrapText(boolean wrap); + + /** + * Enables auto scroll when output. + */ + void enableAutoScroll(boolean enable); + + /** + * Clears the console. + */ + void clearConsole(); + + /** + * Toggles `Wrap text` button. + * + * @param toggle + * use true to toggle the button + */ + void toggleWrapTextButton(boolean toggle); + + /** + * Toggles `Scroll to the end` button. + * + * @param toggle + * use true to toggle the button + */ + void toggleScrollToEndButton(boolean toggle); + + /** + * Enables or disables Stop process button. + * + * @param enable + * new enabled state for the button + */ + void enableStopButton(boolean enable); + /** Action handler for the view actions/controls. */ interface ActionDelegate { + + /** Handle click on `Run process` button. */ + void reRunProcessButtonClicked(); + + /** Handle click on `Stop process` button. */ + void stopProcessButtonClicked(); + + /** Handle click on `Clear console` button. */ + void clearOutputsButtonClicked(); + + /** Handle click on `Wrap text` button. */ + void wrapTextButtonClicked(); + + /** Handle click on `Scroll to end` button. */ + void scrollToBottomButtonClicked(); + + /** Handle scrolling the output. */ + void onOutputScrolled(boolean bottomReached); + } } diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleViewImpl.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleViewImpl.java index 72222fe66e..8aea7eb5c1 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleViewImpl.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleViewImpl.java @@ -15,6 +15,8 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.PreElement; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.ScrollEvent; import com.google.gwt.event.dom.client.ScrollHandler; import com.google.gwt.uibinder.client.UiBinder; @@ -28,6 +30,12 @@ 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.extension.machine.client.MachineLocalizationConstant; +import org.eclipse.che.ide.extension.machine.client.MachineResources; +import org.eclipse.che.ide.ui.Tooltip; +import static org.eclipse.che.ide.ui.menu.PositionController.HorizontalAlign.MIDDLE; +import static org.eclipse.che.ide.ui.menu.PositionController.VerticalAlign.BOTTOM; +import org.vectomatic.dom.svg.ui.SVGImage; /** * View representation of output console. @@ -42,6 +50,8 @@ public class OutputConsoleViewImpl extends Composite implements OutputConsoleVie private static final OutputConsoleViewUiBinder UI_BINDER = GWT.create(OutputConsoleViewUiBinder.class); + private ActionDelegate delegate; + @UiField DockLayoutPanel consolePanel; @@ -66,6 +76,21 @@ public class OutputConsoleViewImpl extends Composite implements OutputConsoleVie @UiField Anchor previewUrlLabel; + @UiField + FlowPanel reRunProcessButton; + + @UiField + FlowPanel stopProcessButton; + + @UiField + FlowPanel clearOutputsButton; + + @UiField + FlowPanel wrapTextButton; + + @UiField + FlowPanel scrollToBottomButton; + /** If true - next printed line should replace the previous one. */ private boolean carriageReturn; @@ -76,13 +101,93 @@ public class OutputConsoleViewImpl extends Composite implements OutputConsoleVie private boolean followScheduled = false; @Inject - public OutputConsoleViewImpl() { + public OutputConsoleViewImpl(MachineResources resources, + MachineLocalizationConstant localization) { initWidget(UI_BINDER.createAndBindUi(this)); + + reRunProcessButton.add(new SVGImage(resources.reRunIcon())); + stopProcessButton.add(new SVGImage(resources.stopIcon())); + clearOutputsButton.add(new SVGImage(resources.clearOutputsIcon())); + + wrapTextButton.add(new SVGImage(resources.lineWrapIcon())); + scrollToBottomButton.add(new SVGImage(resources.scrollToBottomIcon())); + scrollPanel.addDomHandler(this, ScrollEvent.getType()); + + reRunProcessButton.addDomHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + if (!reRunProcessButton.getElement().hasAttribute("disabled") && delegate != null) { + delegate.reRunProcessButtonClicked(); + } + } + }, ClickEvent.getType()); + + stopProcessButton.addDomHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + if (!stopProcessButton.getElement().hasAttribute("disabled") && delegate != null) { + delegate.stopProcessButtonClicked(); + } + } + }, ClickEvent.getType()); + + clearOutputsButton.addDomHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + if (!clearOutputsButton.getElement().hasAttribute("disabled") && delegate != null) { + delegate.clearOutputsButtonClicked(); + } + } + }, ClickEvent.getType()); + + wrapTextButton.addDomHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent clickEvent) { + if (!wrapTextButton.getElement().hasAttribute("disabled") && delegate != null) { + delegate.wrapTextButtonClicked(); + } + } + }, ClickEvent.getType()); + + scrollToBottomButton.addDomHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + if (!scrollToBottomButton.getElement().hasAttribute("disabled") && delegate != null) { + delegate.scrollToBottomButtonClicked(); + } + } + }, ClickEvent.getType()); + + Tooltip.create((elemental.dom.Element) reRunProcessButton.getElement(), + BOTTOM, + MIDDLE, + localization.consolesReRunButtonTooltip()); + + Tooltip.create((elemental.dom.Element) stopProcessButton.getElement(), + BOTTOM, + MIDDLE, + localization.consolesStopButtonTooltip()); + + Tooltip.create((elemental.dom.Element) clearOutputsButton.getElement(), + BOTTOM, + MIDDLE, + localization.consolesClearOutputsButtonTooltip()); + + Tooltip.create((elemental.dom.Element) wrapTextButton.getElement(), + BOTTOM, + MIDDLE, + localization.consolesWrapTextButtonTooltip()); + + Tooltip.create((elemental.dom.Element) scrollToBottomButton.getElement(), + BOTTOM, + MIDDLE, + localization.consolesAutoScrollButtonTooltip()); } @Override public void setDelegate(ActionDelegate delegate) { + this.delegate = delegate; } @Override @@ -96,12 +201,59 @@ public class OutputConsoleViewImpl extends Composite implements OutputConsoleVie } @Override - public void printCommandLine(String commandLine) { + public void wrapText(boolean wrap) { + if (wrap) { + consoleLines.getElement().setAttribute("wrap", ""); + } else { + consoleLines.getElement().removeAttribute("wrap"); + } + } + + @Override + public void enableAutoScroll(boolean enable) { + followOutput = enable; + followOutput(); + } + + @Override + public void clearConsole() { + consoleLines.getElement().setInnerHTML(""); + } + + @Override + public void toggleWrapTextButton(boolean toggle) { + if (toggle) { + wrapTextButton.getElement().setAttribute("toggled", ""); + } else { + wrapTextButton.getElement().removeAttribute("toggled"); + } + } + + @Override + public void toggleScrollToEndButton(boolean toggle) { + if (toggle) { + scrollToBottomButton.getElement().setAttribute("toggled", ""); + } else { + scrollToBottomButton.getElement().removeAttribute("toggled"); + } + } + + @Override + public void enableStopButton(boolean enable) { + if (enable) { + stopProcessButton.getElement().removeAttribute("disabled"); + } else { + stopProcessButton.getElement().setAttribute("disabled", ""); + } + } + + @Override + public void showCommandLine(String commandLine) { commandLabel.setText(commandLine); } @Override - public void printPreviewUrl(String previewUrl) { + public void showPreviewUrl(String previewUrl) { if (Strings.isNullOrEmpty(previewUrl)) { hidePreview(); } else { @@ -112,7 +264,7 @@ public class OutputConsoleViewImpl extends Composite implements OutputConsoleVie } @Override - public void print(String message, boolean cr) { + public void print(String text, boolean cr) { if (carriageReturn) { Node lastChild = consoleLines.getElement().getLastChild(); if (lastChild != null) { @@ -123,7 +275,7 @@ public class OutputConsoleViewImpl extends Composite implements OutputConsoleVie carriageReturn = cr; PreElement pre = DOM.createElement("pre").cast(); - pre.setInnerText(message.isEmpty() ? " " : message); + pre.setInnerText(text.isEmpty() ? " " : text); consoleLines.getElement().appendChild(pre); followOutput(); @@ -133,6 +285,10 @@ public class OutputConsoleViewImpl extends Composite implements OutputConsoleVie public void onScroll(ScrollEvent event) { // Do nothing if content height less scroll area height if (scrollPanel.getElement().getScrollHeight() < scrollPanel.getElement().getOffsetHeight()) { + followOutput = true; + if (delegate != null) { + delegate.onOutputScrolled(followOutput); + } return; } @@ -142,6 +298,10 @@ public class OutputConsoleViewImpl extends Composite implements OutputConsoleVie } else { followOutput = false; } + + if (delegate != null) { + delegate.onOutputScrolled(followOutput); + } } /** @@ -155,6 +315,7 @@ public class OutputConsoleViewImpl extends Composite implements OutputConsoleVie /** Scroll bottom immediately if view is visible */ if (scrollPanel.getElement().getOffsetParent() != null) { scrollPanel.scrollToBottom(); + scrollPanel.scrollToLeft(); return; } @@ -172,6 +333,7 @@ public class OutputConsoleViewImpl extends Composite implements OutputConsoleVie if (scrollPanel.getElement().getOffsetParent() != null) { scrollPanel.scrollToBottom(); + scrollPanel.scrollToLeft(); followScheduled = false; return false; } diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleViewImpl.ui.xml b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleViewImpl.ui.xml index 97c163ff96..f452a299fe 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleViewImpl.ui.xml +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/outputspanel/console/OutputConsoleViewImpl.ui.xml @@ -16,7 +16,82 @@ - .background { + + /** + * Toolbar on the left with buttons. + */ + .toolbar { + overflow: hidden; + background-color: consolesToolbarBackground; + border-right: 1px solid colsolesToolbarBorderColor; + position: absolute; + overflow: hidden; + } + + .toolbarButton { + width: 14px; + height: 14px; + margin-left: 2px; + margin-top: 4px; + cursor: pointer; + font-size: 9px; + line-height: 17px; + font-family: "Droid Sans Mono", monospace; + text-align: center; + font-weight: normal; + overflow: hidden; + color: consolesToolbarButtonColor; + opacity: 0.8; + + position: relative; + } + + .wrapTextButton { + position: absolute; + left: 0px; + bottom: 22px; + } + + .scrollToEndButton { + position: absolute; + left: 0px; + bottom: 4px; + } + + .toolbarButton > svg { + position: absolute; + left: 3px; + top: 3px; + } + + .toolbarButton:HOVER { + color: consolesToolbarHoveredButtonColor; + opacity: 1; + } + + .toolbarButton:ACTIVE { + color: white; + } + + .toolbarButton[toggled] { + opacity: 1; + background: consolesToolbarToggledButtonColor; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5); + } + + .toolbarButton[disabled], + .toolbarButton[disabled]:HOVER, + .toolbarButton[disabled]:ACTIVE { + opacity: 0.4; + color: consolesToolbarDisabledButtonColor; + background-color: transparent; + cursor: default; + } + + /** + * Header with command line and preview URL. + */ + .header { background-color: editorPanelBackgroundColor; -webkit-user-select: none; user-select: none; @@ -59,41 +134,74 @@ margin: 0; } - .commandConsole { + /** + * Console output area. + */ + .consolePanel { background-color: outputBackgroundColor; + border-top: 1px solid separatorColor; + position: absolute; + overflow: hidden; + } + + .console { + color: outputFontColor; + -moz-user-select: text; -webkit-user-select: text; user-select: text; - color: outputFontColor; outline: none; - border-top: 1px solid separatorColor; - -webkit-box-shadow: outputBoxShadow; - -moz-box-shadow: outputBoxShadow; - box-shadow: outputBoxShadow; - padding: 1px 3px 3px 3px; - margin-bottom: 3px; + + padding: 1px 3px 3px 0px; + + border-left: 6px solid transparent; + box-sizing: border-box; + border-top: 2px solid transparent; + + overflow: auto; + position: absolute!important; + left: 0px; + top: 0px; + right: 0px; + bottom: 0px; } - .commandConsole pre { + .console pre { font-family: outputFontFamily; - font-size: fontSize; + font-size: consoleFontSize; + line-height: consoleLineHeight; } - .commandConsoleLines { + .consoleLines { width: 100%; } - .commandConsoleLines > pre { - word-wrap: break-word; + .consoleLines > pre { width: inherit; padding: 0; margin: 0; } + + .consoleLines[wrap] > pre { + white-space: pre-wrap; + word-break: break-all; + word-wrap: break-word; + } + + + + + + + + + + - + - - + + - - - + + + + + diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenter.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenter.java index a94e1f4213..b0304d8cd6 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenter.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenter.java @@ -48,8 +48,6 @@ import org.eclipse.che.ide.extension.machine.client.outputspanel.console.Command import org.eclipse.che.ide.extension.machine.client.outputspanel.console.CommandOutputConsole; import org.eclipse.che.ide.extension.machine.client.outputspanel.console.DefaultOutputConsole; import org.eclipse.che.ide.extension.machine.client.perspective.terminal.TerminalPresenter; -import org.eclipse.che.ide.extension.machine.client.processes.event.ProcessFinishedEvent; -import org.eclipse.che.ide.extension.machine.client.processes.event.ProcessFinishedHandler; import org.eclipse.che.ide.api.dialogs.ConfirmCallback; import org.eclipse.che.ide.api.dialogs.DialogFactory; import org.eclipse.che.ide.util.loging.Log; @@ -79,7 +77,7 @@ import static org.eclipse.che.ide.extension.machine.client.processes.ProcessTree @Singleton public class ConsolesPanelPresenter extends BasePresenter implements ConsolesPanelView.ActionDelegate, HasView, - ProcessFinishedHandler, + ProcessFinishedEvent.Handler, OutputConsole.ConsoleOutputListener, WorkspaceStoppedHandler, MachineStateEvent.Handler { diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/event/ProcessFinishedEvent.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ProcessFinishedEvent.java similarity index 65% rename from plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/event/ProcessFinishedEvent.java rename to plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ProcessFinishedEvent.java index 680a410c47..f8c5180cb2 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/event/ProcessFinishedEvent.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ProcessFinishedEvent.java @@ -8,16 +8,24 @@ * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ -package org.eclipse.che.ide.extension.machine.client.processes.event; +package org.eclipse.che.ide.extension.machine.client.processes; +import com.google.gwt.event.shared.EventHandler; import com.google.gwt.event.shared.GwtEvent; /** * @author Dmitry Shnurenko */ -public class ProcessFinishedEvent extends GwtEvent { +public class ProcessFinishedEvent extends GwtEvent { - public static final Type TYPE = new Type<>(); + public interface Handler extends EventHandler { + + /** Implement this method to handle ProcessFinishedEvent. */ + void onProcessFinished(ProcessFinishedEvent event); + + } + + public static final Type TYPE = new Type<>(); private final String processID; @@ -30,12 +38,12 @@ public class ProcessFinishedEvent extends GwtEvent { } @Override - public Type getAssociatedType() { + public Type getAssociatedType() { return TYPE; } @Override - protected void dispatch(ProcessFinishedHandler handler) { + protected void dispatch(Handler handler) { handler.onProcessFinished(this); } diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ProcessTreeRenderer.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ProcessTreeRenderer.java index d1b8126dab..1d68afb898 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ProcessTreeRenderer.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/ProcessTreeRenderer.java @@ -298,7 +298,6 @@ public class ProcessTreeRenderer implements NodeRenderer { return stopProcessButton; } - @Override public void updateNodeContents(TreeNodeElement treeNode) { } diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/event/ProcessFinishedHandler.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/event/ProcessFinishedHandler.java deleted file mode 100644 index 9e12c452e0..0000000000 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/processes/event/ProcessFinishedHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012-2016 Codenvy, S.A. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Codenvy, S.A. - initial API and implementation - *******************************************************************************/ -package org.eclipse.che.ide.extension.machine.client.processes.event; - -import com.google.gwt.event.shared.EventHandler; - -/** - * @author Dmitry Shnurenko - */ -public interface ProcessFinishedHandler extends EventHandler { - - /**Performs some actions when process finished or cancelled by reason of error.*/ - void onProcessFinished(ProcessFinishedEvent event); - -} diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/MachineLocalizationConstant.properties b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/MachineLocalizationConstant.properties index fc4f0f7385..25b4fd8f2d 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/MachineLocalizationConstant.properties +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/MachineLocalizationConstant.properties @@ -168,6 +168,12 @@ view.machine.running.tooltip=Machine is running view.stop.process.tooltip=Stop process view.close.processOutput.tooltip=Close +consoles.reRunButton.tooltip=Re-run +consoles.stopButton.tooltip=Stop +consoles.clearOutputsButton.tooltip=Clear outputs +consoles.wrapTextButton.tooltip=Wrap the text +consoles.autoScrollButton.tooltip=Scroll to bottom automatically + failed.to.execute.command=Failed to execute command failed.to.create.recipe=Failed to create recipe failed.to.save.recipe=Failed to save recipe diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/clear-outputs.svg b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/clear-outputs.svg new file mode 100644 index 0000000000..4754975c35 --- /dev/null +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/clear-outputs.svg @@ -0,0 +1,20 @@ + + + + + + + + + \ No newline at end of file diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/line-wrap.svg b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/line-wrap.svg new file mode 100644 index 0000000000..ecb0727d9e --- /dev/null +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/line-wrap.svg @@ -0,0 +1,20 @@ + + + + + + + + + \ No newline at end of file diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/re-run.svg b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/re-run.svg new file mode 100644 index 0000000000..65eee19e42 --- /dev/null +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/re-run.svg @@ -0,0 +1,19 @@ + + + + + + + + \ No newline at end of file diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/scroll-to-bottom.svg b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/scroll-to-bottom.svg new file mode 100644 index 0000000000..5259fff6e7 --- /dev/null +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/scroll-to-bottom.svg @@ -0,0 +1,20 @@ + + + + + + + + + \ No newline at end of file diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/stop.svg b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/stop.svg new file mode 100644 index 0000000000..d41eb0d904 --- /dev/null +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/resources/org/eclipse/che/ide/extension/machine/client/images/process/stop.svg @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/test/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenterTest.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/test/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenterTest.java index ef28920480..3c638698b3 100644 --- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/test/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenterTest.java +++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/test/java/org/eclipse/che/ide/extension/machine/client/processes/ConsolesPanelPresenterTest.java @@ -45,7 +45,6 @@ import org.eclipse.che.ide.extension.machine.client.machine.Machine; import org.eclipse.che.ide.extension.machine.client.outputspanel.console.CommandConsoleFactory; import org.eclipse.che.ide.extension.machine.client.outputspanel.console.CommandOutputConsole; import org.eclipse.che.ide.extension.machine.client.perspective.terminal.TerminalPresenter; -import org.eclipse.che.ide.extension.machine.client.processes.event.ProcessFinishedEvent; import org.eclipse.che.ide.api.dialogs.DialogFactory; import org.eclipse.che.ide.api.dialogs.ConfirmDialog; import org.junit.Before;