Lyle J. 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