wx_sugar 0.1.14 → 0.1.15

Sign up to get free protection for your applications and to get access to all the features.
@@ -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