module Fox
  
  class FXCheckButton
    #
    # Return +true+ if the check state for this check button is +TRUE+,
    # or +false+ if the check state is either +FALSE+ or +MAYBE+.
    #
    def checked?
      self.check == TRUE
    end
    
    #
    # Return +true+ if the check state for this check button is +FALSE+,
    # or +false+ if the check state is either +TRUE+ or +MAYBE+.
    #
    def unchecked?
      self.check == FALSE
    end

    # 
    # Return +true+ if the check state for this check button is +MAYBE+,
    # or +false+ if the check state is either +TRUE+ or +FALSE+.
    #
    def maybe?
      self.check == MAYBE
    end
  end

  class FXIconItem
    def <=>(otherItem)
      text <=> otherItem.text
    end
  end

  class FXListItem
    def <=>(otherItem)
      text <=> otherItem.text
    end
  end
  
  class FXTreeItem
    def <=>(otherItem)
      text <=> otherItem.text
    end
  end

  class FXDataTarget
    #
    # Returns the stringified representation of this
    # data target's value.
    #
    def to_s
      value.to_s
    end
  end
  
  class FXHeader
    #
    # Returns true if the specified header item's arrow points
    # up. Raises IndexError if _index_ is out of bounds.
    #
    def arrowUp?(index)
      if index < 0 || index >= numItems 
        raise IndexError, "header item index out of bounds"
      else
        getArrowDir(index) == Fox::TRUE
      end
    end

    #
    # Returns true if the specified header item's arrow points
    # down. Raises IndexError if _index_ is out of bounds.
    #
    def arrowDown?(index)
      if index < 0 || index >= numItems 
        raise IndexError, "header item index out of bounds"
      else
        getArrowDir(index) == Fox::FALSE
      end
    end

    #
    # Returns true if the specified header item does not display
    # any arrow. Raises IndexError if _index_ is out of bounds.
    #
    def arrowMaybe?(index)
      if index < 0 || index >= numItems 
        raise IndexError, "header item index out of bounds"
      else
        getArrowDir(index) == Fox::MAYBE
      end
    end
  end

  class FXMenuCheck
    #
    # Return +true+ if the check state for this menu check item is +TRUE+,
    # or +false+ if the check state is either +FALSE+ or +MAYBE+.
    #
    def checked?
      self.check == TRUE
    end
    
    #
    # Return +true+ if the check state for this menu check item is +FALSE+,
    # or +false+ if the check state is either +TRUE+ or +MAYBE+.
    #
    def unchecked?
      self.check == FALSE
    end

    # 
    # Return +true+ if the check state for this menu check item is +MAYBE+,
    # or +false+ if the check state is either +TRUE+ or +FALSE+.
    #
    def maybe?
      self.check == MAYBE
    end
  end

  class FXScrollArea
	  # Returns a reference to the scroll corner (an FXScrollCorner instance) for this window.
	  def scrollCorner
		  verticalScrollBar.next
		end
	end

  class FXSettings
    #
    # Read a boolean registry entry from the specified _section_ and _key_.
    # If no value is found, the _default_ value is returned.
    #
    def readBoolEntry(section, key, default=false)
      default = default ? 1 : 0
      readIntEntry(section, key, default) != 0
    end
    
    #
    # Write a boolean registry _value_ to the specified _section_ and _key_.
    #
    def writeBoolEntry(section, key, value)
      writeIntEntry(section, key, value ? 1 : 0)
    end
  end
  
  class FXWindow
    #
    # Iterate over the child windows for this window.
    #
    def each_child
      child = self.first
      while child
        yield child
	child = child.next
      end
    end
  end

  #
  # The drag-and-drop data used for colors is a sequence of unsigned short
  # integers, in native byte ordering. Here, we use the 'S' directive for
  # String#unpack (which treats two successive characters as an unsigned short
  # in native byte order) to decode the R, G, B and A values.
  #
  def Fox.fxdecodeColorData(data)
    clr = data.unpack('S4')
    Fox.FXRGBA((clr[0]+128)/257, (clr[1]+128)/257, (clr[2]+128)/257, (clr[3]+128)/257)
  end

  #
  # The drag-and-drop data used for colors is a sequence of unsigned short
  # integers, in native byte ordering. Here, we use the 'S' directive for
  # Array#pack (which treats two successive characters as an unsigned short
  # in native byte order) to encode the R, G, B and A values.
  #
  def Fox.fxencodeColorData(rgba)
    clr = [ 257*Fox.FXREDVAL(rgba), 257*Fox.FXGREENVAL(rgba), 257*Fox.FXBLUEVAL(rgba), 257*Fox.FXALPHAVAL(rgba) ]
    clr.pack('S4')
  end

  #
  # The drag-and-drop data used for clipboard strings (i.e. when the
  # drag type is FXWindow.stringType) is either a null-terminated
  # string (for Microsoft Windows) or a non-null terminated string
  # (for X11). Use this method to convert string data from the
  # clipboard back into a Ruby string.
  #
  def Fox.fxdecodeStringData(data)
    if /mswin/ =~ PLATFORM
      data.chop
    else
      data
    end
  end

  #
  # The drag-and-drop data used for clipboard strings (i.e. when the
  # drag type is FXWindow.stringType) is either a null-terminated
  # string (for Microsoft Windows) or a non-null terminated string
  # (for X11). Use this method to convert Ruby strings into a format
  # appropriate for the current platform.
  #
  def Fox.fxencodeStringData(str)
    if /mswin/ =~ PLATFORM
      str + "\0"
    else
      str
    end
  end

  #
  # FXStreamError is the base class for exceptions which can occur when
  # working with FXStream and its subclasses.
  #
  class FXStreamError < StandardError
    #
    # This is a factory method that takes an FXStreamStatus code
    # as its input and returns the appropriate exception class.
    #
    def FXStreamError.makeStreamError(status)
      case status
	when FXStreamEnd
	  FXStreamEndError
	when FXStreamFull
	  FXStreamFullError
	when FXStreamNoWrite
	  FXStreamNoWriteError
	when FXStreamNoRead
	  FXStreamNoReadError
	when FXStreamFormat
	  FXStreamFormatError
	when FXStreamUnknown
	  FXStreamUnknownError
	when FXStreamAlloc
	  FXStreamAllocError
	when FXStreamFailure
	  FXStreamFailureError
	else
	  FXStreamError
      end
    end
  end
  
  # Tried to read past the end of a stream
  class FXStreamEndError < FXStreamError ; end
  
  # Filled up a stream's internal buffer, or the disk is full
  class FXStreamFullError < FXStreamError ; end
  
  # Unable to open for write
  class FXStreamNoWriteError < FXStreamError ; end
  
  # Unable to open for read
  class FXStreamNoReadError < FXStreamError ; end
  
  # Stream format error
  class FXStreamFormatError < FXStreamError ; end
  
  # Trying to read unknown class
  class FXStreamUnknownError < FXStreamError ; end
  
  # Alloc failed
  class FXStreamAllocError < FXStreamError ; end
  
  # General failure
  class FXStreamFailureError < FXStreamError ; end
  
  class FXDC
    #
    # Draw a circle centered at (_x_, _y_), with specified radius.
    #
    # === Parameters:
    #
    # +x+::	x-coordinate of the circle's center [Integer]
    # +y+::	y-coordinate of the circle's center [Integer]
    # +r+::	radius of the circle, in pixels [Integer]
    #
    # See also #fillCircle.
    #
    def drawCircle(x, y, r)
      drawArc(x-r, y-r, 2*r, 2*r, 0, 360*64)
    end

    #
    # Draw a filled circle centered at (_x_, _y_), with specified radius.
    #
    # === Parameters:
    #
    # +x+::	x-coordinate of the circle's center [Integer]
    # +y+::	y-coordinate of the circle's center [Integer]
    # +r+::	radius of the circle, in pixels [Integer]
    #
    # See also #drawCircle.
    #
    def fillCircle(x, y, r)
      fillArc(x-r, y-r, 2*r, 2*r, 0, 360*64)
    end
  end

  class FXHVec
    def normalize!
      normalized = self.normalize
      0.upto(3) { |idx| self[idx] = normalized[idx] }
      self
    end
  end
  
  class FXTable
    #
    # Append _numColumns_ columns to the right of the table..
    # If _notify_ is +true+, a <tt>SEL_INSERTED</tt> message is sent to the
    # tableÕs message target for each cell that is inserted.
    #
    def appendColumns(numColumns=1, notify=false)
      insertColumns(self.numColumns, numColumns, notify)
    end
    
    #
    # Append _numRows_ rows to the bottom of the table..
    # If _notify_ is +true+, a <tt>SEL_INSERTED</tt> message is sent to the
    # tableÕs message target for each cell that is inserted.
    #
    def appendRows(numRows=1, notify=false)
      insertRows(self.numRows, numRows, notify)
    end
    
    # Select cell at (_row_, _col_).
    # If _notify_ is +true+, a +SEL_SELECTED+ message is sent to the table's message target
    # after the item is selected.
    # Raises IndexError if either _row_ or _col_ is out of bounds.
    #
    def selectItem(row, col, notify=false)
      selectRange(row, row, col, col, notify)
    end
  end
end

