summaryrefslogtreecommitdiff
path: root/ext/tk/lib
diff options
context:
space:
mode:
authornagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-23 22:37:44 +0000
committernagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-23 22:37:44 +0000
commit3ca633b890706c4f5892a179389b8389b5022dc0 (patch)
tree6d334bc0ca75c0dd658d732d0bd017d4ffad1eeb /ext/tk/lib
parent08f2c46ce177bbe5891c0f90fea0bfa9ee153a66 (diff)
* ext/tk/lib/tk.rb: fail to start Tk.mainloop (exit immediately) on some environment (reported on [ruby-talk:381444]).
* ext/tk/lib/tk/canvas.rb: support creating a canvas item object from an item ID number. * ext/tk/lib/tk/image.rb: import documents which are pull-requested. [Ruby 1.9 - Feature #4595] * ext/tk/lib/tk/extconf.rb: search directories for 64bit library (e.g. /usr/lib64), add some new configure options (see README.tcltklib), and bug fix. * ext/tk/lib/tk/README.tcltklib: modify docs for some new configure options. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31717 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/tk/lib')
-rw-r--r--ext/tk/lib/tk.rb38
-rw-r--r--ext/tk/lib/tk/canvas.rb25
-rw-r--r--ext/tk/lib/tk/image.rb128
3 files changed, 183 insertions, 8 deletions
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index 0fd8cfdb20a..574ebf328bd 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -1248,6 +1248,9 @@ module TkCore
raise e
end
+ interp.mainloop_abort_on_exception = true
+ Thread.current.instance_variable_set("@interp", interp)
+
status = [nil]
def status.value
self[0]
@@ -1283,19 +1286,23 @@ proc __startup_rbtk_mainloop__ {args} {
}
set __initial_state_of_rubytk__ 1
trace add variable __initial_state_of_rubytk__ unset __startup_rbtk_mainloop__
+
+# complete initializing
+ruby {TkCore::INTERP_THREAD[:interp] = TkCore::INTERP_THREAD.instance_variable_get('@interp')}
EOS
begin
begin
#TclTkLib.mainloop_abort_on_exception = false
#Thread.current[:status].value = TclTkLib.mainloop(true)
- interp.mainloop_abort_on_exception = true
- Thread.current[:interp] = interp
+ #interp.mainloop_abort_on_exception = true
+ #Thread.current[:interp] = interp
Thread.current[:status].value = interp.mainloop(true)
rescue SystemExit=>e
Thread.current[:status].value = e
rescue Exception=>e
Thread.current[:status].value = e
+ p e if $DEBUG
retry if interp.has_mainwindow?
ensure
INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast }
@@ -1312,12 +1319,20 @@ EOS
end
}
+ # check a Tcl/Tk interpreter is initialized
until INTERP_THREAD[:interp]
- Thread.pass
+ # Thread.pass
+ INTERP_THREAD.run
end
+
# INTERP_THREAD.run
raise INTERP_THREAD[:interp] if INTERP_THREAD[:interp].kind_of? Exception
+ # check an eventloop is running
+ while INTERP_THREAD.alive? && TclTkLib.mainloop_thread?.nil?
+ INTERP_THREAD.run
+ end
+
INTERP = INTERP_THREAD[:interp]
INTERP_THREAD_STATUS = INTERP_THREAD[:status]
@@ -1328,6 +1343,9 @@ EOS
INTERP_THREAD.kill
end
}
+
+ # (for safety's sake) force the eventloop to run
+ INTERP_THREAD.run
end
def INTERP.__getip
@@ -1857,6 +1875,11 @@ EOS
begin
TclTkLib.set_eventloop_window_mode(true)
+
+ # force run the eventloop
+ TkCore::INTERP._eval_without_enc('update')
+ TkCore::INTERP._eval_without_enc('catch {set __initial_state_of_rubytk__}')
+ INTERP_THREAD.run
if check_root
INTERP_MUTEX.synchronize{
INTERP_ROOT_CHECK.wait(INTERP_MUTEX)
@@ -1867,8 +1890,15 @@ EOS
end
}
else
- INTERP_THREAD.value
+ # INTERP_THREAD.value
+ begin
+ INTERP_THREAD.value
+ rescue Exception => e
+ raise e
+ end
end
+ rescue Exception => e
+ raise e
ensure
TclTkLib.set_eventloop_window_mode(false)
end
diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb
index f0cb755bd76..7d3d71675ca 100644
--- a/ext/tk/lib/tk/canvas.rb
+++ b/ext/tk/lib/tk/canvas.rb
@@ -85,6 +85,7 @@ class Tk::Canvas<TkWindow
# create a canvas item without creating a TkcItem object
def create(type, *args)
+ type = TkcItem.type2class(type.to_s) unless type.kind_of?(TkcItem)
type.create(self, *args)
end
@@ -603,6 +604,30 @@ class Tk::Canvas<TkWindow
def itemtype(tag)
TkcItem.type2class(tk_send('type', tagid(tag)))
end
+
+ def create_itemobj_from_id(idnum)
+ id = TkcItem.id2obj(self, idnum.to_i)
+ return id if id.kind_of?(TkcItem)
+
+ typename = tk_send('type', id)
+ unless type = TkcItem.type2class(typename)
+ (itemclass = typename.dup)[0,1] = typename[0,1].upcase
+ type = TkcItem.const_set(itemclass, Class.new(TkcItem))
+ type.const_set("CItemTypeName", typename.freeze)
+ TkcItem::CItemTypeToClass[typename] = type
+ end
+
+ canvas = self
+ (obj = type.allocate).instance_eval{
+ @parent = @c = canvas
+ @path = canvas.path
+ @id = id
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ TkcItem::CItemID_TBL[@path] = {} unless TkcItem::CItemID_TBL[@path]
+ TkcItem::CItemID_TBL[@path][@id] = self
+ }
+ }
+ end
end
#TkCanvas = Tk::Canvas unless Object.const_defined? :TkCanvas
diff --git a/ext/tk/lib/tk/image.rb b/ext/tk/lib/tk/image.rb
index 39d63478a64..00bb440d6a5 100644
--- a/ext/tk/lib/tk/image.rb
+++ b/ext/tk/lib/tk/image.rb
@@ -72,7 +72,6 @@ class TkImage<TkObject
end
unless @path
Tk_Image_ID.mutex.synchronize{
- # @path = Tk_Image_ID.join('')
@path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
Tk_Image_ID[1].succ!
}
@@ -128,6 +127,12 @@ class TkBitmapImage<TkImage
end
end
+# A photo is an image whose pixels can display any color or be transparent.
+# At present, only GIF and PPM/PGM formats are supported, but an interface
+# exists to allow additional image file formats to be added easily.
+#
+# This class documentation is a copy from the original Tcl/Tk at
+# http://www.tcl.tk/man/tcl8.5/TkCmd/photo.htm with some rewrited parts.
class TkPhotoImage<TkImage
NullArgOptionKeys = [ "shrink", "grayscale" ]
@@ -146,11 +151,49 @@ class TkPhotoImage<TkImage
end
private :_photo_hash_kv
+ # Create a new image with the given options.
+ # == Examples of use :
+ # === Create an empty image of 300x200 pixels
+ #
+ # image = TkPhotoImage.new(:height => 200, :width => 300)
+ #
+ # === Create an image from a file
+ #
+ # image = TkPhotoImage.new(:file: => 'my_image.gif')
+ #
+ # == Options
+ # Photos support the following options:
+ # * :data
+ # Specifies the contents of the image as a string.
+ # * :format
+ # Specifies the name of the file format for the data.
+ # * :file
+ # Gives the name of a file that is to be read to supply data for the image.
+ # * :gamma
+ # Specifies that the colors allocated for displaying this image in a window
+ # should be corrected for a non-linear display with the specified gamma
+ # exponent value.
+ # * height
+ # Specifies the height of the image, in pixels. This option is useful
+ # primarily in situations where the user wishes to build up the contents of
+ # the image piece by piece. A value of zero (the default) allows the image
+ # to expand or shrink vertically to fit the data stored in it.
+ # * palette
+ # Specifies the resolution of the color cube to be allocated for displaying
+ # this image.
+ # * width
+ # Specifies the width of the image, in pixels. This option is useful
+ # primarily in situations where the user wishes to build up the contents of
+ # the image piece by piece. A value of zero (the default) allows the image
+ # to expand or shrink horizontally to fit the data stored in it.
def initialize(*args)
@type = 'photo'
super(*args)
end
+ # Blank the image; that is, set the entire image to have no data, so it will
+ # be displayed as transparent, and the background of whatever window it is
+ # displayed in will show through.
def blank
tk_send_without_enc('blank')
self
@@ -164,6 +207,10 @@ class TkPhotoImage<TkImage
tk_tcl2ruby(tk_send('cget', '-' << option.to_s))
end
end
+
+ # Returns the current value of the configuration option given by option.
+ # Example, display name of the file from which <tt>image</tt> was created:
+ # puts image.cget :file
def cget(option)
unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
cget_strict(option)
@@ -182,6 +229,51 @@ class TkPhotoImage<TkImage
end
end
+ # Copies a region from the image called source to the image called
+ # destination, possibly with pixel zooming and/or subsampling. If no options
+ # are specified, this method copies the whole of source into destination,
+ # starting at coordinates (0,0) in destination. The following options may be
+ # specified:
+ #
+ # * :from [x1, y1, x2, y2]
+ # Specifies a rectangular sub-region of the source image to be copied.
+ # (x1,y1) and (x2,y2) specify diagonally opposite corners of the rectangle.
+ # If x2 and y2 are not specified, the default value is the bottom-right
+ # corner of the source image. The pixels copied will include the left and
+ # top edges of the specified rectangle but not the bottom or right edges.
+ # If the :from option is not given, the default is the whole source image.
+ # * :to [x1, y1, x2, y2]
+ # Specifies a rectangular sub-region of the destination image to be
+ # affected. (x1,y1) and (x2,y2) specify diagonally opposite corners of the
+ # rectangle. If x2 and y2 are not specified, the default value is (x1,y1)
+ # plus the size of the source region (after subsampling and zooming, if
+ # specified). If x2 and y2 are specified, the source region will be
+ # replicated if necessary to fill the destination region in a tiled fashion.
+ # * :shrink
+ # Specifies that the size of the destination image should be reduced, if
+ # necessary, so that the region being copied into is at the bottom-right
+ # corner of the image. This option will not affect the width or height of
+ # the image if the user has specified a non-zero value for the :width or
+ # :height configuration option, respectively.
+ # * :zoom [x, y]
+ # Specifies that the source region should be magnified by a factor of x
+ # in the X direction and y in the Y direction. If y is not given, the
+ # default value is the same as x. With this option, each pixel in the
+ # source image will be expanded into a block of x x y pixels in the
+ # destination image, all the same color. x and y must be greater than 0.
+ # * :subsample [x, y]
+ # Specifies that the source image should be reduced in size by using only
+ # every xth pixel in the X direction and yth pixel in the Y direction.
+ # Negative values will cause the image to be flipped about the Y or X axes,
+ # respectively. If y is not given, the default value is the same as x.
+ # * :compositingrule rule
+ # Specifies how transparent pixels in the source image are combined with
+ # the destination image. When a compositing rule of <tt>overlay</tt> is set,
+ # the old contents of the destination image are visible, as if the source
+ # image were printed on a piece of transparent film and placed over the
+ # top of the destination. When a compositing rule of <tt>set</tt> is set,
+ # the old contents of the destination image are discarded and the source
+ # image is used as-is. The default compositing rule is <tt>overlay</tt>.
def copy(src, *opts)
if opts.size == 0
tk_send('copy', src)
@@ -201,11 +293,35 @@ class TkPhotoImage<TkImage
self
end
+ # Returns image data in the form of a string. The following options may be
+ # specified:
+ # * :background color
+ # If the color is specified, the data will not contain any transparency
+ # information. In all transparent pixels the color will be replaced by the
+ # specified color.
+ # * :format format-name
+ # Specifies the name of the image file format handler to be used.
+ # Specifically, this subcommand searches for the first handler whose name
+ # matches an initial substring of format-name and which has the capability
+ # to read this image data. If this option is not given, this subcommand
+ # uses the first handler that has the capability to read the image data.
+ # * :from [x1, y1, x2, y2]
+ # Specifies a rectangular region of imageName to be returned. If only x1
+ # and y1 are specified, the region extends from (x1,y1) to the bottom-right
+ # corner of imageName. If all four coordinates are given, they specify
+ # diagonally opposite corners of the rectangular region, including x1,y1
+ # and excluding x2,y2. The default, if this option is not given, is the
+ # whole image.
+ # * :grayscale
+ # If this options is specified, the data will not contain color information.
+ # All pixel data will be transformed into grayscale.
def data(keys={})
- #tk_send('data', *_photo_hash_kv(keys))
tk_split_list(tk_send('data', *_photo_hash_kv(keys)))
end
+ # Returns the color of the pixel at coordinates (x,y) in the image as a list
+ # of three integers between 0 and 255, representing the red, green and blue
+ # components respectively.
def get(x, y)
tk_send('get', x, y).split.collect{|n| n.to_i}
end
@@ -246,11 +362,15 @@ class TkPhotoImage<TkImage
self
end
+ # Returns a boolean indicating if the pixel at (x,y) is transparent.
def get_transparency(x, y)
bool(tk_send('transparency', 'get', x, y))
end
- def set_transparency(x, y, st)
- tk_send('transparency', 'set', x, y, st)
+
+ # Makes the pixel at (x,y) transparent if <tt>state</tt> is true, and makes
+ # that pixel opaque otherwise.
+ def set_transparency(x, y, state)
+ tk_send('transparency', 'set', x, y, state)
self
end