/******************************************************************************* * Copyright (c) 2012-2015 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.part.editor; import org.eclipse.che.ide.api.constraints.Constraints; import org.eclipse.che.ide.api.editor.EditorPartPresenter; import org.eclipse.che.ide.api.editor.EditorWithErrors; import org.eclipse.che.ide.api.event.ProjectActionEvent; import org.eclipse.che.ide.api.event.ProjectActionHandler; import org.eclipse.che.ide.api.parts.EditorPartStack; import org.eclipse.che.ide.api.parts.PartPresenter; import org.eclipse.che.ide.api.parts.PartStackView; import org.eclipse.che.ide.api.parts.PropertyListener; import org.eclipse.che.ide.api.project.tree.VirtualFile; import org.eclipse.che.ide.collections.Array; import org.eclipse.che.ide.collections.Collections; import org.eclipse.che.ide.texteditor.openedfiles.ListOpenedFilesPresenter; import org.eclipse.che.ide.part.PartStackPresenter; import org.eclipse.che.ide.util.loging.Log; import com.google.gwt.core.client.Scheduler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.web.bindery.event.shared.EventBus; import org.vectomatic.dom.svg.ui.SVGImage; import org.vectomatic.dom.svg.ui.SVGResource; /** * EditorPartStackPresenter is a special PartStackPresenter that is shared among all * Perspectives and used to display Editors. * * @author Nikolay Zamosenchuk * @author Stéphane Daviet */ @Singleton public class EditorPartStackPresenter extends PartStackPresenter implements EditorPartStack, ShowListButtonClickHandler { private ListOpenedFilesPresenter listOpenedFilesPresenter; private interface CloseTabCallback { void onTabsClosed(); } @Inject public EditorPartStackPresenter(final EditorPartStackView view, EventBus eventBus, PartStackEventHandler partStackEventHandler, ListOpenedFilesPresenter listOpenedFilesPresenter) { super(eventBus, partStackEventHandler, view, null); partsClosable = true; this.listOpenedFilesPresenter = listOpenedFilesPresenter; view.setShowListButtonHandler(this); eventBus.addHandler(ProjectActionEvent.TYPE, new ProjectActionHandler() { @Override public void onProjectOpened(ProjectActionEvent event) { //do nothing } @Override public void onProjectClosed(ProjectActionEvent event) { if (!parts.isEmpty()) { close(activePart, new CloseTabCallback() { @Override public void onTabsClosed() { closeActivePart(this); } }); } } }); } /** {@inheritDoc} */ @Override public void addPart(PartPresenter part, Constraints constraint) { addPart(part); } /** {@inheritDoc} */ @Override public void addPart(PartPresenter part) { if (!(part instanceof EditorPartPresenter)) { Log.warn(getClass(), "EditorPartStack is not intended to be used to open non-Editor Parts."); } if (parts.contains(part)) { // part already exists // activate it setActivePart(part); // and return return; } parts.add(part); part.addPropertyListener(propertyListener); // include close button SVGResource titleSVGResource = part.getTitleSVGImage(); SVGImage titleSVGImage = null; if (titleSVGResource != null) { titleSVGImage = part.decorateIcon(new SVGImage(titleSVGResource)); } PartStackView.TabItem tabItem = view.addTab(titleSVGImage, part.getTitle(), part.getTitleToolTip(), null, partsClosable); if (part instanceof EditorWithErrors) { final EditorWithErrors presenter = ((EditorWithErrors)part); final TabItemWithMarks tab = (TabItemWithMarks)tabItem; part.addPropertyListener(new PropertyListener() { @Override public void propertyChanged(PartPresenter source, int propId) { if (presenter.getErrorState() != null) { if (presenter.getErrorState().equals(EditorWithErrors.EditorState.ERROR)) { tab.setErrorMark(true); } else { tab.setErrorMark(false); } if (presenter.getErrorState().equals(EditorWithErrors.EditorState.WARNING)) { tab.setWarningMark(true); } else { tab.setWarningMark(false); } } } }); } bindEvents(tabItem, part); part.go(partViewContainer); setActivePart(part); } /** {@inheritDoc} */ @Override public void setActivePart(PartPresenter part) { if (!(part instanceof EditorPartPresenter)) { Log.warn(getClass(), "EditorPartStack is not intended to be used to open non-Editor Parts."); } if (activePart == part) { return; } activePart = part; if (part == null) { view.setActiveTab(-1); } else { view.setActiveTab(parts.indexOf(activePart)); } // request part stack to get the focus onRequestFocus(); } /*close active part and do action from callBack*/ protected void closeActivePart(final CloseTabCallback closeTabCallback) { if (activePart != null) { close(activePart, closeTabCallback); } else { Log.warn(getClass(), "No active part"); } } /** {@inheritDoc} */ @Override protected void close(final PartPresenter part) { close(part, null); } /*close tab and do action from callBack*/ protected void close(final PartPresenter part, final CloseTabCallback closeTabCallback) { part.onClose(new AsyncCallback<Void>() { @Override public void onFailure(Throwable throwable) { } @Override public void onSuccess(Void aVoid) { view.removeTab(parts.indexOf(part)); parts.remove(part); part.removePropertyListener(propertyListener); if (activePart == part) { //select another part setActivePart(parts.isEmpty() ? null : parts.get(parts.size() - 1)); Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { @Override public void execute() { if (closeTabCallback != null) { closeTabCallback.onTabsClosed(); } } }); } } }); } /** {@inheritDoc} */ @Override public void onShowListClicked(int x, int y, AsyncCallback<Void> callback) { Array<VirtualFile> openedFiles = Collections.createArray(); for (PartPresenter part : getParts().asIterable()) { if (part instanceof EditorPartPresenter) { openedFiles.add(((EditorPartPresenter)part).getEditorInput().getFile()); } } listOpenedFilesPresenter.showDialog(openedFiles, x, y, callback); } @Override protected void sortPartsOnView(Constraints constraint) { } }