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.
- data/lib/wx_sugar/enumerable_controls.rb +162 -0
- data/lib/wx_sugar/version.rb +1 -1
- data/lib/wx_sugar/wx_classes/control_with_items.rb +23 -0
- data/lib/wx_sugar/wx_classes/listctrl.rb +38 -0
- data/lib/wx_sugar/wx_classes/treectrl.rb +27 -6
- data/lib/wx_sugar/wx_classes/window.rb +16 -1
- data/lib/wx_sugar.rb +10 -7
- data/samples/sugar-sample.rb +13 -3
- metadata +5 -2
@@ -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
|
data/lib/wx_sugar/version.rb
CHANGED
@@ -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
|
4
|
-
#
|
5
|
-
#
|
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
|
-
#
|
8
|
-
#
|
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.
|
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
|
-
|
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
|
#
|
data/samples/sugar-sample.rb
CHANGED
@@ -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
|
-
|
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.
|
7
|
-
date: 2007-03
|
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
|