"""
/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License") you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http:#www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
"""
from pyjamas.ui.Panel import Panel
from pyjamas.ui.Event import Event

import DOM

class SplitPanel(Panel):
    """ Abstract base class for {@link HorizontalSplitPanel} and
        {@link VerticalSplitPanel}.
    """

    def __init__(self, mainElem, splitElem, headElem, tailElem):
        """ Initializes the split panel.
           @param mainElem the root element for the split panel
           @param splitElem the element that acts as the splitter
           @param headElem the element to contain the top or left most widget
           @param tailElem the element to contain the bottom or right most widget
        """

        Panel.__init__(self)

        self.widgets = [None, None]
        self.elements = [headElem, tailElem]
        self.isResizing = False

        self.setElement(mainElem)
        self.splitElem = splitElem
        self.sinkEvents(Event.MOUSEEVENTS)

    def addAbsolutePositoning(self, elem):
        """ Sets an elements positioning to absolute.
        """
        DOM.setStyleAttribute(elem, "position", "absolute")

    def addClipping(self, elem):
        """ Adds clipping to an element.
        """
        DOM.setStyleAttribute(elem, "overflow", "hidden")

    def addScrolling(self, elem):
        """ Adds as-needed scrolling to an element.
        """
        DOM.setStyleAttribute(elem, "overflow", "auto")

    def expandToFitParentUsingCssOffsets(self, elem):
        """ Sizes and element to consume the full area of its parent
            using the CSS properties left, right, top, and
            bottom. This method is used for all browsers except IE6/7.
        """
        zeroSize = "0px"

        self.addAbsolutePositoning(elem)
        self.setLeft(elem, zeroSize)
        self.setRight(elem, zeroSize)
        self.setTop(elem, zeroSize)
        self.setBottom(elem, zeroSize)

    def expandToFitParentUsingPercentages(self, elem):
        """ Sizes an element to consume the full areas of its parent
            using 100% width and height. This method is used on IE6/7
            where CSS offsets don't work reliably.
        """
        zeroSize = "0px"
        fullSize = "100%"

        self.addAbsolutePositoning(elem)
        self.setTop(elem, zeroSize)
        self.setLeft(elem, zeroSize)
        self.setElemWidth(elem, fullSize)
        self.setElemHeight(elem, fullSize)

    def getOffsetHeight(self, elem):
        """ Returns the offsetHeight element property.
        """
        return DOM.getIntAttribute(elem, "offsetHeight")

    def getOffsetWidth(self, elem):
        """  Returns the offsetWidth element property.
        """
        return DOM.getIntAttribute(elem, "offsetWidth")

    def preventBoxStyles(self, elem):
        """ Adds zero or none CSS values for padding, margin and
            border to prevent stylesheet overrides. Returns the
            element for convenience to support builder pattern.
        """
        DOM.setIntStyleAttribute(elem, "padding", 0)
        DOM.setIntStyleAttribute(elem, "margin", 0)
        DOM.setStyleAttribute(elem, "border", "none")
        return elem

    def setBottom(self, elem, size):
        """ Convenience method to set bottom offset of an element.
        """
        DOM.setStyleAttribute(elem, "bottom", size)

    def setElemHeight(self, elem, height):
        """ Convenience method to set the height of an element.
        """
        DOM.setStyleAttribute(elem, "height", height)

    def setLeft(self, elem, left):
        """ Convenience method to set the left offset of an element.
        """
        DOM.setStyleAttribute(elem, "left", left)

    def setRight(self, elem, right):
        """ Convenience method to set the right offset of an element.
        """
        DOM.setStyleAttribute(elem, "right", right)

    def setTop(self, elem, top):
        """ Convenience method to set the top offset of an element.
        """
        DOM.setStyleAttribute(elem, "top", top)

    def setElemWidth(self, elem, width):
        """ Convenience method to set the width of an element.
        """
        DOM.setStyleAttribute(elem, "width", width)

    def add(self, w):
        if self.getWidget(0) == None:
            self.setWidget(0, w)
        elif self.getWidget(1) == None:
            self.setWidget(1, w)
        #else:
        #    raise IllegalStateException("A Splitter can only contain two Widgets.")

    def isResizing(self):
        """ Indicates whether the split panel is being resized.

            @return <code>True</code> if the user is dragging the splitter,
                    <code>False</code> otherwise
        """
        return self.isResizing

    def __iter__(self):
        return self.widgets.__iter__()

    def onBrowserEvent(self, event):
        typ = DOM.eventGetType(event)

        if typ == "mousedown":
            target = DOM.eventGetTarget(event)
            if DOM.isOrHasChild(self.splitElem, target):
                self.startResizingFrom(DOM.eventGetClientX(event) -
                                       self.getAbsoluteLeft(),
                          DOM.eventGetClientY(event) - self.getAbsoluteTop())
                DOM.setCapture(self.getElement())
                DOM.eventPreventDefault(event)

        elif typ == "mouseup":
            DOM.releaseCapture(self.getElement())
            self.stopResizing()

        elif typ == 'mousemove':
            if self.isResizing:
                #assert DOM.getCaptureElement() != None
                self.onSplitterResize(DOM.eventGetClientX(event) -
                                      self.getAbsoluteLeft(),
                          DOM.eventGetClientY(event) - self.getAbsoluteTop())
                DOM.eventPreventDefault(event)

    def remove(self, widget):
        if widgets[0] == widget:
            setWidget(0, None)
            return True
        elif widgets[1] == widget:
            setWidget(1, None)
            return True
        return False

    def setSplitPosition(self, size):
        """ Moves the position of the splitter.
            @param size the new size of the left region in CSS units
            (e.g. "10px", "1em")
        """
        pass

    def getWidgetElement(self, index):
        """ Gets the content element for the given index.
            @param index the index of the element, only 0 and 1 are valid.
            @return the element
        """
        return self.elements[index]

    def getSplitElement(self):
        """ Gets the element that is acting as the splitter.
            @return the element
        """
        return self.splitElem

    def getWidget(self, index):
        """ Gets one of the contained widgets.
            @param index the index of the widget, only 0 and 1 are valid.
            @return the widget
        """
        return self.widgets[index]

    def setWidget(self, index, w):
        """ Sets one of the contained widgets.
            @param index the index, only 0 and 1 are valid
            @param w the widget
        """
        oldWidget = self.widgets[index]

        if oldWidget == w:
          return

        if (w != None):
          w.removeFromParent()

        # Remove the old child.
        if (oldWidget != None):
          # Orphan old.
          self.disown(oldWidget)
          # Physical detach old.
          #DOM.removeChild(self.elements[index], oldWidget.getElement())

        # Logical detach old / attach new.
        self.widgets[index] = w

        if (w != None):
            # Physical attach new.
            DOM.appendChild(self.elements[index], w.getElement())

            # Adopt new.
            self.adopt(w)

    def onSplitterResize(self, x, y):
        """ Called on each mouse drag event as the user is dragging
            the splitter.
            @param x the x coord of the mouse relative to the panel's extent
            @param y the y coord of the mosue relative to the panel's extent
        """
        pass

    def onSplitterResizeStarted(self, x, y):
        """ Called when the user starts dragging the splitter.
            @param x the x coord of the mouse relative to the panel's extent
            @param y the y coord of the mouse relative to the panel's extent
        """

    def startResizingFrom(self, x, y):
        self.isResizing = True
        self.onSplitterResizeStarted(x, y)

    def stopResizing(self):
        self.isResizing = False
