/* * 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; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.xwiki.gwt.user.client.Cache; import org.xwiki.gwt.user.client.Config; import org.xwiki.gwt.user.client.Console; import org.xwiki.gwt.user.client.ui.ToolBar; import org.xwiki.gwt.user.client.ui.rta.RichTextArea; import org.xwiki.gwt.wysiwyg.client.plugin.PluginManager; import org.xwiki.gwt.wysiwyg.client.plugin.UIExtension; import org.xwiki.gwt.wysiwyg.client.plugin.separator.ToolBarSeparator; import org.xwiki.gwt.wysiwyg.client.syntax.SyntaxValidator; import com.google.gwt.user.client.ui.Widget; /** * {@link ToolBar} controller. * * @version $Id: 1a747a610af329ab14c90e28cb610cba38ec2abc $ */ public class ToolBarController { /** * The string used to identify the tool bar extension point. */ public static final String TOOLBAR_ROLE = "toolbar"; /** * The list of features this controller will attempt to place on the tool bar by default if the configuration * doesn't specify the tool bar features. */ public static final String DEFAULT_TOOLBAR_FEATURES = "bold italic underline strikethrough teletype | subscript superscript" + " | justifyleft justifycenter justifyright justifyfull | unorderedlist orderedlist | outdent indent" + " | undo redo | format | fontname fontsize forecolor backcolor | hr removeformat symbol"; /** * The underlying tool bar that is managed by this object. */ private final ToolBar toolBar; /** * The features that have been placed on the tool bar. The key is the feature name and the value is the widget that * has been placed on the tool bar. */ private final Map<String, UIExtension> toolBarFeatures = new HashMap<String, UIExtension>(); /** * Creates a new tool bar controller. * * @param toolBar the tool bar to be managed */ public ToolBarController(ToolBar toolBar) { this.toolBar = toolBar; } /** * Fills the tool bar with the features specified in the configuration. * * @param config the configuration object * @param pluginManager the object used to access the tool bar {@link UIExtension}s */ public void fill(Config config, PluginManager pluginManager) { toolBar.clear(); toolBarFeatures.clear(); for (String featureName : split(config.getParameter(TOOLBAR_ROLE, DEFAULT_TOOLBAR_FEATURES), pluginManager)) { UIExtension extension = pluginManager.getUIExtension(TOOLBAR_ROLE, featureName); toolBarFeatures.put(featureName, extension); toolBar.add((Widget) extension.getUIObject(featureName)); } } /** * Updates the tool bar state, i.e. disables/enables tool bar features, based on the given set of rules and the * current state of the rich text area. * * @param richTextArea the rich text area whose state is used to determine if a feature must be enabled or disabled * @param syntaxValidator the object used to assert if a feature must be enabled or disabled in the current state of * the rich text area */ public void update(RichTextArea richTextArea, SyntaxValidator syntaxValidator) { Cache selectionCache = new Cache(richTextArea.getElement()); selectionCache.clear(false); for (Map.Entry<String, UIExtension> entry : toolBarFeatures.entrySet()) { try { entry.getValue().setEnabled(entry.getKey(), syntaxValidator.isValid(entry.getKey(), richTextArea)); } catch (Exception e) { Console.getInstance().error(e, "Failed to update tool bar: " + entry.getKey()); } } selectionCache.clear(true); } /** * Splits a string representing the tool bar feature list into its components, i.e. feature names, and removes * useless separators (e.g. to avoid empty lines or empty groups) and unavailable features. * * @param toolBar a string listing the tool bar features separated by {@link ToolBarSeparator#VERTICAL_BAR} or * {@link ToolBarSeparator#LINE_BREAK} * @param pluginManager the object used to check which tool bar features are available * @return the list of available tool bar features in the order they appear on the tool bar */ public List<String> split(String toolBar, PluginManager pluginManager) { List<String> features = new ArrayList<String>(); String[] toolBarFeatureNames = toolBar.split("\\s+"); boolean pendingLineBreak = false; boolean pendingGroupEnd = false; for (int i = 0; i < toolBarFeatureNames.length; i++) { String featureName = toolBarFeatureNames[i]; UIExtension uie = pluginManager.getUIExtension(TOOLBAR_ROLE, featureName); if (uie == null) { continue; } else if (ToolBarSeparator.VERTICAL_BAR.equals(featureName)) { pendingGroupEnd = features.size() > 0; } else if (ToolBarSeparator.LINE_BREAK.equals(featureName)) { pendingLineBreak = features.size() > 0; } else { if (pendingLineBreak) { features.add(ToolBarSeparator.LINE_BREAK); } else if (pendingGroupEnd) { features.add(ToolBarSeparator.VERTICAL_BAR); } pendingLineBreak = false; pendingGroupEnd = false; features.add(featureName); } } return features; } /** * Destroys this tool bar controller. */ public void destroy() { toolBarFeatures.clear(); } }