wx_sugar 0.1.14 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,162 @@
1
+ # This module enhances the family of GUI controls which display a list
2
+ # of labelled items and allow the user to select one or more
3
+ # items. Classes of this type include Wx::Choice, Wx::ComboBox and
4
+ # Wx::ListBox. This module allows easy iteration over the contents of
5
+ # these object using Ruby's +each+ and Enumerable methods.
6
+ #
7
+ # Note that including this file on its own won't enable this behaviour
8
+ # for any classes; you should load it via the class extensions for
9
+ # +control_with_items.rb+ and +listctrl.rb+.
10
+ module WxSugar::EnumerableControl
11
+ include Enumerable
12
+ module ClassMethods
13
+ # Used internally to define a proxy object for items.
14
+ def collection(name, coll_class)
15
+ define_method(name) { coll_class.new(self) }
16
+ end
17
+ end
18
+
19
+ def self.included(klass)
20
+ klass.extend ClassMethods
21
+ end
22
+
23
+ # Iterates over the items in the control. In its simplest form, it
24
+ # passes the index of each item into the passed block:
25
+ #
26
+ # control.each | i |
27
+ # puts "String at #{i} is '#{control.string(i)}'"
28
+ # end
29
+ #
30
+ # The passed block may have up to three block parameters, +i+,
31
+ # +string+, and +data+. The second parameter, if requested, is filled
32
+ # with the string label of the item within the control. The third
33
+ # parameter is filled with the client data associated with the
34
+ # item. Note that if you don't need the string or client data, it is
35
+ # more efficient to iterate over the indexes only.
36
+ def each(&block)
37
+ last = get_count - 1
38
+ case block.arity
39
+ when 1
40
+ 0.upto(last) { | i | yield i }
41
+ when 2
42
+ 0.upto(last) { | i | yield i, get_string(i) }
43
+ when 3
44
+ 0.upto(last) { | i | yield i, get_string(i), get_item_data(i) }
45
+ else
46
+ raise ArgumentError, "Invalid number of block parameters"
47
+ end
48
+ end
49
+
50
+ # Returns the index of the item in the control corresponding to
51
+ # +value+. +value+ may be a string label, or it may be any ruby object
52
+ # set as client data to a list item. Returns +nil+ if nothing matches.
53
+ def index(value)
54
+ # -1 means 'not found' in WxWidgets
55
+ if value.kind_of?(String) && ( i = find_string(value, true) ) && i > -1
56
+ return i
57
+ end
58
+ indices = (0 ... get_count).to_a
59
+ return indices.find { | i | get_item_data(i) == value }
60
+ end
61
+
62
+ # Appends this string to the control
63
+ def <<(str)
64
+ append(str)
65
+ end
66
+
67
+ # Deletes any items in the control for which the passed block
68
+ # evaluates to +true+.
69
+ def delete_if
70
+ deletions = []
71
+ each { | i | deletions << i if yield i }
72
+ deletions.reverse.each { | i | delete(i) }
73
+ end
74
+
75
+ # These classes provide proxy accessors for items within the control.
76
+ # ItemCollection is an abstract base class.
77
+ class ItemCollection
78
+ attr_reader :cwi
79
+ def initialize(cwi)
80
+ @cwi = cwi
81
+ end
82
+
83
+ # Do a bounds-checked call of some value-fetching method +methdo+
84
+ # for the item +i+
85
+ def [](method, i)
86
+ unless index?(i)
87
+ raise IndexError, "No such item #{i} in #{self.cwi}"
88
+ end
89
+ cwi.send( method, i )
90
+ end
91
+
92
+ # Do a bounds-checked call of some value-setting method +methdo+
93
+ # for the item +i+ to value +val+
94
+ def []=(method, i, val)
95
+ unless index?(i)
96
+ raise IndexError, "No such item #{i} in #{self.cwi}"
97
+ end
98
+ cwi.send( method, i, val )
99
+ end
100
+
101
+ # over-ridden by some subclasses
102
+ def index?(i)
103
+ i >= 0 and i < cwi.get_count
104
+ end
105
+ end
106
+
107
+ # A proxy class for the item_data functions.
108
+ class ItemDataCollection < ItemCollection
109
+ def each
110
+ cwi.each { | i | yield cwi.get_item_data(i) }
111
+ end
112
+
113
+ # Retrieves the item data for item +i+
114
+ def [](i)
115
+ super :get_item_data, i
116
+ end
117
+
118
+ # Sets the item data for +i+ to be +obj+
119
+ def []=(i, obj)
120
+ super :set_item_data, i, obj
121
+ end
122
+ end
123
+
124
+ # A proxy class for classes that use get/set_string to set labels,
125
+ # inheriting from ControlWithItems.
126
+ class StringsCollection < ItemCollection
127
+ def each
128
+ cwi.each { | i | yield cwi.get_string(i) }
129
+ end
130
+
131
+ # Retrieves the string for item +i+
132
+ def [](i)
133
+ super :get_string, i
134
+ end
135
+
136
+ # Sets a string within the control
137
+ def []=(i, str)
138
+ super :set_string, i, str
139
+ end
140
+ end
141
+
142
+ # Fetching strings from a ListCtrl
143
+ class ListItemTextCollection < ItemCollection
144
+ def each
145
+ cwi.each { | i | yield cwi.get_item_text(i) }
146
+ end
147
+
148
+ # Retrieves the string for item +i+
149
+ def [](i)
150
+ super :get_item_text, i
151
+ end
152
+
153
+ # Sets a string within the control
154
+ def []=(i, str)
155
+ super :set_item_text, i, str
156
+ end
157
+
158
+ def index?(i)
159
+ i >= 0 and i < cwi.get_item_count
160
+ end
161
+ end
162
+ end
@@ -1,3 +1,3 @@
1
1
  module WxSugar
