wxruby 1.9.10-universal-darwin-9 → 2.0.0-universal-darwin-9

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.
@@ -5,16 +5,21 @@
5
5
  # * get_position()
6
6
  # * set_size(a_size)
7
7
  # * is_checked()
8
+ # * can_undo()
9
+ # * has_style(a_style)
8
10
  #
9
11
  # and so on. Methods that retrieve set, or query attributes of an object
10
- # are more normally in Ruby called simply by the attribute name:
12
+ # are more normally in Ruby called simply by the attribute name, or, in
13
+ # other cases, with a predicate method:
11
14
  #
12
- # * position()
13
- # * size = a_size
14
- # * checked?
15
+ # * pos = my_widget.position
16
+ # * my_widget.size = a_size
17
+ # * my_widget.checked?
18
+ # * my_widget.can_undo?
19
+ # * my_widget.has_style?
15
20
  #
16
21
  # This extension creates an alias for every WxRuby instance method that
17
- # begins with +get_+, +set_+ or +is_+. Note that if you are calling a
22
+ # begins with +get_+, +set_+, +is_+, +can_+ and +has_+. Note that if you are calling a
18
23
  # 'setter' method on self, you must explicitly send the message to self:
19
24
  #
20
25
  # # set's self size to be 100px by 100px
@@ -23,11 +28,18 @@
23
28
  # size = Wx::Size.new
24
29
 
25
30
  module WxRubyStyleAccessors
31
+ # Ruby-style method named are implemented by method-missing; if an
32
+ # unknown method is called, see if it is a rubyish name for a real
33
+ # method. In principle it would be possible to set up real aliases for
34
+ # them at start-up, but in practice this is far too slow for all the
35
+ # classes that need to be started up.
26
36
  def method_missing(sym, *args)
27
37
  case sym.to_s
28
- when /^(.*)\=$/
38
+ when /^(\w+)\=$/
29
39
  meth = "set_#{$1}"
30
- when /^(.*)\?$/
40
+ when /^((?:has|can)\w+)\?$/
41
+ meth = $1
42
+ when /^(\w+)\?$/
31
43
  meth = "is_#{$1}"
32
44
  else
33
45
  meth = "get_#{sym}"
@@ -25,6 +25,9 @@ class Wx::Bitmap
25
25
  new(img, depth)
26
26
  end
27
27
 
28
+ # Ruby methods that switch class are conventionally named to_foo
29
+ alias :to_image :convert_to_image
30
+
28
31
  # Redefine the initialize method so it raises an exception if a
29
32
  # non-existent file is given to the constructor; otherwise, wx Widgets
30
33
  # just carries on with an empty bitmap, which may cause faults
@@ -1,8 +1,4 @@
1
1
  class Wx::Clipboard
2
- # See if we like these better
3
- alias :place :set_data
4
- alias :fetch :get_data
5
-
6
2
  class << self
7
3
  # This is provided internally by the SWIG interface file, but all
8
4
  # public access should be via Clipboard.open; see below
@@ -29,4 +25,32 @@ class Wx::Clipboard
29
25
  clip.close if clip
30
26
  end
31
27
  end
28
+
29
+ # Need to do some internal record-keeping to protect data objects on
30
+ # the clipboard from garbage collection
31
+ @@__clip_data = []
32
+
33
+ # These methods affect the clipboard contents; each time, update the
34
+ # record with the changed data contents
35
+ wx_add_data = instance_method(:add_data)
36
+ define_method(:add_data) do | the_data |
37
+ @@__clip_data << the_data
38
+ wx_add_data.bind(self).call(the_data)
39
+ end
40
+
41
+ wx_clear = instance_method(:clear)
42
+ define_method(:clear) do
43
+ @@__clip_data.clear
44
+ wx_clear.bind(self).call
45
+ end
46
+
47
+ wx_set_data = instance_method(:set_data)
48
+ define_method(:set_data) do | the_data |
49
+ @@__clip_data = [ the_data ]
50
+ wx_set_data.bind(self).call(the_data)
51
+ end
52
+
53
+ # Aliases, more clearly expressive?
54
+ alias :place :set_data
55
+ alias :fetch :get_data
32
56
  end
