text: """
  - /*
  - * Copyright 2008 Google Inc.
  - * Copyright (C) 2009 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
  - * Copyright (C) 2010 Rich Newpol <rich.newpol@gmail.com>
  - *
  - * 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__ import console
  from pyjamas import DOM
  from pyjamas import Window
  from pyjamas import DeferredCommand
  from pyjamas.EventController import EventGenerator
  from pyjamas.ui import GlassWidget
  from pyjamas.ui.SimplePanel import SimplePanel
  from pyjamas.ui.AbsolutePanel import AbsolutePanel
  from pyjamas.ui.ScrollPanel import ScrollPanel
  from pyjamas.ui.MouseListener import MouseHandler, fireMouseEvent
  from pyjamas.ui import Event
  
  
  class SplitPanelSplitter(SimplePanel, MouseHandler):
      """ a splitter is just a SimplePanel which can receive mouse events """
  
      def __init__(self, splitPanel, **kwargs):
          # keep a ref to our parent panel for event callback
          self._splitpanel = splitPanel
          SimplePanel.__init__(self, **kwargs)
          MouseHandler.__init__(self)
          self.addMouseListener(self)
          # set some constant styles
          elem = self.getElement()
          # the following allows splitter to be small enough in IE
          DOM.setStyleAttribute(elem, "overflow", "hidden")
  
      def onMouseDown(self, sender, x, y):
          """ catch a mouse down for parent """
  
          ev = DOM.eventGetCurrentEvent()
          # ignore right-button downs
          if DOM.eventGetButton(ev) != Event.BUTTON_LEFT:
              return
          DOM.eventPreventDefault(DOM.eventGetCurrentEvent())
          # parent will capture the mouse and handle the dragging from here
          self._splitpanel.startSplitterDrag(x, y)
  
  
  class SplitPanel(AbsolutePanel, MouseHandler, EventGenerator):
      """ Provides the SplitPanel baseclass functionality
          A SplitPanel is an AbsolutePanel containing an HTMLTable
          with three cells. The first cell holds the first ScrollPanel,
          while the center cell holds a Splitter, and the last cell
          holds the other ScrollPanel.
      """
  
      def __init__(self, vertical=False, **kwargs):
          # set defaults
          if not 'StyleName' in kwargs:
              if vertical:    # vertical split panel
                  kwargs['StyleName'] = "gwt-VerticalSplitPanel"
              else:
                  kwargs['StyleName'] = "gwt-HorizontalSplitPanel"
          # splitter drag state vars
          self._drag_start = None
          self._pos = "50%"
          # orientation
          self._vertical = vertical
          # now init the bases
          AbsolutePanel.__init__(self, **kwargs)
          MouseHandler.__init__(self)
          # add our event support?
          self.addListenedEvent("Resize")
          # create the top/left widget container
          self._container1 = ScrollPanel()
          # create the bottom/right widget container
          self._container2 = ScrollPanel()
          # create the splitter
          self._splitter = SplitPanelSplitter(self)
          # add splitter handling
          self._splitter.addMouseListener(self)
          # add mouse event handling
          self.addMouseListener(self)
          # add the parts
          AbsolutePanel.add(self, self._container1, 0, 0)
          AbsolutePanel.add(self, self._splitter, 0, 0)
          AbsolutePanel.add(self, self._container2, 0, 0)
  
          # set the layout
          if vertical:    # vertical split panel
              self._splitter.setStyleName("vsplitter")
              self._splitter.setWidth("100%")
              self._container1.setWidth("100%")
              self._container2.setWidth("100%")
              # set drag cursor
              DOM.setStyleAttribute(self._splitter.getElement(),
                                      "cursor", "n-resize")
          else:   # horizontal split panel
              self._splitter.setStyleName("hsplitter")
              self._splitter.setHeight("100%")
              self._container1.setHeight("100%")
              self._container2.setHeight("100%")
              # set drag cursor
              DOM.setStyleAttribute(self._splitter.getElement(),
                                      "cursor", "e-resize")
  
      def onAttach(self):
          AbsolutePanel.onAttach(self)
          self.setSplitPosition()
  
      # fixup the container 2 size and position
      def _finalizePositions(self, pos=None):
          finalized = False
          if self._vertical:
              if pos is None:
                  pos = self._container1.getOffsetHeight()
              space = self.getOffsetHeight()
              sz = self._splitter.getOffsetHeight()
              if space > 0 and sz > 0 and pos > 0:
                  # limit pos
                  if pos > space - sz:
                      pos = space - sz
                      self._container1.setHeight(pos)
                  self.setWidgetPosition(self._splitter, 0, pos)
                  self.setWidgetPosition(self._container2, 0, pos + sz)
                  self._container2.setHeight(space - (pos + sz))
                  finalized = True
          else:
              if pos is None:
                  pos = self._container1.getOffsetWidth()
              space = self.getOffsetWidth()
              sz = self._splitter.getOffsetWidth()
              if space > 0 and sz > 0 and pos > 0:
                  # limit pos
                  if pos > space - sz:
                      pos = space - sz
                      self._container1.setWidth(pos)
                  self.setWidgetPosition(self._splitter, pos, 0)
                  self.setWidgetPosition(self._container2, pos + sz, 0)
                  self._container2.setWidth(space - (pos + sz))
                  finalized = True
          if finalized:
              self.dispatchResizeEvent(self, pos)
          return finalized
  
      # end a drag operation
      def _stopDragging(self):
          if self._drag_start is not None:
              # we are no longer dragging
              self._drag_start = None
              # deactivate the transparent overlay
              GlassWidget.hide()
              # don't let a mouse-up become a click event
              DOM.eventCancelBubble(DOM.eventGetCurrentEvent(), True)
  
      def _isDragging(self):
          return self._drag_start is not None
  
      # start a drag operation (called by splitter)
      def startSplitterDrag(self, x, y):
          if self._drag_start is None:
              # remember where on the slider we are dragging
              if self._vertical:
                  self._drag_start = y
              else:
                  self._drag_start = x
              # activate the transparent overlay to keep mouse events flowing to
              # the splitter (and to us) even if the mouse leaves the splitter
              GlassWidget.show(self)
  
      # add handlers for mouse events to support dragging the slider
      # NOTE: the x,y positioni s relative to the splitter
      def onMouseMove(self, sender, x, y):
          # if dragging, then use current mouse position
          # to reset splitter position
          if not self._isDragging():
              return
          # remove the offset into the splitter
          # where we started dragging
          if self._vertical:
              self._pos = y - self._drag_start
          else:
              self._pos = x - self._drag_start
          # apply limit
          if self._pos < 1:
              self._pos = 1
          # apply new position
          self.setSplitPosition()
  
      def onMouseUp(self, sender, x, y):
          ev = DOM.eventGetCurrentEvent()
          # ignore right-button ups
          if DOM.eventGetButton(ev) != Event.BUTTON_LEFT:
              return
          DOM.eventPreventDefault(ev)
          # if we are dragging
          if self._isDragging():
              # stop dragging on mouse up
              self._stopDragging()
  
      # called when we start dragging
      def onMouseGlassEnter(self, sender):
          pass
  
      # called when we drag out of the window
      # (NOT called when we just stop dragging)
      def onMouseGlassLeave(self, sender):
          # we left the window, so stop dragging
          self._stopDragging()
  
      #
      # Start the inherited 'public' API
      #
  
      # specify splitter position in pix OR percentage
      # if pixels (number) specified, we can make change now
      # otherwise, we have to set the offset as specified, then
      # 'fixup' the remaining space after rendering
      def setSplitPosition(self, pos=None):
          if pos is not None:
              # remember last pos set
              self._pos = pos
          else:
              pos = self._pos
          if pos < 1:
              pos = 1
              self._pos = pos
          # change adjustable dimension
          if self._vertical:
              self._container1.setHeight(pos)
          else:
              self._container1.setWidth(pos)
          # if pix are given, we can try to finalize the positions
          finalized = False
          if isinstance(pos, int):
              finalized = self._finalizePositions(pos)
          # if needed, queue callback to finalize
          if not finalized:
              DeferredCommand.add(self._finalizePositions)
  
      def getWidget(self, index):
          if index == 0:
              return self._container1.getWidget()
          return self._container2.getWidget()
  
      def setWidget(self, index, widget):
          if index == 0:
              return self._container1.setWidget(widget)
          return self._container2.setWidget(widget)
  
      # Adds a widget to a pane
      def add(self, widget):
          if self.getWidget(0) == None:
              self.setWidget(0, widget)
          elif self.getWidget(1) == None:
              self.setWidget(1, widget)
          else:
              console.error("SimplePanel can only contain one child widget")
  
      # Removes a child widget.
      def remove(self, widget):
          if self.getWidget(0) == widget:
              self._container1.remove(widget)
          elif self.getWidget(1) == widget:
              self._container2.remove(widget)
          else:
              AbsolutePanel.remove(self, widget)
  
      # Gets the content element for the given index.
      def getElement(self, index=None):
          if index is None:
              return AbsolutePanel.getElement(self)
          return self.getWidget(index).getElement()
  
      # Gets the widget in the pane at end of the line direction for the layout
      def getEndOfLineWidget(self):
          return self.getWidget(1)
  
      # Gets the element that is acting as the splitter.
      def getSplitElement(self):
          return self._splitter.getElement()
  
      # Gets the widget in the pane at the start of line direction for the layout
      def getStartOfLineWidget(self):
          return self.getWidget(0)
  
      # Indicates whether the split panel is being resized.
      def isResizing(self):
          return False
  
      # Sets the widget in the pane at the end of line direction for the layout
      def setEndOfLineWidget(self, widget):
          self.setWidget(1, widget)
  
      def setStartOfLineWidget(self, widget):
          self.setWidget(0, widget)
  