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