module Tk

Manipulate Tk internal state

Ttk package merged Tcl/Tk core (Tcl/Tk 8.5+)

Constants

ALL_EVENTS
BREAK
CONTINUE
DONT_WAIT
ERROR
Error
FILE_EVENTS
HOST_OS
IDLE_EVENTS
None
OK
RETURN
RUN_EVENTLOOP_ON_MAIN_THREAD
TCL_CALLBACK
TCL_DELETE
TCL_EVENT
TCL_LIBPATH
TIMER_EVENTS
TK_LIBPATH
WINDOW_EVENTS

Attributes

callbacks[R]
widgets[R]

Public Class Methods

option_menu(pathname, *values) click to toggle source
# File lib/ffi-tk/command/option_menu.rb, line 3
def self.option_menu(pathname, *values)
  variable = Variable.new('the_option_menu')

  Tk.execute_only(:tk_optionMenu, pathname, variable, *values)
  variable
end
popup(menu, x, y, entry = None) click to toggle source

This procedure posts a menu at a given position on the screen and configures Tk so that the menu and its cascaded children can be traversed with the mouse or the keyboard. menu is the name of a menu widget and x and y are the root coordinates at which to display the menu. If entry is omitted, the menu's upper left corner is positioned at the given point. Otherwise +entry gives the index of an entry in menu and the menu will be positioned so that the entry is positioned over the given point.

set_palette(background, *rest) click to toggle source
# File lib/ffi-tk/command/set_palette.rb, line 3
def self.set_palette(background, *rest)
  if rest.empty?
    Tk.execute(:tk_setPalette, background)
  else
    Tk.execute(:tk_setPalette, background, *rest)
  end
end

Public Instance Methods

boolean(obj) click to toggle source
# File lib/ffi-tk/tk.rb, line 205
def boolean(obj)
  boolean_pointer = FFI::MemoryPointer.new(:int)
  FFI::Tcl.get_boolean(interp, obj.to_s, boolean_pointer)
  boolean_pointer.get_int(0) == 1
end
callback_break() click to toggle source
# File lib/ffi-tk/tk.rb, line 88
def callback_break
  throw :callback_break
end
callback_continue() click to toggle source
# File lib/ffi-tk/tk.rb, line 92
def callback_continue
  throw :callback_continue
end
choose_color(options = None) click to toggle source

Pops up a dialog box for the user to select a color.

If the user selects a color, this method will return the name of the color. If the user cancels the dialog, nil will be returned.

The following options are possible:

initialcolor: color
  Specifies the color to display in the dialog.

parent: window
  Makes window the logical parent of the color dialog.
  The dialog is displayed on top of its parent window.

title: string
  Specifies a string to display as the title of the dialog box.
  If this option is not specified, then a default title will be displayed.

@example usage

Tk::Button.new(Tk.root,
  bg: Tk.choose_color(initial_color: 'gray', title: 'Choose color'))
# File lib/ffi-tk/command/choose_color.rb, line 27
def choose_color(options = None)
  Tk.execute(:tk_chooseColor, options.to_tcl_options?).to_s?
end
choose_directory(options = None) click to toggle source

Pops up a dialog box for the user to select a directory.

The following options are possible:

initialdir: dirname
  Specifies that the directories in directory should be displayed when the
  dialog pops up.
  If this parameter is not specified, then the directories in the current
  working directory are displayed.
  If the parameter specifies a relative path, the return value will
  convert the relative path to an absolute path.

mustexist: boolean
  Specifies whether the user may specify non-existent directories.
  If this parameter is true, then the user may only select directories
  that already exist.
  The default value is false.

parent: window
  Makes window the logical parent of the dialog.
  The dialog is displayed on top of its parent window.
  On Mac OS X, this turns the file dialog into a sheet attached to the
  parent window.

title: string
  Specifies a string to display as the title of the
  dialog box.
  If this option is not specified, then a default title will be displayed.

@example usage

dir = Tk.choose_directory(initialdir: '~', title: 'Choose a directory')

if dir
  Tk::Label.new(Tk.root, text: "Selected #{dir}")
else
  Tk::Label.new(Tk.root, text: 'No directory selected')
end
# File lib/ffi-tk/command/choose_directory.rb, line 43
def choose_directory(options = None)
  Tk.execute(:tk_chooseDirectory, options.to_tcl_options?).to_s?
end
convert_arguments(*args) click to toggle source
# File lib/ffi-tk/tk.rb, line 211
def convert_arguments(*args)
  args.map(&:to_tcl).compact.join(' ')
end
dialog(window, title, text, bitmap, default, *answers) click to toggle source

