Module: WxSugar::Arranger

Defined in:
lib/wx_sugar/layout.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#paddingObject

Returns the value of attribute padding.



62
63
64
# File 'lib/wx_sugar/layout.rb', line 62

def padding
  @padding
end

Class Method Details

.included(klass) ⇒ Object



53
54
55
56
57
58
59
60
# File 'lib/wx_sugar/layout.rb', line 53

def self.included(klass)
  old_meths = klass.instance_methods
  # Needs to be correct for both ruby 1.8 and ruby 1.9
  unless old_meths.include?('add') or old_meths.include?(:add)
    # don't over-write methods in sizer
    klass.module_eval { alias_method :add, :nest }
  end
end

Instance Method Details

#arrange(a_sizer, layout = {}) ⇒ Object

Set the main or current sizer of this container window to be a_sizer. If no block is given, then a_sizer is used as the main default sizer for this window. Note that this form should only be called once, before any child widgets have been added to the container.

If a block is passed, then the a_sizer is nested within the container window’s main default sizer. For the duration of the block Widgets added to the container will be added to the nested sizer. If the nested form is called, layout may contain a layout hint hash. This can contain the key :proportion, which should specify the integer resizing proportion for this nested sizer within the container’s main arrangement.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/wx_sugar/layout.rb', line 96

def arrange(a_sizer, layout = {})
  # run as a subordinate block
  if block_given? and @current_sizer
    if layout[:padding]
      old_padding = @padding
      @padding = layout[:padding] 
    end

    superior_sizer, @current_sizer = @current_sizer, a_sizer
    yield(a_sizer)
    @current_sizer = superior_sizer
    proportion = layout[:proportion] || 0
    this_padding = padding || 0
    superior_sizer.add( a_sizer, proportion, 
                        Wx::EXPAND|Wx::ALL|Wx::ADJUST_MINSIZE,
                       this_padding)

    if layout[:padding]
      @padding = old_padding
    end
  # set as main sizer            
  else
    if @current_sizer
      warn "Sizer already specified, redefining layout for #{self}"
    end        
    @padding = layout[:padding] if layout[:padding]
    @current_sizer = a_sizer
    yield(a_sizer) if block_given?
    self.set_sizer(a_sizer)
  end
end

#arrange_grid(layout, &block) ⇒ Object

takes hash arguments layout

:rows - integer, number of rows (mandatory, see below)
:cols - integer, number of columns (mandatory, see below)
:vgap - integer, extra vertical space between each child (optional)
:hgap - integer, extra horizontal space between each child (optional)

At least one of :rows and :cols must be specified. If one is not specified, the other will be calculated dynamically based on the total number of child widgets added.



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/wx_sugar/layout.rb', line 190

def arrange_grid(layout, &block)
  unless layout[:rows] or layout[:cols]
    Kernel.raise ArgumentError,
                 "At least one of :rows or :cols must be specified"
  end

  if layout[:padding]
    layout[:vgap] = layout[:hgap] = layout[:padding]
  end

  # wxruby wants them in this order, and with nought if null
  args = [ :rows, :cols, :vgap, :hgap ].map { | arg | layout[arg] or 0 }
  sizer = Wx::FlexGridSizer.new(*args)
  arrange( sizer, layout, &block )
end

#arrange_horizontally(layout = { }, &block) ⇒ Object



153
154
155
# File 'lib/wx_sugar/layout.rb', line 153

def arrange_horizontally( layout = { }, &block )
  arrange_linear( layout.merge( :direction => :horizontal ), &block )
end

#arrange_linear(layout = { }, &block) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/wx_sugar/layout.rb', line 157

def arrange_linear( layout = { }, &block)
  if layout[:direction].to_s.downcase == 'horizontal'
    direction = Wx::HORIZONTAL
  elsif layout[:direction].to_s.downcase == 'vertical'
    direction = Wx::VERTICAL
  else
    Kernel.raise ArgumentError, 
                 "Unknown direction '#{layout[:direction].inspect}'"
  end
  
  if layout[:label]
    sb = Wx::StaticBox.new( self, -1, layout[:label] )
    sizer = Wx::StaticBoxSizer.new( sb, direction )
  elsif layout[:box]
    sb = Wx::StaticBox.new( self, -1, '' )
    sizer = Wx::StaticBoxSizer.new( sb, direction )
  else
    sizer = Wx::BoxSizer.new(direction)
  end
  arrange(sizer, layout, &block)
end

#arrange_vertically(layout = { }, &block) ⇒ Object



149
150
151
# File 'lib/wx_sugar/layout.rb', line 149

def arrange_vertically( layout = { }, &block )
  arrange_linear( layout.merge( :direction => :vertical ), &block )
end

#build_child(child) ⇒ Object

Construct a WxWidget as specified by child to add to my arrangement



207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/wx_sugar/layout.rb', line 207

def build_child(child)
  case child
  when Proc # delayed constructor
    child = child.call(self)
  when Class # bare class
    child = child.new(self)
  when Wx::Window, Wx::Sizer # ready-to-go widget
    child = child
  else
    Kernel.raise ArgumentError,
                 "Cannot add #{child.inspect} to #{self}"
  end
end

#current_sizerObject

Returns the underlying sizer currently being used by this container. User code should not normally need to call this method.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/wx_sugar/layout.rb', line 66

def current_sizer()
  if @current_sizer
    return @current_sizer 
  else
    begin 
      if @current_sizer = self.get_sizer
        return @current_sizer
      end
    rescue RuntimeError # Some wxRuby versions would error on get_sizer
    end
  end
  
  @current_sizer = Wx::BoxSizer.new(Wx::VERTICAL)
  self.set_sizer(@current_sizer)
  @current_sizer
end

#hints_to_constants(layout_hints) ⇒ Object

Convert a hash of layout hints to WxWidgets Sizer constants



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/wx_sugar/layout.rb', line 223

def hints_to_constants(layout_hints)
  if layout_hints[:pad]
    layout = layout_hints[:pad].split(',').inject(0) do | l, edge |
      l | Wx::const_get(edge.upcase)
    end
  else
    layout = Wx::ALL
  end

  if layout_hints[:minsize]
    layout = layout | Wx::ADJUST_MINSIZE|Wx::EXPAND
  end
  if layout_hints[:proportion]
    layout = layout | Wx::EXPAND
  end

  
  if align = layout_hints[:align]
    begin
      align_const = Wx::const_get('ALIGN_' << align.to_s.upcase)
      layout = layout | align_const
    rescue NameError
      Kernel.raise ArgumentError,
                   "Invalid align argument #{layout_hints[:align]}"
    end
  end
  layout
end

#nest(child, layout_hints = {}) {|child| ... } ⇒ Object

Add child to the container window’s layout, sizing and placing it according to layout_hints

Layout hints may contain the keys

:proportion
:minsize

Yields:

  • (child)


134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/wx_sugar/layout.rb', line 134

def nest(child, layout_hints = {})
  child  = build_child(child)
  layout = hints_to_constants(layout_hints)
  proportion = layout_hints[:proportion] || 0
  siz = self.current_sizer
  padding = layout_hints[:padding] || @padding

  siz.add(child, proportion, layout, padding || 0)
  siz.layout()
  
  yield child if block_given?
  return child
end