/* 
@ITMillApache2LicenseForJavaFiles@
 */

package com.itmill.toolkit.terminal.gwt.client.ui.richtextarea;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusListener;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RichTextArea;
import com.google.gwt.user.client.ui.Widget;
import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
import com.itmill.toolkit.terminal.gwt.client.Paintable;
import com.itmill.toolkit.terminal.gwt.client.UIDL;
import com.itmill.toolkit.terminal.gwt.client.Util;
import com.itmill.toolkit.terminal.gwt.client.ui.Field;

/**
 * This class represents a basic text input field with one row.
 * 
 * @author IT Mill Ltd.
 * 
 */
public class IRichTextArea extends Composite implements Paintable, Field,
        ChangeListener, FocusListener {

    /**
     * The input node CSS classname.
     */
    public static final String CLASSNAME = "i-richtextarea";

    protected String id;

    protected ApplicationConnection client;

    private boolean immediate = false;

    private RichTextArea rta = new RichTextArea();

    private IRichTextToolbar formatter = new IRichTextToolbar(rta);

    private HTML html = new HTML();

    private final FlowPanel fp = new FlowPanel();

    private boolean enabled = true;

    private int extraHorizontalPixels = -1;
    private int extraVerticalPixels = -1;

    public IRichTextArea() {
        fp.add(formatter);

        rta.setWidth("100%");
        rta.addFocusListener(this);

        fp.add(rta);

        initWidget(fp);
        setStyleName(CLASSNAME);

    }

    public void setEnabled(boolean enabled) {
        if (this.enabled != enabled) {
            rta.setEnabled(enabled);
            if (enabled) {
                fp.remove(html);
                fp.add(rta);
            } else {
                html.setHTML(rta.getHTML());
                fp.remove(rta);
                fp.add(html);
            }

            this.enabled = enabled;
        }
    }

    public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
        this.client = client;
        id = uidl.getId();

        if (uidl.hasVariable("text")) {
            rta.setHTML(uidl.getStringVariable("text"));
        }
        setEnabled(!uidl.getBooleanAttribute("disabled"));

        if (client.updateComponent(this, uidl, true)) {
            return;
        }

        immediate = uidl.getBooleanAttribute("immediate");

    }

    public void onChange(Widget sender) {
        if (client != null && id != null) {
            client.updateVariable(id, "text", rta.getText(), immediate);
        }
    }

    public void onFocus(Widget sender) {

    }

    public void onLostFocus(Widget sender) {
        final String html = rta.getHTML();
        client.updateVariable(id, "text", html, immediate);

    }

    /**
     * @return space used by components paddings and borders
     */
    private int getExtraHorizontalPixels() {
        if (extraHorizontalPixels < 0) {
            detectExtraSizes();
        }
        return extraHorizontalPixels;
    }

    /**
     * @return space used by components paddings and borders
     */
    private int getExtraVerticalPixels() {
        if (extraVerticalPixels < 0) {
            detectExtraSizes();
        }
        return extraVerticalPixels;
    }

    /**
     * Detects space used by components paddings and borders.
     */
    private void detectExtraSizes() {
        Element clone = Util.cloneNode(getElement(), false);
        DOM.setElementAttribute(clone, "id", "");
        DOM.setStyleAttribute(clone, "visibility", "hidden");
        DOM.setStyleAttribute(clone, "position", "absolute");
        // due FF3 bug set size to 10px and later subtract it from extra pixels
        DOM.setStyleAttribute(clone, "width", "10px");
        DOM.setStyleAttribute(clone, "height", "10px");
        DOM.appendChild(DOM.getParent(getElement()), clone);
        extraHorizontalPixels = DOM.getElementPropertyInt(clone, "offsetWidth") - 10;
        extraVerticalPixels = DOM.getElementPropertyInt(clone, "offsetHeight") - 10;

        DOM.removeChild(DOM.getParent(getElement()), clone);
    }

    @Override
    public void setHeight(String height) {
        if (height.endsWith("px")) {
            int h = Integer.parseInt(height.substring(0, height.length() - 2));
            h -= getExtraVerticalPixels();
            if (h < 0) {
                h = 0;
            }

            super.setHeight(h + "px");
        } else {
            super.setHeight(height);
        }

        if (height == null || height.equals("")) {
            rta.setHeight("");
        } else {
            int editorHeight = getOffsetHeight() - getExtraVerticalPixels()
                    - formatter.getOffsetHeight();
            rta.setHeight(editorHeight + "px");
        }
    }

    @Override
    public void setWidth(String width) {
        if (width.endsWith("px")) {
            int w = Integer.parseInt(width.substring(0, width.length() - 2));
            w -= getExtraHorizontalPixels();
            if (w < 0) {
                w = 0;
            }

            super.setWidth(w + "px");
        } else {
            super.setWidth(width);
        }
    }

}

@@ -593,16 +593,75 @@
 ection;%0A
+import com.itmill.toolkit.terminal.gwt.client.BrowserInfo;%0A
 import c
@@ -5419,32 +5419,371 @@
 idth(w + %22px%22);%0A
+        %7D else if (width.equals(%22%22) && BrowserInfo.get().isIE7()) %7B%0A            /*%0A             * IE7 cannot calculate the width of the 100%25 iframe if there is no%0A             * width specified for the parent so we use the width of the%0A             * toolbar.%0A             */%0A            super.setWidth(formatter.getOffsetWidth() + %22px%22);%0A
         %7D else %7B

Fix for #2312 - RichTextArea size in IE7