Create modal dialog and wait for response

@param window

Name of top-level window to use for dialog.
Any existing window by this name is destroyed.

@param title [String]

Text to appear in the window manager's title bar for the dialog.

@param text [String]

Message to appear in the top portion of the dialog box.

@param bitmap [nil String]

If non-nil, specifies a bitmap to display in the top portion of the
dialog, to the left of the text.
If this is nil then no bitmap is displayed in the dialog.

@param default [nil Integer]

If this is an integer greater than or equal to zero, then it gives the
index of the button that is to be the default button for the dialog (0 for
the leftmost button, and so on).
If less than zero or nil then there will not be any default button.

@param answers

There will be one button for each of these arguments.
Each answer element specifies text to display in a button, in order from
left to right.

After creating a dialog box, [dialog] waits for the user to select one of the buttons either by clicking on the button with the mouse or by typing return to invoke the default button (if any).

Then it returns the index of the selected button: 0 for the leftmost button, 1 for the button next to it, and so on. If the dialog's window is destroyed before the user selects one of the buttons, then nil is returned.

While waiting for the user to respond, [dialog] sets a local grab. This prevents the user from interacting with the application in any way except to invoke the dialog box.

@example usage

reply = Tk.dialog('.foo', 'The Title', 'Do you want to say yes?',
  'questhead', 0, 'Yes', 'No', "I'm not sure")
# File lib/ffi-tk/command/dialog.rb, line 50
def dialog(window, title, text, bitmap, default, *answers)
  answer = Tk.execute(:tk_dialog,
                      window, title, text, bitmap, default, *answers).to_i
  return answer unless answer == -1
end
eval(string) click to toggle source
# File lib/ffi-tk/tk.rb, line 63
def eval(string)
  interp.eval(string)
end
execute(*args) click to toggle source
# File lib/ffi-tk/tk.rb, line 71
def execute(*args)
  interp.eval(convert_arguments(*args))
  result.tap{|r| puts "eval= %p" % [r] if $DEBUG }
end
execute_only(*args) click to toggle source
# File lib/ffi-tk/tk.rb, line 67
def execute_only(*args)
  interp.eval(convert_arguments(*args))
end
exit() click to toggle source
# File lib/ffi-tk/tk.rb, line 80
def exit
  execute('exit')
end
get_open_file(options = None) click to toggle source

Pop up a dialog box for the user to select a file to open.

This method is usually associated with the “Open” command in the “File” menu. Its purpose is for the user to select an existing file only. If the user enters a non-existing file, the dialog box gives the user an error prompt and requires the user to give an alternative selection. If an application allows the user to create new files, it should do so by providing a separate “New” command in the “File” menu.

If a user selects a file, the full pathname of the file is returned. If the user cancels the dialog, nil is returned.

The following options may be given:

defaultextension: extension
  Specifies a string that will be appended to the filename if the user
  enters a filename without an extension.
  The default value is the empty string, which means no extension will be
  appended to the filename in any case.
  This option is ignored on Mac OS X, which does not require extensions to
  filenames, and the UNIX implementation guesses reasonable values for
  this from the :filetypes option when this is not supplied.

filetypes: file_pattern_list
  If a File types listbox exists in the file dialog on the particular
  platform, this option gives the filetypes in this listbox.
  When the user choose a filetype in the listbox, only the files of that
  type are listed.
  If this option is unspecified, or if it is set to the empty list, or if
  the File types listbox is not supported by the particular platform then
  all files are listed regardless of their types.

initialdir: directory
  Specifies that the files in directory should be displayed when the
  dialog pops up.
  If this parameter is not specified, then the files in the current
  working directory are displayed.
  If the parameter specifies a relative path, the return value will
  convert the relative path to an absolute path.

initialfile: filename
  Specifies a filename to be displayed in the dialog when it pops up.

message: string
  Specifies a message to include in the client area of the dialog.
  This is only available on Mac OS X.

multiple: boolean
  Allows the user to choose multiple files from the dialog.

parent: window
  Makes window the logical parent of the file dialog.
  The file dialog is displayed on top of its parent window.
  On Mac OS X, this turns the file dialog into a sheet attached to the
  parent window.

title: string
  Specifies a string to display as the title of the dialog box.
  If this option is not specified, then a default title is displayed.

On the Unix and Macintosh platforms, extensions are matched using glob-style pattern matching. On the Windows platform, extensions are matched by the underlying operating system.

The types of possible extensions are:

* the special extension "*" matches any file
* the special extension "" matches any files that do not have an extension
  (i.e., the filename contains no full stop character)
