/*
* 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.macro.exec;
import java.util.Collections;
import org.xwiki.gwt.user.client.Console;
import org.xwiki.gwt.user.client.ui.LoadingPanel;
import org.xwiki.gwt.user.client.ui.rta.Reloader;
import org.xwiki.gwt.user.client.ui.rta.RichTextArea;
import org.xwiki.gwt.user.client.ui.rta.SelectionPreserver;
import org.xwiki.gwt.user.client.ui.rta.cmd.Command;
import org.xwiki.gwt.user.client.ui.rta.cmd.CommandManager;
import org.xwiki.gwt.user.client.ui.rta.cmd.internal.AbstractSelectionExecutable;
import com.google.gwt.user.client.rpc.AsyncCallback;
/**
* Refreshes all the macros present on the edited document.
*
* @version $Id: fd62a5773382a7a81b6e6212ece0d21367c2d7df $
*/
public class RefreshExecutable extends AbstractSelectionExecutable implements AsyncCallback<Object>
{
/**
* The command used to notify all the plug-ins that the content of the rich text area is about to be submitted.
*/
private static final Command SUBMIT = new Command("submit");
/**
* The command used to notify all the rich text area listeners when its content has been reset.
*/
private static final Command RESET = new Command("reset");
/**
* Used to prevent typing in the rich text area while waiting for the updated content from the server.
*/
private final LoadingPanel waiting = new LoadingPanel();
/**
* The object used to reload the rich text area.
*/
private final Reloader reloader;
/**
* The object used to restore the default selection after the rich text area content is reloaded.
*/
private final SelectionPreserver selectionPreserver;
/**
* Creates a new executable that can be used to refresh the specified rich text area. We use a {@link Reloader} to
* submit the content of the rich text area to the given URL and then use the response to reset the content of the
* rich text area.
*
* @param rta the execution target
* @param url the URL to take the content from
*/
public RefreshExecutable(RichTextArea rta, String url)
{
super(rta);
reloader = new Reloader(rta, url);
selectionPreserver = new SelectionPreserver(rta);
}
@Override
public boolean execute(String param)
{
// Check if there is a refresh in progress.
if (waiting.isLoading()) {
return false;
}
// Prevent typing while waiting for the updated content.
waiting.startLoading(rta);
waiting.setFocus(true);
// Request the updated content.
CommandManager cmdManager = rta.getCommandManager();
refresh(cmdManager.execute(SUBMIT) ? cmdManager.getStringValue(SUBMIT) : rta.getHTML());
return true;
}
/**
* Sends a request to the server to parse and re-render the content of the given rich text area.
*
* @param html the HTML content of the rich text area
*/
private void refresh(String html)
{
reloader.reload(Collections.singletonMap("html", html), this);
}
@Override
public void onFailure(Throwable caught)
{
Console.getInstance().error(caught.getLocalizedMessage());
// Try to focus the rich text area.
rta.setFocus(true);
waiting.stopLoading();
}
@Override
public void onSuccess(Object result)
{
// Restore the default selection.
// Note: We haven't saved the selection before reloading the content because the current implementation of
// SelectionPreserver can't save the selection across reloads: it stores references to DOM nodes which are
// replaced after the content is reloaded. We use the selection preserver just to be able to restore the default
// selection in a consistent manner (without duplicating code).
selectionPreserver.restoreSelection();
// Reset the content of the rich text area.
rta.getCommandManager().execute(RESET);
// Store the initial value of the rich text area in case it is submitted without gaining focus.
rta.getCommandManager().execute(SUBMIT, true);
// Try to focus the rich text area.
rta.setFocus(true);
waiting.stopLoading();
}
}