/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xwiki.gwt.wysiwyg.client.plugin.image.ui; import java.util.List; import org.xwiki.gwt.user.client.StringUtils; import org.xwiki.gwt.user.client.ui.VerticalResizePanel; import org.xwiki.gwt.user.client.ui.wizard.NavigationListener; import org.xwiki.gwt.user.client.ui.wizard.SourcesNavigationEvents; import org.xwiki.gwt.wysiwyg.client.Strings; import org.xwiki.gwt.wysiwyg.client.plugin.image.ImageConfig; import org.xwiki.gwt.wysiwyg.client.widget.PageSelector; import org.xwiki.gwt.wysiwyg.client.widget.SpaceSelector; import org.xwiki.gwt.wysiwyg.client.widget.WikiSelector; import org.xwiki.gwt.wysiwyg.client.widget.wizard.util.AbstractSelectorWizardStep; import org.xwiki.gwt.wysiwyg.client.wiki.AttachmentReference; import org.xwiki.gwt.wysiwyg.client.wiki.EntityLink; import org.xwiki.gwt.wysiwyg.client.wiki.EntityReference; import org.xwiki.gwt.wysiwyg.client.wiki.EntityReference.EntityType; import org.xwiki.gwt.wysiwyg.client.wiki.WikiPageReference; import org.xwiki.gwt.wysiwyg.client.wiki.WikiServiceAsync; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Panel; /** * Wizard step to explore and select images from all the pages in the wiki. * * @version $Id: e4423e468b91ea642baee6fc80d03d86e97994c4 $ */ public class ImagesExplorerWizardStep extends AbstractSelectorWizardStep<EntityLink<ImageConfig>> implements ChangeHandler, SourcesNavigationEvents { /** * Loading class for the time to load the step to which it has been toggled. */ private static final String STYLE_LOADING = "loading"; /** * Selector for the wiki to get images from. */ private WikiSelector wikiSelector; /** * Selector for the space to get images from. */ private SpaceSelector spaceSelector; /** * Selector for the page to get images from. */ private PageSelector pageSelector; /** * Flag to mark whether this explorer should show the selector to choose an image from a different wiki or not. */ private boolean displayWikiSelector; /** * The image selector for the currently selected page in this wizard step. This will be instantiated every time the * list of pages for a selected page needs to be displayed, and the functionality of this aggregator will be * delegated to it. */ private CurrentPageImageSelectorWizardStep pageWizardStep; /** * The service used to access the wiki. */ private final WikiServiceAsync wikiService; /** * Builds an image explorer with the default selection on the passed resource. * * @param displayWikiSelector whether this explorer should show the selector to choose an image from a different * wiki or not * @param wikiService the service used to access the wiki */ public ImagesExplorerWizardStep(boolean displayWikiSelector, WikiServiceAsync wikiService) { super(new VerticalResizePanel()); this.wikiService = wikiService; setStepTitle(Strings.INSTANCE.imageSelectImageTitle()); Label helpLabel = new Label(Strings.INSTANCE.imageSelectImageLocationHelpLabel()); helpLabel.addStyleName("xHelpLabel"); display().add(helpLabel); // initialize selectors, mainPanel display().addStyleName("xImagesExplorer"); this.displayWikiSelector = displayWikiSelector; display().add(getSelectorsPanel()); pageWizardStep = new CurrentPageImageSelectorWizardStep(wikiService, true); display().add(pageWizardStep.display()); display().setExpandingWidget(pageWizardStep.display(), true); } /** * @return the panel with the selectors to choose the source for the attachments panel */ private Panel getSelectorsPanel() { // create selectors for the page to get images from FlowPanel selectorsPanel = new FlowPanel(); if (displayWikiSelector) { wikiSelector = new WikiSelector(wikiService); wikiSelector.addChangeHandler(this); selectorsPanel.add(wikiSelector); } spaceSelector = new SpaceSelector(wikiService); spaceSelector.addChangeHandler(this); selectorsPanel.add(spaceSelector); pageSelector = new PageSelector(wikiService); selectorsPanel.add(pageSelector); Button updateImagesListButton = new Button(Strings.INSTANCE.imageUpdateListButton()); updateImagesListButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { WikiPageReference originPage = new WikiPageReference(getData().getOrigin()); AttachmentReference imageReferenceTemplate = new AttachmentReference(); imageReferenceTemplate.getWikiPageReference().setWikiName( displayWikiSelector ? wikiSelector.getSelectedWiki() : originPage.getWikiName()); imageReferenceTemplate.getWikiPageReference().setSpaceName(spaceSelector.getSelectedSpace()); imageReferenceTemplate.getWikiPageReference().setPageName(pageSelector.getSelectedPage()); initCurrentPage(imageReferenceTemplate, null); } }); selectorsPanel.add(updateImagesListButton); selectorsPanel.addStyleName("xPageChooser"); return selectorsPanel; } /** * Refreshes the list of images with the images attached to the same page as the specified image, and then selects * the specified image. * * @param imageReference a reference to the image to be selected * @param cb the object to be notified after the specified image is selected */ public void setSelection(final AttachmentReference imageReference, final AsyncCallback< ? > cb) { if (displayWikiSelector) { setWikiSelection(imageReference, cb); } else { setSpaceSelection(imageReference, cb); } } /** * Sets the selected wiki based on the specified image and updates the space selector. * * @param imageReference the image to be selected * @param cb the object to be notified after the specified image is selected */ private void setWikiSelection(final AttachmentReference imageReference, final AsyncCallback< ? > cb) { wikiSelector.refreshList(imageReference.getWikiPageReference().getWikiName(), new AsyncCallback<List<String>>() { public void onSuccess(List<String> result) { setSpaceSelection(imageReference, cb); } public void onFailure(Throwable caught) { if (cb != null) { cb.onFailure(caught); } } }); } /** * Sets the selected space based on the specified image and updates the page selector. * * @param imageReference the image to be selected * @param cb the object to be notified after the specified image is selected */ private void setSpaceSelection(AttachmentReference imageReference, final AsyncCallback< ? > cb) { // Clone the image reference because we might modify it. See the next comment. final AttachmentReference actualImageReference = imageReference.clone(); WikiPageReference wikiPageReference = actualImageReference.getWikiPageReference(); spaceSelector.setWiki(displayWikiSelector ? wikiSelector.getSelectedWiki() : wikiPageReference.getWikiName()); // Replace the image reference components that point to missing entities with the entities selected by default. // In this case, if the image reference points to a wiki that doesn't exist then we update the image reference // to use the wiki selected by default. wikiPageReference.setWikiName(spaceSelector.getWiki()); spaceSelector.refreshList(wikiPageReference.getSpaceName(), new AsyncCallback<List<String>>() { public void onSuccess(List<String> result) { setPageSelection(actualImageReference, cb); } public void onFailure(Throwable caught) { if (cb != null) { cb.onFailure(caught); } } }); } /** * Sets the selected page based on the specified image and updates the list of images accordingly. * * @param imageReference the image to be selected * @param cb the object to be notified after the specified image is selected */ private void setPageSelection(final AttachmentReference imageReference, final AsyncCallback< ? > cb) { pageSelector.setWiki(spaceSelector.getWiki()); pageSelector.setSpace(spaceSelector.getSelectedSpace()); // Replace the image reference components that point to missing entities with the entities selected by default. // In this case, if the image reference points to a space that doesn't exist then we update the image reference // to use the space selected by default. imageReference.getWikiPageReference().setSpaceName(pageSelector.getSpace()); pageSelector.refreshList(imageReference.getWikiPageReference().getPageName(), new AsyncCallback<List<String>>() { public void onSuccess(List<String> result) { // Replace the image reference components that point to missing entities with the entities selected by // default. In this case, if the image reference points to a page that doesn't exist then we update the // image reference to use the page selected by default. imageReference.getWikiPageReference().setPageName(pageSelector.getSelectedPage()); initCurrentPage(imageReference, cb); } public void onFailure(Throwable caught) { if (cb != null) { cb.onFailure(caught); } } }); } @Override public void onChange(ChangeEvent event) { if (event.getSource() == wikiSelector) { spaceSelector.setWiki(wikiSelector.getSelectedWiki()); spaceSelector.refreshList(spaceSelector.getSelectedSpace(), new AsyncCallback<List<String>>() { @Override public void onFailure(Throwable caught) { } @Override public void onSuccess(List<String> result) { pageSelector.setWiki(wikiSelector.getSelectedWiki()); pageSelector.setSpace(spaceSelector.getSelectedSpace()); pageSelector.refreshList(pageSelector.getSelectedPage()); } }); } else if (event.getSource() == spaceSelector) { pageSelector.setWiki(spaceSelector.getWiki()); pageSelector.setSpace(spaceSelector.getSelectedSpace()); pageSelector.refreshList(pageSelector.getSelectedPage()); } } /** * Initializes and displays list of images attached to the same page as the specified image, and selects the * specified image. * * @param imageReference a reference to the image to be selected after the list of images is updated * @param cb the object to be notified after the list of images is updated */ protected void initCurrentPage(AttachmentReference imageReference, final AsyncCallback< ? > cb) { display().addStyleName(STYLE_LOADING); getData().getDestination().setEntityReference(imageReference.getEntityReference()); pageWizardStep.init(getData(), new AsyncCallback<Object>() { public void onSuccess(Object result) { onCurrenPageInitialization(); if (cb != null) { cb.onSuccess(null); } } public void onFailure(Throwable caught) { if (cb != null) { cb.onFailure(caught); } else { showCurrentPageInitializationError(); } } }); } /** * Helper function to handle the error on current page initialization: display an error message in the reserved * panel. */ private void showCurrentPageInitializationError() { display().removeStyleName(STYLE_LOADING); Label error = new Label(Strings.INSTANCE.linkErrorLoadingData()); error.addStyleName("errormessage"); display().remove(pageWizardStep.display()); display().add(error); } /** * Helper function to handle the success on initialization of the current page wizard step. */ private void onCurrenPageInitialization() { // if the current page's display is not there (maybe an error before removed it), remove the error and add if (display().getWidgetIndex(pageWizardStep.display()) < 0) { // FIXME: the error panel shouldn't be identified by its position! display().remove(display().getWidgetCount() - 1); display().add(pageWizardStep.display()); } display().removeStyleName(STYLE_LOADING); } @Override public VerticalResizePanel display() { return (VerticalResizePanel) super.display(); } @Override public String getNextStep() { return pageWizardStep.getNextStep(); } @Override protected void initializeSelection(AsyncCallback< ? > cb) { if (!StringUtils.isEmpty(getData().getData().getReference()) && getData().getDestination().getEntityReference().getType() == EntityType.ATTACHMENT) { // Edit internal image. setSelection(new AttachmentReference(getData().getDestination().getEntityReference()), cb); } else if (pageSelector.getSelectedPage() == null) { // Insert image. No page selected so initialize the list of images. setSelection(new AttachmentReference(getData().getOrigin()), cb); } else { // Insert image. There is a previous selection, preserve it and re-initialize the list of images. EntityReference destinationReference = pageWizardStep.getData().getDestination().getEntityReference(); initCurrentPage(new AttachmentReference(destinationReference), cb); } } @Override public void onCancel() { pageWizardStep.onCancel(); } @Override public void onSubmit(AsyncCallback<Boolean> async) { pageWizardStep.onSubmit(async); } @Override public void addNavigationListener(NavigationListener listener) { pageWizardStep.addNavigationListener(listener); } @Override public void removeNavigationListener(NavigationListener listener) { pageWizardStep.removeNavigationListener(listener); } @Override public void setActive() { if (displayWikiSelector) { wikiSelector.setFocus(true); } else { spaceSelector.setFocus(true); } } @Override public Object getResult() { return pageWizardStep.getResult(); } }