@@ -17,6 +17,11 @@ class Wx::Image
17
17
  bmp.convert_to_image
18
18
  end
19
19
 
20
+ # Ruby methods that switch class are conventionally named to_foo
21
+ def to_bitmap
22
+ Wx::Bitmap.from_image(self)
23
+ end
24
+
20
25
  # Redefine the initialize method so it raises an exception if a
21
26
  # non-existent file is given to the constructor; otherwise, wx Widgets
22
27
  # just carries on with an invalid image, which may cause faults
@@ -2,20 +2,23 @@
2
2
  class Wx::ToolBar
3
3
  # Generic method to add items, supporting positional and named
4
4
  # arguments
5
- ADD_ITEM_PARAMS = [ Wx::Parameter[ :position, -1 ],
5
+ ADD_ITEM_PARAMS = [
6
+ Wx::Parameter[ :bitmap2, Wx::NULL_BITMAP ],
7
+ Wx::Parameter[ :position, -1 ],
6
8
  Wx::Parameter[ :id, -1 ],
7
9
  Wx::Parameter[ :label, "" ],
8
- Wx::Parameter[ :bitmap2, Wx::NULL_BITMAP ],
9
10
  Wx::Parameter[ :kind, Wx::ITEM_NORMAL ],
10
11
  Wx::Parameter[ :short_help, "" ],
11
12
  Wx::Parameter[ :long_help, "" ],
12
13
  Wx::Parameter[ :client_data, nil ] ]
13
14
 
14
- def add_item(bitmap, *mixed_args)
15
+ def add_item(bitmap1, *mixed_args)
15
16
  args = Wx::args_as_list(ADD_ITEM_PARAMS, *mixed_args)
16
17
 
18
+ bitmap2 = args.shift
17
19
  pos = args.shift
18
- args.insert(2, bitmap)
20
+ args.insert(2, bitmap1)
21
+ args.insert(3, bitmap2)
19
22
 
20
23
  # Call add_tool to append if default position
21
24
  if pos == -1
@@ -0,0 +1,7 @@
1
+ class Wx::Validator
2
+ # Default implementation of clone, may need to be over-ridden in
3
+ # custom subclasses should state variables need to be copied
4
+ def clone
5
+ self.class.new
6
+ end
7
+ end
@@ -246,8 +246,25 @@ Wx::define_keyword_ctors('FindReplaceDialog') do
246
246
  wx_ctor_params :style
247
247
  end
248
248
 
249
- # wxMultiChoiceDialog Dialog to get one or more selections from a list
250
- # wxSingleChoiceDialog Dialog to get a single selection from a list and return the string
249
+ # Dialog to get one or more selections from a list
250
+ Wx::define_keyword_ctors('MultiChoiceDialog') do
251
+ wx_ctor_params :message => ''
252
+ wx_ctor_params :caption => ''
253
+ wx_ctor_params :choices => []
254
+ wx_ctor_params :style => Wx::DEFAULT_DIALOG_STYLE|Wx::RESIZE_BORDER|
255
+ Wx::OK|Wx::CANCEL|Wx::CENTRE
256
+ wx_ctor_params :pos
257
+ end
258
+
259
+ # Dialog to get a single selection from a list and return the string
260
+ Wx::define_keyword_ctors('SingleChoiceDialog') do
261
+ wx_ctor_params :message => ''
262
+ wx_ctor_params :caption => ''
263
+ wx_ctor_params :choices => []
264
+ wx_ctor_params :style => Wx::DEFAULT_DIALOG_STYLE|Wx::RESIZE_BORDER|
265
+ Wx::OK|Wx::CANCEL|Wx::CENTRE
266
+ wx_ctor_params :pos
267
+ end
251
268
 
252
269
  # Dialog to get a single line of text from the user
253
270
  Wx::define_keyword_ctors('TextEntryDialog') do
@@ -1,3 +1,3 @@
1
1
  module Wx
2
- WXRUBY_VERSION = '1.9.10'
2
+ WXRUBY_VERSION = '2.0.0'
3
3
  end
Binary file
@@ -169,37 +169,37 @@ class SettingsPanel < Wx::Panel
169
169
 
170
170
 
171
171
  def update_colours()
172
- art = @frame.get_dock_art
172
+ art = @frame.dock_art
173
173
 
174
- col = art.get_color(Wx::AUI_DOCKART_BACKGROUND_COLOUR)
175
- @bckg_colour.set_bitmap_label( create_colour_bitmap(col) )
174
+ col = art.colour(Wx::AUI_DOCKART_BACKGROUND_COLOUR)
175
+ @bckg_colour.bitmap_label = ( create_colour_bitmap(col) )
176
176
 
177
- col = art.get_color(Wx::AUI_DOCKART_SASH_COLOUR)
178
- @sash_colour.set_bitmap_label( create_colour_bitmap(col) )
177
+ col = art.colour(Wx::AUI_DOCKART_SASH_COLOUR)
178
+ @sash_colour.bitmap_label = ( create_colour_bitmap(col) )
179
179
 
180
- col = art.get_color(Wx::AUI_DOCKART_INACTIVE_CAPTION_COLOUR)
181
- @capt_colour.set_bitmap_label( create_colour_bitmap(col) )
180
+ col = art.colour(Wx::AUI_DOCKART_INACTIVE_CAPTION_COLOUR)
181
+ @capt_colour.bitmap_label = ( create_colour_bitmap(col) )
182
182
 
183
- col = art.get_color(Wx::AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR)
184
- @capt_gradnt.set_bitmap_label( create_colour_bitmap(col) )
183
+ col = art.colour(Wx::AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR)
184
+ @capt_gradnt.bitmap_label = ( create_colour_bitmap(col) )
185
185
 
186
- col = art.get_color(Wx::AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR)
187
- @capt_text.set_bitmap_label( create_colour_bitmap(col) )
186
+ col = art.colour(Wx::AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR)
187
+ @capt_text.bitmap_label = ( create_colour_bitmap(col) )
188
188
 
189
- col = art.get_color(Wx::AUI_DOCKART_ACTIVE_CAPTION_COLOUR)
190
- @acap_colour.set_bitmap_label( create_colour_bitmap(col) )
189
+ col = art.colour(Wx::AUI_DOCKART_ACTIVE_CAPTION_COLOUR)
190
+ @acap_colour.bitmap_label = ( create_colour_bitmap(col) )
191
191
 
192
- col = art.get_color(Wx::AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR)
193
- @acap_gradnt.set_bitmap_label( create_colour_bitmap(col) )
192
+ col = art.colour(Wx::AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR)
193
+ @acap_gradnt.bitmap_label = ( create_colour_bitmap(col) )
194
194
 
195
- col = art.get_color(Wx::AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR)
196
- @acap_text.set_bitmap_label( create_colour_bitmap(col) )
195
+ col = art.colour(Wx::AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR)
196
+ @acap_text.bitmap_label = ( create_colour_bitmap(col) )
197
197
 
198
- col = art.get_color(Wx::AUI_DOCKART_SASH_COLOUR)
199
- @brdr_colour.set_bitmap_label( create_colour_bitmap(col) )
198
+ col = art.colour(Wx::AUI_DOCKART_SASH_COLOUR)
199
+ @brdr_colour.bitmap_label = ( create_colour_bitmap(col) )
200
200
 
201
- col = art.get_color(Wx::AUI_DOCKART_GRIPPER_COLOUR)
202
- @grip_colour.set_bitmap_label( create_colour_bitmap(col) )
201
+ col = art.colour(Wx::AUI_DOCKART_GRIPPER_COLOUR)
202
+ @grip_colour.bitmap_label = ( create_colour_bitmap(col) )
203
203
  end
204
204
 
205
205
  def on_pane_border_size(event)
@@ -41,7 +41,7 @@ class MyCalendar < CalendarCtrl
41
41
 
42
42
  def on_calendar_change(event)
43
43
  @date = event.date
44
- log_status("Selected date: #{@date.strftime('%Y-%M-%D')}")
44
+ log_status("Selected date: #{@date.strftime('%A %d %B %Y')}")
45
45
  end
46
46
 
47
47
  def on_cal_month_change
@@ -11,14 +11,20 @@ require 'wx'
11
11
  # This sample demonstrates how to draw an image from a file onto a
12
12
  # window. This one uses a small PNG file, but other formats such as JPEG
13
13
  # are supported - see documentation for more details.
14
+ #
15
+ # This sample uses the Wx::Bitmap class, which is a platform-specific
16
+ # representation of an image. This is the class that must be used to
17
+ # display an image, but see also Wx::Image, which allows a much wider
18
+ # range of manipulations (such as rescaling) and writing to files.
19
+
14
20
 
15
21
  class ImageFrame < Wx::Frame
16
22
  def initialize
17
23
  super(nil, :title => 'Simple image demo')
18
24
 
19
25
  # Load a PNG bitmap from a file for drawing
20
- img_file = File.join( File.dirname(__FILE__), 'paperclip.png')
21
- @bitmap = Wx::Bitmap.new(img_file, Wx::BITMAP_TYPE_PNG)
26
+ img_file = File.join( File.dirname(__FILE__), 'wxruby-logo.png')
27
+ @bitmap = Wx::Bitmap.new(img_file)
22
28
 
23
29
  # Set up the drawing to be done when the frame needs re-painting
24
30
  evt_paint :on_paint
@@ -26,7 +32,8 @@ class ImageFrame < Wx::Frame
26
32
 
27
33
  def on_paint
28
34
  paint do | dc |
29
- dc.draw_bitmap(@bitmap, 0, 0, false)
35
+ # Draw the bitmap at offset 10px, 10px, with no transparency
36
+ dc.draw_bitmap(@bitmap, 10, 10, false)
30
37
  end
31
38
  end
32
39
  end
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env ruby
2
+ # wxRuby2 Sample Code. Copyright (c) 2004-2008 wxRuby development team
3
+ # Freely reusable code: see SAMPLES-LICENSE.TXT for details
4
+ begin
5
+ require 'rubygems'
6
+ rescue LoadError
7
+ end
8
+ require 'wx'
9
+
10
+ # Bitmap sample (rewritten by Chauk-Mean Proum)
11
+
12
+ # This sample demonstrates how to draw the same image in various forms
13
+ # (original, mirrored, greyscaled and blurred).
14
+ #
15
+ # This sample uses :
16
+ # - Wx::Image, which allows a wide range of manipulations such as rescaling
17
+ # and writing to files.
18
+ # - Wx::Bitmap, which is a platform-specific representation of an image.
19
+ # This is the class that must be used to actually display an image.
20
+
21
+ class ImageFrame < Wx::Frame
22
+ def initialize
23
+ super(nil, :title => 'Simple image demo', :size => [600, 600])
24
+
25
+ # Create the various images from the bitmap file
26
+ img_file = File.join( File.dirname(__FILE__), 'ruby-logo.jpg')
27
+ @image = Wx::Image.new(img_file)
28
+ @mirrored_image = Wx::Image.new(img_file).mirror
29
+ @greyscaled_image = Wx::Image.new(img_file).convert_to_greyscale
30
+ @blurred_image = Wx::Image.new(img_file).blur(15)
31
+
32
+ # Create the corresponding bitmaps
33
+ compute_bitmaps
34
+
35
+ # Set up event handling
36
+ evt_size :on_size
37
+ evt_idle :on_idle
38
+ evt_paint :on_paint
39
+ end
40
+
41
+ # Create a bitmap for the specified image and size
42
+ def compute_bitmap image, width, height
43
+ rescaled_image = Wx::Image.new(image).rescale(width, height)
44
+ rescaled_image.to_bitmap
45
+ end
46
+
47
+ # Create the bitmaps corresponding to the images and with half the size of the frame
48
+ def compute_bitmaps
49
+ width = client_size.x / 2
50
+ height = client_size.y / 2
51
+ @bitmap1 = compute_bitmap(@image, width, height)
52
+ @bitmap2 = compute_bitmap(@mirrored_image, width, height)
53
+ @bitmap3 = compute_bitmap(@greyscaled_image, width, height)
54
+ @bitmap4 = compute_bitmap(@blurred_image, width, height)
55
+ @done = true
56
+ end
57
+
58
+ # Note to recompute the bitmaps on a resize
59
+ def on_size(event)
60
+ @done = false
61
+ event.skip
62
+ end
63
+
64
+ # Recompute the bitmaps if needed, then do a refresh
65
+ def on_idle
66
+ if not @done
67
+ compute_bitmaps
68
+ refresh
69
+ end
70
+ end
71
+
72
+ # Paint the frame with the bitmaps
73
+ def on_paint
74
+ paint do | dc |
75
+
76
+ if @done
77
+ width = client_size.x / 2
78
+ height = client_size.y / 2
79
+ dc.draw_bitmap(@bitmap1, 0, 0, false)
80
+ dc.draw_bitmap(@bitmap2, width, 0, false)
81
+ dc.draw_bitmap(@bitmap3, 0, height, false)
82
+ dc.draw_bitmap(@bitmap4, width, height, false)
83
+ end
84
+
85
+ end
86
+ end
87
+ end
88
+
89
+ Wx::App.run do
90
+ ImageFrame.new.show
91
+ end
92
+
@@ -0,0 +1,265 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # wxRuby2 Sample Code. Copyright (c) 2004-2009 wxRuby development team
4
+ # Freely reusable code: see SAMPLES-LICENSE.TXT for details
5
+
6
+ require 'wx'
7
+ include Wx
8
+ include Math
9
+
10
+ # This sample was originally written by Alex Fenton as an answer to Ruby
11
+ # Quiz #191, which challenged entrants to create an application which
12
+ # could draw images based on mathematical functions:
13
+ #
14
+ # http://rubyquiz.strd6.com/quizzes/191/
15
+ #
16
+ # To use the application, enter functions which take input values of x
17
+ # and y from 0 to 1, and return intensities of red, green and blue. If a
18
+ # bad function is entered, a cross is displayed; hover over this to get
19
+ # a hint on the problem.
20
+ #
21
+ # The sample demonstrates some uses of the Wx::Image class, a
22
+ # platform-independent representation of an image which can be
23
+ # manipulated (for example, resizing) and written to files in various
24
+ # formats. It also shows how an image's data can be written directly, by
25
+ # using Array#pack.
26
+
27
+ # A canvas that draws and displays a mathematically generated image
28
+ class MathsDrawing < Window
29
+ # The functions which return the colour components at each pixel
30
+ attr_writer :red, :green, :blue
31
+ # The time taken to render, whether re-rendering is needed, and the
32
+ # source image
33
+ attr_reader :render_time, :done, :img
34
+
35
+ def initialize(parent)
36
+ super(parent)
37
+ # Create a dummy image
38
+ @default_image = Image.new(1, 1)
39
+ @default_image.data = [255, 255, 255].pack('CCC')
40
+ @img = @default_image
41
+
42
+ @red = lambda { | x, y | 1 }
43
+ @green = lambda { | x, y | 1 }
44
+ @blue = lambda { | x, y | 1 }
45
+
46
+ @done = true
47
+
48
+ evt_size :on_size
49
+ evt_paint :on_paint
50
+ evt_idle :on_idle
51
+ end
52
+
53
+ # Paint the image on the screen. The actual image rendering is done in
54
+ # idle time, so that the GUI is responsive whilst redrawing - eg, when
55
+ # resized. Painting is done by quickly rescaling the cached image.
56
+ def on_paint
57
+ paint do | dc |
58
+ draw_img = @img.scale(client_size.x, client_size.y)
59
+ dc.draw_bitmap(draw_img.convert_to_bitmap, 0, 0, true)
60
+ end
61
+ end
62
+
63
+ # Regenerate the image if needed, then do a refresh
64
+ def on_idle
65
+ if not @done
66
+ @img = make_image
67
+ refresh
68
+ end
69
+ @done = true
70
+ end
71
+
72
+ # Note to regenerate the image if the canvas has been resized
73
+ def on_size(event)
74
+ @done = false
75
+ event.skip
76
+ end
77
+
78
+ # Call this to force a re-render - eg if the functions have changed
79
+ def redraw
80
+ @done = false
81
+ end
82
+
83
+ # Actually make the image
84
+ def make_image
85
+ size_x, size_y = client_size.x, client_size.y
86
+ if size_x < 1 or size_y < 1
87
+ return @default_image
88
+ end
89
+
90
+ start_time = Time.now
91
+ # The string holding raw image data
92
+ data = ''
93
+ x_factor = size_x.to_f
94
+ y_factor = size_y.to_f
95
+
96
+ # Input values from the range 0 to 1, with origin in the bottom left
97
+ (size_y - 1).downto(0) do | y |
98
+ the_y = y.to_f / y_factor
99
+ 0.upto(size_x - 1) do | x |
100
+ the_x = x.to_f / x_factor
101
+ red = @red.call(the_x, the_y) * 255
102
+ green = @green.call(the_x, the_y) * 255
103
+ blue = @blue.call(the_x, the_y) * 255
104
+ data << [red, green, blue].pack("CCC")
105
+ end
106
+ end
107
+ img = Image.new(size_x, size_y)
108
+ img.data = data
109
+ @render_time = Time.now - start_time
110
+ img
111
+ end
112
+ end
113
+
114
+ # A helper dialog for saving the image to a file
115
+ class SaveImageDialog < FileDialog
116
+ # The image file formats on offer
117
+ TYPES = [ [ "PNG file (*.png)|*.png", BITMAP_TYPE_PNG ],
118
+ [ "TIF file (*.tif)|*.tif", BITMAP_TYPE_TIF ],
119
+ [ "BMP file (*.bmp)|*.bmp", BITMAP_TYPE_BMP ] ]
120
+
121
+ WILDCARD = TYPES.map { | type | type.first }.join("|")
122
+
123
+ def initialize(parent)
124
+ super(parent, :wildcard => WILDCARD,
125
+ :message => 'Save Image',
126
+ :style => FD_SAVE|FD_OVERWRITE_PROMPT)
127
+ end
128
+
129
+ # Returns the Wx identifier for the selected image type.
130
+ def image_type
131
+ TYPES[filter_index].last
132
+ end
133
+ end
134
+
135
+ # A Panel for displaying the image and controls to manipulate it
136
+ class MathsPanel < Panel
137
+ # Set functions to some nice initial values
138
+ RED_INITIAL = "cos(x)"
139
+ GREEN_INITIAL = "cos(y ** x)"
140
+ BLUE_INITIAL = "(x ** 4) + ( y ** 3 ) - (4.5 * x ** 2 ) + ( y * 2)"
141
+
142
+ # Symbols to show correct and incorrect functions
143
+ TICK = "\xE2\x9C\x94"
144
+ CROSS = "\xE2\x9C\x98"
145
+
146
+ attr_reader :drawing
147
+
148
+ def initialize(parent)
149
+ super(parent)
150
+ self.sizer = VBoxSizer.new
151
+ # The canvas
152
+ @drawing = MathsDrawing.new(self)
153
+ sizer.add @drawing, 1, GROW
154
+
155
+ sizer.add Wx::StaticLine.new(self)
156
+
157
+ # The text controls for entering functions
158
+ grid_sz = FlexGridSizer.new(3, 8, 8)
159
+ grid_sz.add_growable_col(1, 1)
160
+
161
+ grid_sz.add StaticText.new(self, :label => "Red")
162
+ @red_tx = TextCtrl.new(self, :value => RED_INITIAL)
163
+ grid_sz.add @red_tx, 0, GROW
164
+ @red_err = StaticText.new(self, :label => TICK)
165
+ grid_sz.add @red_err, 0, ALIGN_CENTRE
166
+
167
+ grid_sz.add StaticText.new(self, :label => "Green")
168
+ @green_tx = TextCtrl.new(self, :value => GREEN_INITIAL)
169
+ grid_sz.add @green_tx, 0, GROW
170
+ @green_err = StaticText.new(self, :label => TICK)
171
+ grid_sz.add @green_err, 0, ALIGN_CENTRE
172
+
173
+ grid_sz.add StaticText.new(self, :label => "Blue")
174
+ @blue_tx = TextCtrl.new(self, :value => BLUE_INITIAL)
175
+ grid_sz.add @blue_tx, 0, GROW
176
+ @blue_err = StaticText.new(self, :label => TICK)
177
+ grid_sz.add @blue_err, 0, ALIGN_CENTRE
178
+
179
+ # Buttons to save and render
180
+ grid_sz.add nil
181
+ butt_sz = HBoxSizer.new
182
+ render_bt = Button.new(self, :label => "Render")
183
+ butt_sz.add render_bt, 0, Wx::RIGHT, 8
184
+ evt_button render_bt, :on_render
185
+
186
+ save_bt = Button.new(self, :label => "Save Image")
187
+ butt_sz.add save_bt, 0, Wx::RIGHT, 8
188
+ evt_button save_bt, :on_save
189
+
190
+ # Disable the buttons whilst redrawing
191
+ evt_update_ui(render_bt) { | evt | evt.enable(@drawing.done) }
192
+ evt_update_ui(save_bt) { | evt | evt.enable(@drawing.done) }
193
+ grid_sz.add butt_sz
194
+
195
+ # Add the controls sizer to the whole thing
196
+ sizer.add grid_sz, 0, GROW|ALL, 10
197
+
198
+ on_render
199
+ end
200
+
201
+ # Update the functions that generate the image, then re-render it
202
+ def on_render
203
+ @drawing.red = make_a_function(@red_tx.value, @red_err)
204
+ @drawing.green = make_a_function(@green_tx.value, @green_err)
205
+ @drawing.blue = make_a_function(@blue_tx.value, @blue_err)
206
+ @drawing.redraw
207
+ end
208
+
209
+ # Display a dialog to save the image to a file
210
+ def on_save
211
+ dlg = SaveImageDialog.new(parent)
212
+ if dlg.show_modal == ID_OK
213
+ @drawing.img.save_file(dlg.path, dlg.image_type)
214
+ end
215
+ end
216
+
217
+ # A function which doesn't do anything
218
+ NULL_FUNC = lambda { | x, y | 1 }
219
+
220
+ # Takes a string source +source+, returns a lambda. If the string
221
+ # source isn't valid, flag this in the GUI static text +error_outlet+
222
+ def make_a_function(source, error_outlet)
223
+ return NULL_FUNC if source.empty?
224
+ func = nil
225
+ begin
226
+ # Create the function and test it, to check for wrong names
227
+ func = eval "lambda { | x, y | #{source} }"
228
+ func.call(0, 0)
229
+ rescue Exception => e
230
+ error_outlet.label = CROSS
231
+ error_outlet.tool_tip = e.class.name + ":\n" +
232
+ e.message.sub(/^\(eval\):\d+: /, '')
233
+ return NULL_FUNC
234
+ end
235
+
236
+ # Things are good, note this and return the function
237
+ error_outlet.label = TICK
238
+ error_outlet.tool_tip = ''
239
+ func
240
+ end
241
+ end
242
+
243
+ class MathsFrame < Frame
244
+ def initialize
245
+ super(nil, :title => 'Maths drawing',
246
+ :size => [400, 500],
247
+ :pos => [50, 50])
248
+ sb = create_status_bar(1)
249
+ evt_update_ui sb, :on_update_status
250
+ @panel = MathsPanel.new(self)
251
+ end
252
+
253
+ def on_update_status
254
+ if @panel.drawing.done
255
+ pixels = @panel.drawing.client_size
256
+ msg = "[#{pixels.x} x #{pixels.y}] drawing completed in " +
257
+ "#{@panel.drawing.render_time}s"
258
+ status_bar.status_text = msg
259
+ end
260
+ end
261
+ end
262
+
263
+ App.run do
264
+ MathsFrame.new.show
265
+ end