Class: SimpleTk::Window

Inherits:
Object
  • Object
show all
Defined in:
lib/simple_tk/window.rb

Overview

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.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}, &block) ⇒ Window

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.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# 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

Instance Attribute Details

#linked_objectObject

Allows you to get or set the linked object for this window.

A linked object can be used to provide command callbacks.



38
39
40
# File 'lib/simple_tk/window.rb', line 38

def linked_object
  @linked_object
end

Instance Method Details

#add_button(name, label_text, options = {}, &block) ⇒ Object

Adds a new button 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 button. Common options are :column, :row, :sticky, and :command.

If a block is provided, it will be used for the button command. Otherwise the :command option will be used. This can be a Proc or Symbol. If it is a Symbol it should reference a method in the current Window object or in the linked_object.

If no block or proc is provided, a default proc that prints to $stderr is created.



227
228
229
230
231
# File 'lib/simple_tk/window.rb', line 227

def add_button(name, label_text, options = {}, &block)
  options = options.dup
  proc = get_command(options.delete(:command), &block) || ->{ $stderr.puts "Button '#{name}' does nothing when clicked." }
  add_widget Tk::Tile::Button, name, label_text, options, &proc
end

#add_check_box(name, label_text, options = {}, &block) ⇒ Object

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.



293
294
295
296
297
# 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

#add_combo_box(name, options = {}, &block) ⇒ Object

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.



385
386
387
388
389
390
391
392
393
# 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

#add_frame(name, options = {}, &block) ⇒ Object

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.

Raises:



407
408
409
410
411
412
# 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

#add_image(name, image_path, options = {}) ⇒ Object

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.



205
206
207
208
# 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

#add_image_button(name, image_path, options = {}, &block) ⇒ Object

Adds a new image button 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 button. Common options are :column, :row, :sticky, and :command.

If a block is provided, it will be used for the button command. Otherwise the :command option will be used. This can be a Proc or Symbol. If it is a Symbol it should reference a method in the current Window object or in the linked_object.

If no block or proc is provided, a default proc that prints to $stderr is created.



248
249
250
251
252
253
# File 'lib/simple_tk/window.rb', line 248

def add_image_button(name, image_path, options = {}, &block)
  options = options.dup
  image = TkPhotoImage.new(file: image_path)
  proc = get_command(options.delete(:command), &block) || ->{ $stderr.puts "Button '#{name}' does nothing when clicked." }
  add_widget Tk::Tile::Button, name, nil, options.merge(image: image), &proc
end

#add_image_check_box(name, image_path, options = {}, &block) ⇒ Object

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.



310
311
312
313
314
315
# 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

#add_image_radio_button(name, group, image_path, options = {}, &block) ⇒ Object

Adds a new radio button to the window.

name

A unique label for this item, cannot be nil.

group

The name of the variable this radio button uses.

image_path

The path to the image, can be relative or absolute.

options

Options for the check box. Common options are :column, :row, :sticky, :value, and :selected.

Accepts a block or command the same as a button. Unlike a button there is no default proc assigned.

Raises:

  • (ArgumentError)


359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/simple_tk/window.rb', line 359

def add_image_radio_button(name, group, image_path, options = {}, &block)
  raise ArgumentError, 'group cannot be blank' if group.to_s.strip == ''
  options               = options.dup
  group                 = group.to_sym
  @stkw_var_list[group] ||= TkVariable.new
  options[:variable]    = @stkw_var_list[group]
  options[:value]       ||= name.to_s.strip
  if options.delete(:selected)
    @stkw_var_list[group] = options[:value]
  end
  proc = get_command(options.delete(:command), &block)
  image = TkPhotoImage.new(file: image_path)
  add_widget Tk::Tile::Radiobutton, name, nil, options.merge(image: image), &proc
end

#add_label(name, label_text, options = {}) ⇒ Object

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.



192
193
194
# 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

#add_radio_button(name, group, label_text, options = {}, &block) ⇒ Object

Adds a new radio button to the window.

name

A unique label for this item, cannot be nil.

group

The name of the variable this radio button uses.

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, :value, and :selected.

Accepts a block or command the same as a button. Unlike a button there is no default proc assigned.

Raises:

  • (ArgumentError)


332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/simple_tk/window.rb', line 332

def add_radio_button(name, group, label_text, options = {}, &block)
  raise ArgumentError, 'group cannot be blank' if group.to_s.strip == ''
  options               = options.dup
  group                 = group.to_sym
  @stkw_var_list[group] ||= TkVariable.new
  options[:variable]    = @stkw_var_list[group]
  options[:value]       ||= name.to_s.strip
  if options.delete(:selected)
    @stkw_var_list[group] = options[:value]
  end
  proc = get_command(options.delete(:command), &block)
  add_widget Tk::Tile::Radiobutton, name, label_text, options, &proc
end

#add_text_box(name, options = {}, &block) ⇒ Object

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).



265
266
267
268
269
270
271
272
273
274
275
276
277
278
# 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

#childrenObject

Gets all of the children on this window.



148
149
150
# File 'lib/simple_tk/window.rb', line 148

def children
  TkWinfo.children(content)
end

#column_countObject

Gets the number of columns in use.



124
125
126
# File 'lib/simple_tk/window.rb', line 124

def column_count
  @stkw_config[:max_col]
end

#config_column(col, options = {}) ⇒ Object

Allows you to configure the grid options for all cells in a column.



136
137
138
# File 'lib/simple_tk/window.rb', line 136

def config_column(col, options = {})
  TkGrid.columnconfigure content, col, options
end

#config_row(row, options = {}) ⇒ Object

Allows you to configure the grid options for all cells in a row.



142
143
144
# File 'lib/simple_tk/window.rb', line 142

def config_row(row, options = {})
  TkGrid.rowconfigure content, row, options
end

#objectObject

Gets objects from the window.



154
155
156
# File 'lib/simple_tk/window.rb', line 154

def object
  @object_helper ||= SimpleTk::GetSetHelper.new(self, :@stkw_object_list, true, nil, ->(i,v) {  } )
end

#on(event, proc = nil, &block) ⇒ Object

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.



176
177
178
179
# 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

#row_countObject

Gets the number of rows in use.



130
131
132
# File 'lib/simple_tk/window.rb', line 130

def row_count
  @stkw_config[:max_row]
end

#set_placement_mode(mode, options = {}) ⇒ Object

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.

Raises:

  • (ArgumentError)


432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
# 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

#varObject

Gets or sets variable values for this window.



160
161
162
# File 'lib/simple_tk/window.rb', line 160

def var
  @var_helper ||= SimpleTk::GetSetHelper.new(self, :@stkw_var_list, true, :value, :value=)
end

#with_options(options = {}, &block) ⇒ Object

Executes a block with the specified options preset.



474
475
476
477
478
479
480
481
482
483
# 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