//
// Copyright (c) 2008, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   15 Sep 08  Andy Frank   Creation
//   10 Aug 09  Brian Frank  Refactor to use gfx::Border
//

using gfx

**
** BorderPane is used paint a CSS styled border around a content widget.
**
@Js
@Serializable { collection = true }
class BorderPane : ContentPane
{
  **
  ** Border to paint around the edge of the content.
  ** Default is zero pixels.
  **
  Border border := Border.defVal

  **
  ** Background to paint under content, or null for transparent.
  ** The background does not include the border itself, but
  ** does include the insets and content.  Default is null.
  **
  Brush? bg := null

  **
  ** Insets to leave between border and the content.
  ** Default is zero pixels.
  **
  Insets insets := Insets(0,0,0,0)

  override Size prefSize(Hints hints := Hints.defVal)
  {
    edgew := border.widthLeft + insets.left + insets.right  + border.widthRight
    edgeh := border.widthTop  + insets.top  + insets.bottom + border.widthBottom
    edge  := Size(edgew, edgeh)
    if (content == null) return edge
    pref  := content.prefSize(hints - edge)
    return Size(pref.w + edgew, pref.h + edgeh)
  }

  override Void onLayout()
  {
    if (content == null) return
    size := this.size
    content.bounds = Rect(
      border.widthLeft + insets.left,
      border.widthTop + insets.top,
      size.w - border.widthLeft - insets.left - insets.right  - border.widthRight,
      size.h - border.widthTop  - insets.top  - insets.bottom - border.widthBottom)
  }

  internal Void onPaint(Graphics g)
  {
    w := size.w
    h := size.h
    shade := 0.3f

    // background (doesn't support radius well yet)
    if (bg != null)
    {
      g.brush = bg
      g.fillRect(0, 0, w, h)
    }

    // left side
    if (border.widthLeft > 0)
    {
      g.pen = Pen { width = border.widthLeft }
      switch (border.styleLeft)
      {
        case Border.styleInset:  g.brush = border.colorLeft.darker(shade)
        case Border.styleOutset: g.brush = border.colorLeft.lighter(shade)
        default:                 g.brush = border.colorLeft
      }

      off := border.widthLeft / 2
      x := off

      g.drawLine(x, border.radiusTopLeft+off, x, h-border.radiusBottomLeft-off)
    }

    // right side
    if (border.widthRight > 0)
    {
      g.pen = Pen { width = border.widthRight }
      switch (border.styleRight)
      {
        case Border.styleInset:  g.brush = border.colorRight.lighter(shade)
        case Border.styleOutset: g.brush = border.colorRight.darker(shade)
        default:                 g.brush = border.colorRight
      }

      off := border.widthRight / 2
      if (border.widthRight.isOdd) ++off
      x := w - off

      g.drawLine(x, border.radiusTopRight+off, x, h-border.radiusBottomRight-off)
    }

    // top side
    if (border.widthTop > 0)
    {
      g.pen = Pen { width = border.widthTop }
      switch (border.styleTop)
      {
        case Border.styleInset:  g.brush = border.colorTop.darker(shade)
        case Border.styleOutset: g.brush = border.colorTop.lighter(shade)
        default:                 g.brush = border.colorTop
      }

      off := border.widthTop / 2
      y := off

      g.drawLine(border.radiusTopLeft+off, y, w-border.radiusTopRight-off, y)

      // top-left corner
      if (border.radiusTopLeft > 0)
        g.drawArc(off, off, border.radiusTopLeft*2, border.radiusTopLeft*2, 90, 90)

      // top-right corner
      if (border.radiusTopRight > 0)
        g.drawArc(w-border.radiusTopRight*2-off-1, off, border.radiusTopRight*2, border.radiusTopRight*2, 0, 90)
    }

    // bottom side
    if (border.widthBottom > 0)
    {
      g.pen = Pen { width = border.widthBottom }
      switch (border.styleBottom)
      {
        case Border.styleInset:  g.brush = border.colorBottom.lighter(shade)
        case Border.styleOutset: g.brush = border.colorBottom.darker(shade)
        default:                 g.brush = border.colorBottom
      }

      off := border.widthBottom / 2
      if (border.widthBottom.isOdd) ++off
      y := h - off

      g.drawLine(border.radiusBottomLeft+off, y, w-border.radiusBottomRight-off, y)

      // bottom-left corner
      if (border.radiusBottomLeft > 0)
        g.drawArc(off, h-border.radiusBottomLeft*2-off, border.radiusBottomLeft*2, border.radiusBottomLeft*2, 180, 90)

      // bottom-right corner
      if (border.radiusBottomRight > 0)
        g.drawArc(w-border.radiusBottomRight*2-off, h-border.radiusBottomRight*2-off, border.radiusBottomRight*2, border.radiusBottomRight*2, 270, 90)
    }
  }

  // to force native peer
  private native Void dummyBorderPane()

}