/*******************************************************************************
* 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.plugin.svn.ide.commit;
import elemental.dom.Element;
import elemental.dom.Node;
import elemental.events.MouseEvent;
import elemental.html.TableCellElement;
import elemental.html.TableElement;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
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.CheckBox;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Singleton;
import org.eclipse.che.plugin.svn.ide.SubversionExtensionLocalizationConstants;
import org.eclipse.che.plugin.svn.ide.SubversionExtensionResources;
import org.eclipse.che.plugin.svn.shared.StatusItem;
import org.eclipse.che.ide.ui.Tooltip;
import org.eclipse.che.ide.ui.list.SimpleList;
import org.eclipse.che.ide.ui.menu.PositionController;
import org.eclipse.che.ide.ui.window.Window;
import org.eclipse.che.ide.util.dom.Elements;
import org.eclipse.che.ide.util.dom.MouseGestureListener;
import org.vectomatic.dom.svg.OMSVGSVGElement;
import javax.inject.Inject;
import java.util.List;
/**
* Implementation of {@link CommitView}.
*
* @author Vladyslav Zhukovskyi
*/
@Singleton
public class CommitViewImpl extends Window implements CommitView {
interface CommitViewImplUiBinder extends UiBinder<Widget, CommitViewImpl> {
}
private static CommitViewImplUiBinder uiBinder = GWT.create(CommitViewImplUiBinder.class);
private ActionDelegate delegate;
@UiField(provided = true)
SubversionExtensionLocalizationConstants locale;
@UiField(provided = true)
SubversionExtensionResources resources;
@UiField
RadioButton commitAll;
@UiField
RadioButton commitSelection;
@UiField
CheckBox keepLocks;
@UiField
TextArea message;
@UiField
ScrollPanel changesWrapper;
@UiField
Label changedFilesCount;
private SimpleList<StatusItem> changesList;
private Button btnCommit;
private OMSVGSVGElement alertMarker;
private static final String PLACEHOLDER = "placeholder";
private static final String ADDED = org.eclipse.che.ide.api.theme.Style.getVcsConsoleStagedFilesColor();
private static final String CONFLICTED = org.eclipse.che.ide.api.theme.Style.getVcsConsoleErrorColor();
private static final String DELETED = org.eclipse.che.ide.api.theme.Style.getVcsConsoleErrorColor();
private static final String MODIFIED = org.eclipse.che.ide.api.theme.Style.getVcsConsoleModifiedFilesColor();
private static final String REPLACED = org.eclipse.che.ide.api.theme.Style.getVcsConsoleModifiedFilesColor();
private static final String DEFAULT = org.eclipse.che.ide.api.theme.Style.getMainFontColor();
@Inject
public CommitViewImpl(final SubversionExtensionLocalizationConstants constants,
final SubversionExtensionResources resources,
final Window.Resources windowResources,
org.eclipse.che.ide.Resources coreRes) {
this.locale = constants;
this.resources = resources;
this.setTitle(locale.commitTitle());
this.setWidget(uiBinder.createAndBindUi(this));
Button btnCancel = createButton(locale.buttonCancel(), "svn-commit-cancel", new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
delegate.onCancelClicked();
}
});
btnCommit = createButton(locale.buttonCommit(), "svn-commit-commit", new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
delegate.onCommitClicked();
}
});
addButtonToFooter(btnCancel);
addButtonToFooter(btnCommit);
btnCommit.setEnabled(false);
SimpleList.ListEventDelegate<StatusItem> listChangesDelegate = new SimpleList.ListEventDelegate<StatusItem>() {
/** {@inheritDoc} */
@Override
public void onListItemClicked(Element listItemBase, StatusItem itemData) {
//stub
}
/** {@inheritDoc} */
@Override
public void onListItemDoubleClicked(Element listItemBase, StatusItem itemData) {
//stub
}
};
TableElement changesElement = Elements.createTableElement();
changesElement.setAttribute("style", "width: 100%; background: none;");
changesElement.setCellSpacing("1px");
changesList = SimpleList.create((SimpleList.View)changesElement, coreRes.defaultSimpleListCss(), new ChangesListRenderer(),
listChangesDelegate);
changesWrapper.add(changesList);
message.getElement().setAttribute(PLACEHOLDER, locale.commitPlaceholder());
alertMarker = resources.alert().getSvg();
alertMarker.getStyle().setWidth(22, Style.Unit.PX);
alertMarker.getStyle().setHeight(22, Style.Unit.PX);
alertMarker.getStyle().setMarginTop(5, Style.Unit.PX);
getFooter().getElement().appendChild(alertMarker.getElement());
Tooltip.create((elemental.dom.Element)alertMarker.getElement(),
PositionController.VerticalAlign.TOP,
PositionController.HorizontalAlign.MIDDLE,
locale.commitMessageEmpty());
alertMarker.getStyle().setVisibility(Style.Visibility.VISIBLE);
}
/** {@inheritDoc} */
@Override
public void onClose() {
hide();
}
/** {@inheritDoc} */
@Override
public void setDelegate(final ActionDelegate delegate) {
this.delegate = delegate;
}
/** {@inheritDoc} */
@Override
public void onShow() {
commitAll.setValue(true);
commitSelection.setValue(false);
show();
}
/** {@inheritDoc} */
@Override
public String getMessage() {
return this.message.getText();
}
/** {@inheritDoc} */
@Override
public boolean isKeepLocksStateSelected() {
return keepLocks.getValue();
}
/** {@inheritDoc} */
@Override
public boolean isCommitAllSelected() {
return commitAll.getValue();
}
/** {@inheritDoc} */
@Override
public boolean isCommitSelectionSelected() {
return commitSelection.getValue();
}
/** {@inheritDoc} */
@Override
public void setChangesList(List<StatusItem> changes) {
changesList.render(changes);
changedFilesCount.setText(String.valueOf(changes.size()));
}
@UiHandler("message")
@SuppressWarnings("unused")
public void onMessageChanged(KeyUpEvent event) {
btnCommit.setEnabled(!message.getText().isEmpty());
alertMarker.getStyle().setVisibility(!message.getText().isEmpty() ? Style.Visibility.HIDDEN : Style.Visibility.VISIBLE);
}
@UiHandler({"commitAll", "commitSelection"})
@SuppressWarnings("unused")
public void onCommitModeChanged(ClickEvent event) {
delegate.onCommitModeChanged();
}
private class ChangesListRenderer extends SimpleList.ListItemRenderer<StatusItem> {
/** {@inheritDoc} */
@Override
public void render(Element listItemBase, StatusItem itemData) {
Node changedItemStatusNote = getChangedItemStatus(itemData);
Node changedItemPath = getChangedItemPath(itemData);
Node changedItemDiffLink = getChangedItemDiffLink(itemData);
listItemBase.appendChild(changedItemStatusNote);
listItemBase.appendChild(changedItemPath);
listItemBase.appendChild(changedItemDiffLink);
}
/** {@inheritDoc} */
@Override
public Element createElement() {
return Elements.createTRElement();
}
private Node getChangedItemStatus(StatusItem item) {
TableCellElement htmlNode = Elements.createTDElement();
htmlNode.setInnerText(item.getFileState().getValue());
htmlNode.setWidth("16px");
htmlNode.setAlign("center");
htmlNode.getStyle().setPaddingTop("3px");
htmlNode.getStyle().setFontSize("11px");
return htmlNode;
}
private Node getChangedItemPath(StatusItem item) {
final String[] pathElements = item.getPath().split("/");
final StringBuilder sb = new StringBuilder();
//append file name
sb.append("<span style=\"color:")
.append(getChangedItemColor(item))
.append("\">")
.append(new SafeHtmlBuilder().appendEscaped(pathElements[pathElements.length - 1]).toSafeHtml().asString())
.append("</span>");
//append path
if (pathElements.length > 1) {
String rawPath = item.getPath().substring(0, item.getPath().length() - pathElements[pathElements.length - 1].length() - 1);
String escapedPath = new SafeHtmlBuilder().appendEscaped(rawPath).toSafeHtml().asString();
sb.append(" <span>(");
sb.append(escapedPath);
sb.append(")</span>");
}
final String html = sb.toString();
TableCellElement htmlNode = Elements.createTDElement();
htmlNode.setInnerHTML(html);
htmlNode.getStyle().setProperty("max-width", "200px");
htmlNode.getStyle().setProperty("text-overflow", "ellipsis");
return htmlNode;
}
private Node getChangedItemDiffLink(final StatusItem item) {
Button showDiff = new Button();
showDiff.setText("Diff");
TableCellElement htmlNode = Elements.createTDElement();
htmlNode.appendChild((Element)showDiff.getElement());
htmlNode.setWidth("1px");
if (!(item.getFileState() == StatusItem.FileState.MODIFIED
|| item.getFileState() == StatusItem.FileState.DELETED
|| item.getFileState() == StatusItem.FileState.CONFLICTED)) {
showDiff.setEnabled(false);
Tooltip.create((Element)showDiff.getElement(),
PositionController.VerticalAlign.MIDDLE,
PositionController.HorizontalAlign.LEFT,
locale.commitDiffUnavailable());
}
MouseGestureListener.createAndAttach((Element)showDiff.getElement(), new MouseGestureListener.Callback() {
/** {@inheritDoc} */
@Override
public boolean onClick(int clickCount, MouseEvent event) {
delegate.showDiff(item.getPath());
return false;
}
/** {@inheritDoc} */
@Override
public void onDrag(MouseEvent event) {
//stub
}
/** {@inheritDoc} */
@Override
public void onDragRelease(MouseEvent event) {
//stub
}
});
return htmlNode;
}
private String getChangedItemColor(StatusItem item) {
switch (item.getFileState()) {
case ADDED:
return ADDED;
case CONFLICTED:
return CONFLICTED;
case DELETED:
return DELETED;
case MODIFIED:
return MODIFIED;
case REPLACED:
return REPLACED;
default:
return DEFAULT;
}
}
}
}