Package org.projectforge.web.wicket.flowlayout

Source Code of org.projectforge.web.wicket.flowlayout.DiffTextPanel

/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
//         www.projectforge.org
//
// Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition 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 General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.web.wicket.flowlayout;

import java.util.LinkedList;

import name.fraser.neil.plaintext.DiffMatchPatch;
import name.fraser.neil.plaintext.DiffMatchPatch.Diff;

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.projectforge.web.HtmlHelper;
import org.projectforge.web.dialog.ModalDialog;
import org.projectforge.web.wicket.AbstractSecuredPage;
import org.projectforge.web.wicket.WicketUtils;

/**
* Represents a text panel showing the difference between two texts. The old and new version of the text is shown in a pop-over.
* @author Kai Reinhard (k.reinhard@micromata.de)
*
*/
public class DiffTextPanel extends Panel
{
  private static final long serialVersionUID = -4688885351297467119L;

  public static final String WICKET_ID = "text";

  private final Label label;

  private String prettyHtml;

  private ModalDialog modalDialog;

  private boolean showModalDialog = true;

  private IModel<String> newText, oldText;

  @SuppressWarnings("serial")
  public DiffTextPanel(final String id, final IModel<String> newText, final IModel<String> oldText, final Behavior... behaviors)
  {
    super(id);
    this.newText = newText;
    this.oldText = oldText;
    label = new Label(WICKET_ID, new Model<String>() {
      @Override
      public String getObject()
      {
        if (prettyHtml == null) {
          final DiffMatchPatch diffMatchPatch = new DiffMatchPatch();
          String newValue = newText.getObject();
          if (newValue == null || "null".equals(newValue) == true) {
            newValue = getString("label.null");
          }
          String oldValue = oldText.getObject();
          if (oldValue == null || "null".equals(oldValue) == true) {
            oldValue = getString("label.null");
          }
          final LinkedList<Diff> diffs = diffMatchPatch.diff_main(oldValue, newValue);
          diffMatchPatch.diff_cleanupSemantic(diffs);
          prettyHtml = getPrettyHtml(diffs);
        }
        return prettyHtml;
      }
    });
    label.add(behaviors).setEscapeModelStrings(false);
    add(label);
  }

  /**
   * If set to true, then the user is able to click on this panel and a modal dialog will open with the old and new text to copy.
   * @param showModalDialog the showModalDialog to set (default is true).
   * @return this for chaining.
   */
  public DiffTextPanel setShowModalDialog(final boolean showModalDialog)
  {
    this.showModalDialog = showModalDialog;
    return this;
  }

  /**
   * If the models of old and/or new text were changed you may call this method to force a new running of the diff algorithm.
   * @return this for chaining.
   */
  public DiffTextPanel recalculate()
  {
    prettyHtml = null;
    return this;
  }

  /**
   * Calls setRenderBodyOnly(false) and setOutputMarkupId(true) for the enclosed label.
   * @return the label
   */
  public Label getLabel4Ajax()
  {
    label.setRenderBodyOnly(false).setOutputMarkupId(true);
    return label;
  }

  /**
   * @return the label
   */
  public Label getLabel()
  {
    return label;
  }

  /**
   * @see org.apache.wicket.Component#setMarkupId(java.lang.String)
   */
  @Override
  public DiffTextPanel setMarkupId(final String markupId)
  {
    label.setOutputMarkupId(true);
    label.setMarkupId(markupId);
    return this;
  }

  /**
   * @see WicketUtils#setStrong(org.apache.wicket.markup.html.form.FormComponent)
   * @return this for chaining.
   */
  public DiffTextPanel setStrong()
  {
    WicketUtils.setStrong(label);
    return this;
  }

  /**
   * @see org.apache.wicket.Component#onInitialize()
   */
  @SuppressWarnings("serial")
  @Override
  protected void onInitialize()
  {
    super.onInitialize();
    if (showModalDialog == true && getPage() != null && getPage() instanceof AbstractSecuredPage) {
      final AbstractSecuredPage parentPage = (AbstractSecuredPage) getPage();
      modalDialog = new ModalDialog(parentPage.newModalDialogId()) {
        @Override
        public void init()
        {
          setTitle(getString("changes"));
          init(new Form<String>(getFormId()));
          {
            final FieldsetPanel fs = gridBuilder.newFieldset(getString("history.oldValue")).setLabelSide(false);
            final TextArea<String> textArea = new TextArea<String>(fs.getTextAreaId(), oldText);
            fs.add(textArea).setAutogrow(1, 10);
            textArea.add(AttributeModifier.replace("onClick", "$(this).select();"));
          }
          {
            final FieldsetPanel fs = gridBuilder.newFieldset(getString("history.newValue")).setLabelSide(false);
            final TextArea<String> textArea = new TextArea<String>(fs.getTextAreaId(), newText);
            fs.add(textArea).setAutogrow(1, 10);
            textArea.add(AttributeModifier.replace("onClick", "$(this).select();"));
          }
        }
      };
      modalDialog.setBigWindow();
      modalDialog.setLazyBinding();
      parentPage.add(modalDialog);
      final AjaxEventBehavior behavior = new AjaxEventBehavior("onClick") {
        @Override
        protected void onEvent(final AjaxRequestTarget target)
        {
          if (modalDialog.isBound() == false) {
            // First call, have to initialize it.
            modalDialog.init();
            target.add(modalDialog.getMainContainer());
            modalDialog.bind(target);
          }
          modalDialog.open(target);
        }
      };
      label.add(behavior);
      label.add(AttributeModifier.append("style", "cursor: pointer;"));
    }
  }

  protected String getPrettyHtml(final LinkedList<Diff> diffs)
  {
    final StringBuilder html = new StringBuilder();
    for (final Diff aDiff : diffs) {
      final String text = HtmlHelper.escapeHtml(aDiff.text, true);
      switch (aDiff.operation) {
        case INSERT:
          html.append("<ins>").append(text).append("</ins>");
          break;
        case DELETE:
          html.append("<del>").append(text).append("</del>");
          break;
        case EQUAL:
          html.append("<span>").append(text).append("</span>");
          break;
      }
    }
    return html.toString();

  }
}
TOP

Related Classes of org.projectforge.web.wicket.flowlayout.DiffTextPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.