/******************************************************************************* * 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.ext.java.client.refactoring.preview; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Tree; import com.google.gwt.user.client.ui.TreeItem; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionModel; import com.google.gwt.view.client.SingleSelectionModel; import com.google.inject.Inject; import com.google.inject.Singleton; import org.eclipse.che.commons.annotation.Nullable; import org.eclipse.che.ide.api.theme.Style; import org.eclipse.che.ide.api.theme.ThemeAgent; import org.eclipse.che.ide.ext.java.client.JavaLocalizationConstant; import org.eclipse.che.ide.ext.java.shared.dto.refactoring.ChangePreview; import org.eclipse.che.ide.ext.java.shared.dto.refactoring.RefactoringPreview; import org.eclipse.che.ide.ext.java.shared.dto.refactoring.RefactoringStatus; import org.eclipse.che.ide.ext.java.shared.dto.refactoring.RefactoringStatusEntry; import org.eclipse.che.ide.orion.compare.CompareConfig; import org.eclipse.che.ide.orion.compare.CompareFactory; import org.eclipse.che.ide.orion.compare.CompareWidget; import org.eclipse.che.ide.orion.compare.FileOptions; import org.eclipse.che.ide.ui.loaders.request.LoaderFactory; import org.eclipse.che.ide.ui.window.Window; import javax.validation.constraints.NotNull; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.google.gwt.dom.client.Style.Float.LEFT; import static com.google.gwt.dom.client.Style.Unit.PX; import static org.eclipse.che.ide.api.theme.Style.getEditorSelectionColor; /** * @author Dmitry Shnurenko * @author Valeriy Svydenko */ @Singleton final class PreviewViewImpl extends Window implements PreviewView { interface PreviewViewImplUiBinder extends UiBinder<Widget, PreviewViewImpl> { } private static final PreviewViewImplUiBinder UI_BINDER = GWT.create(PreviewViewImplUiBinder.class); @UiField(provided = true) final JavaLocalizationConstant locale; @UiField SimplePanel diff; @UiField FlowPanel diffPanelToHide; @UiField SimplePanel noPreviewToHide; @UiField VerticalPanel treePanel; @UiField Label errorLabel; private ActionDelegate delegate; private FileOptions newFile; private FileOptions oldFile; private CompareWidget compare; private ThemeAgent themeAgent; private final LoaderFactory loaderFactory; private final CompareFactory compareFactory; private Map<TreeItem, RefactoringPreview> containerChanges = new HashMap<>(); private Element selectedElement; @Inject public PreviewViewImpl(JavaLocalizationConstant locale, LoaderFactory loaderFactory, CompareFactory compareFactory, ThemeAgent themeAgent) { this.locale = locale; this.loaderFactory = loaderFactory; this.compareFactory = compareFactory; this.themeAgent = themeAgent; setTitle(locale.moveDialogTitle()); setWidget(UI_BINDER.createAndBindUi(this)); Button backButton = createButton(locale.moveDialogButtonBack(), "preview-back-button", new ClickHandler() { @Override public void onClick(ClickEvent event) { delegate.onBackButtonClicked(); } }); Button cancelButton = createButton(locale.moveDialogButtonCancel(), "preview-cancel-button", new ClickHandler() { @Override public void onClick(ClickEvent event) { hide(); delegate.onCancelButtonClicked(); } }); Button acceptButton = createButton(locale.moveDialogButtonOk(), "preview-ok-button", new ClickHandler() { @Override public void onClick(ClickEvent event) { delegate.onAcceptButtonClicked(); } }); addButtonToFooter(acceptButton); addButtonToFooter(cancelButton); addButtonToFooter(backButton); diff.getElement().setId(Document.get().createUniqueId()); showDiff(null); } /** {@inheritDoc} */ @Override public void setDelegate(ActionDelegate delegate) { this.delegate = delegate; } /** {@inheritDoc} */ @Override public void show() { errorLabel.setText(""); diff.clear(); compare = null; treePanel.clear(); containerChanges.clear(); super.show(); } /** {@inheritDoc} */ @Override protected void onClose() { delegate.onCancelButtonClicked(); super.onClose(); } /** {@inheritDoc} */ @Override public void setTreeOfChanges(final RefactoringPreview changes) { showDiffPanel(false); final SelectionModel<RefactoringPreview> selectionModel = new SingleSelectionModel<>(); selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { @Override public void onSelectionChange(SelectionChangeEvent event) { RefactoringPreview selectedNode = (RefactoringPreview)((SingleSelectionModel)selectionModel).getSelectedObject(); delegate.onSelectionChanged(selectedNode); } }); Tree tree = new Tree(); tree.getElement().setId("tree-of-changes"); for (RefactoringPreview parentChange : changes.getChildrens()) { TreeItem treeItem = new TreeItem(); containerChanges.put(treeItem, parentChange); createTreeElement(treeItem, parentChange.getText(), parentChange.getChildrens()); tree.addItem(treeItem); } tree.addSelectionHandler(new SelectionHandler<TreeItem>() { @Override public void onSelection(SelectionEvent<TreeItem> event) { if (selectedElement != null) { selectedElement.getStyle().setProperty("background", "transparent"); } selectedElement = event.getSelectedItem().getWidget().getElement(); selectedElement.getStyle().setProperty("background", getEditorSelectionColor()); } }); treePanel.add(tree); } private void createTreeElement(final TreeItem root, String changeName, List<RefactoringPreview> children) { FlowPanel element = new FlowPanel(); element.getElement().getStyle().setFloat(LEFT); CheckBox itemCheckBox = new CheckBox(); itemCheckBox.setValue(true); itemCheckBox.getElement().getStyle().setFloat(LEFT); itemCheckBox.getElement().getStyle().setMarginTop(3, PX); Label name = new Label(changeName); name.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { delegate.onSelectionChanged(containerChanges.get(root)); root.setSelected(true); } }); name.getElement().getStyle().setFloat(LEFT); element.add(itemCheckBox); element.add(name); root.setWidget(element); element.getElement().getParentElement().getStyle().setMargin(1, PX); itemCheckBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() { @Override public void onValueChange(ValueChangeEvent<Boolean> event) { checkChildrenState(root, event.getValue()); checkParentState(root, event.getValue()); RefactoringPreview change = containerChanges.get(root); change.setEnabled(event.getValue()); delegate.onEnabledStateChanged(change); } }); if (children.isEmpty()) { return; } for (RefactoringPreview child : children) { TreeItem treeItem = new TreeItem(); containerChanges.put(treeItem, child); createTreeElement(treeItem, child.getText(), child.getChildrens()); root.addItem(treeItem); } } private void checkParentState(TreeItem treeItem, Boolean value) { TreeItem parentItem = treeItem.getParentItem(); if (parentItem == null) { return; } if (!(parentItem.getWidget() instanceof FlowPanel)) { return; } FlowPanel parentChangeContainer = (FlowPanel)parentItem.getWidget(); if (!(parentChangeContainer.getWidget(0) instanceof CheckBox)) { return; } CheckBox parentCheckBox = (CheckBox)parentChangeContainer.getWidget(0); if (value && !parentCheckBox.getValue()) { parentCheckBox.setValue(true); checkParentState(parentItem, true); } } private void checkChildrenState(TreeItem treeItem, Boolean value) { int childCount = treeItem.getChildCount(); if (childCount == 0) { return; } for (int i = 0; i < childCount; i++) { TreeItem childItem = treeItem.getChild(i); if (!(childItem.getWidget() instanceof FlowPanel)) { return; } FlowPanel childItemContainer = (FlowPanel)childItem.getWidget(); if (!(childItemContainer.getWidget(0) instanceof CheckBox)) { return; } CheckBox childCheckBox = (CheckBox)childItemContainer.getWidget(0); childCheckBox.setValue(value); checkChildrenState(childItem, value); } } private void showDiffPanel(boolean isVisible) { diffPanelToHide.setVisible(isVisible); noPreviewToHide.setVisible(!isVisible); } /** {@inheritDoc} */ @Override public void showErrorMessage(RefactoringStatus status) { errorLabel.getElement().getStyle().setColor(Style.getErrorColor()); showMessage(status); } /** {@inheritDoc} */ @Override public void showDiff(@Nullable ChangePreview preview) { if (preview == null) { showDiffPanel(false); } else { showDiffPanel(true); if (compare == null) { prepareDiffEditor(preview); return; } refreshComperingFiles(preview); compare.reload(); } } private void refreshComperingFiles(@NotNull ChangePreview preview) { newFile.setContent(preview.getNewContent()); newFile.setName(preview.getFileName()); oldFile.setContent(preview.getOldContent()); oldFile.setName(preview.getFileName()); } private void prepareDiffEditor(@NotNull ChangePreview preview) { newFile = compareFactory.createFieOptions(); newFile.setReadOnly(true); oldFile = compareFactory.createFieOptions(); oldFile.setReadOnly(true); refreshComperingFiles(preview); CompareConfig compareConfig = compareFactory.createCompareConfig(); compareConfig.setNewFile(newFile); compareConfig.setOldFile(oldFile); compareConfig.setShowTitle(true); compareConfig.setShowLineStatus(true); compare = new CompareWidget(compareConfig, themeAgent.getCurrentThemeId(), loaderFactory); diff.add(compare); } private void showMessage(RefactoringStatus status) { RefactoringStatusEntry statusEntry = getEntryMatchingSeverity(status.getSeverity(), status.getEntries()); if (statusEntry != null) { errorLabel.setText(statusEntry.getMessage()); } else { errorLabel.setText(""); } } /** * Returns the first entry which severity is equal or greater than the * given severity. If more than one entry exists that matches the * criteria the first one is returned. Returns <code>null</code> if no * entry matches. * * @param severity * the severity to search for. Must be one of <code>FATAL * </code>, <code>ERROR</code>, <code>WARNING</code> or <code>INFO</code> * @param entries * list of the refactoring status entries * @return the entry that matches the search criteria */ private RefactoringStatusEntry getEntryMatchingSeverity(int severity, List<RefactoringStatusEntry> entries) { for (RefactoringStatusEntry entry : entries) { if (entry.getSeverity() >= severity) return entry; } return null; } }