2
- VERSION = '0.1.14'
2
+ VERSION = '0.1.15'
3
3
  end
@@ -0,0 +1,23 @@
1
+ require 'wx_sugar/enumerable_controls'
2
+
3
+ # Uses WxSugar::EnumerableControl to provide methods for iterating over
4
+ # the items within the control.
5
+ #
6
+ # Instances of all ControlWithItems classes then have an +each+ and an
7
+ # +index+ method, plus all the methods supplied by Enumerable, such as
8
+ # +collect+, +find+ and +any?+.
9
+ #
10
+ # They also have a +strings+ method which can be used as an array-like
11
+ # accessor to the labels of the string:
12
+ #
13
+ # choice = Wx::Choice.new(parent, :choices => %w|foo bar|)
14
+ # choice.strings[1] # bar
15
+ # choice.strings[0] = 'quux' # set the first item in the control
16
+ #
17
+ # Similarly, there is a +data+ method to access the item data associated
18
+ # with the control by numeric index.
19
+ class Wx::ControlWithItems
20
+ include WxSugar::EnumerableControl
21
+ collection :strings, StringsCollection
22
+ collection :data, ItemDataCollection
23
+ end
@@ -0,0 +1,38 @@
1
+ require 'wx_sugar/enumerable_controls'
2
+
3
+ class Wx::ListCtrl
4
+ include WxSugar::EnumerableControl
5
+ collection :strings, ListItemTextCollection
6
+ collection :data, ItemDataCollection
7
+
8
+ alias :get_string :get_item_text
9
+ alias :set_string :set_item_text
10
+ alias :get_count :get_item_count
11
+
12
+ # Appends
13
+ def <<(str)
14
+ insert_item(get_item_count, str)
15
+ end
16
+
17
+ # Emulate the ControlWithItems find_string method. Like the cognate
18
+ # method, it returns -1 if the string was not found.
19
+ def find_string(str, case_sensitive = false)
20
+ if case_sensitive
21
+ find_string_sensitively(str)
22
+ else
23
+ find_item(-1, str)
24
+ end
25
+ end
26
+
27
+ private
28
+ # Implement a case-sensitive search for ListCtrl (default find_item
29
+ # with string is always case-insensitive)
30
+ def find_string_sensitively(str)
31
+ start = -1
32
+ until found = find_item(start, str) and get_item_text(found) == str
33
+ break if found == -1 # Not found at all
34
+ start = found + 1
35
+ end
36
+ return found
37
+ end
38
+ end
@@ -1,13 +1,34 @@
1
1
  class Wx::TreeCtrl
