class SimpleTk::Window
A class representing a window that all the other controls get piled into.
We use the “grid” layout manager. Each widget gets assigned to the grid using specific column and row settings.
To simplify things the Window
class allows either “free” mode or “flow” mode placement. In “free” mode, you must specify the :column and :row option for each widget you add. In “flow” mode, the :column and :row are computed for you automatically.
There are multiple ways to give the Window
the grid coordinates for the new widget.
You can explicitly set the :column, :row, :columnspan, and :rowspan options. The :col option is equivalent to :column and the :colspan option is equivalent to the :columnspan option. The :columnspan and :rowspan options default to a value of 1 if you do not specify them.
add_label :xyz, 'XYZ', :column => 1, :row => 2, :columnspan => 1, :rowspan => 1 add_label :xyz, 'XYZ', :col => 1, :row => 2, :colspan => 1, :rowspan => 1
You can also set the :position option. The :pos option is equivalent to the :position option. The argument to this option is either an Array or a Hash. If an Array is specified, it should have either 2 or 4 values.
Attributes
Allows you to get or set the linked object for this window.
A linked object can be used to provide command callbacks.
Public Class Methods
Creates a new window.
Some valid options:
- title
-
The title to put on the window. Defaults to “My Application”.
- parent
-
The parent window for this window. Use your main window for any popup windows you create. Defaults to nil.
- padding
-
The padding for the content frame. This can be a single value to have the same padding all around. It can also be two numbers to specify horizontal and vertical padding. If you specify four numbers, they are for left, top, right, and bottom padding. Defaults to “3”.
- sticky
-
The stickiness for the content frame. This defaults to “nsew” and most likely you don’t want to change it, but the option is available.
Window
options can be prefixed with ‘window_’ or put into a hash under a ‘window’ option.
SimpleTk::Window.new(window: { geometry: '300x300' }) SimpleTk::Window.new(window_geometry: '300x300')
Any options not listed above or explicitly assigned to the window are applied to the content frame.
If you provide a block it will be executed in the scope of the window.
# File lib/simple_tk/window.rb, line 70 def initialize(options = {}, &block) @stkw_object_list = {} @stkw_var_list = {} options = { title: 'My Application', padding: '3', sticky: 'nsew' }.merge(options.inject({}) { |m,(k,v)| m[k.to_sym] = v; m}) title = options.delete(:title) || 'My Application' parent = options.delete(:parent) is_frame = options.delete(:stk___frame) win_opt, options = split_window_content_options(options) @stkw_object_list[:stk___root] = if is_frame parent elsif parent TkToplevel.new(parent) else TkRoot.new end unless is_frame root.title title TkGrid.columnconfigure root, 0, weight: 1 TkGrid.rowconfigure root, 0, weight: 1 apply_options root, win_opt end @stkw_object_list[:stk___content] = Tk::Tile::Frame.new(root) apply_options content, options @stkw_config = { placement: :free, row_start: -1, col_start: -1, col_count: -1, cur_col: -1, cur_row: -1, base_opt: { }, max_col: 0, max_row: 0 } if block_given? instance_eval &block end end
Public Instance Methods
Adds a new check box to the window
- name
-
A unique label for this item, cannot be nil.
- label_text
-
The text to put in the button. If this is a Symbol, then a variable will be created with this value as its name. Otherwise the button will be given the string value as a static label.
- options
-
Options for the check box. Common options are :column, :row, :sticky, and :value.
Accepts a block or command the same as a button. Unlike a button there is no default proc assigned.
# File lib/simple_tk/window.rb, line 293 def add_check_box(name, label_text, options = {}, &block) options = options.dup proc = get_command(options.delete(:command), &block) add_widget Tk::Tile::Checkbutton, name, label_text, options.merge(create_var: :variable), &proc end
Adds a new combo box to the window.
- name
-
A unique label for this item, cannot be nil.
- options
-
Options for the check box. Common options are :column, :row, :sticky, :value, and :values.
The :values option will define the items in the combo box, the :value option sets the selected option if set.
Accepts a block or command the same as a button. Unlike a button there is no default proc assigned.
# File lib/simple_tk/window.rb, line 385 def add_combo_box(name, options = {}, &block) options = options.dup proc = get_command(options.delete(:command), &block) item = add_widget Tk::Tile::Combobox, name, nil, options.merge(create_var: :textvariable) if proc item.bind('<ComboboxSelected>') { proc.call } end item end
Adds a new frame to the window.
- name
-
A unique label for this item, cannot be nil.
- options
-
Options for the frame. Common options are :column, :row, and :padding.
A frame can be used as a sub-window. The returned object has all of the same methods as a Window
so you can add other widgets to it and use it as a grid within the parent grid.
If you provide a block, it will be executed in the scope of the frame.
# File lib/simple_tk/window.rb, line 407 def add_frame(name, options = {}, &block) name = name.to_sym raise DuplicateNameError if @stkw_object_list.include?(name) options = fix_position(options.dup) @stkw_object_list[name] = SimpleTk::Window.new(options.merge(parent: content, stk___frame: true), &block) end
Adds a new image to the window.
- name
-
A unique label for this item, cannot be nil.
- image_path
-
The path to the image, can be relative or absolute.
- options
-
Options for the image. Common options are :column, :row, and :sticky.
# File lib/simple_tk/window.rb, line 205 def add_image(name, image_path, options = {}) image = TkPhotoImage.new(file: image_path) add_widget Tk::Tile::Label, name, nil, options.merge(image: image) end
Adds a new image check box to the window
- name
-
A unique label for this item, cannot be nil.
- image_path
-
The path to the image, can be relative or absolute.
- options
-
Options for the check box. Common options are :column, :row, :sticky, and :value.
Accepts a block or command the same as a button. Unlike a button there is no default proc assigned.
# File lib/simple_tk/window.rb, line 310 def add_image_check_box(name, image_path, options = {}, &block) options = options.dup image = TkPhotoImage.new(file: image_path) proc = get_command(options.delete(:command), &block) add_widget Tk::Tile::Checkbutton, name, nil, options.merge(image: image, create_var: :variable), &proc end
Adds a new label to the window.
- name
-
A unique label for this item, cannot be nil.
- label_text
-
The text to put in the label. If this is a Symbol, then a variable will be created with this value as its name. Otherwise the label will be given the string value as a static label.
- options
-
Options for the label. Common options are :column, :row, and :sticky.
# File lib/simple_tk/window.rb, line 192 def add_label(name, label_text, options = {}) add_widget Tk::Tile::Label, name, label_text, options end
Adds a new text box to the window.
- name
-
A unique label for this item, cannot be nil.
- options
-
Options for the text box. Common options are :column, :row, :sticky, :width, :value, and :password.
Accepts a block or command the same as a button. Unlike the button there is no default proc assigned. The proc, if specified, will be called for each keypress. It should return 1 (success) or 0 (failure).
# File lib/simple_tk/window.rb, line 265 def add_text_box(name, options = {}, &block) options = options.dup if options.delete(:password) options[:show] = '*' end proc = get_command(options.delete(:command), &block) item = add_widget Tk::Tile::Entry, name, nil, options.merge(create_var: :textvariable) # FIXME: Should the command be processed for validation or bound to a specific event? if proc item.send :validate, 'key' item.send(:validatecommand) { proc.call } end item end
Gets all of the children on this window.
# File lib/simple_tk/window.rb, line 148 def children TkWinfo.children(content) end
Gets the number of columns in use.
# File lib/simple_tk/window.rb, line 124 def column_count @stkw_config[:max_col] end
Allows you to configure the grid options for all cells in a column.
# File lib/simple_tk/window.rb, line 136 def config_column(col, options = {}) TkGrid.columnconfigure content, col, options end
Allows you to configure the grid options for all cells in a row.
# File lib/simple_tk/window.rb, line 142 def config_row(row, options = {}) TkGrid.rowconfigure content, row, options end
Gets objects from the window.
# File lib/simple_tk/window.rb, line 154 def object @object_helper ||= SimpleTk::GetSetHelper.new(self, :@stkw_object_list, true, nil, ->(i,v) { } ) end
Binds a method or Proc to a window event.
- event
-
The event to bind to (eg - “1”, “Return”, “Shift-2”)
- proc
-
A predefined proc to bind to the event, only used if no block is provided.
If a block is provided it will be bound, otherwise the proc
argument is looked at. If the proc argument specifies a Proc it will be bound. If the proc argument is a Symbol and the Window
or linked_object
responds to the proc, then the method from the Window
or linked_object
will be bound.
# File lib/simple_tk/window.rb, line 176 def on(event, proc = nil, &block) cmd = get_command proc, &block root.bind(event) { cmd.call } end
Gets the number of rows in use.
# File lib/simple_tk/window.rb, line 130 def row_count @stkw_config[:max_row] end
Sets the placement mode for this window.
- mode
-
This can be either :free or :flow. The default mode for a new window is :free. Frames do not inherit this setting from the parent window. In free placement mode, you must provide the :column and :row for every widget. In flow placement mode, you must not provide the :column or :row for any widget. Flow placement will add each widget to the next column moving to the next row as needed.
- options
-
Options are ignored in free placement mode. In flow placement mode, you must provide :first_column, :first_row, and either :last_column or :column_count. If you specify both :last_column and :column_count then :last_column will be used. The :first_column and :first_row must be greater than or equal to zero. The :last_column can be equal to the first column but the computed :column_count must be at least 1.
# File lib/simple_tk/window.rb, line 432 def set_placement_mode(mode, options = {}) raise ArgumentError, 'mode must be :free or :flow' unless [ :free, :flow ].include?(mode) if mode == :flow first_col = options[:first_column] col_count = if (val = options[:last_column]) val - first_col + 1 elsif (val = options[:column_count]) val else nil end first_row = options[:first_row] raise ArgumentError, ':first_column must be provided for flow placement' unless first_col raise ArgumentError, ':first_row must be provided for flow placement' unless first_row raise ArgumentError, ':last_column or :column_count must be provided for flow placement' unless col_count raise ArgumentError, ':first_column must be >= 0' unless first_col >= 0 raise ArgumentError, ':first_row must be >= 0' unless first_row >= 0 raise ArgumentError, ':column_count must be > 0' unless col_count > 0 @stkw_config.merge!( placement: :flow, col_start: first_col, row_start: first_row, col_count: col_count, cur_row: first_row, cur_col: first_col ) elsif mode == :free @stkw_config.merge!( placement: :free, col_start: -1, row_start: -1, col_count: -1, cur_row: -1, cur_col: -1 ) end end
Gets or sets variable values for this window.
# File lib/simple_tk/window.rb, line 160 def var @var_helper ||= SimpleTk::GetSetHelper.new(self, :@stkw_var_list, true, :value, :value=) end
Executes a block with the specified options preset.
# File lib/simple_tk/window.rb, line 474 def with_options(options = {}, &block) return unless block backup_options = @stkw_config[:base_opt] @stkw_config[:base_opt] = @stkw_config[:base_opt].merge(options) begin instance_eval &block ensure @stkw_config[:base_opt] = backup_options end end
Private Instance Methods
# File lib/simple_tk/window.rb, line 562 def add_widget(klass, name, label_text, options = {}, &block) raise ArgumentError, 'name cannot be blank' if name.to_s.strip == '' name = name.to_sym raise DuplicateNameError if @stkw_object_list.include?(name) options = options.dup cmd = get_command options.delete(:command), &block if cmd options[:command] = cmd end options = fix_position(options) if (attrib = options.delete(:create_var)) @stkw_var_list[name] ||= TkVariable.new if attrib.is_a?(Symbol) options[attrib] = @stkw_var_list[name] end init_val = options.delete(:value) var[name] = init_val if init_val end @stkw_object_list[name] = klass.new(content) if label_text set_text @stkw_object_list[name], label_text end apply_options @stkw_object_list[name], options # add disable, disabled?, and enable methods. @stkw_object_list[name].extend SimpleTk::DisableHelpers # return the object after creation @stkw_object_list[name] end
# File lib/simple_tk/window.rb, line 619 def apply_options(object, options) widget_opt, grid_opt = split_widget_grid_options(options) widget_opt.each do |key,val| if val.is_a?(Proc) object.send key, &val else object.send key, val end end object.grid(grid_opt) unless grid_opt.empty? end
# File lib/simple_tk/window.rb, line 491 def content @stkw_object_list[:stk___content] end
# File lib/simple_tk/window.rb, line 495 def fix_position(options) col = options.delete(:column) || options.delete(:col) row = options.delete(:row) width = options.delete(:columnspan) || options.delete(:colspan) || options.delete(:columns) || 1 height = options.delete(:rowspan) || options.delete(:rows) || 1 pos = options.delete(:position) || options.delete(:pos) skip = options.delete(:skip) if pos.is_a?(Array) col = pos[0] || col row = pos[1] || row width = pos[2] || width height = pos[3] || height elsif pos.is_a?(Hash) col = pos[:column] || pos[:col] || pos[:x] || col row = pos[:row] || pos[:y] || row width = pos[:width] || pos[:w] || pos[:columnspan] || pos[:colspan] || width height = pos[:height] || pos[:h] || pos[:rowspan] || height end if @stkw_config[:placement] == :free raise ArgumentError, ':column must be set for free placement mode' unless col raise ArgumentError, ':row must be set for free placement mode' unless row raise ArgumentError, ':skip must not be set for free placement mode' if skip elsif @stkw_config[:placement] == :flow raise ArgumentError, ':column cannot be set for flow placement mode' if col raise ArgumentError, ':row cannot be set for flow placement mode' if row raise ArgumentError, ":columnspan cannot be more than #{@stkw_config[:col_count]} in flow placement mode" if width > @stkw_config[:col_count] raise ArgumentError, ':rowspan cannot be more than 1 in flow placement mode' if height > 1 # skip cells if the user requested it. if skip @stkw_config[:cur_col] += skip while @stkw_config[:cur_col] >= @stkw_config[:col_start] + @stkw_config[:col_count] @stkw_config[:cur_row] += 1 @stkw_config[:cur_col] -= @stkw_config[:col_count] end end if width > @stkw_config[:col_count] - @stkw_config[:cur_col] + 1 @stkw_config[:cur_row] += 1 @stkw_config[:cur_col] = @stkw_config[:col_start] end col = @stkw_config[:cur_col] row = @stkw_config[:cur_row] @stkw_config[:cur_col] += width if @stkw_config[:cur_col] >= @stkw_config[:col_start] + @stkw_config[:col_count] @stkw_config[:cur_col] = @stkw_config[:col_start] @stkw_config[:cur_row] += 1 end end options[:column] = col options[:row] = row options[:columnspan] = width options[:rowspan] = height end_col = options[:column] + options[:columnspan] - 1 end_row = options[:row] + options[:rowspan] - 1 # track the columns and rows. @stkw_config[:max_col] = end_col if end_col > @stkw_config[:max_col] @stkw_config[:max_row] = end_row if end_row > @stkw_config[:max_row] options end
# File lib/simple_tk/window.rb, line 596 def get_command(proc, &block) if block block elsif proc.is_a?(Proc) proc elsif proc.is_a?(Symbol) && self.respond_to?(proc, true) self.method(proc) elsif linked_object && proc.is_a?(Symbol) && linked_object.respond_to?(proc, true) linked_object.method(proc) else nil end end
# File lib/simple_tk/window.rb, line 487 def root @stkw_object_list[:stk___root] end
# File lib/simple_tk/window.rb, line 610 def set_text(object, label_text) if label_text.is_a?(Symbol) @stkw_var_list[label_text] ||= TkVariable.new object.textvariable @stkw_var_list[label_text] else object.text label_text end end
# File lib/simple_tk/window.rb, line 631 def split_widget_grid_options(options) wopt = options.dup gopt = {} [ :row, :column, :columnspan, :rowspan, :padx, :pady, :ipadx, :ipady, :sticky, ].each do |attr| val = wopt.delete(attr) if val gopt[attr] = val end end [ wopt, gopt ] end
# File lib/simple_tk/window.rb, line 649 def split_window_content_options(options) options = options.dup wopt = options.delete(:window) || { } copt = { } options.each do |k,v| ks = k.to_s if ks =~ /^window_/ wopt[ks[7..-1].to_sym] = v else copt[k] = v end end [ wopt, copt ] end