Simon Kröger
2/9/2006 8:43:00 PM
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