* any character string that does not contain any wild card characters ("*"
  and "?").

Due to the different pattern matching rules on the various platforms, to ensure portability, wild card characters are not allowed in the extensions, except as in the special extension “*”. Extensions without a full stop character (e.g. “~”) are allowed but may not work on all platforms.

# File lib/ffi-tk/command/get_open_file.rb, line 83
def get_open_file(options = None)
  result = Tk.execute(:tk_getOpenFile, options.to_tcl_options?)
  path = result.respond_to?(:to_str) ? result.to_str : result.to_s?
  path unless path.empty?
end
get_save_file(options = None) click to toggle source

Pop up a dialog box for the user to select a file to save.

This method is usually associated with the “Save as” command in the “File” menu. If the user enters a file that already exists, the dialog box prompts the user for confirmation whether the existing file should be overwritten or not.

If a user selects a file, the full pathname of the file is returned. If the user cancels the dialog, nil is returned.

The following options may be given:

defaultextension: extension
  Specifies a string that will be appended to the filename if the user
  enters a filename without an extension.
  The default value is the empty string, which means no extension will be
  appended to the filename in any case.
  This option is ignored on Mac OS X, which does not require extensions to
  filenames, and the UNIX implementation guesses reasonable values for
  this from the :filetypes option when this is not supplied.

filetypes: file_pattern_list
  If a File types listbox exists in the file dialog on the particular
  platform, this option gives the filetypes in this listbox.
  When the user choose a filetype in the listbox, only the files of that
  type are listed.
  If this option is unspecified, or if it is set to the empty list, or if
  the File types listbox is not supported by the particular platform then
  all files are listed regardless of their types.

initialdir: directory
  Specifies that the files in directory should be displayed when the
  dialog pops up.
  If this parameter is not specified, then the files in the current
  working directory are displayed.
  If the parameter specifies a relative path, the return value will
  convert the relative path to an absolute path.

initialfile: filename
  Specifies a filename to be displayed in the dialog when it pops up.

message: string
  Specifies a message to include in the client area of the dialog.
  This is only available on Mac OS X.

multiple: boolean
  Allows the user to choose multiple files from the dialog.

parent: window
  Makes window the logical parent of the file dialog.
  The file dialog is displayed on top of its parent window.
  On Mac OS X, this turns the file dialog into a sheet attached to the
  parent window.

title: string
  Specifies a string to display as the title of the dialog box.
  If this option is not specified, then a default title is displayed.

On the Unix and Macintosh platforms, extensions are matched using glob-style pattern matching. On the Windows platform, extensions are matched by the underlying operating system.

The types of possible extensions are:

* the special extension "*" matches any file
* the special extension "" matches any files that do not have an extension
  (i.e., the filename contains no full stop character)
* any character string that does not contain any wild card characters ("*"
  and "?").

Due to the different pattern matching rules on the various platforms, to ensure portability, wild card characters are not allowed in the extensions, except as in the special extension “*”. Extensions without a full stop character (e.g. “~”) are allowed but may not work on all platforms.

# File lib/ffi-tk/command/get_save_file.rb, line 81
def get_save_file(options = None)
  result = Tk.execute(:tk_getSaveFile, options.to_tcl_options?)
  path = result.respond_to?(:to_str) ? result.to_str : result.to_s?
  path unless path.empty?
end
handle_callback(id, *args) click to toggle source
# File lib/ffi-tk/tk.rb, line 163
def handle_callback(id, *args)
  callback = @callbacks.fetch(id.to_i)
  callback.call(*args)
end
init() click to toggle source
# File lib/ffi-tk/tk.rb, line 18
def init
  @interp = if RUN_EVENTLOOP_ON_MAIN_THREAD
              FFI::Tcl.setup_eventloop_on_main_thread
            else
              FFI::Tcl.setup_eventloop_on_new_thread
            end

  FFI::Tcl.init(@interp)
  FFI::Tcl::EvalResult.reset_types(@interp)
  FFI::Tk.init(@interp)

  @root = Root.new

  @interp.eval('namespace eval RubyFFI {}')

  FFI::Tcl.create_obj_command(@interp, 'RubyFFI::callback', TCL_CALLBACK, 0, TCL_DELETE)
  FFI::Tcl.create_obj_command(@interp, 'RubyFFI::event',    TCL_EVENT,    0, TCL_DELETE)

  module_eval('class << Tk; attr_reader :interp, :root; end')

  @interp
end
interp() click to toggle source

A little something so people don't have to call Tk.init

# File lib/ffi-tk/tk.rb, line 42
def interp
  Tk.init
  @interp
