/* * 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.gadget; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import org.xwiki.gwt.dom.client.JavaScriptObject; import org.xwiki.gwt.user.client.Config; import org.xwiki.gwt.user.client.internal.DefaultConfig; import org.xwiki.gwt.user.client.ui.wizard.Wizard; import org.xwiki.gwt.user.client.ui.wizard.WizardListener; import org.xwiki.gwt.user.client.ui.wizard.WizardStepMap; import org.xwiki.gwt.user.client.ui.wizard.NavigationListener.NavigationDirection; import org.xwiki.gwt.wysiwyg.client.Images; import org.xwiki.gwt.wysiwyg.client.Strings; import org.xwiki.gwt.wysiwyg.client.plugin.macro.MacroCall; import org.xwiki.gwt.wysiwyg.client.plugin.macro.MacroService; import org.xwiki.gwt.wysiwyg.client.plugin.macro.MacroServiceAsync; import org.xwiki.gwt.wysiwyg.client.plugin.macro.MacroServiceAsyncCacheProxy; import org.xwiki.gwt.wysiwyg.client.plugin.macro.ui.EditMacroWizardStep; import org.xwiki.gwt.wysiwyg.client.plugin.macro.ui.SelectMacroWizardStep; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.ui.Image; /** * The Gadget Wizard, along with its javascript API, allowing to create macros insert and edit wizards, to be used as * gadget wizards. The javascript API allows this wizard to be used from javascript outside the WYSiWYG (e.g. the * dashboard). * * @version $Id: 863f48727cdabc1cab66388dd9b82ed1289f0f4a $ * @since 3.0M3 */ public class GadgetWizardApi implements WizardListener { /** * The name of the edit gadget wizard step. */ private static final String EDIT_STEP_NAME = "edit"; /** * The name of the select gadget wizard step. */ private static final String SELECT_STEP_NAME = "select"; /** * The magic wand used to start the potion to create a macro call from user input. */ private Wizard insertWizard; /** * The magic wand used to transform the macros in other things. */ private Wizard editWizard; /** * The object used to configure this wizard. */ private final Config config; /** * The macro service used to retrieve macro descriptors. */ private final MacroServiceAsync macroService; /** * The javascript callback called when the insert is done. */ private JavaScriptObject insertCallback; /** * The javascript callback called when the edit is done. */ private JavaScriptObject editCallback; /** * Creates a new gadget wizard. * * @deprecated: Since 7.0M2. Use {@link #GadgetWizardApi(JavaScriptObject)} instead */ @Deprecated public GadgetWizardApi() { this(JavaScriptObject.fromJson("{syntax:'xwiki/2.0'}")); } /** * Creates a new gadget wizard. * * @param jsConfig the {@link JavaScriptObject} used to configure the newly created gadget */ public GadgetWizardApi(JavaScriptObject jsConfig) { this.config = new DefaultConfig(jsConfig); this.macroService = new MacroServiceAsyncCacheProxy((MacroServiceAsync) GWT.create(MacroService.class)); } /** * Starts the insert wizard, which will guide the user into choosing a macro and defining its parameters. */ public void insert() { // Compute the list of macros inserted in the edited document. List<String> usedMacroIds = new ArrayList<String>(); // Cast the spell. getInsertWizard().start(SELECT_STEP_NAME, usedMacroIds); } /** * Sets the native js insert callback to be called when the insert wizard is done. * * @param insertHandler the native js callback to call when the insert wizard is finished successfully. */ public void setInsertCallback(JavaScriptObject insertHandler) { this.insertCallback = insertHandler; } /** * Handles the call of the js callback when the insert is done. * * @param macroCall the macro call used as a content of this gadget * @param gadgetTitle the title of the gadget */ protected native void onInsertDone(String macroCall, String gadgetTitle) /*-{ var insertCallback = this.@org.xwiki.gwt.wysiwyg.client.gadget.GadgetWizardApi::insertCallback; if (typeof insertCallback == 'function') { var result = {'title' : gadgetTitle, 'content' : macroCall}; insertCallback(result); } }-*/; /** * Starts the edit wizard, to edit the specified macro call. * * @param macroCall the macro call to edit, passed as a html comment from the annotated syntax. * @param title the title of the gadget to edit */ public void edit(String macroCall, String title) { GadgetInstance gadgetInstance = new GadgetInstance(); gadgetInstance.setMacroCall(new MacroCall(macroCall)); gadgetInstance.setTitle(title); getEditWizard().start(EDIT_STEP_NAME, gadgetInstance); } /** * Sets the native js edit callback to be called when the edit wizard is done. * * @param editHandler the native js callback to call when the edit wizard is finished successfully. */ public void setEditCallback(JavaScriptObject editHandler) { this.editCallback = editHandler; } /** * Handles the call of the js callback when the edit is done. * * @param macroCall the new macro call used as a content of the edited gadget * @param gadgetTitle the title of the gadget */ protected native void onEditDone(String macroCall, String gadgetTitle) /*-{ var editCallback = this.@org.xwiki.gwt.wysiwyg.client.gadget.GadgetWizardApi::editCallback; if (typeof editCallback == 'function') { var result = {'title' : gadgetTitle, 'content' : macroCall}; editCallback(result); } }-*/; @Override public void onCancel(Wizard sender) { // nothing } @Override public void onFinish(Wizard sender, Object result) { if (sender == getInsertWizard()) { GadgetInstance gadgetResult = (GadgetInstance) result; this.onInsertDone(gadgetResult.getMacroCall().toString(), gadgetResult.getTitle()); } if (sender == getEditWizard()) { GadgetInstance gadgetResult = (GadgetInstance) result; this.onEditDone(gadgetResult.getMacroCall().toString(), gadgetResult.getTitle()); } } /** * @return {@link #insertWizard} */ private Wizard getInsertWizard() { if (insertWizard == null) { // create a gadgets select step SelectMacroWizardStep selectStep = new SelectGadgetWizardStep(config, macroService); selectStep.setNextStep(EDIT_STEP_NAME); selectStep.setValidDirections(EnumSet.of(NavigationDirection.NEXT)); selectStep.setDirectionName(NavigationDirection.NEXT, Strings.INSTANCE.select()); // and a gadgets parameters edit step EditMacroWizardStep editStep = new EditGadgetWizardStep(config, macroService); editStep.setDirectionName(NavigationDirection.FINISH, Strings.INSTANCE.gadgetInsertActionLabel()); editStep.setValidDirections(EnumSet.of(NavigationDirection.PREVIOUS, NavigationDirection.FINISH)); // ... and put them all together in a wizard WizardStepMap insertSteps = new WizardStepMap(); insertSteps.put(SELECT_STEP_NAME, selectStep); insertSteps.put(EDIT_STEP_NAME, editStep); insertWizard = new Wizard(Strings.INSTANCE.gadgetInsertDialogCaption(), new Image(Images.INSTANCE.macroInsert())); insertWizard.setProvider(insertSteps); insertWizard.addWizardListener(this); } return insertWizard; } /** * @return {@link #editWizard} */ private Wizard getEditWizard() { if (editWizard == null) { EditMacroWizardStep editStep = new EditGadgetWizardStep(config, macroService); editStep.setDirectionName(NavigationDirection.FINISH, Strings.INSTANCE.gadgetInsertActionLabel()); editStep.setValidDirections(EnumSet.of(NavigationDirection.FINISH)); WizardStepMap editSteps = new WizardStepMap(); editSteps.put(EDIT_STEP_NAME, editStep); editWizard = new Wizard(Strings.INSTANCE.gadgetEditDialogCaption(), new Image(Images.INSTANCE.macroEdit())); editWizard.setProvider(editSteps); editWizard.addWizardListener(this); } return editWizard; } /** * Destroy this wizard. */ public void destroy() { if (insertWizard != null) { insertWizard.removeWizardListener(this); insertWizard.onDirection(NavigationDirection.CANCEL); insertWizard = null; } if (editWizard != null) { editWizard.removeWizardListener(this); editWizard.onDirection(NavigationDirection.CANCEL); editWizard = null; } } /** * Publishes the JavaScript API that can be used to create and control {@link GadgetWizardApi}s. */ public static native void publish() /*-{ $wnd.XWiki = $wnd.XWiki || {} // Attach the Gadget wizard $wnd.XWiki.GadgetWizard = function(config) { // Make sure we always have a config passed, even if an empty/default one, for backwards compatibility. if (typeof config != 'object') { config = { syntax : 'xwiki/2.0' }; } this.instance = @org.xwiki.gwt.wysiwyg.client.gadget.GadgetWizardApi::new(Lorg/xwiki/gwt/dom/client/JavaScriptObject;)(config); } // attach the add function, which will start the insert wizard $wnd.XWiki.GadgetWizard.prototype.add = function(onComplete) { this.instance.@org.xwiki.gwt.wysiwyg.client.gadget.GadgetWizardApi::setInsertCallback(Lorg/xwiki/gwt/dom/client/JavaScriptObject;)(onComplete); this.instance.@org.xwiki.gwt.wysiwyg.client.gadget.GadgetWizardApi::insert()(); } // attach the edit function, which will start the edit wizard $wnd.XWiki.GadgetWizard.prototype.edit = function(macroCall, macroTitle, onComplete) { this.instance.@org.xwiki.gwt.wysiwyg.client.gadget.GadgetWizardApi::setEditCallback(Lorg/xwiki/gwt/dom/client/JavaScriptObject;)(onComplete); this.instance.@org.xwiki.gwt.wysiwyg.client.gadget.GadgetWizardApi::edit(Ljava/lang/String;Ljava/lang/String;)(macroCall, macroTitle); } }-*/; }