Lyle Johnson wrote:
> I'm looking to make an API change for some methods in FXRuby and would
> appreciate some suggestions about how to improve them. The pattern shows up
> in several places in the code, but it always boils down to some widget
> attribute that can have a combination of bit-flags. 

Well, i haven't used FXRuby very much, so i might miss the problem with 
the current interface, but from what i see below i think this new 
version doesn't justify breaking old code.

> For example, the 4-way
> splitter window can be configured to expand only its top-left pane:
> 
> splitter1.expanded = TOP_LEFT

Seems perfectly fine. Ok :top_left if more ruby'ish but also more 
dangerous.

> or to expand both the top left and top right panes:
> 
> splitter2.expanded = TOP_LEFT | TOP_RIGHT

Also fine. Perhaps define a TOP constant for those who don't like binary 
operations.

> And to check whether, say, the BOTTOM_LEFT pane is expanded:
> 
> (splitter3.expanded & BOTTOM_LEFT) != 0

Ok, agreed, this isn't very nice.

> Now, what I'm thinking of doing is replacing the symbolic constants with
> Ruby symbols, and doing something like this instead:
> 
> splitter1.expand(:top_left)
> splitter2.expand(:top_left, :top_right)

Well, i don't like using 2 parameters when it is only one logically.

> and then having checks like:
> 
> splitter3.expanded? :bottom_left

I don't like that either.

> I think that in order to "turn off" one of those bits, I'm probably also
> going to need to add something like:
> 
> splitter4.unexpand(:bottom_right)

Oh, and i realy dislike this.

> Now, the question is, is there some existing pattern in Ruby that this
> reminds you of? In other words, what is the Ruby Way to handle this kind of
> setting?

The following isn't meant to be 'the soultion' but perhaps food for 
thoughts:
-------------------------------------------------------------
require 'set'

class Symbol
   def method_missing meth, *param
     set = Set[self]
     set.send meth, param.to_a if set.respond_to?(meth)
   end
end

class Splitter
   attr_accessor :expanded
end

TOP_LEFT = :top_left
TOP_RIGHT =  :top_right
BOTTOM_LEFT = :bottom_right
BOTTOM_RIGHT = :bottom_right

splitter = Splitter.new

splitter.expanded = TOP_LEFT
p splitter.expanded
#=> :top_left

splitter.expanded = TOP_LEFT | TOP_RIGHT
p splitter.expanded
#=><Set: {:top_right, :top_left}>

p splitter.expanded.include?(BOTTOM_LEFT)
#=> false

p splitter.expanded.include?(TOP_LEFT)
#=> true

splitter.expanded = :bottom_left | :top_left
p splitter.expanded
#=> #<Set: {:bottom_left, :top_left}>

splitter.expanded.delete(:top_left)
p splitter.expanded
#=> #<Set: {:bottom_left}>
-------------------------------------------------------------

cheers

Simon