This patch was partially provided by Marcela Mihai, I changed it where needed
and completed it.
Sorry I forgot to mention it in the svn comment, as appropriate.
Happy coding,
Anca Luca
lucaa (SVN) wrote:
Author: lucaa
Date: 2008-11-12 23:17:54 +0100 (Wed, 12 Nov 2008)
New Revision: 14184
Added:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkGenerator.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/AbstractHasLinkTab.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/EnterListener.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/HasLink.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkDialog.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToEmailAddressTab.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToWebPageTab.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/CreateLinkExecutable.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/UnlinkExecutable.java
Modified:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/editor/Strings.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/editor/WysiwygEditorFactory.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkPlugin.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/syntax/internal/DefaultSyntaxValidator.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/Command.java
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/DefaultCommandManager.java
platform/web/trunk/wysiwyg/src/main/resources/com/xpn/xwiki/wysiwyg/client/editor/Strings.properties
platform/web/trunk/wysiwyg/src/main/resources/com/xpn/xwiki/wysiwyg/public/Wysiwyg.css
Log:
XWIKI-2826: Create links to external addresses
* Created the link plugin with link and unlink features.
* Added command to create a wikilink and remove a wiklink from the wysiwyg html
* Added the link plugin ui: dialogs to get links information from the user, just for
external addresses ftm
* Added a link generator class, to generate the wikilink html from the user data
Modified:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/editor/Strings.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/editor/Strings.java 2008-11-12
19:52:43 UTC (rev 14183)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/editor/Strings.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -82,8 +82,6 @@
String justifyRight();
- String link();
-
String macro();
String normal();
@@ -114,5 +112,29 @@
String undo();
+ String link();
+
String unlink();
+
+ String linkCreateLinkButon();
+
+ String linkEmailTab();
+
+ String linkWebPageTab();
+
+ String linkLabelLabel();
+
+ String linkWebPageLabel();
+
+ String linkEmailLabel();
+
+ String linkEmailAddressTextBox();
+
+ String linkWebPageTextBox();
+
+ String linkEmailAddressError();
+
+ String linkWebPageAddressError();
+
+ String linkNoLabelError();
}
Modified:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/editor/WysiwygEditorFactory.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/editor/WysiwygEditorFactory.java 2008-11-12
19:52:43 UTC (rev 14183)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/editor/WysiwygEditorFactory.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -27,6 +27,7 @@
import com.xpn.xwiki.wysiwyg.client.plugin.indent.IndentPluginFactory;
import com.xpn.xwiki.wysiwyg.client.plugin.internal.DefaultPluginFactoryManager;
import com.xpn.xwiki.wysiwyg.client.plugin.justify.JustifyPluginFactory;
+import com.xpn.xwiki.wysiwyg.client.plugin.link.LinkPluginFactory;
import com.xpn.xwiki.wysiwyg.client.plugin.list.ListPluginFactory;
import com.xpn.xwiki.wysiwyg.client.plugin.separator.SeparatorPluginFactory;
import com.xpn.xwiki.wysiwyg.client.plugin.symbol.SymbolPluginFactory;
@@ -69,6 +70,7 @@
pfm.addPluginFactory(ColorPluginFactory.getInstance());
pfm.addPluginFactory(SyncPluginFactory.getInstance());
pfm.addPluginFactory(SymbolPluginFactory.getInstance());
+ pfm.addPluginFactory(LinkPluginFactory.getInstance());
pfm.addPluginFactory(TablePluginFactory.getInstance());
// add additional PluginFactory for other plug-ins
}
Added:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkGenerator.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkGenerator.java
(rev 0)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkGenerator.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -0,0 +1,74 @@
+/*
+ * 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 com.xpn.xwiki.wysiwyg.client.plugin.link;
+
+/**
+ * Generates html link blocks for all types of links.
+ * @version $Id$
+ */
+public final class LinkGenerator
+{
+ /**
+ * The singleton instance of this class.
+ */
+ private static LinkGenerator instance;
+
+ /**
+ * Class constructor, private so that the class is a singleton.
+ */
+ private LinkGenerator()
+ {
+ }
+
+ /**
+ * @return the instance of this class.
+ */
+ public static synchronized LinkGenerator getInstance()
+ {
+ if (instance == null) {
+ instance = new LinkGenerator();
+ }
+ return instance;
+ }
+
+ /**
+ * Generates link to an external url (web page or email address).
+ *
+ * @param label link label
+ * @param externalURL external url to link to
+ * @return the html link block.
+ */
+ public String getExternalLink(String label, String externalURL)
+ {
+ // <!--startwikilink:http://xwiki.org-->
+ // <span class="wikiexternallink">
+ // <a href="http://xwiki.org">label</a>
+ // </span>
+ // <!--stopwikilink-->
+
+ // <!--startwikilink:mailto:john@doe.com-->
+ // <span class="wikiexternallink">
+ // <a href="mailto:john@doe.com">label</a>
+ // </span>
+ // <!--stopwikilink-->
+ return "<!--startwikilink:" + externalURL + "--><span
class=\"wikiexternallink\"><a href=\"" + externalURL
+ + "\">" + label +
"</a></span><!--stopwikilink-->";
+ }
+}
Modified:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkPlugin.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkPlugin.java 2008-11-12
19:52:43 UTC (rev 14183)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/LinkPlugin.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -27,15 +27,45 @@
import com.xpn.xwiki.wysiwyg.client.editor.Strings;
import com.xpn.xwiki.wysiwyg.client.plugin.internal.AbstractPlugin;
import com.xpn.xwiki.wysiwyg.client.plugin.internal.FocusWidgetUIExtension;
+import com.xpn.xwiki.wysiwyg.client.plugin.link.ui.LinkDialog;
import com.xpn.xwiki.wysiwyg.client.util.Config;
+import com.xpn.xwiki.wysiwyg.client.widget.PopupListener;
+import com.xpn.xwiki.wysiwyg.client.widget.SourcesPopupEvents;
import com.xpn.xwiki.wysiwyg.client.widget.rta.RichTextArea;
+import com.xpn.xwiki.wysiwyg.client.widget.rta.SelectionPreserver;
+import com.xpn.xwiki.wysiwyg.client.widget.rta.cmd.Command;
-public class LinkPlugin extends AbstractPlugin implements ClickListener
+/**
+ * Rich text editor plug-in for inserting links, using a dialog to get link settings
from the user. It installs two
+ * buttons in the toolbar, for its two actions: link and unlink.
+ *
+ * @version $Id$
+ */
+public class LinkPlugin extends AbstractPlugin implements ClickListener, PopupListener
{
+ /**
+ * The button from the toolbar for create a link.
+ */
private PushButton link;
+ /**
+ * The button from the toolbar for destroy a link.
+ */
private PushButton unlink;
+ /**
+ * The dialog for create a link.
+ */
+ private LinkDialog linkDialog;
+
+ /**
+ * Selection preserver to store the selection before and after the dialog showing.
+ */
+ private SelectionPreserver selectionPreserver;
+
+ /**
+ * The toolbar extension used to add the link buttons to the toolbar.
+ */
private final FocusWidgetUIExtension toolBarExtension = new
FocusWidgetUIExtension("toolbar");
/**
@@ -47,15 +77,23 @@
{
super.init(wysiwyg, textArea, config);
- link = new PushButton(Images.INSTANCE.link().createImage(), this);
- link.setTitle(Strings.INSTANCE.link());
- toolBarExtension.addFeature("link", link);
+ if (getTextArea().getCommandManager().isSupported(Command.CREATE_LINK)) {
+ link = new PushButton(Images.INSTANCE.link().createImage(), this);
+ link.setTitle(Strings.INSTANCE.link());
+ toolBarExtension.addFeature("link", link);
+ }
- unlink = new PushButton(Images.INSTANCE.unlink().createImage(), this);
- unlink.setTitle(Strings.INSTANCE.unlink());
- toolBarExtension.addFeature("unlink", unlink);
+ if (getTextArea().getCommandManager().isSupported(Command.UNLINK)) {
+ unlink = new PushButton(Images.INSTANCE.unlink().createImage(), this);
+ unlink.setTitle(Strings.INSTANCE.unlink());
+ toolBarExtension.addFeature("unlink", unlink);
+ }
- getUIExtensionList().add(toolBarExtension);
+ if (toolBarExtension.getFeatures().length > 0) {
+ getTextArea().addClickListener(this);
+ getUIExtensionList().add(toolBarExtension);
+ selectionPreserver = new SelectionPreserver(textArea);
+ }
}
/**
@@ -65,16 +103,29 @@
*/
public void destroy()
{
- link.removeFromParent();
- link.removeClickListener(this);
- link = null;
+ if (link != null) {
+ link.removeFromParent();
+ link.removeClickListener(this);
+ link = null;
- unlink.removeFromParent();
- unlink.removeClickListener(this);
- unlink = null;
+ if (linkDialog != null) {
+ linkDialog.hide();
+ linkDialog.removeFromParent();
+ linkDialog.removePopupListener(this);
+ linkDialog = null;
+ }
+ }
- toolBarExtension.clearFeatures();
+ if (unlink != null) {
+ unlink.removeFromParent();
+ unlink.removeClickListener(this);
+ unlink = null;
+ }
+ if (toolBarExtension.getFeatures().length > 0) {
+ getTextArea().removeClickListener(this);
+ toolBarExtension.clearFeatures();
+ }
super.destroy();
}
@@ -86,19 +137,76 @@
public void onClick(Widget sender)
{
if (sender == link) {
- onLink();
+ onLink(true);
} else if (sender == unlink) {
onUnlink();
}
}
- public void onLink()
+ /**
+ * Depending on the passed parameter, the link dialog is displayed for the user to
create a link or the created link
+ * is inserted in the document.
+ *
+ * @param show true if the link dialog must be shown, false otherwise
+ */
+ public void onLink(boolean show)
{
- // TODO
+ if (show) {
+ // save the selection
+ selectionPreserver.saveSelection();
+ // setup the dialog data
+ // use only the first range in the user selection
+
getLinkDialog().setLabel(getTextArea().getDocument().getSelection().getRangeAt(0).toHTML(),
+ getTextArea().getDocument().getSelection().getRangeAt(0).toString());
+ // show the dialog
+ getLinkDialog().center();
+ } else {
+ // restore selection, to be sure to execute the command on the right
selection
+ selectionPreserver.restoreSelection();
+ String url = getLinkDialog().getLink();
+ if (url != null) {
+ getTextArea().getCommandManager().execute(Command.CREATE_LINK, url);
+ // restore the selection once again to select the inserted text
+ selectionPreserver.restoreSelection();
+ } else {
+ // We get here if the link dialog has been closed by clicking the close
button.
+ // In this case we return the focus to the text area.
+ getTextArea().setFocus(true);
+ }
+ }
}
+ /**
+ * Executed when the unlink button is clicked.
+ */
public void onUnlink()
{
- // TODO
+ getTextArea().getCommandManager().execute(Command.UNLINK);
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see PopupListener#onPopupClosed(PopupPanel, boolean)
+ */
+ public void onPopupClosed(SourcesPopupEvents sender, boolean autoHide)
+ {
+ if (sender == getLinkDialog() && !autoHide) {
+ onLink(false);
+ }
+ }
+
+ /**
+ * Lazy creation of the link dialog, to optimize editor loading time.
+ *
+ * @return the link dialog to be used for inserting the link.
+ */
+ private LinkDialog getLinkDialog()
+ {
+ if (linkDialog == null) {
+ linkDialog = new LinkDialog();
+ linkDialog.addPopupListener(this);
+ }
+ return linkDialog;
+ }
}
Added:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/AbstractHasLinkTab.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/AbstractHasLinkTab.java
(rev 0)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/AbstractHasLinkTab.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -0,0 +1,200 @@
+/*
+ * 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 com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.ClickListenerCollection;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.TextBox;
+import com.xpn.xwiki.wysiwyg.client.editor.Strings;
+
+/**
+ * Abstract class to use as the superclass for the link generating tabs. Implements
basic functionality for the link
+ * tabs and stores basic data.
+ *
+ * @version $Id$
+ */
+public abstract class AbstractHasLinkTab extends Composite implements HasLink
+{
+ /**
+ * Click listeners for this click events source.
+ */
+ private final ClickListenerCollection clickListeners = new
ClickListenerCollection();
+
+ /**
+ * The result link string.
+ */
+ private String link;
+
+ /**
+ * The HTML string for the label of the link to be created.
+ */
+ private String labelHTML;
+
+ /**
+ * The text for the label of the link to be created (stripped of potential HTML
tags).
+ */
+ private String labelText;
+
+ /**
+ * The text box where the user will insert the text of the link to create (if any).
+ */
+ private TextBox labelTextBox = new TextBox();
+
+ /**
+ * @return the labelTextBox
+ */
+ protected TextBox getLabelTextBox()
+ {
+ return labelTextBox;
+ }
+
+ /**
+ * @param labelTextBox the labelTextBox to set
+ */
+ protected void setLabelTextBox(TextBox labelTextBox)
+ {
+ this.labelTextBox = labelTextBox;
+ }
+
+ /**
+ * Setter for the HTML link string generated by this widget.
+ *
+ * @param link the link to set to this widget.
+ */
+ protected void setLink(String link)
+ {
+ this.link = link;
+ }
+
+ /**
+ * @return the click listener collection of this click events source.
+ */
+ protected ClickListenerCollection getClickListeners()
+ {
+ return clickListeners;
+ }
+
+ /**
+ * Setter for value of field <i>labelHTML</i>.
+ *
+ * @param label the new value for <i>labelHTML</i>
+ */
+ protected void setLabelHTML(String label)
+ {
+ this.labelHTML = label;
+ }
+
+ /**
+ * @return the HTML of the label of the link to be generated by this widget.
+ */
+ protected String getLabelHTML()
+ {
+ return labelHTML;
+ }
+
+ /**
+ * @return the labelText
+ */
+ protected String getLabelText()
+ {
+ return labelText;
+ }
+
+ /**
+ * @param labelText the labelText to set
+ */
+ protected void setLabelText(String labelText)
+ {
+ this.labelText = labelText;
+ if (labelTextBox != null) {
+ labelTextBox.setText(labelText);
+ }
+ }
+
+ /**
+ * Sets the label for which this {@link HasLink} will generate the link HTML.
+ *
+ * @param labelHTML the label's HTML value
+ * @param labelText the label's text value
+ */
+ public void setLabel(String labelHTML, String labelText) {
+ setLabelHTML(labelHTML);
+ setLabelText(labelText);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see SourcesClickEvents#addClickListener(ClickListener)
+ */
+ public void addClickListener(ClickListener listener)
+ {
+ clickListeners.add(listener);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see SourcesClickEvents#removeClickListener(ClickListener)
+ */
+ public void removeClickListener(ClickListener listener)
+ {
+ clickListeners.remove(listener);
+ }
+
+ /**
+ * @return the url give by user.
+ */
+ public String getLink()
+ {
+ return link;
+ }
+
+ /**
+ * Get the label for the link to generate. If the label text was modified, use that
one, otherwise use the HTML
+ * label.
+ *
+ * @return the label for the link to generate.
+ */
+ protected String getLinkLabel()
+ {
+ if (this.labelTextBox.getText().trim().equals(this.getLabelText())) {
+ return getLabelHTML();
+ } else {
+ return this.labelTextBox.getText().trim();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean validateUserInput()
+ {
+ // the label cannot be void, for the moment
+ // TODO: find a way to allow void labels to be set and get the automatically
generated labels.
+ if (this.labelTextBox.getText().trim().length() == 0) {
+ Window.alert(Strings.INSTANCE.linkNoLabelError());
+ return false;
+ }
+ return true;
+ }
+}
Added:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/EnterListener.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/EnterListener.java
(rev 0)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/EnterListener.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -0,0 +1,62 @@
+/*
+ * 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 com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Keyboard listener adapter to be able to automatically click a button when the enter
key is pressed inside a
+ * {@link SourcesKeyboardEvents}.
+ *
+ * @version $Id$
+ */
+public class EnterListener extends KeyboardListenerAdapter
+{
+ /**
+ * The button which will be click when enter key will be press.
+ */
+ private Button button;
+
+ /**
+ * Class constructor.
+ *
+ * @param button which will be click when enter key will be press.
+ */
+ public EnterListener(Button button)
+ {
+ this.button = button;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see KeyboardListenerAdapter#onKeyPress(Widget, char, int)
+ */
+ public void onKeyPress(Widget sender, char c, int i)
+ {
+ super.onKeyPress(sender, c, i);
+ // Check if it's the enter key that has been pressed
+ if (c == 13) {
+ button.click();
+ }
+ }
+}
Added:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/HasLink.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/HasLink.java
(rev 0)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/HasLink.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -0,0 +1,49 @@
+/*
+ * 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 com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import com.google.gwt.user.client.ui.SourcesClickEvents;
+
+/**
+ * Interface for widgets that return a link html block from user input and are
clickable.
+ *
+ * @version $Id$
+ */
+public interface HasLink extends SourcesClickEvents
+{
+ /**
+ * Returns the link html block to use with the <i>create_link</i>
command.
+ *
+ * @return the link html block
+ */
+ String getLink();
+
+ /**
+ * Some setup need for the moment when the widget will be display.
+ */
+ void initialize();
+
+ /**
+ * Validates the user input for this widget, to be used for validation before the
link is created / returned.
+ *
+ * @return true if the user input for this widget is valid, false otherwise.
+ */
+ boolean validateUserInput();
+}
Added:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkDialog.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkDialog.java
(rev 0)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkDialog.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -0,0 +1,205 @@
+/*
+ * 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 com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.DeferredCommand;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.SourcesTabEvents;
+import com.google.gwt.user.client.ui.TabListener;
+import com.google.gwt.user.client.ui.TabPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.xpn.xwiki.wysiwyg.client.editor.Strings;
+import com.xpn.xwiki.wysiwyg.client.widget.CompositeDialogBox;
+
+/**
+ * Extends {@link com.xpn.xwiki.wysiwyg.client.widget.CompositeDialogBox}.
+ *
+ * @version $Id$
+ */
+public class LinkDialog extends CompositeDialogBox implements ClickListener,
TabListener
+{
+ /**
+ * Helper command to set the selection in this dialog to the stored selected.
+ */
+ private class SelectCommand implements Command
+ {
+ /**
+ * {@inheritDoc}
+ */
+ public void execute()
+ {
+ tabs.selectTab(selectedTabIndex);
+ }
+ }
+
+ /**
+ * Tabs to add to this dialog.
+ */
+ private final TabPanel tabs;
+
+ /**
+ * The tab to get the link to a web page.
+ */
+ private final LinkToWebPageTab linkToWebPageTab;
+
+ /**
+ * The tab to get the link to an email address.
+ */
+ private final LinkToEmailAddressTab linkToEmailAddressTab;
+
+ /**
+ * This variable contains the index of the selected tab.
+ */
+ private int selectedTabIndex;
+
+ /**
+ * True if the dialog is close by the close button, and false if the dialog is close
by <i>Create link</i> button.
+ */
+ private boolean closeByCreateLink;
+
+ /**
+ * Default constructor.
+ */
+ public LinkDialog()
+ {
+ super(false, true);
+ linkToWebPageTab = new LinkToWebPageTab();
+ linkToEmailAddressTab = new LinkToEmailAddressTab();
+
+ tabs = new TabPanel();
+ tabs.addTabListener(this);
+
+ addTab(linkToWebPageTab, Strings.INSTANCE.linkWebPageTab());
+ addTab(linkToEmailAddressTab, Strings.INSTANCE.linkEmailTab());
+ tabs.selectTab(0);
+ selectedTabIndex = 0;
+
+ getDialog().setText(Strings.INSTANCE.link());
+ getDialog().setAnimationEnabled(false);
+ getDialog().addStyleName("linkDialog");
+
+ initWidget(tabs);
+
+ // set the initial label HTML to void string, as if no selection was made.
+ setLabel("", "");
+ }
+
+ /**
+ * Sets the label for the link created by this dialog. This label has an HTML form
and a text form, the stripped
+ * version of the HTML version. If the text form is edited by the user, that label
will be used, otherwise the HTML
+ * version, with formatting.
+ *
+ * @param labelHTML the HTML of the label for the created link.
+ * @param labelText the text of the label for the created link (stripped of HTML
tags)
+ */
+ public void setLabel(String labelHTML, String labelText)
+ {
+ if (linkToWebPageTab != null) {
+ linkToWebPageTab.setLabel(labelHTML, labelText);
+ }
+ if (linkToEmailAddressTab != null) {
+ linkToEmailAddressTab.setLabel(labelHTML, labelText);
+ }
+ }
+
+ /**
+ * @param content Widget that would be add in tab.
+ * @param tabName The name of the tab.
+ */
+ private void addTab(Widget content, String tabName)
+ {
+ if (content instanceof HasLink) {
+ tabs.add(content, tabName);
+ ((HasLink) content).addClickListener(this);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see ClickListener#onClick(Widget)
+ */
+ public void onClick(Widget sender)
+ {
+ if (sender instanceof HasLink) {
+ closeByCreateLink = true;
+ hide();
+ }
+ }
+
+ /**
+ * @return the url from the selected tab.
+ */
+ public String getLink()
+ {
+ if (closeByCreateLink) {
+ closeByCreateLink = false;
+ return getSelectedTab().getLink();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see TabListener#onBeforeTabSelected(SourcesTabEvents, int)
+ */
+ public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see TabListener#onTabSelected(SourcesTabEvents, int)
+ */
+ public void onTabSelected(SourcesTabEvents sender, int tabIndex)
+ {
+ if (sender == tabs) {
+ selectedTabIndex = tabIndex;
+ getSelectedTab().initialize();
+ }
+ }
+
+ /**
+ * Gets the widget from the tab corresponding with the selected index.
+ *
+ * @return the widget from the current tab.
+ */
+ private HasLink getSelectedTab()
+ {
+ return (HasLink) tabs.getWidget(selectedTabIndex);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see CompositeDialog#center()
+ */
+ public void center()
+ {
+ super.center();
+ DeferredCommand.addCommand(new SelectCommand());
+ }
+}
Added:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToEmailAddressTab.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToEmailAddressTab.java
(rev 0)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToEmailAddressTab.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -0,0 +1,154 @@
+/*
+ * 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 com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.Widget;
+import com.xpn.xwiki.wysiwyg.client.editor.Strings;
+import com.xpn.xwiki.wysiwyg.client.plugin.link.LinkGenerator;
+
+/**
+ * Tab to add to the link dialog to get user data and produce an URL to an email
address.
+ *
+ * @version $Id$
+ */
+public class LinkToEmailAddressTab extends AbstractHasLinkTab implements ClickListener
+{
+ /**
+ * URL protocol constant.
+ */
+ private static final String MAILTO = "mailto:";
+
+ /**
+ * The text box where the user will insert the address of the web page.
+ */
+ private final TextBox emailTextBox;
+
+ /**
+ * The link creation button.
+ */
+ private final Button createLinkButton;
+
+ /**
+ * Default constructor.
+ */
+ public LinkToEmailAddressTab()
+ {
+ Label emailLabel = new Label(Strings.INSTANCE.linkEmailLabel());
+ Label labelLabel = new Label(Strings.INSTANCE.linkLabelLabel());
+ createLinkButton = new Button(Strings.INSTANCE.linkCreateLinkButon());
+ createLinkButton.addClickListener(this);
+
+ EnterListener enterListener = new EnterListener(createLinkButton);
+ emailTextBox = new TextBox();
+ emailTextBox.setText(Strings.INSTANCE.linkEmailAddressTextBox());
+ emailTextBox.addClickListener(this);
+ emailTextBox.addKeyboardListener(enterListener);
+
+ getLabelTextBox().addKeyboardListener(enterListener);
+
+ FlowPanel mainPanel = new FlowPanel();
+ mainPanel.addStyleName("xLinkToUrl");
+ FlowPanel labelPanel = new FlowPanel();
+ labelPanel.addStyleName("label");
+ labelPanel.add(labelLabel);
+ labelPanel.add(getLabelTextBox());
+ FlowPanel emailPanel = new FlowPanel();
+ emailPanel.addStyleName("url");
+ emailPanel.add(emailLabel);
+ emailPanel.add(emailTextBox);
+
+ mainPanel.add(labelPanel);
+ mainPanel.add(emailPanel);
+ mainPanel.add(createLinkButton);
+
+ initWidget(mainPanel);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see ClickListener#onClick(Widget)
+ */
+ public void onClick(Widget sender)
+ {
+ if (sender == createLinkButton) {
+ // try to create the link and close the dialog. Fail if the input does not
validate
+ String url;
+ String emailAddress = emailTextBox.getText();
+ if (!validateUserInput()) {
+ url = null;
+ } else {
+ if (emailAddress.startsWith(MAILTO)) {
+ url = emailAddress;
+ } else {
+ url = MAILTO + emailAddress;
+ }
+ setLink(LinkGenerator.getInstance().getExternalLink(getLinkLabel(),
url));
+ getClickListeners().fireClick(this);
+ }
+ }
+ if (sender == emailTextBox) {
+ emailTextBox.selectAll();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see HasLink#initialize()
+ */
+ public void initialize()
+ {
+ emailTextBox.setText(Strings.INSTANCE.linkEmailAddressTextBox());
+ // If there is label to set, set focus in the label field
+ if (getLabelTextBox().getText().trim().length() == 0) {
+ getLabelTextBox().setFocus(true);
+ } else {
+ emailTextBox.setFocus(true);
+ }
+ emailTextBox.selectAll();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see HasLink#validateUserInput()
+ */
+ public boolean validateUserInput()
+ {
+ // Check the super class validation result
+ if (!super.validateUserInput()) {
+ return false;
+ }
+ // the email address must not be void. Check if this happens
+ if (this.emailTextBox.getText().trim().length() == 0
+ ||
this.emailTextBox.getText().equals(Strings.INSTANCE.linkEmailAddressTextBox())) {
+ Window.alert(Strings.INSTANCE.linkEmailAddressError());
+ return false;
+ }
+ return true;
+ }
+}
Added:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToWebPageTab.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToWebPageTab.java
(rev 0)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/plugin/link/ui/LinkToWebPageTab.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -0,0 +1,149 @@
+/*
+ * 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 com.xpn.xwiki.wysiwyg.client.plugin.link.ui;
+
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.Widget;
+import com.xpn.xwiki.wysiwyg.client.editor.Strings;
+import com.xpn.xwiki.wysiwyg.client.plugin.link.LinkGenerator;
+
+/**
+ * Tab to add to the link dialog to get user data and produce a link to an external web
page.
+ *
+ * @version $Id$
+ */
+public class LinkToWebPageTab extends AbstractHasLinkTab implements ClickListener
+{
+ /**
+ * The text box where the user will insert the address of the web page.
+ */
+ private final TextBox urlTextBox;
+
+ /**
+ * The link creation button.
+ */
+ private final Button createLinkButton;
+
+ /**
+ * Class constructor.
+ */
+ public LinkToWebPageTab()
+ {
+ Label urlLabel = new Label(Strings.INSTANCE.linkWebPageLabel());
+ Label labelLabel = new Label(Strings.INSTANCE.linkLabelLabel());
+ createLinkButton = new Button(Strings.INSTANCE.linkCreateLinkButon());
+ createLinkButton.addClickListener(this);
+
+ EnterListener enterListener = new EnterListener(createLinkButton);
+ urlTextBox = new TextBox();
+ urlTextBox.setText(Strings.INSTANCE.linkWebPageTextBox());
+ urlTextBox.addClickListener(this);
+ urlTextBox.addKeyboardListener(enterListener);
+
+ getLabelTextBox().addKeyboardListener(enterListener);
+
+ FlowPanel mainPanel = new FlowPanel();
+ mainPanel.addStyleName("xLinkToUrl");
+ FlowPanel labelPanel = new FlowPanel();
+ labelPanel.addStyleName("label");
+ labelPanel.add(labelLabel);
+ labelPanel.add(getLabelTextBox());
+ FlowPanel urlPanel = new FlowPanel();
+ urlPanel.addStyleName("url");
+ urlPanel.add(urlLabel);
+ urlPanel.add(urlTextBox);
+
+ mainPanel.add(labelPanel);
+ mainPanel.add(urlPanel);
+ mainPanel.add(createLinkButton);
+
+ initWidget(mainPanel);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see ClickListener#onClick(Widget)
+ */
+ public void onClick(Widget sender)
+ {
+ if (sender == createLinkButton) {
+ String url;
+ String webPageAddress = urlTextBox.getText();
+ if (!validateUserInput()) {
+ url = null;
+ } else {
+ // check if any protocol is use
+ if (webPageAddress.contains("://")) {
+ url = webPageAddress;
+ } else {
+ url = "http://" + webPageAddress;
+ }
+ setLink(LinkGenerator.getInstance().getExternalLink(getLinkLabel(),
url));
+ getClickListeners().fireClick(this);
+ }
+ }
+ if (sender == urlTextBox) {
+ urlTextBox.selectAll();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see HasLink#initialize()
+ */
+ public void initialize()
+ {
+ urlTextBox.setText(Strings.INSTANCE.linkWebPageTextBox());
+ if (getLabelTextBox().getText().trim().length() == 0) {
+ getLabelTextBox().setFocus(true);
+ } else {
+ urlTextBox.setFocus(true);
+ }
+ urlTextBox.selectAll();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see HasLink#validateUserInput()
+ */
+ public boolean validateUserInput()
+ {
+ // Check the super class validation result
+ if (!super.validateUserInput()) {
+ return false;
+ }
+ // The url inserted by the user must not be void. Check that
+ if (this.urlTextBox.getText().trim().length() == 0
+ || this.urlTextBox.getText().equals(Strings.INSTANCE.linkWebPageTextBox()))
{
+ Window.alert(Strings.INSTANCE.linkWebPageAddressError());
+ return false;
+ }
+ return true;
+ }
+}
Modified:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/syntax/internal/DefaultSyntaxValidator.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/syntax/internal/DefaultSyntaxValidator.java 2008-11-12
19:52:43 UTC (rev 14183)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/syntax/internal/DefaultSyntaxValidator.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -64,7 +64,8 @@
addValidationRule(new DefaultValidationRule("fontsize",
Command.FONT_SIZE));
addValidationRule(new DefaultValidationRule("forecolor",
Command.FORE_COLOR));
addValidationRule(new DefaultValidationRule("backcolor",
Command.BACK_COLOR));
-
+ addValidationRule(new DefaultValidationRule("link",
Command.CREATE_LINK));
+ addValidationRule(new DefaultValidationRule("unlink",
Command.UNLINK));
// FIXME : implement this in the table plugin when possible
addValidationRule(new DefaultValidationRule("deletecol", new
Command("deletecol")));
addValidationRule(new DefaultValidationRule("deleterow", new
Command("deleterow")));
Modified:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/Command.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/Command.java 2008-11-12
19:52:43 UTC (rev 14183)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/Command.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -41,6 +41,12 @@
public static final Command BOLD = new Command("bold");
/**
+ * This command will insert a link in place of the current selection, either if it
is a collapsed selection or an
+ * expanded one. It is based on the insert HTML command, and it will insert the link
HTML received as a parameter.
+ */
+ public static final Command CREATE_LINK = new Command("createlink");
+
+ /**
* This command will set the font face for a selection or at the insertion point if
there is no selection.<br/>
* The given string is such as would be used in the "name" attribute of
the font tag.
*/
@@ -205,6 +211,12 @@
public static final Command UNDO = new Command("undo");
/**
+ * If the insertion point is within a link or if the current selection contains a
link, the link will be removed and
+ * the text will remain.
+ */
+ public static final Command UNLINK = new Command("unlink");
+
+ /**
* The name of the command. For predefined commands (supported by the built-in rich
text editor, the one offered by
* the browser) this is the name of the command execute with the native API. For the
rest (custom commands) this is
* just a string identifier.
Added:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/CreateLinkExecutable.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/CreateLinkExecutable.java
(rev 0)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/CreateLinkExecutable.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -0,0 +1,103 @@
+/*
+ * 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 com.xpn.xwiki.wysiwyg.client.widget.rta.cmd.internal;
+
+import com.google.gwt.core.client.GWT;
+import com.xpn.xwiki.wysiwyg.client.dom.DOMUtils;
+import com.xpn.xwiki.wysiwyg.client.dom.Range;
+import com.xpn.xwiki.wysiwyg.client.widget.rta.RichTextArea;
+import com.xpn.xwiki.wysiwyg.client.widget.rta.cmd.Executable;
+
+/**
+ * Creates a link by inserting the link xhtml.
+ *
+ * @version $Id$
+ */
+public class CreateLinkExecutable implements Executable
+{
+ /**
+ * Insert HTML executable to use for the insertion of the links. Cannot extend it
because we need to get it in a
+ * cross browser manner.
+ */
+ private Executable insertHTMLExecutable;
+
+ /**
+ * Default constructor, creating a {@link DefaultExecutable} for the
<code>inserthtml</code> command.
+ */
+ public CreateLinkExecutable()
+ {
+ // Create the InsertHTML cross-browser executable
+ insertHTMLExecutable = GWT.create(InsertHTMLExecutable.class);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean execute(RichTextArea rta, String parameter)
+ {
+ return insertHTMLExecutable.execute(rta, parameter);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see DefaultExecutable#isEnabled(RichTextArea)
+ */
+ public boolean isEnabled(RichTextArea rta)
+ {
+ String anchorTagName = "a";
+ // This option is enabled only if we're not in another or the selection does
not touch an anchor
+ Range range =
DOMUtils.getInstance().getTextRange(rta.getDocument().getSelection().getRangeAt(0));
+ //Check the parent first, for it's shorter
+ if (DOMUtils.getInstance().getFirstAncestor(range.getCommonAncestorContainer(),
anchorTagName) != null) {
+ return false;
+ }
+ // if no anchor on ancestor, test all the nodes touched by the selection to not
contain an anchor
+ return DOMUtils.getInstance().getFirstDescendant(range.cloneContents(),
anchorTagName) == null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see DefaultExecutable#isExecuted(RichTextArea)
+ */
+ public boolean isExecuted(RichTextArea rta)
+ {
+ // Although we should also check the parents of the anchor we are in
+ return !isEnabled(rta);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSupported(RichTextArea rta)
+ {
+ return insertHTMLExecutable.isSupported(rta);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getParameter(RichTextArea rta)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
Modified:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/DefaultCommandManager.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/DefaultCommandManager.java 2008-11-12
19:52:43 UTC (rev 14183)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/DefaultCommandManager.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -57,6 +57,7 @@
EXECUTABLES = new HashMap<Command, Executable>();
EXECUTABLES.put(Command.BACK_COLOR, (Executable)
GWT.create(BackColorExecutable.class));
EXECUTABLES.put(Command.BOLD, new BoldExecutable());
+ EXECUTABLES.put(Command.CREATE_LINK, new CreateLinkExecutable());
EXECUTABLES.put(Command.FONT_NAME, new
DefaultExecutable(Command.FONT_NAME.toString()));
EXECUTABLES.put(Command.FONT_SIZE, new
DefaultExecutable(Command.FONT_SIZE.toString()));
EXECUTABLES.put(Command.FORE_COLOR, new
DefaultExecutable(Command.FORE_COLOR.toString()));
@@ -87,6 +88,7 @@
EXECUTABLES.put(Command.TELETYPE, new StyleExecutable("tt", null,
Style.FONT_FAMILY, "monospace", true, true));
EXECUTABLES.put(Command.UNDERLINE, new StyleExecutable("ins", null,
Style.TEXT_DECORATION,
Style.TextDecoration.UNDERLINE, false, true));
+ EXECUTABLES.put(Command.UNLINK, new UnlinkExecutable());
EXECUTABLES.put(Command.UNDO, new UndoExecutable());
}
Added:
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/UnlinkExecutable.java
===================================================================
---
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/UnlinkExecutable.java
(rev 0)
+++
platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/client/widget/rta/cmd/internal/UnlinkExecutable.java 2008-11-12
22:17:54 UTC (rev 14184)
@@ -0,0 +1,222 @@
+/*
+ * 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 com.xpn.xwiki.wysiwyg.client.widget.rta.cmd.internal;
+
+import com.google.gwt.dom.client.Node;
+import com.xpn.xwiki.wysiwyg.client.dom.DOMUtils;
+import com.xpn.xwiki.wysiwyg.client.dom.Document;
+import com.xpn.xwiki.wysiwyg.client.dom.Element;
+import com.xpn.xwiki.wysiwyg.client.dom.Range;
+import com.xpn.xwiki.wysiwyg.client.dom.Selection;
+import com.xpn.xwiki.wysiwyg.client.widget.rta.RichTextArea;
+import com.xpn.xwiki.wysiwyg.client.widget.rta.cmd.Executable;
+
+/**
+ * Executable for the unlink command, to remove a link in the wiki document. The
following rules apply:
+ * <ul>
+ * <li>if there is no selection and the cursor is inside a wikilink, remove the
enclosing link</li>
+ * <li>if there is a selection which is fully inside or equal to a wikilink,
remove the enclosing link</li>
+ * <li>the command is not enabled in any other situation</li>
+ * </ul>
+ *
+ * @version $Id$
+ */
+public class UnlinkExecutable implements Executable
+{
+ /**
+ * Hold the name of the anchor tag.
+ */
+ private static final String ANCHOR = "a";
+
+ /**
+ * Constant for the comment node type.
+ */
+ private static final short NODE_TYPE_COMMENT = 8;
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean execute(RichTextArea rta, String param)
+ {
+ // Get the wrapping anchor
+ Range range =
DOMUtils.getInstance().getTextRange(rta.getDocument().getSelection().getRangeAt(0));
+ Node anchor =
DOMUtils.getInstance().getFirstAncestor(range.getCommonAncestorContainer(), ANCHOR);
+ if (anchor == null) {
+ return false;
+ }
+ // check its parent, if it's a span
+ Node wrappingSpan = anchor.getParentNode();
+ if (wrappingSpan == null || wrappingSpan.getNodeType() != Node.ELEMENT_NODE
+ || !wrappingSpan.getNodeName().equalsIgnoreCase("span")) {
+ // we have no span wrapping the anchor, is not a wikilink
+ boolean result = removeAnchor(Element.as(anchor), rta, range);
+ }
+ // check the span class
+ String spanClass = Element.as(wrappingSpan).getClassName();
+ if (!spanClass.equalsIgnoreCase("wikilink") &&
!spanClass.equalsIgnoreCase("wikiexternallink")
+ && !spanClass.equalsIgnoreCase("wikicreatelink")) {
+ // we haven't the expected class on the span
+ return removeAnchor(Element.as(anchor), rta, range);
+ }
+ // check the comments before and after
+ Node nodeBefore = wrappingSpan.getPreviousSibling();
+ Node nodeAfter = wrappingSpan.getNextSibling();
+ if (nodeBefore == null || nodeAfter == null || nodeBefore.getNodeType() !=
NODE_TYPE_COMMENT
+ || nodeAfter.getNodeType() != NODE_TYPE_COMMENT) {
+ // missing or wrong sibling nodes for the wikilink span
+ return removeAnchor(Element.as(anchor), rta, range);
+ }
+ if (nodeBefore.getNodeValue().startsWith("startwikilink:")
+ &&
nodeAfter.getNodeValue().equalsIgnoreCase("stopwikilink")) {
+ // WOUHOU! found wikilink, remove it
+ return removeWikiLink(nodeBefore, Element.as(anchor), rta, range);
+ }
+ return removeAnchor(Element.as(anchor), rta, range);
+ }
+
+ /**
+ * Removes an anchor by replacing it with all its children.
+ *
+ * @param anchor the anchor to remove
+ * @param rta the rich text area to remove the anchor from
+ * @param textRange the text area's original selection text range. Passed here
just for cache purposes.
+ * @return the result of this operation
+ */
+ private boolean removeAnchor(Element anchor, RichTextArea rta, Range textRange)
+ {
+ // Store the current selection
+ Node startNode = textRange.getStartContainer();
+ int startOffset = textRange.getStartOffset();
+ Node endNode = textRange.getEndContainer();
+ int endOffset = textRange.getEndOffset();
+ // Remove all children from the anchor and insert them before the anchor.
+ Node currentNode = anchor.getFirstChild();
+ while (currentNode != null) {
+ anchor.removeChild(currentNode);
+ anchor.getParentNode().insertBefore(currentNode, anchor);
+ currentNode = anchor.getFirstChild();
+ }
+ // remove the anchor from its parent
+ anchor.getParentElement().removeChild(anchor);
+ // restore the selection of the rta to the original text range
+ Range newRange = rta.getDocument().createRange();
+ newRange.setStart(startNode, startOffset);
+ newRange.setEnd(endNode, endOffset);
+ rta.getDocument().getSelection().removeAllRanges();
+ rta.getDocument().getSelection().addRange(newRange);
+ return true;
+ }
+
+ /**
+ * Removes a wikilink by replacing it with the contents of the passed anchor. The
wikilink is given by the
+ * startComment, considering that, along with the next 2 nodes, it represents the
wikilink.
+ *
+ * @param startComment the start comment of this wikilink
+ * @param anchor the anchor enclosed by this wikilink
+ * @param rta the rich text area to remove the wikilink from
+ * @param textRange the text area's original selection text range. Passed here
just for cache purposes.
+ * @return the result of the replacement
+ */
+ private boolean removeWikiLink(Node startComment, Element anchor, RichTextArea rta,
Range textRange)
+ {
+ // Store the current selection
+ Node startNode = textRange.getStartContainer();
+ int startOffset = textRange.getStartOffset();
+ Node endNode = textRange.getEndContainer();
+ int endOffset = textRange.getEndOffset();
+ Node currentNode = anchor.getFirstChild();
+ Node spanNode = startComment.getNextSibling();
+ if (spanNode == null) {
+ return false;
+ }
+ Node endComment = spanNode.getNextSibling();
+ if (endComment == null) {
+ return false;
+ }
+ while (currentNode != null) {
+ anchor.removeChild(currentNode);
+ startComment.getParentNode().insertBefore(currentNode, startComment);
+ currentNode = anchor.getFirstChild();
+ }
+ // Done, remove the comments & spans from the parent
+ startComment.getParentNode().removeChild(startComment);
+ spanNode.getParentNode().removeChild(spanNode);
+ endComment.getParentNode().removeChild(endComment);
+ // restore the selection of the rta to the original text range
+ Range newRange = rta.getDocument().createRange();
+ newRange.setStart(startNode, startOffset);
+ newRange.setEnd(endNode, endOffset);
+ rta.getDocument().getSelection().removeAllRanges();
+ rta.getDocument().getSelection().addRange(newRange);
+ return true;
+ }
+
+ /**
+ * Restores the current selection to the passed text range. To be used after the DOM
operations to restore the
+ * selection in the text area. The selection will be set to the passed
<code>textRange</code> to be sure that we are
+ * not trying to set the selection inside a removed element. We use just a range for
the original selection since we
+ * use only the first range of the selection anyway.
+ *
+ * @param rta the {@link RichTextArea} for which the selection restore is done
+ * @param textRange text range to set the first range of the selection to
+ */
+ private void restoreSelection(RichTextArea rta, Range textRange)
+ {
+
+ Document doc = rta.getDocument();
+ Selection selection = doc.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(textRange);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getParameter(RichTextArea rta)
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEnabled(RichTextArea rta)
+ {
+ // Check the selection, to be either void or inside a link.
+ Range range =
DOMUtils.getInstance().getTextRange(rta.getDocument().getSelection().getRangeAt(0));
+ return
DOMUtils.getInstance().getFirstAncestor(range.getCommonAncestorContainer(), ANCHOR) !=
null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isExecuted(RichTextArea rta)
+ {
+ return !isEnabled(rta);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSupported(RichTextArea rta)
+ {
+ return true;
+ }
+}
Modified:
platform/web/trunk/wysiwyg/src/main/resources/com/xpn/xwiki/wysiwyg/client/editor/Strings.properties
===================================================================
---
platform/web/trunk/wysiwyg/src/main/resources/com/xpn/xwiki/wysiwyg/client/editor/Strings.properties 2008-11-12
19:52:43 UTC (rev 14183)
+++
platform/web/trunk/wysiwyg/src/main/resources/com/xpn/xwiki/wysiwyg/client/editor/Strings.properties 2008-11-12
22:17:54 UTC (rev 14184)
@@ -29,7 +29,6 @@
justifyFull=Align full
justifyLeft=Align left
justifyRight=Align right
-link=Insert/edit link
ol=Ordered list
outdent=Outdent
paste=Paste
@@ -50,4 +49,16 @@
insertTable=Inserts a new table
underline=Underline (CTRL+U)
undo=Undo (CTRL+Z)
-unlink=Unlink
\ No newline at end of file
+link=Insert link
+unlink=Unlink
+linkCreateLinkButon=Create Link
+linkEmailTab=Email address
+linkWebPageTab=Web page
+linkLabelLabel=Label:
+linkWebPageLabel=Webpage address:
+linkEmailLabel=Email address:
+linkEmailAddressTextBox=Type here the email address you want to link to...
+linkWebPageTextBox=Type here the address of the webpage you want to link to...
+linkEmailAddressError=The email address wasn't set!
+linkWebPageAddressError=The web page address wasn't set!
+linkNoLabelError=The label of the link cannot be void!
\ No newline at end of file
Modified:
platform/web/trunk/wysiwyg/src/main/resources/com/xpn/xwiki/wysiwyg/public/Wysiwyg.css
===================================================================
---
platform/web/trunk/wysiwyg/src/main/resources/com/xpn/xwiki/wysiwyg/public/Wysiwyg.css 2008-11-12
19:52:43 UTC (rev 14183)
+++
platform/web/trunk/wysiwyg/src/main/resources/com/xpn/xwiki/wysiwyg/public/Wysiwyg.css 2008-11-12
22:17:54 UTC (rev 14184)
@@ -179,6 +179,7 @@
background-color:#FFA500;
white-space:nowrap;
line-height:16px;
+ height: 16px;
cursor:move;
}
@@ -215,3 +216,54 @@
/* IE6 */
width: 1px;
}
+/********styles for link********/
+.gwt-TabBar {
+}
+.gwt-TabBar .gwt-TabBarFirst {
+ width: 5px; /* first tab distance from the left */
+}
+.gwt-TabBar .gwt-TabBarRest {
+}
+.gwt-TabBar .gwt-TabBarItem {
+ margin-left: 6px;
+ padding: 3px 6px 3px 6px;
+ cursor: pointer;
+ cursor: hand;
+ color: black;
+ font-weight: bold;
+ text-align: center;
+ background: #d0e4f6;
+}
+.gwt-TabBar .gwt-TabBarItem-selected {
+ cursor: default;
+ background: #92c1f0;
+}
+.gwt-TabPanel {
+ padding: 6px;
+}
+.gwt-TabPanelBottom {
+ border-color: #92c1f0;
+ border-style: solid;
+ border-width: 3px 2px 2px;
+ overflow: hidden;
+ padding: 6px;
+}
+.gwt-PopupPanel {
+ background: white;
+}
+
+.xLinkToUrl .gwt-Label{
+ font-weight: bold;
+ width: 300px;
+ padding: 5px;
+
+}
+.xLinkToUrl .gwt-TextBox{
+ font-size: x-small;
+ margin: 0 5px;
+ width: 300px;
+}
+.xLinkToUrl .gwt-Button{
+ font-size: x-small;
+ margin: 8px;
+}
\ No newline at end of file
_______________________________________________
notifications mailing list
notifications(a)xwiki.org
http://lists.xwiki.org/mailman/listinfo/notifications