2
2
  # Recurses over the tree item +start_item+ and its descendants,
3
- # yielding each Wx::TreeItemId in turn into the passed block. This
4
- # TreeItemId can be used as an argument to many other methods within
5
- # TreeCtrl (for example, get_item_text).
3
+ # yielding each item in the tree in turn into the block. If
4
+ # +start_item+ is not specified, this method will recurse over every
5
+ # item within the tree, starting with the root item.
6
6
  #
7
- # If +start_item+ is not specified, this method will recurse over
8
- # every item within the tree, starting with the root item.
7
+ # In its simplest form, the method accepts a block with one parameter,
8
+ # which will be the TreeItemId of the item. This is an opaque integer
9
+ # value which uniquely identifies the tree item. It can be used as an
10
+ # argument to many other methods within TreeCtrl (for example,
11
+ # get_item_text).
12
+ #
13
+ # The block passed to +traverse+ may optionally receive two additional
14
+ # parameters, +text+ and +data+. If these are specified, they will be
15
+ # filled with the text label for the item and any ruby item data
16
+ # associated with the item, respectively.
9
17
  def traverse(start_item = self.get_root_item, &block)
10
- block.call(start_item)
18
+ case block.arity
19
+ when 1
20
+ block.call(start_item)
21
+ when 2
22
+ block.call(start_item,
23
+ get_item_text(start_item))
24
+ when 3
25
+ block.call(start_item,
26
+ get_item_text(start_item),
27
+ get_item_data(start_item))
28
+ else
29
+ raise ArgumentError, "Invalid number of block parameters"
30
+ end
31
+
11
32
  if has_children(start_item)
12
33
  child, cookie = get_first_child(start_item)
13
34
  while child.nonzero?
@@ -18,7 +18,7 @@ class Wx::Window
18
18
  # # Example - find a StaticText with a label matching /foo/
19
19
  # a_frame.find_window(Wx::StaticText) { | tx | tx.label =~ /foo/ }
20
20
  def find_window(a_class = Wx::Window, &block)
21
- descendants.grep(a_class).detect(&block)
21
+ get_descendants.grep(a_class).detect(&block)
22
22
  end
23
23
 
24
24
  # Returns the window's current size as a two element array
@@ -32,4 +32,19 @@ class Wx::Window
32
32
  pos = get_position
33
33
  return pos.x, pos.y
34
34
  end
35
+
36
+ # Tests if the GUI object has the given window style +style+. Returns
37
+ # +style+ if it has been applied, or +nil+ if the window does not have
38
+ # that style.
39
+ #
40
+ # combobox.has_style?(Wx::CB_READONLY)
41
+ # textctrl.has_style?(Wx::TE_MULTILINE)
42
+ #
43
+ # Note that you should at least know that the constant +style+ is
44
+ # applicable to self. You may get false positives if testing a widget
45
+ # for a style belonging to an irrelevant class, e.g. testing a
46
+ # Wx::TextCtrl for the WX::CB_READONLY style.
47
+ def has_style?(style)
48
+ ( get_window_style & style ).nonzero?
49
+ end
35
50
  end
data/lib/wx_sugar.rb CHANGED
@@ -37,22 +37,25 @@
37
37
  #
38
38
  # The following are the WxSugar behaviours that are available. In
39
39
  # general you require one of these extensions, it modifies the behaviour
40
- # of all relevant Wx classes, and affects all new instances.
40
+ # of all relevant Wx classes, and affects all new instances. The
41
+ # following are listed in order of interest
41
42
  #
42
43
  # [accessors]
43
44
  # Provide ruby-style getters, setters and question-mark methods
