ffi-tk 2009.11.29

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.
Files changed (189) hide show
  1. data/CHANGELOG +748 -0
  2. data/MANIFEST +188 -0
  3. data/README.md +85 -0
  4. data/Rakefile +47 -0
  5. data/TODO.md +62 -0
  6. data/bin/rwish +33 -0
  7. data/doc/MIT_LICENSE +18 -0
  8. data/doc/TCL_LICENSE +39 -0
  9. data/example/choose_color.rb +22 -0
  10. data/example/choose_directory.rb +22 -0
  11. data/example/dialog.rb +37 -0
  12. data/example/hello.rb +11 -0
  13. data/example/message_box.rb +26 -0
  14. data/example/option_menu.rb +17 -0
  15. data/example/popup.rb +24 -0
  16. data/example/set_palette.rb +32 -0
  17. data/example/text.rb +47 -0
  18. data/example/tile/kroc_demo_small.rb +123 -0
  19. data/example/tile/kroc_rb_demo.rb +135 -0
  20. data/example/tile/notebook.rb +48 -0
  21. data/example/tile/theme_hello.rb +38 -0
  22. data/example/tile/treeview.rb +71 -0
  23. data/example/various.rb +25 -0
  24. data/example/wait.rb +16 -0
  25. data/ffi-tk.gemspec +33 -0
  26. data/lib/ffi-tk.rb +76 -0
  27. data/lib/ffi-tk/command.rb +39 -0
  28. data/lib/ffi-tk/command/after.rb +36 -0
  29. data/lib/ffi-tk/command/bell.rb +34 -0
  30. data/lib/ffi-tk/command/bind.rb +11 -0
  31. data/lib/ffi-tk/command/bindtags.rb +69 -0
  32. data/lib/ffi-tk/command/cget.rb +92 -0
  33. data/lib/ffi-tk/command/choose_color.rb +29 -0
  34. data/lib/ffi-tk/command/choose_directory.rb +45 -0
  35. data/lib/ffi-tk/command/clipboard.rb +102 -0
  36. data/lib/ffi-tk/command/configure.rb +88 -0
  37. data/lib/ffi-tk/command/destroy.rb +12 -0
  38. data/lib/ffi-tk/command/dialog.rb +54 -0
  39. data/lib/ffi-tk/command/event.rb +79 -0
  40. data/lib/ffi-tk/command/focus.rb +70 -0
  41. data/lib/ffi-tk/command/font.rb +124 -0
  42. data/lib/ffi-tk/command/get_open_file.rb +85 -0
  43. data/lib/ffi-tk/command/get_save_file.rb +83 -0
  44. data/lib/ffi-tk/command/grab.rb +141 -0
  45. data/lib/ffi-tk/command/grid.rb +246 -0
  46. data/lib/ffi-tk/command/image.rb +79 -0
  47. data/lib/ffi-tk/command/lower.rb +23 -0
  48. data/lib/ffi-tk/command/message_box.rb +65 -0
  49. data/lib/ffi-tk/command/option_menu.rb +8 -0
  50. data/lib/ffi-tk/command/pack.rb +99 -0
  51. data/lib/ffi-tk/command/place.rb +91 -0
  52. data/lib/ffi-tk/command/popup.rb +14 -0
  53. data/lib/ffi-tk/command/raise.rb +25 -0
  54. data/lib/ffi-tk/command/scrollable.rb +151 -0
  55. data/lib/ffi-tk/command/selection.rb +132 -0
  56. data/lib/ffi-tk/command/set_palette.rb +9 -0
  57. data/lib/ffi-tk/command/tk_cmd.rb +155 -0
  58. data/lib/ffi-tk/command/vars.rb +82 -0
  59. data/lib/ffi-tk/command/wait.rb +39 -0
  60. data/lib/ffi-tk/command/winfo.rb +668 -0
  61. data/lib/ffi-tk/command/wm.rb +1025 -0
  62. data/lib/ffi-tk/core_extensions.rb +154 -0
  63. data/lib/ffi-tk/event/data.rb +60 -0
  64. data/lib/ffi-tk/event/handler.rb +44 -0
  65. data/lib/ffi-tk/ffi/tcl.rb +92 -0
  66. data/lib/ffi-tk/ffi/tcl/cmd_proc.rb +10 -0
  67. data/lib/ffi-tk/ffi/tcl/eval_result.rb +148 -0
  68. data/lib/ffi-tk/ffi/tcl/interp.rb +95 -0
  69. data/lib/ffi-tk/ffi/tcl/obj.rb +89 -0
  70. data/lib/ffi-tk/ffi/tcl/time.rb +36 -0
  71. data/lib/ffi-tk/ffi/tk.rb +35 -0
  72. data/lib/ffi-tk/geometry.rb +32 -0
  73. data/lib/ffi-tk/thread_sender.rb +26 -0
  74. data/lib/ffi-tk/tk.rb +222 -0
  75. data/lib/ffi-tk/variable.rb +46 -0
  76. data/lib/ffi-tk/widget.rb +68 -0
  77. data/lib/ffi-tk/widget/button.rb +41 -0
  78. data/lib/ffi-tk/widget/canvas.rb +806 -0
  79. data/lib/ffi-tk/widget/canvas/arc.rb +18 -0
  80. data/lib/ffi-tk/widget/canvas/bitmap.rb +13 -0
  81. data/lib/ffi-tk/widget/canvas/image.rb +10 -0
  82. data/lib/ffi-tk/widget/canvas/item.rb +170 -0
  83. data/lib/ffi-tk/widget/canvas/line.rb +16 -0
  84. data/lib/ffi-tk/widget/canvas/oval.rb +15 -0
  85. data/lib/ffi-tk/widget/canvas/polygon.rb +16 -0
  86. data/lib/ffi-tk/widget/canvas/rectangle.rb +15 -0
  87. data/lib/ffi-tk/widget/canvas/text.rb +15 -0
  88. data/lib/ffi-tk/widget/canvas/window.rb +11 -0
  89. data/lib/ffi-tk/widget/checkbutton.rb +63 -0
  90. data/lib/ffi-tk/widget/entry.rb +208 -0
  91. data/lib/ffi-tk/widget/frame.rb +12 -0
  92. data/lib/ffi-tk/widget/label.rb +26 -0
  93. data/lib/ffi-tk/widget/labelframe.rb +7 -0
  94. data/lib/ffi-tk/widget/listbox.rb +192 -0
  95. data/lib/ffi-tk/widget/menu.rb +318 -0
  96. data/lib/ffi-tk/widget/menubutton.rb +7 -0
  97. data/lib/ffi-tk/widget/message.rb +36 -0
  98. data/lib/ffi-tk/widget/panedwindow.rb +164 -0
  99. data/lib/ffi-tk/widget/radiobutton.rb +43 -0
  100. data/lib/ffi-tk/widget/root.rb +8 -0
  101. data/lib/ffi-tk/widget/scale.rb +44 -0
  102. data/lib/ffi-tk/widget/scrollbar.rb +114 -0
  103. data/lib/ffi-tk/widget/spinbox.rb +198 -0
  104. data/lib/ffi-tk/widget/text.rb +893 -0
  105. data/lib/ffi-tk/widget/text/peer.rb +10 -0
  106. data/lib/ffi-tk/widget/tile.rb +70 -0
  107. data/lib/ffi-tk/widget/tile/button.rb +8 -0
  108. data/lib/ffi-tk/widget/tile/checkbutton.rb +8 -0
  109. data/lib/ffi-tk/widget/tile/combobox.rb +43 -0
  110. data/lib/ffi-tk/widget/tile/entry.rb +8 -0
  111. data/lib/ffi-tk/widget/tile/frame.rb +13 -0
  112. data/lib/ffi-tk/widget/tile/label.rb +9 -0
  113. data/lib/ffi-tk/widget/tile/labelframe.rb +8 -0
  114. data/lib/ffi-tk/widget/tile/menubutton.rb +8 -0
  115. data/lib/ffi-tk/widget/tile/notebook.rb +93 -0
  116. data/lib/ffi-tk/widget/tile/panedwindow.rb +9 -0
  117. data/lib/ffi-tk/widget/tile/progressbar.rb +59 -0
  118. data/lib/ffi-tk/widget/tile/radiobutton.rb +8 -0
  119. data/lib/ffi-tk/widget/tile/scale.rb +8 -0
  120. data/lib/ffi-tk/widget/tile/scrollbar.rb +41 -0
  121. data/lib/ffi-tk/widget/tile/separator.rb +23 -0
  122. data/lib/ffi-tk/widget/tile/sizegrip.rb +24 -0
  123. data/lib/ffi-tk/widget/tile/style.rb +114 -0
  124. data/lib/ffi-tk/widget/tile/treeview.rb +414 -0
  125. data/lib/ffi-tk/widget/toplevel.rb +14 -0
  126. data/spec/ffi-tk/command/bindtags.rb +18 -0
  127. data/spec/ffi-tk/command/clipboard.rb +18 -0
  128. data/spec/ffi-tk/command/font.rb +67 -0
  129. data/spec/ffi-tk/command/grid.rb +6 -0
  130. data/spec/ffi-tk/command/image.rb +26 -0
  131. data/spec/ffi-tk/command/pack.rb +20 -0
  132. data/spec/ffi-tk/command/place.rb +20 -0
  133. data/spec/ffi-tk/command/selection.rb +13 -0
  134. data/spec/ffi-tk/command/vars.rb +32 -0
  135. data/spec/ffi-tk/command/winfo.rb +233 -0
  136. data/spec/ffi-tk/command/wm.rb +185 -0
  137. data/spec/ffi-tk/event.rb +95 -0
  138. data/spec/ffi-tk/tile/button.rb +51 -0
  139. data/spec/ffi-tk/tile/checkbutton.rb +13 -0
  140. data/spec/ffi-tk/tile/combobox.rb +65 -0
  141. data/spec/ffi-tk/tile/entry.rb +61 -0
  142. data/spec/ffi-tk/tile/frame.rb +65 -0
  143. data/spec/ffi-tk/tile/label.rb +17 -0
  144. data/spec/ffi-tk/tile/labelframe.rb +13 -0
  145. data/spec/ffi-tk/tile/menubutton.rb +13 -0
  146. data/spec/ffi-tk/tile/notebook.rb +103 -0
  147. data/spec/ffi-tk/tile/panedwindow.rb +13 -0
  148. data/spec/ffi-tk/tile/progressbar.rb +78 -0
  149. data/spec/ffi-tk/tile/radiobutton.rb +13 -0
  150. data/spec/ffi-tk/tile/scale.rb +13 -0
  151. data/spec/ffi-tk/tile/scrollbar.rb +43 -0
  152. data/spec/ffi-tk/tile/separator.rb +22 -0
  153. data/spec/ffi-tk/tile/sizegrip.rb +13 -0
  154. data/spec/ffi-tk/tile/style.rb +161 -0
  155. data/spec/ffi-tk/tile/treeview.rb +101 -0
  156. data/spec/ffi-tk/variable.rb +24 -0
  157. data/spec/ffi-tk/widget/button.rb +22 -0
  158. data/spec/ffi-tk/widget/canvas.rb +169 -0
  159. data/spec/ffi-tk/widget/checkbutton.rb +44 -0
  160. data/spec/ffi-tk/widget/entry.rb +155 -0
  161. data/spec/ffi-tk/widget/frame.rb +8 -0
  162. data/spec/ffi-tk/widget/label.rb +16 -0
  163. data/spec/ffi-tk/widget/labelframe.rb +12 -0
  164. data/spec/ffi-tk/widget/listbox.rb +19 -0
  165. data/spec/ffi-tk/widget/menu.rb +12 -0
  166. data/spec/ffi-tk/widget/menubutton.rb +12 -0
  167. data/spec/ffi-tk/widget/message.rb +12 -0
  168. data/spec/ffi-tk/widget/panedwindow.rb +12 -0
  169. data/spec/ffi-tk/widget/radiobutton.rb +12 -0
  170. data/spec/ffi-tk/widget/root.rb +9 -0
  171. data/spec/ffi-tk/widget/scale.rb +12 -0
  172. data/spec/ffi-tk/widget/scrollbar.rb +12 -0
  173. data/spec/ffi-tk/widget/spinbox.rb +12 -0
  174. data/spec/ffi-tk/widget/text.rb +246 -0
  175. data/spec/ffi-tk/widget/toplevel.rb +12 -0
  176. data/spec/helper.rb +3 -0
  177. data/tasks/authors.rake +21 -0
  178. data/tasks/bacon.rake +66 -0
  179. data/tasks/changelog.rake +18 -0
  180. data/tasks/gem.rake +22 -0
  181. data/tasks/gem_setup.rake +113 -0
  182. data/tasks/grancher.rake +12 -0
  183. data/tasks/manifest.rake +4 -0
  184. data/tasks/rcov.rake +17 -0
  185. data/tasks/release.rake +65 -0
  186. data/tasks/reversion.rake +8 -0
  187. data/tasks/setup.rake +12 -0
  188. data/tasks/ycov.rake +84 -0
  189. metadata +261 -0