end
library() click to toggle source

This variable holds the file name for a directory containing a library of Tcl scripts related to Tk. These scripts include an initialization file that is normally processed whenever a Tk application starts up, plus other files containing procedures that implement default behaviors for widgets. The initial value of tcl_library is set when Tk is added to an interpreter; this is done by searching several different directories until one is found that contains an appropriate Tk startup script. If the TK_LIBRARY environment variable exists, then the directory it names is checked first. If TK_LIBRARY is not set or does not refer to an appropriate directory, then Tk checks several other directories based on a compiled-in default location, the location of the Tcl library directory, the location of the binary containing the application, and the current working directory. The variable can be modified by an application to switch to a different library.

# File lib/ffi-tk/command/vars.rb, line 31
def library
  @library.to_s
end
library=(new_library) click to toggle source
# File lib/ffi-tk/command/vars.rb, line 35
def library=(new_library)
  @library.set(new_library.to_s)
end
mainloop() click to toggle source
# File lib/ffi-tk/tk.rb, line 53
def mainloop
  @running = true

  interp.do_one_event(0) while @running && interp.wait_for_event(0.05)
end
message_box(options = None) click to toggle source

Pops up a message window and waits for user response. This procedure creates and displays a message window with an application-specified message, an icon and a set of buttons. Each of the buttons in the message window is identified by a unique symbolic name (see the :type options).

After the message window is popped up, [message_box] waits for the user to select one of the buttons. Then it returns the symbolic name of the selected button.

The following options pairs are supported:

default: name
  Name gives the symbolic name of the default button for this message
  window (:ok, :cancel, and so on).
  See :type for a list of the symbolic names.
  If this option is not specified, the first button in the dialog will be
  made the default.

detail: string
  Specifies an auxiliary message to the main message given by the :message
  option. Where supported by the underlying OS, the message detail will be
  presented in a less emphasized font than the main message.

icon: icon_image
  Specifies an icon to display.
  icon_image must be one of the following: :error, :info, :question or
  :warning. If this option is not specified, then the info icon will be
  displayed.

message: string
  Specifies the message to display in this message box.

parent: window
  Makes window the logical parent of the message box.
  The message box is displayed on top of its parent window.

title: string
  Specifies a string to display as the title of the message box.
  The default value is an empty string.

type: predefined_type
  Arranges for a predefined set of buttons to be displayed.

The following values are possible for predefined_type:

:abortretryignore

Displays three buttons whose symbolic names are :abort, :retry and :ignore.

:ok

Displays one button whose symbolic name is :ok.

:okcancel

Displays two buttons whose symbolic names are :ok and :cancel.

:retrycancel

Displays two buttons whose symbolic names are :retry and :cancel.

:yesno

Displays two buttons whose symbolic names are :yes and :no.

:yesnocancel

Displays three buttons whose symbolic names are :yes, :no and :cancel.
# File lib/ffi-tk/command/message_box.rb, line 63
def message_box(options = None)
  Tk.execute(:tk_messageBox, options.to_tcl_options?).to_sym
end
patchlevel() click to toggle source

Contains a decimal integer giving the current patch level for Tk. The patch level is incremented for each new release or patch, and it uniquely identifies an official version of Tk.

# File lib/ffi-tk/command/vars.rb, line 42
def patchlevel
  @patchlevel.to_s
end
pathname_to_widget(pathname) click to toggle source
# File lib/ffi-tk/tk.rb, line 215
def pathname_to_widget(pathname)
  @widgets[pathname]
end
register_object(parent, object) click to toggle source
# File lib/ffi-tk/tk.rb, line 168
def register_object(parent, object)
  parent_name = parent.respond_to?(:tk_pathname) ? parent.tk_pathname : parent
  cmd = object.class.tk_command

  id = "#{cmd}#{uuid(cmd)}".gsub('::', '__') # :: is namespace convention.
  pathname = [parent_name, id].join('.').squeeze('.')
  @widgets[pathname] = object

  pathname
