;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; button widget
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
register-widget button:
  lambda button-ctor ()
    define super new-basic-widget()
    define mouse-inside #f
    define default #f
    define escape #f
    define def/esc-activate #f
    ;;
    method-lambda button-widget
      super: (self)
        super
      type: (self)
        button:
      selectable?: (self)
        {not self[ignore?:]}
      text-set!: (self value)
        ;printf "button: new text: %o\n" value
        assert {string? value} "invalid text property"
        inherited text-set!: value
        {self[pref-width:] := {lgfx:text-width-hi(value) + 4}}
        self
      ;;
      def/esc-activate?: (self)
        def/esc-activate
      def/esc-activate-set!: (self value)
        assert {boolean? value} "def/esc-activate flag should be boolean"
        {def/esc-activate := value}
        self
      ;;
      default?: (self) default
      default-set!: (self value)
        assert {boolean? value} "default flag should be boolean"
        {default := value}
        self
      ;;
      escape?: (self) escape
      escape-set!: (self value)
        assert {boolean? value} "escape flag should be boolean"
        {escape := value}
        self
      ;;
      pref-width-set!: (self value)
        define text self[text:]
        define tw {lgfx:text-width-hi(text) + 4}
        {value := max(value tw)}
        inherited pref-width-set!: value
        self
      ;;
      paint: (self)
        define wdt self[final-width:]
        define hgt self[final-height:]
        define bc self[style-color-prop: "back"]
        define tc self[style-color-prop: "text"]
        define hc self[style-color-prop: "hi"]
        lgfx:fill-round-rect 0 0 wdt hgt bc
        self[update-clip-rect: 1 1 {wdt - 2} {hgt - 2}]
        define text self[text:]
        define tw lgfx:text-width-hi(text)
        define xofs 0
        define yofs 0
        if {mouse-inside and {not-zero? mouse-button-state} and self[active?:]}
          then
            inc! xofs
            inc! yofs
        lgfx:print-str-hi
          {xofs + {{wdt - tw} div 2}}
          {yofs + {{hgt - lgfx:text-height()} div 2} + lgfx:text-ascender()}
          text
          tc
          hc
        self
      ;;
      handle-event: (self evt)
        if {evt[alive?:] and self[active?:]}
          case evt[type:]
            (KEY-DOWN)
              if (or sdl:names-equal?("space" evt[keysym:])
                     sdl:names-equal?("return" evt[keysym:])
                     sdl:names-equal?(self[hotkey:] evt[keysym:])
                     {self[escape?:] and sdl:names-equal?("escape" evt[keysym:])})
                then
                  {mouse-inside := #f}
                  evt[eat!:]
                  self[perform-action:]
            (MOUSE-MOTION)
              cond
                {zero? mouse-button-state}
                  if mouse-inside
                    then
                      evt[dirty!:]
                      {mouse-inside := #f}
                else
                  if {mouse-inside <> {{mouse-inside := self[xy-in-box?: evt[x:] evt[y:]]}}}
                    evt[dirty!:]
            (MOUSE-DOWN)
              if {mouse-inside <> {{mouse-inside := self[xy-in-box?: evt[x:] evt[y:]]}}}
                evt[dirty!:]
            (MOUSE-UP)
              if {mouse-inside <> {{mouse-inside := self[xy-in-box?: evt[x:] evt[y:]]}}}
                evt[dirty!:]
              if {evt[destination:] eq? self}
                then
                  evt[eat!:]
                  if (and {zero? mouse-button-state}
                          self[xy-in-box?: evt[x:] evt[y:]])
                    then
                      {mouse-inside := #f}
                      self[perform-action:]
            else #void
          ;; hotkey, default, escape
          if (and evt[alive?:]
                  evt[key-broadcast?:]
                  {evt[type:] eq? 'KEY-DOWN})
            if (or sdl:names-equal?(self[hotkey:] evt[keysym:])
                   {self[default?:] and sdl:names-equal?("return" evt[keysym:])}
                   {self[escape?:] and sdl:names-equal?("escape" evt[keysym:])})
              then
                {mouse-inside := #f}
                evt[eat!:]
                if self[def/esc-activate?:]
                  self[top-widget:][activate-widget: self]
                self[perform-action:]
        if evt[alive?:]
          inherited handle-event: evt
      ;;
      handle-property: (self name value)
        self[property-changed: name value]
        case name
          (default:)
            {self[default:] := value}
            #t
          (escape:)
            {self[escape:] := value}
            #t
          (def/esc-activate:)
            {self[def/esc-activate:] := value}
            #t
          else
            inherited handle-property: name value
      ;;
      else
        super