44
- # [delayed_constructors]
45
- # Required by +layout+, of limited independent interest
46
- # [event_connector]
47
- # Neater syntax for connecting event listeners
48
45
  # [keyword_constructors]
49
46
  # Use keyword-style hash arguments to construct widgets
47
+ # [event_connector]
48
+ # Neater syntax for connecting event listeners
50
49
  # [layout]
51
50
  # Easy interface to using WxWidgets Sizers to arrange controls
52
- # [menu]
53
- # Create and update menus without a mess of system ids
54
51
  # [wx_classes]
55
52
  # Useful ruby methods added to individual Wx classes.
53
+ # [menu]
54
+ # Create and update menus without a mess of system ids
55
+ # [enumerable controls]
56
+ # Treat list-like GUI controls as Ruby enumerables with an +each+ method
57
+ # [delayed_constructors]
58
+ # Required by +layout+, of limited independent interest
56
59
  #
57
60
  # === Deprecated extensions
58
61
  #
@@ -18,9 +18,12 @@ class SugaryFrame < Wx::Frame
18
18
  add( Wx::Panel, :proportion => 1 ) do | panel |
19
19
  # a text control
20
20
  panel.background_colour = Wx::Colour.new(200, 150, 100)
21
- panel.add( Wx::TextCtrl[ :value => 'initial value',
21
+ tx = panel.add( Wx::TextCtrl[ :value => 'initial value',
22
22
  :style => Wx::TE_MULTILINE,
23
23
  :size => [200, 300] ] )
24
+ # test if a style is applied to a control
25
+ tx.has_style?(Wx::TE_MULTILINE) # true
26
+ tx.has_style?(Wx::TE_READONLY) # false
24
27
  end
25
28
 
26
29
  # use a nested grid sizer to arrange bottom area
@@ -32,8 +35,15 @@ class SugaryFrame < Wx::Frame
32
35
  end
33
36
 
34
37
  # a drop down
35
- choices = %w[ nasty nice ]
36
- add( Wx::Choice[ :choices => choices ], :padding => 4)
38
+ choices = add( Wx::Choice[ :choices => %w[ nasty nice salty ] ],
39
+ :padding => 4 )
40
+ choices << 'sweet'
41
+ # access client data via a collection
42
+ choices.data[3] = Object.new
43
+ # iterate over a dropdown's content simply
44
+ choices.each { | i | nil }
45
+ # iterate over a dropdown's full content
46
+ choices.each { | i, str, data | nil }
37
47
 
38
48
  # another button
39
49
  add( Wx::Button[ :label => 'foo' ] ) do | button |
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: wx_sugar
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.14
7
- date: 2007-03-22 00:00:00 +00:00
6
+ version: 0.1.15
7
+ date: 2007-04-03 00:00:00 +01:00
8
8
  summary: Syntax extensions for WxRuby.
9
9
  require_paths:
10
10
  - lib
@@ -36,6 +36,7 @@ files:
36
36
  - lib/wx_sugar/all.rb
37
37
  - lib/wx_sugar/class_definitions.rb
38
38
  - lib/wx_sugar/delayed_constructors.rb
39
+ - lib/wx_sugar/enumerable_controls.rb
39
40
  - lib/wx_sugar/event_connector.rb
40
41
  - lib/wx_sugar/itemdata.rb
41
42
  - lib/wx_sugar/keyword_classes.rb
@@ -46,6 +47,8 @@ files:
46
47
  - lib/wx_sugar/wx_classes
47
48
  - lib/wx_sugar/wx_classes.rb
48
49
  - lib/wx_sugar/wx_classes/colour.rb
50
+ - lib/wx_sugar/wx_classes/control_with_items.rb
51
+ - lib/wx_sugar/wx_classes/listctrl.rb
49
52
  - lib/wx_sugar/wx_classes/position.rb
50
53
  - lib/wx_sugar/wx_classes/size.rb
51
54
  - lib/wx_sugar/wx_classes/treectrl.rb