end
register_proc(proc, argument_string = '') click to toggle source
# File lib/ffi-tk/tk.rb, line 187
def register_proc(proc, argument_string = '')
  id = uuid(:proc) { |uuid| @callbacks[uuid] = proc }
  [id, %(RubyFFI::callback #{id} #{argument_string})]
end
result() click to toggle source
# File lib/ffi-tk/tk.rb, line 76
def result
  interp.guess_result
end
root() click to toggle source

A little something so people don't have to call Tk.init

# File lib/ffi-tk/tk.rb, line 48
def root
  Tk.init
  @root
end
stop() click to toggle source
# File lib/ffi-tk/tk.rb, line 59
def stop
  @running = false
end
strict_motif() click to toggle source

This variable is set to zero by default. If an application sets it to one, then Tk attempts to adhere as closely as possible to Motif look-and-feel standards. For example, active elements such as buttons and scrollbar sliders will not change color when the pointer passes over them.

# File lib/ffi-tk/command/vars.rb, line 51
def strict_motif
  @strict_motif.to_boolean
end
strict_motif=(new_value) click to toggle source
# File lib/ffi-tk/command/vars.rb, line 55
def strict_motif=(new_value)
  @strict_motif.set(new_value ? true : false)
end
tcl_callback(_client_data, interp, objc, objv) click to toggle source

TODO: support for break and continue return status (by catch/throw) 1 means true, 0 means false.

# File lib/ffi-tk/tk.rb, line 104
def tcl_callback(_client_data, interp, objc, objv)
  cmd, id, *args = tcl_cmd_args(interp, objc, objv)
  id = id.first if id.is_a?(Array)

  catch :callback_break do
    catch :callback_continue do
      result = handle_callback(id, *args)
      FFI::Tcl::Interp.new(interp).obj_result = result

      return OK
    end

    return CONTINUE
  end

  return BREAK
rescue => ex
  FFI::Tcl::Interp.new(interp).obj_result = ex
  return ERROR
end
tcl_cmd_args(interp, objc, objv) click to toggle source
# File lib/ffi-tk/tk.rb, line 147
def tcl_cmd_args(interp, objc, objv)
  length = FFI::MemoryPointer.new(0)
  array = objv.read_array_of_pointer(objc)
  array.map do |e|
    obj = FFI::Tcl::EvalResult.guess(interp, e)
    case obj
    when Integer, Float
      obj
    when nil
      nil
    else
      obj.respond_to?(:dup) ? obj.dup : obj
    end
  end
end
tcl_delete(_client_data) click to toggle source

without our callbacks, nothing goes anymore, abort mission

# File lib/ffi-tk/tk.rb, line 97
def tcl_delete(_client_data)
  raise 'tcl function is going to be removed'
end
tcl_event(_client_data, interp, objc, objv) click to toggle source

TODO: support for break and continue return status (by catch/throw)

# File lib/ffi-tk/tk.rb, line 127
def tcl_event(_client_data, interp, objc, objv)
  cmd, id, sequence, *args = tcl_cmd_args(interp, objc, objv)

  catch :callback_break do
    catch :callback_continue do
      Event::Data.new(id.to_i, sequence.to_s, *args).call

      return OK
    end

    return CONTINUE
  end

  return BREAK
rescue => ex
  FFI::Tcl::Interp.new(interp).obj_result = ex
  return ERROR
end
text_redraw() click to toggle source

These variables are set by text widgets when they have debugging turned on. The values written to these variables can be used to test or debug text widget operations. These variables are mostly used by Tk's test suite.

# File lib/ffi-tk/command/vars.rb, line 63
def text_redraw
  @text_redraw.get
end
text_relayout() click to toggle source
# File lib/ffi-tk/command/vars.rb, line 67
def text_relayout
  @text_relayout.get
end
unregister_object(object) click to toggle source
# File lib/ffi-tk/tk.rb, line 179
def unregister_object(object)
  @widgets.delete_if { |_path, obj| obj == object }
end
unregister_objects(*objects) click to toggle source
# File lib/ffi-tk/tk.rb, line 183
def unregister_objects(*objects)
  @widgets.delete_if { |_path, obj| objects.include?(obj) }
end
unregister_proc(id) click to toggle source
# File lib/ffi-tk/tk.rb, line 192
def unregister_proc(id)
  @callbacks.delete(id)
end
update(idletasks = None) click to toggle source
# File lib/ffi-tk/tk.rb, line 84
def update(idletasks = None)
  execute('update', idletasks)
end
uuid(name) { |id| ... } click to toggle source
# File lib/ffi-tk/tk.rb, line 196
def uuid(name)
  @mutex.synchronize do
    id = @register[name]
    @register[name] += 1
    yield id if block_given?
    id
  end
end
version() click to toggle source

Tk sets this variable in the interpreter for each application. The variable holds the current version number of the Tk library in the form major.minor. Major and minor are integers. The major version number increases in any Tk release that includes changes that are not backward compatible (i.e. whenever existing Tk applications and scripts may have to change to work with the new release). The minor version number increases with each new release of Tk, except that it resets to zero whenever the major version number changes.

# File lib/ffi-tk/command/vars.rb, line 80
def version
  @version.to_s
end