module Tk
  # Translation from Tcl: http://wiki.tcl.tk/1954
  class Tooltip < Struct.new(:text, :tooltip)
    def bind_to(widget)
      widget.bind('<Any-Enter>') { Tk::After.ms(500) { show(widget) } }
      widget.bind('<Any-Leave>') { Tk::After.ms(500) { destroy } }
      widget.bind('<Any-KeyPress>') { Tk::After.ms(500) { destroy } }
      widget.bind('<Any-Button>') { Tk::After.ms(500) { destroy } }
    end

    def destroy
      tooltip.destroy
    rescue NoMethodError, RuntimeError => ex
    end

    def show_on(widget)
      root = Tk.root
      root_pointerx = root.winfo_pointerx
      root_pointery = root.winfo_pointery
      return unless Tk::Winfo.containing(root_pointerx, root_pointery)

      destroy

      scrh = widget.winfo_screenheight
      scrw = widget.winfo_screenwidth

      self.tooltip = tooltip = Tk::Toplevel.new(widget, bd: true, bg: 'black')
      tooltip.wm_geometry = "+#{scrh}+#{scrw}"
      tooltip.wm_overrideredirect = true
      tooltip.attributes(topmost: true) if tooltip.tk_windowingsystem == :win32

      label = Tk::Label.new(tooltip, bg: :lightyellow, fg: :black,
                                     text: text, justify: :left).pack

      width = label.winfo_reqwidth
      height = label.winfo_reqheight

      position_x = root_pointerx
      position_y = root_pointery + 25
      root_screen_width = root.winfo_screenwidth

      if (position_x + width) > root_screen_width
        position_x -= ((position_x + width) - root_screen_width)
      end

      tooltip.wm_geometry = "#{width}x#{height}+#{position_x}+#{position_y}"
      tooltip.raise

      tooltip.bind('Any-Enter') { destroy }
      tooltip.bind('Any-Leave') { destroy }
    end
  end
end

if $PROGRAM_NAME == __FILE__
  require 'ffi-tk'

  button = Tk::Button.new(text: 'hello').pack
  tooltip = Tk::Tooltip.new('Hello, World!')
  tooltip.bind_to(button)

  Tk.mainloop
end