@@ -0,0 +1,46 @@
1
+ module Tk
2
+ # This class is used for communication of variables with Tcl.
3
+ class Variable
4
+ attr_reader :name, :tcl_name, :bytesize
5
+
6
+ def initialize(name, value = None)
7
+ @name = name.freeze
8
+ @tcl_name = "$#{name}".freeze
9
+ set(value) unless None == value
10
+ end
11
+
12
+ def get
13
+ Tk.execute('set', name)
14
+ rescue RuntimeError
15
+ raise NameError, "can't read %p: no such variable" % [name]
16
+ end
17
+
18
+ def set(value)
19
+ Tk.execute_only('set', name, value)
20
+ end
21
+
22
+ def unset
23
+ Tk.execute_only('unset', name)
24
+ end
25
+
26
+ def to_tcl
27
+ TclString.new(name)
28
+ end
29
+
30
+ def to_s
31
+ get.to_s
32
+ end
33
+
34
+ def to_i
35
+ get.to_i
36
+ end
37
+
38
+ def to_boolean
39
+ get.to_boolean
40
+ end
41
+
42
+ def to_f
43
+ get.to_f
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,68 @@
1
+ module Tk
2
+ class Widget
3
+ include Pack, Destroy, Bind, Bindtags, WM, Winfo, Grid, Clipboard, Place, TkCmd
4
+
5
+ attr_reader :tk_parent, :tk_pathname
6
+
7
+ def self.tk_command
8
+ raise NotImplementedError, "Implement in subclass"
9
+ end
10
+
11
+ def initialize(tk_parent = Tk.root, options = None)
12
+ if tk_parent.respond_to?(:to_tcl_options?)
13
+ tk_parent, options = Tk.root, tk_parent
14
+ end
15
+
16
+ if !options || None == options
17
+ options = {}
18
+ else
19
+ options = options.dup
20
+ end
21
+
22
+ @tk_parent = tk_parent
23
+
24
+ yield(options) if block_given? && !options[:command]
25
+
26
+ command = self.class.tk_command
27
+ Tk.execute(command, assign_pathname, options.to_tcl_options?)
28
+ end
29
+
30
+ def to_tcl
31
+ tk_pathname.dump
32
+ end
33
+
34
+ def focus(option = None)
35
+ Focus.focus(self, option)
36
+ end
37
+
38
+ def focus_next
39
+ Focus.next(self)
40
+ end
41
+
42
+ def focus_prev
43
+ Focus.prev(self)
44
+ end
45
+
46
+ def raise(above = None)
47
+ Raise.raise(self, above)
48
+ end
49
+
50
+ def lower(below = None)
51
+ Lower.lower(self, below)
52
+ end
53
+
54
+ def execute(command, *args)
55
+ Tk.execute(tk_pathname, command, *args)
56
+ end
57
+
58
+ def execute_only(command, *args)
59
+ Tk.execute_only(tk_pathname, command, *args)
60
+ end
61
+
62
+ private
63
+
64
+ def assign_pathname
65
+ @tk_pathname = Tk.register_object(tk_parent, self)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,41 @@
1
+ module Tk
2
+ # A button is a widget that displays a textual string, bitmap or image.
3
+ # If text is displayed, it must all be in a single font, but it can occupy
4
+ # multiple lines on the screen (if it contains newlines or if wrapping occurs
5
+ # because of the wrapLength option) and one of the characters may optionally
6
+ # be underlined using the underline option.
7
+ # It can display itself in either of three different ways, according to the
8
+ # state option; it can be made to appear raised, sunken, or flat; and it can
9
+ # be made to flash.
10
+ # When a user invokes the button (by pressing mouse button 1 with the cursor
11
+ # over the button), then the command specified in the -command option is
12
+ # invoked.
13
+ class Button < Widget
14
+ include Cget, Configure
15
+
16
+ def self.tk_command; 'button'; end
17
+
18
+ # TODO: implement custom procs
19
+ def initialize(parent = Tk.root, options = None, &block)
20
+ if block
21
+ options = {} unless options.respond_to?(:[]=)
22
+ options[:command] = register_command(:command, &block)
23
+ end
24
+
25
+ super
26
+ end
27
+
28
+ def destroy
29
+ unregister_commands
30
+ super
31
+ end
32
+
33
+ def invoke
34
+ execute_only('invoke')
35
+ end
36
+
37
+ def flash
38
+ execute_only('flash')
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,806 @@
1
+ module Tk
2
+ # Canvas widgets implement structured graphics.
3
+ #
4
+ # A canvas displays any number of items, which may be things like rectangles,
5
+ # circles, lines, and text.
6
+ # Items may be manipulated (e.g. moved or re-colored) and commands may be
7
+ # associated with items in much the same way that the bind command allows
8
+ # commands to be bound to widgets.
9
+ # For example, a particular command may be associated with the <Button-1>
10
+ # event so that the command is invoked whenever button 1 is pressed with the
11
+ # mouse cursor over an item.
12
+ # This means that items in a canvas can have behaviors defined.
13
+ class Canvas < Widget
14
+ require "ffi-tk/widget/canvas/item.rb"
15
+ require "ffi-tk/widget/canvas/arc.rb"
16
+ require "ffi-tk/widget/canvas/bitmap.rb"
17
+ require "ffi-tk/widget/canvas/image.rb"
18
+ require "ffi-tk/widget/canvas/line.rb"
19
+ require "ffi-tk/widget/canvas/oval.rb"
20
+ require "ffi-tk/widget/canvas/polygon.rb"
21
+ require "ffi-tk/widget/canvas/rectangle.rb"
22
+ require "ffi-tk/widget/canvas/text.rb"
23
+ require "ffi-tk/widget/canvas/window.rb"
24
+
25
+ include Cget, Configure
26
+
27
+ def self.tk_command; 'canvas'; end
28
+
29
+ # For each item that meets the constraints specified by +search_spec+ and
30
+ # the +args+, add +tag+ to the list of tags associated with the item if it
31
+ # is not already present on that list.
32
+ # It is possible that no items will satisfy the constraints given by
33
+ # +search_spec+ and +args+, in which case the command has no effect.
34
+ def addtag(tag, search_spec, *args)
35
+ execute_only(:addtag, tag, search_spec, *args)
36
+ end
37
+
38
+ # Selects the item just after (above) the one given by +tag_or_id+ in the
39
+ # display list.
40
+ # If +tag_or_id+ denotes more than one item, then the last (topmost) of
41
+ # these items in the display list is used.
42
+ def addtag_above(tag, tag_or_id)
43
+ execute_only(:addtag, tag, :above, tag_or_id)
44
+ end
45
+
46
+ # Selects all the items in the canvas.
47
+ def addtag_all(tag)
48
+ execute_only(:addtag, tag, :all)
49
+ end
50
+
51
+ # Selects the item just before (below) the one given by +tag_or_id+ in the
52
+ # display list.
53
+ # If +tag_or_id+ denotes more than one item, then the first (lowest) of
54
+ # these items in the display list is used.
55
+ def addtag_below(tag, tag_or_id)
56
+ execute_only(:addtag, tag, :below, tag_or_id)
57
+ end
58
+
59
+ # Selects the item closest to the point given by +x+ and +y+.
60
+ # If more than one item is at the same closest distance (e.g. two items
61
+ # overlap the point), then the top-most of these items (the last one in the
62
+ # display list) is used.
63
+ #
64
+ # If +halo+ is specified, then it must be a non-negative value.
65
+ # Any item closer than +halo+ to the point is considered to overlap it.
66
+ #
67
+ # The +start+ argument may be used to step circularly through all the
68
+ # closest items.
69
+ # If +start+ is specified, it names an item using a tag or id (if by tag, it
70
+ # selects the first item in the display list with the given tag).
71
+ # Instead of selecting the topmost closest item, this form will select the
72
+ # topmost closest item that is below +start+ in the display list; if no such
73
+ # item exists, then the selection behaves as if the +start+ argument had not
74
+ # been specified.
75
+ def addtag_closest(tag, x, y, halo = None, start = None)
76
+ execute_only(:addtag, tag, :closest, x, y, halo, start)
77
+ end
78
+
79
+ # Selects all the items completely enclosed within the rectangular region
80
+ # given by +x1+, +y1+, +x2+, and +y2+.
81
+ # +x1+ must be no greater then +x2+ and +y1+ must be no greater than +y2+.
82
+ def addtag_enclosed(tag, x1, y1, x2, y2)
83
+ execute_only(:addtag, tag, :enclosed, x1, y1, x2, y2)
84
+ end
85
+
86
+ # Selects all the items that overlap or are enclosed within the rectangular
87
+ # region given by +x1+, +y1+, +x2+, and +y2+.
88
+ # +x1+ must be no greater then +x2+ and +y1+ must be no greater than +y2+.
89
+ def addtag_overlapping(tag, x1, y1, x2, y2)
90
+ execute_only(:addtag, tag, :overlapping, x1, y1, x2, y2)
91
+ end
92
+
93
+ # Selects all the items given by +tag_or_id+.
94
+ def addtag_withtag(tag, tag_or_id)
95
+ execute_only(:addtag, tag, :withtag, tag_or_id)
96
+ end
97
+
98
+ # Returns a list with four elements giving an approximate bounding box for
99
+ # all the items named by the +tags_or_ids+ argument.
100
+ # The list has the form `[x1, y1, x2, y2]` such that the drawn areas of all
101
+ # the named elements are within the region bounded by x1 on the left, x2 on
102
+ # the right, y1 on the top, and y2 on the bottom.
103
+ # The return value may overestimate the actual bounding box by a few pixels.
104
+ # If no items match any of the +tags_or_ids+ argument or if the matching
105
+ # items have empty bounding boxes (i.e. they have nothing to display) then
106
+ # nil is returned.
107
+ def bbox(*tags_or_ids)
108
+ execute(:bbox, *tags_or_ids).to_a?(&:to_i)
109
+ end
110
+
111
+ # This method associates +command+ with all the items given by +tag_or_id+
112
+ # such that whenever the event sequence given by +sequence+ occurs for one
113
+ # of the items the command will be invoked.
114
+ #
115
+ # This widget command is similar to the bind command except that it operates
116
+ # on items in a canvas rather than entire widgets.
117
+ # See the bind manual entry for complete details on the syntax of +sequence+
118
+ # and the substitutions performed on command before invoking it.
119
+ #
120
+ # If all arguments are specified then a new binding is created, replacing
121
+ # any existing binding for the same +sequence+ and +tag_or_id+.
122
+ # See [bind_append] for information of how augment an existing binding
123
+ # instead of replacing it.
124
+ #
125
+ # In this case the return value is nil.
126
+ #
127
+ # If +command+ is omitted then the method returns the command associated
128
+ # with +tag_or_id+ and +sequence+ (an error occurs if there is no such binding).
129
+ # If both +command+ and +sequence+ are omitted then the command returns a list
130
+ # of all the sequences for which bindings have been defined for +tag_or_id+.
131
+ #
132
+ # The only events for which bindings may be specified are those related to
133
+ # the mouse and keyboard (such as Enter, Leave, ButtonPress, Motion, and
134
+ # KeyPress) or virtual events.
135
+ # The handling of events in canvases uses the current item defined in ITEM
136
+ # IDS AND TAGS above.
137
+ # Enter and Leave events trigger for an item when it becomes the current
138
+ # item or ceases to be the current item; note that these events are
139
+ # different than Enter and Leave events for windows.
140
+ # Mouse-related events are directed to the current item, if any.
141
+ # Keyboard-related events are directed to the focus item, if any (see the
142
+ # focus widget command below for more on this).
143
+ # If a virtual event is used in a binding, that binding can trigger only if
144
+ # the virtual event is defined by an underlying mouse-related or
145
+ # keyboard-related event.
146
+ # It is possible for multiple bindings to match a particular event.
147
+ # This could occur, for example, if one binding is associated with the
148
+ # item's id and another is associated with one of the item's tags.
149
+ # When this occurs, all of the matching bindings are invoked.
150
+ # A binding associated with the all tag is invoked first, followed by one
151
+ # binding for each of the item's tags (in order), followed by a binding
152
+ # associated with the item's id.
153
+ # If there are multiple matching bindings for a single tag, then only the
154
+ # most specific binding is invoked.
155
+ # A continue command in a binding script terminates that script, and a
156
+ # break command terminates that script and skips any remaining scripts for
157
+ # the event, just as for the bind command.
158
+ # If bindings have been created for a canvas window using the bind command,
159
+ # then they are invoked in addition to bindings created for the canvas's
160
+ # items using the bind widget command.
161
+ # The bindings for items will be invoked before any of the bindings for
162
+ # the window as a whole.
163
+ def bind(tag_or_id, sequence = None, &script)
164
+ unless script
165
+ if None == sequence
166
+ return Tk.execute(:bind, tag_or_id)
167
+ else
168
+ return Tk.execute(:bind, tag_or_id, sequence)
169
+ end
170
+ end
171
+
172
+ name = "#{tag_or_id}_#{tag_name}".scan(/\w+/).join('_')
173
+ @events ||= {}
174
+ unregister_event(name)
175
+
176
+ Event::Handler.register_custom(script) do |id|
177
+ code = "%s bind %s %s { ::RubyFFI::event %d '' %s }"
178
+ props = Event::Data::PROPERTIES.transpose[0].join(' ')
179
+ tcl = code % [tk_pathname, tag_or_id, sequence, id, props]
180
+ Tk.interp.eval(tcl)
181
+ @events[name] = id
182
+ end
183
+ end
184
+
185
+ # Given a window x-coordinate in the canvas +screenx+, this command returns
186
+ # the canvas x-coordinate that is displayed at that location.
187
+ # If +gridspacing+ is true, then the canvas coordinate is rounded to the
188
+ # nearest multiple of gridspacing units.
189
+ def canvasx(screenx, gridspacing = false)
190
+ execute(:canvasx, screenx, gridspacing ? :gridspacing : None)
191
+ end
192
+
193
+ # Given a window y-coordinate in the canvas +screeny+ this command returns
194
+ # the canvas y-coordinate that is displayed at that location.
195
+ # If +gridspacing+ is true, then the canvas coordinate is rounded to the
196
+ # nearest multiple of gridspacing units.
197
+ def canvasy(screeny, gridspacing = false)
198
+ execute(:canvasy, screeny, gridspacing ? :gridspacing : None)
199
+ end
200
+
201
+ # Query or modify the coordinates that define an item.
202
+ # If no coordinates are specified, this command returns a list whose
203
+ # elements are the coordinates of the item named by +tag_or_id+.
204
+ # If coordinates are specified, then they replace the current coordinates
205
+ # for the named item.
206
+ # If +tag_or_id+ refers to multiple items, then the first one in the display
207
+ # list is used.
208
+ def coords(tag_or_id, *coord_list)
209
+ if coord_list.empty?
210
+ execute(:coords, tag_or_id).to_a
211
+ else
212
+ execute_only(:coords, tag_or_id, *coord_list.flatten)
213
+ end
214
+ end
215
+
216
+ # Create a new item in pathName of type type.
217
+ # The exact format of the arguments after type depends on type, but usually
218
+ # they consist of the coordinates for one or more points, followed by
219
+ # specifications for zero or more item options.
220
+ # See the subsections on individual item types below for more on the syntax
221
+ # of this command.
222
+ # This command returns the id for the new item.
223
+ def create(type, coord_list, options = {})
224
+ options = options ? options.to_tcl_options : None
225
+ id = execute(:create, type, coord_list, options).to_i
226
+ Item.create(self, type, id)
227
+ end
228
+
229
+ # Items of type arc appear on the display as arc-shaped regions.
230
+ # An arc is a section of an oval delimited by two angles (specified by the
231
+ # :start and :extent options) and displayed in one of several ways
232
+ # (specified by the :style option).
233
+ def create_arc(x1, y1, x2, y2, options = {})
234
+ create(:arc, [x1, y1, x2, y2], options)
235
+ end
236
+
237
+ # Items of type bitmap appear on the display as images with two colors,
238
+ # foreground and background.
239
+ def create_bitmap(x, y, options = {})
240
+ create(:bitmap, [x, y], options)
241
+ end
242
+
243
+ # Items of type image are used to display images on a canvas.
244
+ def create_image(x, y, options = {})
245
+ create(:image, [x, y], options)
246
+ end
247
+
248
+ # Items of type line appear on the display as one or more connected line
249
+ # segments or curves.
250
+ # Line items support coordinate indexing operations using the methods
251
+ # [dchars], [index], and [insert].
252
+ def create_line(*arguments)
253
+ options, coords = arguments.partition{|arg| arg.respond_to?(:to_tcl_options) }
254
+ create(:line, coords, options.first)
255
+ end
256
+
257
+ # Items of type oval appear as circular or oval regions on the display.
258
+ # Each oval may have an outline, a fill, or both.
259
+ def create_oval(x1, y1, x2, y2, options = {})
260
+ create(:oval, [x1, y1, x2, y2], options)
261
+ end
262
+
263
+ # Items of type polygon appear as polygonal or curved filled regions on the
264
+ # display. Polygon items support coordinate indexing operations using the
265
+ # methods [dchars], [index], or [insert].
266
+ def create_polygon(*arguments)
267
+ options, coords = arguments.partition{|arg| arg.respond_to?(:to_tcl_options) }
268
+ create(:polygon, coords, options.first)
269
+ end
270
+
271
+ # Items of type rectangle appear as rectangular regions on the display.
272
+ # Each rectangle may have an outline, a fill, or both.
273
+ def create_rectangle(x1, y1, x2, y2, options = {})
274
+ create(:rectangle, [x1, y1, x2, y2], options)
275
+ end
276
+
277
+ # A text item displays a string of characters on the screen in one or more
278
+ # lines. Text items support indexing and selection, along with the following
279
+ # text-related methods: [dchars], [focus], [icursor], [index], [insert], and
280
+ # [select].
281
+ def create_text(x, y, options = {})
282
+ create(:text, [x, y], options)
283
+ end
284
+
285
+ # Items of type window cause a particular window to be displayed at a given
286
+ # position on the canvas.
287
+ def create_window(x, y, options = {})
288
+ create(:window, [x, y], options)
289
+ end
290
+
291
+ # For each item given by +tag_or_id+, delete the characters, or coordinates, in
292
+ # the range given by +first+ and +last+, inclusive.
293
+ # If some of the items given by +tag_or_id+ do not support indexing
294
+ # operations then they ignore dchars.
295
+ # Text items interpret +first+ and +last+ as indices to a character, line and
296
+ # polygon items interpret them indices to a coordinate (an x,y pair).
297
+ # Indices are described in INDICES above.
298
+ # If +last+ is omitted, it defaults to +first+.
299
+ # This command returns nil.
300
+ def dchars(tag_or_id, first, last = None)
301
+ execute_only(:dchars, tag_or_id, first, last)
302
+ end
303
+
304
+ # Delete the items associated with the given +tags_or_ids+, and return nil.
305
+ def delete(*tags_or_ids)
306
+ execute_only(:delete, *tags_or_ids)
307
+ end
308
+
309
+ # For each of the items given by +tag_or_id+, delete the tag given by
310
+ # +tag_to_delete+ from the list of those associated with the item.
311
+ # If an item does not have the tag +tag_to_delete+ then the item is
312
+ # unaffected by the command.
313
+ # If +tag_to_delete+ is omitted then it defaults to +tag_or_id+.
314
+ # This command returns nil.
315
+ def dtag(tag_or_id, tag_to_delete = None)
316
+ execute_only(:dtag, tag_or_id, tag_to_delete)
317
+ end
318
+
319
+ # This command returns a list consisting of all the items that meet the
320
+ # constraints specified by +search_command+ and +args+.
321
+ # +search_command+ and +args+ have any of the forms accepted by the [addtag]
322
+ # method.
323
+ # The items are returned in stacking order, with the lowest item first.
324
+ def find(search_command, *args)
325
+ execute(:find, search_command, *args)
326
+ end
327
+
328
+ def find_above(tag, tag_or_id)
329
+ execute(:find, tag, :above, tag_or_id)
330
+ end
331
+
332
+ def find_all(tag)
333
+ execute(:find, tag, :all)
334
+ end
335
+
336
+ def find_below(tag, tag_or_id)
337
+ execute(:find, tag, :below, tag_or_id)
338
+ end
339
+
340
+ def find_closest(tag, x, y, halo = None, start = None)
341
+ execute(:find, tag, :closest, x, y, halo, start)
342
+ end
343
+
344
+ def find_enclosed(tag, x1, y1, x2, y2)
345
+ execute(:find, tag, :enclosed, x1, y1, x2, y2)
346
+ end
347
+
348
+ def find_overlapping(tag, x1, y1, x2, y2)
349
+ execute(:find, tag, :overlapping, x1, y1, x2, y2)
350
+ end
351
+
352
+ def find_withtag(tag, tag_or_id)
353
+ execute(:find, tag, :withtag, tag_or_id)
354
+ end
355
+
356
+ # Set the keyboard focus for the canvas widget to the item given by
357
+ # +tag_or_id+.
358
+ # If +tag_or_id+ refers to several items, then the focus is set to the
359
+ # first such item in the display list that supports the insertion cursor.
360
+ # If +tag_or_id+ does not refer to any items, or if none of them support the
361
+ # insertion cursor, then the focus is not changed.
362
+ # If +tag_or_id+ is an empty string, then the focus item is reset so that no
363
+ # item has the focus.
364
+ # If +tag_or_id+ is not specified then the command returns the id for the item
365
+ # that currently has the focus, or an empty string if no item has the
366
+ # focus. Once the focus has been set to an item, the item will display the
367
+ # insertion cursor and all keyboard events will be directed to that item.
368
+ # The focus item within a canvas and the focus window on the screen (set
369
+ # with the focus command) are totally independent: a given item does not
370
+ # actually have the input focus unless (a) its canvas is the focus window
371
+ # and (b) the item is the focus item within the canvas.
372
+ # In most cases it is advisable to follow the focus widget command with the
373
+ # focus command to set the focus window to the canvas (if it was not there
374
+ # already).
375
+ def focus(tag_or_id)
376
+ execute_only(:focus, tag_or_id)
377
+ end
378
+
379
+ # Return a list whose elements are the tags associated with the item given
380
+ # by +tag_or_id+.
381
+ # If +tag_or_id+ refers to more than one item, then the tags are returned from
382
+ # the first such item in the display list.
383
+ # If +tag_or_id+ does not refer to any items, or if the item contains no tags,
384
+ # then an empty string is returned.
385
+ def gettags(tag_or_id)
386
+ execute(:gettags, tag_or_id).to_a
387
+ end
388
+
389
+ # Set the position of the insertion cursor for the item(s) given by +tag_or_id+
390
+ # to just before the character whose position is given by index.
391
+ # If some or all of the items given by +tag_or_id+ do not support an insertion
392
+ # cursor then this command has no effect on them.
393
+ # See INDICES above for a description of the legal forms for index.
394
+ # Note: the insertion cursor is only displayed in an item if that item
395
+ # currently has the keyboard focus (see the widget command focus, below),
396
+ # but the cursor position may be set even when the item does not have the
397
+ # focus. This command returns an empty string.
398
+ def icursor(tag_or_id, index)
399
+ execute_only(:icursor, tag_or_id, index)
400
+ end
401
+
402
+ # This command returns a decimal string giving the numerical index within
403
+ # +tag_or_id+ corresponding to index.
404
+ # Index gives a textual description of the desired position as described in
405
+ # INDICES above.
406
+ # Text items interpret index as an index to a character, line and polygon
407
+ # items interpret it as an index to a coordinate (an x,y pair).
408
+ # The return value is guaranteed to lie between 0 and the number of
409
+ # characters, or coordinates, within the item, inclusive.
410
+ # If +tag_or_id+ refers to multiple items, then the index is processed in the
411
+ # first of these items that supports indexing operations (in display list
412
+ # order).
413
+ def index(tag_or_id, index)
414
+ execute(:index, tag_or_id, index)
415
+ end
416
+
417
+ # For each of the items given by +tag_or_id+, if the item supports text or
418
+ # coordinate, insertion then string is inserted into the item's text just
419
+ # before the character, or coordinate, whose index is +before+.
420
+ # Text items interpret +before+ as an index to a character, line and
421
+ # polygon items interpret it as an index to a coordinate (an x,y pair).
422
+ # For lines and polygons the string must be a valid coordinate sequence.
423
+ # See INDICES above for information about the forms allowed for +before+.
424
+ # This command returns an empty string.
425
+ def insert(tag_or_id, before, string)
426
+ execute(:insert, tag_or_id, before, string)
427
+ end
428
+
429
+ # Returns the current value of the configuration option for the item given
430
+ # by +tag_or_id+ whose name is option.
431
+ # This command is similar to the cget widget command except that it applies
432
+ # to a particular item rather than the widget as a whole.
433
+ # Option may have any of the values accepted by the create widget command
434
+ # when the item was created.
435
+ # If +tag_or_id+ is a tag that refers to more than one item, the first (lowest)
436
+ # such item is used.
437
+ def itemcget(tag_or_id, option)
438
+ execute(:itemcget, tag_or_id, option.to_tcl_option)
439
+ end
440
+
441
+ # This command is similar to the configure widget command except that it
442
+ # modifies item-specific options for the items given by +tag_or_id+ instead of
443
+ # modifying options for the overall canvas widget.
444
+ # If no option is specified, returns a list describing all of the available
445
+ # options for the first item given by +tag_or_id+ (see Tk_ConfigureInfo for
446
+ # information on the format of this list).
447
+ # If option is specified with no value, then the command returns a list
448
+ # describing the one named option (this list will be identical to the
449
+ # corresponding sublist of the value returned if no option is specified).
450
+ # If one or more option-value pairs are specified, then the command
451
+ # modifies the given widget option(s) to have the given value(s) in each of
452
+ # the items given by +tag_or_id+; in this case the command returns an empty
453
+ # string. The options and values are the same as those permissible in the
454
+ # create widget command when the item(s) were created; see the sections
455
+ # describing individual item types below for details on the legal options.
456
+ def itemconfigure(tag_or_id, options = None)
457
+ common_configure([:itemconfigure, tag_or_id], options)
458
+ end
459
+
460
+ # Move all of the items given by +tag_or_id+ to a new position in the display
461
+ # list just before the item given by belowThis.
462
+ # If +tag_or_id+ refers to more than one item then all are moved but the
463
+ # relative order of the moved items will not be changed.
464
+ # BelowThis is a tag or id; if it refers to more than one item then the
465
+ # first (lowest) of these items in the display list is used as the
466
+ # destination location for the moved items.
467
+ #
468
+ # Note: this command has no effect on window items.
469
+ # Window items always obscure other item types, and the stacking order of
470
+ # window items is determined by the raise and lower commands, not the raise
471
+ # and lower widget commands for canvases.
472
+ # This command returns nil.
473
+ def lower(tag_or_id, below = None)
474
+ execute_only(:lower, tag_or_id, below)
475
+ end
476
+
477
+ # Move each of the items given by +tag_or_id+ in the canvas coordinate space
478
+ # by adding +x_amount+ to the x-coordinate of each point associated with the
479
+ # item and +y_amount+ to the y-coordinate of each point associated with the
480
+ # item.
481
+ # This command returns nil.
482
+ def move(tag_or_id, x_amount, y_amount)
483
+ execute_only(:move, tag_or_id, x_amount, y_amount)
484
+ end
485
+
486
+ # Generate a Postscript representation for part or all of the canvas.
487
+ #
488
+ # If the :file option is specified then the Postscript is written to a file
489
+ # and an empty string is returned; otherwise the Postscript is returned as
490
+ # the result of the command.
491
+ # If the interpreter that owns the canvas is marked as safe, the operation
492
+ # will fail because safe interpreters are not allowed to write files.
493
+ #
494
+ # If the :channel option is specified, the argument denotes the name of a
495
+ # channel already opened for writing.
496
+ # The Postscript is written to that channel, and the channel is left open
497
+ # for further writing at the end of the operation.
498
+ #
499
+ # The Postscript is created in Encapsulated Postscript form using version
500
+ # 3.0 of the Document Structuring Conventions.
501
+ #
502
+ # Note: by default Postscript is only generated for information that
503
+ # appears in the canvas's window on the screen.
504
+ # If the canvas is freshly created it may still have its initial size of
505
+ # 1x1 pixel so nothing will appear in the Postscript.
506
+ # To get around this problem either invoke the update command to wait for
507
+ # the canvas window to reach its final size, or else use the :width and
508
+ # :height options to specify the area of the canvas to print.
509
+ #
510
+ # The +options+ argument provides additional information to control the
511
+ # generation of Postscript.
512
+ #
513
+ # The following options are supported:
514
+ #
515
+ # colormap: var_name
516
+ # var_name must be the name of an array variable that specifies a color
517
+ # mapping to use in the Postscript.
518
+ # Each element of var_name must consist of Postscript code to set a
519
+ # particular color value (e.g.
520
+ # "1.0 1.0 0.0 setrgbcolor").
521
+ # When outputting color information in the Postscript, Tk checks to see if
522
+ # there is an element of var_name with the same name as the color.
523
+ # If so, Tk uses the value of the element as the Postscript command to set
524
+ # the color.
525
+ # If this option has not been specified, or if there is no entry in
526
+ # var_name for a given color, then Tk uses the red, green, and blue
527
+ # intensities from the X color.
528
+ #
529
+ # colormode: mode
530
+ # Specifies how to output color information.
531
+ # Mode must be either color (for full color output), gray (convert all
532
+ # colors to their gray-scale equivalents) or mono (convert all colors to
533
+ # black or white).
534
+ #
535
+ # file: file_name
536
+ # Specifies the name of the file in which to write the Postscript.
537
+ # If this option is not specified then the Postscript is returned as the
538
+ # result of the command instead of being written to a file.
539
+ #
540
+ # fontmap: var_name
541
+ # var_name must be the name of an array variable that specifies a font
542
+ # mapping to use in the Postscript.
543
+ # Each element of var_name must consist of a Tcl list with two elements,
544
+ # which are the name and point size of a Postscript font.
545
+ # When outputting Postscript commands for a particular font, Tk checks to
546
+ # see if var_name contains an element with the same name as the font.
547
+ # If there is such an element, then the font information contained in that
548
+ # element is used in the Postscript.
549
+ # Otherwise Tk attempts to guess what Postscript font to use.
550
+ # Tk's guesses generally only work for well-known fonts such as Times and
551
+ # Helvetica and Courier, and only if the X font name does not omit any
552
+ # dashes up through the point size.
553
+ # For example, -*-Courier-Bold-R-Normal--*-120-* will work but
554
+ # *Courier-Bold-R-Normal*120* will not; Tk needs the dashes to parse the
555
+ # font name).
556
+ #
557
+ # height: size
558
+ # Specifies the height of the area of the canvas to print.
559
+ # Defaults to the height of the canvas window.
560
+ #
561
+ # pageanchor: anchor
562
+ # Specifies which point of the printed area of the canvas should appear
563
+ # over the positioning point on the page (which is given by the :pagex and
564
+ # :pagey options).
565
+ # For example, pageanchor: n means that the top center of the area of the
566
+ # canvas being printed (as it appears in the canvas window) should be over
567
+ # the positioning point.
568
+ # Defaults to center.
569
+ #
570
+ # pageheight: size
571
+ # Specifies that the Postscript should be scaled in both x and y so that
572
+ # the printed area is size high on the Postscript page.
573
+ # Size consists of a floating-point number followed by c for centimeters,
574
+ # i for inches, m for millimeters, or p or nothing for printer's points
575
+ # (1/72 inch).
576
+ # Defaults to the height of the printed area on the screen.
577
+ # If both :pageheight and :pagewidth are specified then the scale factor
578
+ # from :pagewidth is used (non-uniform scaling is not implemented).
579
+ #
580
+ # pagewidth: size
581
+ # Specifies that the Postscript should be scaled in both x and y so that
582
+ # the printed area is size wide on the Postscript page.
583
+ # Size has the same form as for -pageheight.
584
+ # Defaults to the width of the printed area on the screen.
585
+ # If both -pageheight and -pagewidth are specified then the scale factor
586
+ # from -pagewidth is used (non-uniform scaling is not implemented).
587
+ #
588
+ # pagex: position
589
+ # Position gives the x-coordinate of the positioning point on the
590
+ # Postscript page, using any of the forms allowed for -pageheight.
591
+ # Used in conjunction with the -pagey and -pageanchor options to determine
592
+ # where the printed area appears on the Postscript page.
593
+ # Defaults to the center of the page.
594
+ #
595
+ # pagey: position
596
+ # Position gives the y-coordinate of the positioning point on the
597
+ # Postscript page, using any of the forms allowed for -pageheight.
598
+ # Used in conjunction with the -pagex and -pageanchor options to determine
599
+ # where the printed area appears on the Postscript page.
600
+ # Defaults to the center of the page.
601
+ #
602
+ # rotate: boolean
603
+ # Boolean specifies whether the printed area is to be rotated 90 degrees.
604
+ # In non-rotated output the x-axis of the printed area runs along the
605
+ # short dimension of the page ("portrait" orientation); in rotated output
606
+ # the x-axis runs along the long dimension of the page
607
+ # ("landscape" orientation). Defaults to non-rotated.
608
+ #
609
+ # width:
610
+ # size Specifies the width of the area of the canvas to print.
611
+ # Defaults to the width of the canvas window.
612
+ #
613
+ # x: position
614
+ # Specifies the x-coordinate of the left edge of the area of the canvas
615
+ # that is to be printed, in canvas coordinates, not window coordinates.
616
+ # Defaults to the coordinate of the left edge of the window.
617
+ #
618
+ # y: position
619
+ # Specifies the y-coordinate of the top edge of the area of the canvas
620
+ # that is to be printed, in canvas coordinates, not window coordinates.
621
+ # Defaults to the coordinate of the top edge of the window.
622
+ def postscript(options = {})
623
+ execute(:postscript, options.to_tcl_options).to_s?
624
+ end
625
+
626
+ # Move all of the items given by +tag_or_id+ to a new position in the
627
+ # display list just after the item given by +above+.
628
+ # If +tag_or_id+ refers to more than one item then all are moved but the
629
+ # relative order of the moved items will not be changed.
630
+ # AboveThis is a tag or id; if it refers to more than one item then the last
631
+ # (topmost) of these items in the display list is used as the destination
632
+ # location for the moved items.
633
+ #
634
+ # Note: this command has no effect on window items.
635
+ # Window items always obscure other item types, and the stacking order of
636
+ # window items is determined by the raise and lower commands, not the raise
637
+ # and lower widget commands for canvases.
638
+ # This command returns nil.
639
+ def raise(tag_or_id, above = None)
640
+ execute_only(:raise, tag_or_id, above)
641
+ end
642
+
643
+ # Rescale all of the items given by +tag_or_id+ in canvas coordinate space.
644
+ # +x_origin+ and +y_origin+ identify the origin for the scaling operation
645
+ # and +x_scale+ and +y_scale+ identify the scale factors for x- and
646
+ # y-coordinates, respectively (a scale factor of 1.0 implies no change to
647
+ # that coordinate).
648
+ # For each of the points defining each item, the x-coordinate is adjusted to
649
+ # change the distance from +x_origin+ by a factor of +x_scale+.
650
+ # Similarly, each y-coordinate is adjusted to change the distance from
651
+ # +y_origin+ by a factor of +y_scale+.
652
+ # This command returns nil.
653
+ def scale(tag_or_id, x_origin, y_origin, x_scale, y_scale)
654
+ execute(:scale, tag_or_id, x_origin, y_origin, x_scale, y_scale)
655
+ end
656
+
657
+ # Records x and y and the canvas's current view; used in conjunction with
658
+ # later scan dragto commands.
659
+ # Typically this command is associated with a mouse button press in the
660
+ # widget and x and y are the coordinates of the mouse.
661
+ # It returns nil.
662
+ def scan_mark(x, y)
663
+ execute_only(:scan, :mark, x, y)
664
+ end
665
+
666
+ # This command computes the difference between its x and y arguments (which
667
+ # are typically mouse coordinates) and the x and y arguments to the last
668
+ # scan mark command for the widget.
669
+ # It then adjusts the view by gain times the difference in coordinates,
670
+ # where gain defaults to 10.
671
+ # This command is typically associated with mouse motion events in the
672
+ # widget, to produce the effect of dragging the canvas at high speed
673
+ # through its window.
674
+ # The return value is nil.
675
+ def scan_dragto(x, y, gain = None)
676
+ execute_only(:scan, :dragto, x, y, gain)
677
+ end
678
+
679
+ # Locate the end of the selection in +tag_or_id+ nearest to the character given
680
+ # by index, and adjust that end of the selection to be at index (i.e.
681
+ # including but not going beyond index).
682
+ # The other end of the selection is made the anchor point for future select
683
+ # to commands.
684
+ # If the selection is not currently in +tag_or_id+ then this command behaves
685
+ # the same as the select to widget command.
686
+ # Returns nil.
687
+ def select_adjust(tag_or_id, index)
688
+ execute_only(:select, :adjust, tag_or_id, index)
689
+ end
690
+
691
+ # Clear the selection if it is in this widget.
692
+ # If the selection is not in this widget then the command has no effect.
693
+ # Returns nil.
694
+ def select_clear
695
+ execute_only(:select, :clear)
696
+ end
697
+
698
+ # Set the selection anchor point for the widget to be just before the
699
+ # character given by index in the item given by +tag_or_id+.
700
+ # This command does not change the selection; it just sets the fixed end of
701
+ # the selection for future select to commands.
702
+ # Returns nil.
703
+ def select_from(tag_or_id, index)
704
+ execute(:select, :from, tag_or_id, index)
705
+ end
706
+
707
+ # Returns the id of the selected item, if the selection is in an item in
708
+ # this canvas.
709
+ # If the selection is not in this canvas then nil is returned.
710
+ def select_item
711
+ execute(:select, :item).to_s?
712
+ end
713
+
714
+ # Set the selection to consist of those characters of +tag_or_id+ between the
715
+ # selection anchor point and index.
716
+ # The new selection will include the character given by index; it will
717
+ # include the character given by the anchor point only if index is greater
718
+ # than or equal to the anchor point.
719
+ # The anchor point is determined by the most recent select adjust or select
720
+ # from command for this widget.
721
+ # If the selection anchor point for the widget is not currently in +tag_or_id+,
722
+ # then it is set to the same character given by index.
723
+ # Returns an empty string.
724
+ def select_to(tag_or_id, index)
725
+ execute(:select, :to, tag_or_id, index)
726
+ end
727
+
728
+ # Returns the type of the item given by +tag_or_id+, such as rectangle or text.
729
+ # If +tag_or_id+ refers to more than one item, then the type of the first item
730
+ # in the display list is returned.
731
+ # If +tag_or_id+ does not refer to any items at all then nil is returned.
732
+ def type(tag_or_id)
733
+ execute(:type, tag_or_id).to_sym?
734
+ end
735
+
736
+ # Returns a list containing two elements.
737
+ # Each element is a real fraction between 0 and 1; together they describe
738
+ # the horizontal span that is visible in the window.
739
+ # For example, if the first element is .2 and the second element is .6, 20%
740
+ # of the canvas's area (as defined by the -scrollregion option) is
741
+ # off-screen to the left, the middle 40% is visible in the window, and 40%
742
+ # of the canvas is off-screen to the right.
743
+ # These are the same values passed to scrollbars via the -xscrollcommand
744
+ # option.
745
+ def xview
746
+ execute(:xview).to_a(&:to_f)
747
+ end
748
+
749
+ # Adjusts the view in the window so that fraction of the total width of the
750
+ # canvas is off-screen to the left.
751
+ # Fraction must be a fraction between 0 and 1.
752
+ def xview_moveto(fraction)
753
+ execute_only(:xview, :moveto, fraction)
754
+ end
755
+
756
+ # This command shifts the view in the window left or right according to
757
+ # number and what.
758
+ # Number must be an integer.
759
+ # What must be either units or pages or an abbreviation of one of these.
760
+ # If what is units, the view adjusts left or right in units of the
761
+ # xScrollIncrement option, if it is greater than zero, or in units of
762
+ # one-tenth the window's width otherwise.
763
+ # If what is pages then the view adjusts in units of nine-tenths the
764
+ # window's width.
765
+ # If number is negative then information farther to the left becomes
766
+ # visible; if it is positive then information farther to the right becomes
767
+ # visible.
768
+ def xview_scroll(number, what)
769
+ execute_only(:xview, :scroll, number, what)
770
+ end
771
+
772
+ # Returns a list containing two elements.
773
+ # Each element is a real fraction between 0 and 1; together they describe
774
+ # the vertical span that is visible in the window.
775
+ # For example, if the first element is .6 and the second element is 1.0,
776
+ # the lowest 40% of the canvas's area (as defined by the -scrollregion
777
+ # option) is visible in the window.
778
+ # These are the same values passed to scrollbars via the -yscrollcommand
779
+ # option.
780
+ def yview
781
+ execute(:yview).to_a?(&:to_f)
782
+ end
783
+
784
+ # Adjusts the view in the window so that fraction of the canvas's area is
785
+ # off-screen to the top.
786
+ # Fraction is a fraction between 0 and 1.
787
+ def yview_moveto(fraction)
788
+ execute(:yview, :moveto, fraction)
789
+ end
790
+
791
+ # This command adjusts the view in the window up or down according to
792
+ # number and what.
793
+ # Number must be an integer.
794
+ # What must be either units or pages.
795
+ # If what is units, the view adjusts up or down in units of the
796
+ # yScrollIncrement option, if it is greater than zero, or in units of
797
+ # one-tenth the window's height otherwise.
798
+ # If what is pages then the view adjusts in units of nine-tenths the
799
+ # window's height.
800
+ # If number is negative then higher information becomes visible; if it is
801
+ # positive then lower information becomes visible.
802
+ def yview_scroll(number, what)
803
+ execute(:yview, :scroll, number, what)
804
+ end
805
+ end
806
+ end