glimmer-dsl-tk 0.0.32 → 0.0.36

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.
@@ -40,7 +40,7 @@ module Glimmer
40
40
 
41
41
  def handle_listener(listener_name, &listener)
42
42
  case listener_name.to_s.downcase
43
- when 'change'
43
+ when 'change', 'changed', 'modified'
44
44
  tk.textvariable.trace('write') {
45
45
  listener.call(@tk.textvariable)
46
46
  }
@@ -36,6 +36,7 @@ module Glimmer
36
36
 
37
37
  def post_add_content
38
38
  set_attribute('iconphoto', File.expand_path('../../../icons/glimmer.png', __dir__)) if @tk.iconphoto.nil?
39
+ super
39
40
  end
40
41
 
41
42
  def open
@@ -27,59 +27,106 @@ module Glimmer
27
27
  #
28
28
  # Follows the Proxy Design Pattern
29
29
  class TextProxy < WidgetProxy
30
+ ALL_TAG = '__all__'
31
+ FORMAT_DEFAULT_MAP = {
32
+ 'justify' => 'left',
33
+ }
34
+
30
35
  def handle_listener(listener_name, &listener)
31
36
  case listener_name.to_s.downcase
32
37
  when '<<modified>>', '<modified>', 'modified'
33
38
  modified_listener = Proc.new do |*args|
39
+ @modified_count ||= 0
40
+ @modified_count += 1
34
41
  listener.call(*args)
42
+ @insert_mark_moved_proc&.call
35
43
  @tk.modified = false
36
44
  end
37
- bind('<Modified>', modified_listener)
45
+ @tk.bind('<Modified>', modified_listener)
38
46
  when '<<selection>>', '<selection>', 'selection'
39
- bind('<Selection>', listener)
47
+ @tk.bind('<Selection>', listener)
40
48
  when 'destroy'
41
49
  super
42
- else
43
- @tk.tag_add('__all__', '1.0', 'end') unless @tk.tag_names.include?('__all__')
44
- # TODO make listener pass an event that has a modifiers attribute for easy representation of :shift, :meta, :control, etc... while a letter button is pressed
45
- begin
46
- @tk.tag_bind('__all__', listener_name, &listener)
47
- rescue => e
48
- Glimmer::Config.logger.debug {"Unable to bind to #{listener_name} .. attempting to surround with <>"}
49
- Glimmer::Config.logger.debug {e.full_message}
50
- listener_name = "<#{listener_name}" if !listener_name.start_with?('<')
51
- listener_name = "#{listener_name}>" if !listener_name.end_with?('>')
52
- @tk.tag_bind('__all__', listener_name, &listener)
50
+ when 'insertmarkmove', 'insertmarkmoved', 'insert_mark_move', 'insert_mark_moved'
51
+ if @insert_mark_moved_proc.nil?
52
+ handle_listener('KeyPress') do |event|
53
+ @insert_mark_moved_proc&.call
54
+ end
55
+ handle_listener('KeyRelease') do |event|
56
+ @insert_mark_moved_proc&.call
57
+ end
58
+ handle_listener('ButtonPress') do |event|
59
+ @insert_mark_moved_proc&.call
60
+ end
61
+ handle_listener('ButtonRelease') do |event|
62
+ @insert_mark_moved_proc&.call
63
+ end
64
+ end
65
+ @insert_mark = @tk.index('insert')
66
+ @insert_mark_moved_proc = Proc.new do
67
+ new_insert_mark = @tk.index('insert')
68
+ if new_insert_mark != @insert_mark
69
+ @insert_mark = new_insert_mark
70
+ listener.call(new_insert_mark)
71
+ end
53
72
  end
73
+ else
74
+ super
54
75
  end
55
76
  end
56
-
57
- def add_selection_format(option, value)
58
- process_selection_ranges { |range_start, range_end| add_format(range_start, range_end, option, value) }
77
+
78
+ def edit_undo
79
+ # <Modified> fires twice the first time, which is equivalent to one change.
80
+ if @modified_count.to_i > 2
81
+ # must count the extra 2 modified count that will occur upon undo too
82
+ @modified_count -= 4
83
+ @tk.edit_undo
84
+ end
85
+ end
86
+
87
+ def edit_redo
88
+ begin
89
+ @tk.edit_redo
90
+ rescue => e
91
+ # No Op
92
+ end
93
+ end
94
+
95
+ def add_selection_format(option, value, no_selection_default: :insert_word)
96
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| add_format(range_start, range_end, option, value) }
59
97
  end
60
98
 
61
- def remove_selection_format(option, value)
62
- process_selection_ranges { |range_start, range_end| remove_format(range_start, range_end, option, value) }
99
+ def remove_selection_format(option, value, no_selection_default: :insert_word)
100
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| remove_format(range_start, range_end, option, value) }
63
101
  end
64
102
 
65
- def toggle_selection_format(option, value)
66
- process_selection_ranges { |range_start, range_end| toggle_format(range_start, range_end, option, value) }
103
+ def toggle_selection_format(option, value, no_selection_default: :insert_word)
104
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| toggle_format(range_start, range_end, option, value) }
67
105
  end
68
106
 
69
- def add_selection_font_format(option, value)
70
- process_selection_ranges { |range_start, range_end| add_font_format(range_start, range_end, option, value) }
107
+ def add_selection_font_format(option, value, no_selection_default: :insert_word)
108
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| add_font_format(range_start, range_end, option, value) }
71
109
  end
72
110
 
73
- def remove_selection_font_format(option, value)
74
- process_selection_ranges { |range_start, range_end| remove_font_format(range_start, range_end, option, value) }
111
+ def remove_selection_font_format(option, value, no_selection_default: :insert_word)
112
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| remove_font_format(range_start, range_end, option, value) }
75
113
  end
76
114
 
77
- def toggle_selection_font_format(option, value)
78
- process_selection_ranges { |range_start, range_end| toggle_font_format(range_start, range_end, option, value) }
115
+ def toggle_selection_font_format(option, value, no_selection_default: :insert_word)
116
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| toggle_font_format(range_start, range_end, option, value) }
79
117
  end
80
118
 
81
- def process_selection_ranges(&processor)
82
- @tk.tag_ranges('sel').each do |region|
119
+ def process_selection_ranges(no_selection_default: :insert_word, &processor)
120
+ regions = @tk.tag_ranges('sel')
121
+ if regions.empty?
122
+ case no_selection_default
123
+ when :insert_word
124
+ regions = [[@tk.index('insert wordstart'), @tk.index('insert wordend + 1 char')]]
125
+ when :insert_letter
126
+ regions = [[@tk.index('insert'), @tk.index('insert + 1 char')]]
127
+ end
128
+ end
129
+ regions.each do |region|
83
130
  range_start = region.first
84
131
  range_end = region.last
85
132
  processor.call(range_start, range_end)
@@ -91,7 +138,7 @@ module Glimmer
91
138
  end
92
139
 
93
140
  def applied_format_tags(region_start, region_end, option, value)
94
- tag_names = @tk.tag_names - ['sel']
141
+ tag_names = @tk.tag_names - ['sel', ALL_TAG]
95
142
 
96
143
  tag_names.select do |tag_name|
97
144
  @tk.tag_ranges(tag_name).any? do |range|
@@ -102,9 +149,26 @@ module Glimmer
102
149
  end
103
150
  end
104
151
 
152
+ def applied_format_value(text_index = nil, option)
153
+ text_index ||= @tk.index('insert')
154
+ region_start = text_index
155
+ region_end = text_index
156
+ tag_names = @tk.tag_names - ['sel', ALL_TAG]
157
+
158
+ values = tag_names.map do |tag_name|
159
+ @tk.tag_ranges(tag_name).map do |range|
160
+ if text_index_less_than_or_equal_to_other_text_index?(range.first, region_start) && text_index_greater_than_or_equal_to_other_text_index?(range.last, region_end)
161
+ @tk.tag_cget(tag_name, option)
162
+ end
163
+ end
164
+ end.flatten.reject {|value| value.to_s.empty?}
165
+
166
+ values.last || (@tk.send(option) rescue FORMAT_DEFAULT_MAP[option])
167
+ end
168
+
105
169
  def add_format(region_start, region_end, option, value)
106
170
  @@tag_number = 0 unless defined?(@@tag_number)
107
- tag = "tag#{@@tag_number += 1}"
171
+ tag = "tag_#{option}_#{@@tag_number += 1}"
108
172
  @tk.tag_configure(tag, {option => value})
109
173
  @tk.tag_add(tag, region_start, region_end)
110
174
  tag
@@ -155,15 +219,14 @@ module Glimmer
155
219
  def applied_font_format_tags_and_regions(region_start, region_end)
156
220
  lines = value.split("\n")
157
221
  tags_and_regions = []
158
- all_tag_names = @tk.tag_names - ['sel']
222
+ all_tag_names = (@tk.tag_names - ['sel', ALL_TAG]).select {|tag_name| tag_name.include?('_font_')}
159
223
  (region_start.to_i..region_end.to_i).each do |line_number|
160
224
  start_character_index = 0
161
225
  start_character_index = region_start.to_s.split('.').last.to_i if line_number == region_start.to_i
162
- end_character_index = lines[line_number - 1].size
226
+ end_character_index = lines[line_number - 1].to_s.size
163
227
  end_character_index = region_end.to_s.split('.').last.to_i if line_number == region_end.to_i
164
228
  (start_character_index...end_character_index).each do |character_index|
165
229
  text_index = "#{line_number}.#{character_index}"
166
- # TODO reimplement the following using @tk.tag_names without arg since passing an arg seems broken and returns inaccurate results
167
230
  region_tag = all_tag_names.reverse.find do |tag|
168
231
  @tk.tag_cget(tag, 'font') && @tk.tag_ranges(tag).any? do |range_start, range_end|
169
232
  text_index_less_than_or_equal_to_other_text_index?(range_start, text_index) && text_index_greater_than_or_equal_to_other_text_index?(range_end, text_index)
@@ -179,6 +242,27 @@ module Glimmer
179
242
  end
180
243
  tags_and_regions
181
244
  end
245
+
246
+ def applied_font_format_value(text_index = nil, font_option)
247
+ text_index ||= @tk.index('insert')
248
+ region_start = text_index
249
+ region_end = @tk.index("#{text_index} + 1 chars")
250
+ tag_names = applied_font_format_tags_and_regions(region_start, region_end).map(&:first)
251
+
252
+ values = tag_names.map do |tag_name|
253
+ @tk.tag_ranges(tag_name).map do |range|
254
+ if text_index_less_than_or_equal_to_other_text_index?(range.first, region_start) && text_index_greater_than_or_equal_to_other_text_index?(range.last, region_end)
255
+ @tk.tag_cget(tag_name, 'font')
256
+ end
257
+ end
258
+ end.flatten.reject {|value| value.to_s.empty?}
259
+
260
+ font = values.last
261
+
262
+ value = font && font.send(font_option)
263
+
264
+ value || Hash[@tk.font.actual][font_option]
265
+ end
182
266
 
183
267
  def add_font_format(region_start, region_end, font_option, value)
184
268
  applied_font_format_tags_and_regions(region_start, region_end).each do |tag, tag_region_start, tag_region_end|
@@ -32,6 +32,19 @@ module Glimmer
32
32
  DEFAULT_HEIGHT = 95
33
33
 
34
34
  attr_reader :tk
35
+ attr_accessor :escapable
36
+ alias escapable? escapable
37
+
38
+ def post_add_content
39
+ if escapable?
40
+ on('KeyPress') do |event|
41
+ if event.keysym == 'Escape'
42
+ grab_release
43
+ destroy
44
+ end
45
+ end
46
+ end
47
+ end
35
48
 
36
49
  def has_attribute?(attribute, *args)
37
50
  %w[width height x y].include?(attribute.to_s) || super
@@ -114,6 +127,17 @@ module Glimmer
114
127
  destroy
115
128
  end
116
129
  end
130
+
131
+ def mac_style=(mac_class, mac_attribute_list = nil)
132
+ if OS.mac?
133
+ @mac_style = [mac_class, mac_attribute_list]
134
+ ::Tk.tk_call("::tk::unsupported::MacWindowStyle", "style", @tk, *@mac_style.compact)
135
+ end
136
+ end
137
+
138
+ def mac_style
139
+ @mac_style
140
+ end
117
141
  end
118
142
  end
119
143
  end
@@ -460,14 +460,20 @@ module Glimmer
460
460
  parent_proxy.handle_listener(listener_name, &listener) if parent_proxy
461
461
  # TODO return a listener registration object that has a deregister method
462
462
  else
463
+ @listeners ||= {}
463
464
  begin
464
- @tk.bind(listener_name, &listener)
465
+ @listeners[listener_name] ||= []
466
+ @tk.bind(listener_name) { |event| @listeners[listener_name].each {|l| l.call(event)} } if @listeners[listener_name].empty?
467
+ @listeners[listener_name] << listener
465
468
  rescue => e
469
+ @listeners.delete(listener_name)
466
470
  Glimmer::Config.logger.debug {"Unable to bind to #{listener_name} .. attempting to surround with <>"}
467
471
  Glimmer::Config.logger.debug {e.full_message}
468
472
  listener_name = "<#{listener_name}" if !listener_name.start_with?('<')
469
473
  listener_name = "#{listener_name}>" if !listener_name.end_with?('>')
470
- @tk.bind(listener_name, &listener)
474
+ @listeners[listener_name] ||= []
475
+ @tk.bind(listener_name) { |event| @listeners[listener_name].each {|l| l.call(event)} } if @listeners[listener_name].empty?
476
+ @listeners[listener_name] << listener
471
477
  end
472
478
  end
473
479
  end
@@ -56,7 +56,7 @@ class MetaSample
56
56
 
57
57
  def run_sample(sample)
58
58
  Thread.new do
59
- command = "ruby -r #{glimmer_dsl_tk_file} #{sample} 2>&1"
59
+ command = "#{RbConfig.ruby} -r #{glimmer_dsl_tk_file} #{sample} 2>&1"
60
60
  result = ''
61
61
  IO.popen(command) do |f|
62
62
  f.each_line do |line|
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020-2021 Andy Maleh
1
+ `# Copyright (c) 2020-2021 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -107,11 +107,6 @@ class HelloText
107
107
  frame {
108
108
  grid row: 0, column: 0
109
109
 
110
- label {
111
- grid row: 0, column: 0, columnspan: 17
112
- text 'Select a region of text and then apply formatting from the toolbar'
113
- }
114
-
115
110
  column_index = -1
116
111
 
117
112
  combobox {
@@ -143,7 +138,7 @@ class HelloText
143
138
  orient 'vertical'
144
139
  }
145
140
 
146
- button {
141
+ @bold_button = button {
147
142
  grid row: 1, column: column_index += 1, column_weight: 0
148
143
  text 'B'
149
144
  style font: {weight: 'bold'}
@@ -153,7 +148,7 @@ class HelloText
153
148
  end
154
149
  }
155
150
 
156
- button {
151
+ @italic_button = button {
157
152
  grid row: 1, column: column_index += 1, column_weight: 0
158
153
  text 'I'
159
154
  style font: {slant: 'italic'}
@@ -163,7 +158,7 @@ class HelloText
163
158
  end
164
159
  }
165
160
 
166
- button {
161
+ @underline_button = button {
167
162
  grid row: 1, column: column_index += 1, column_weight: 0
168
163
  text 'U'
169
164
  style font: {underline: true}
@@ -172,36 +167,36 @@ class HelloText
172
167
  @text.toggle_selection_font_format('underline', true)
173
168
  end
174
169
  }
175
-
170
+
176
171
  separator {
177
172
  grid row: 1, column: column_index += 1, column_weight: 0
178
173
  orient 'vertical'
179
174
  }
180
175
 
181
- button {
176
+ @justify_left_button = button {
182
177
  grid row: 1, column: column_index += 1, column_weight: 0
183
- image File.expand_path("images/cut.png", __dir__), subsample: 32
178
+ image File.expand_path("images/align-left.png", __dir__), subsample: 32
184
179
 
185
180
  on('command') do
186
- @text.text_cut
181
+ @text.add_selection_format('justify', 'left')
187
182
  end
188
183
  }
189
184
 
190
- button {
185
+ @justify_center_button = button {
191
186
  grid row: 1, column: column_index += 1, column_weight: 0
192
- image File.expand_path("images/copy.png", __dir__), subsample: 32
187
+ image File.expand_path("images/align-center.png", __dir__), subsample: 32
193
188
 
194
189
  on('command') do
195
- @text.text_copy
190
+ @text.add_selection_format('justify', 'center')
196
191
  end
197
192
  }
198
193
 
199
- button {
194
+ @justify_right_button = button {
200
195
  grid row: 1, column: column_index += 1, column_weight: 0
201
- image File.expand_path("images/paste.png", __dir__), subsample: 32
196
+ image File.expand_path("images/align-right.png", __dir__), subsample: 32
202
197
 
203
198
  on('command') do
204
- @text.text_paste
199
+ @text.add_selection_format('justify', 'right')
205
200
  end
206
201
  }
207
202
 
@@ -212,51 +207,51 @@ class HelloText
212
207
 
213
208
  button {
214
209
  grid row: 1, column: column_index += 1, column_weight: 0
215
- image File.expand_path("images/align-left.png", __dir__), subsample: 32
210
+ image File.expand_path("images/picture.png", __dir__), subsample: 32
216
211
 
217
212
  on('command') do
218
- @text.add_selection_format('justify', 'left')
213
+ @text.get_open_file_to_insert_image
219
214
  end
220
215
  }
221
216
 
222
217
  button {
223
218
  grid row: 1, column: column_index += 1, column_weight: 0
224
- image File.expand_path("images/align-center.png", __dir__), subsample: 32
219
+ image File.expand_path("images/search.png", __dir__), subsample: 32
225
220
 
226
221
  on('command') do
227
- @text.add_selection_format('justify', 'center')
222
+ show_find_dialog
228
223
  end
229
224
  }
230
225
 
226
+ separator {
227
+ grid row: 1, column: column_index += 1, column_weight: 0
228
+ orient 'vertical'
229
+ }
230
+
231
231
  button {
232
232
  grid row: 1, column: column_index += 1, column_weight: 0
233
- image File.expand_path("images/align-right.png", __dir__), subsample: 32
233
+ image File.expand_path("images/cut.png", __dir__), subsample: 32
234
234
 
235
235
  on('command') do
236
- @text.add_selection_format('justify', 'right')
236
+ @text.text_cut
237
237
  end
238
238
  }
239
239
 
240
- separator {
241
- grid row: 1, column: column_index += 1, column_weight: 0
242
- orient 'vertical'
243
- }
244
-
245
240
  button {
246
241
  grid row: 1, column: column_index += 1, column_weight: 0
247
- image File.expand_path("images/undo.png", __dir__), subsample: 32
242
+ image File.expand_path("images/copy.png", __dir__), subsample: 32
248
243
 
249
244
  on('command') do
250
- @text.edit_undo
245
+ @text.text_copy
251
246
  end
252
247
  }
253
248
 
254
249
  button {
255
250
  grid row: 1, column: column_index += 1, column_weight: 0
256
- image File.expand_path("images/redo.png", __dir__), subsample: 32
251
+ image File.expand_path("images/paste.png", __dir__), subsample: 32
257
252
 
258
253
  on('command') do
259
- @text.edit_redo
254
+ @text.text_paste
260
255
  end
261
256
  }
262
257
 
@@ -265,21 +260,22 @@ class HelloText
265
260
  orient 'vertical'
266
261
  }
267
262
 
263
+
268
264
  button {
269
265
  grid row: 1, column: column_index += 1, column_weight: 0
270
- image File.expand_path("images/picture.png", __dir__), subsample: 32
266
+ image File.expand_path("images/undo.png", __dir__), subsample: 32
271
267
 
272
268
  on('command') do
273
- @text.get_open_file_to_insert_image
269
+ @text.edit_undo
274
270
  end
275
271
  }
276
272
 
277
273
  button {
278
274
  grid row: 1, column: column_index += 1, column_weight: 0
279
- image File.expand_path("images/search.png", __dir__), subsample: 32
275
+ image File.expand_path("images/redo.png", __dir__), subsample: 32
280
276
 
281
277
  on('command') do
282
- show_find_dialog
278
+ @text.edit_redo
283
279
  end
284
280
  }
285
281
  }
@@ -290,6 +286,19 @@ class HelloText
290
286
  undo true
291
287
  value <=> [self, :document]
292
288
 
289
+ on('InsertMarkMoved') do
290
+ self.font_family = @text.applied_font_format_value('family')
291
+ self.font_size = @text.applied_font_format_value('size')
292
+ @bold_button.default = @text.applied_font_format_value('weight') == 'bold' ? 'active' : 'normal'
293
+ @italic_button.default = @text.applied_font_format_value('slant') == 'italic' ? 'active' : 'normal'
294
+ @underline_button.default = @text.applied_font_format_value('underline') == true ? 'active' : 'normal'
295
+ self.background = @text.applied_format_value('background')
296
+ self.foreground = @text.applied_format_value('foreground')
297
+ @justify_left_button.default = @text.applied_format_value('justify') == 'left' ? 'active' : 'normal'
298
+ @justify_center_button.default = @text.applied_format_value('justify') == 'center' ? 'active' : 'normal'
299
+ @justify_right_button.default = @text.applied_format_value('justify') == 'right' ? 'active' : 'normal'
300
+ end
301
+
293
302
  on('KeyPress') do |event|
294
303
  show_find_dialog if (event.keysym == 'f') && ((OS.mac? && event.state == 8) || (!OS.mac? && event.state == 4))
295
304
  end
@@ -318,7 +327,7 @@ class HelloText
318
327
  end
319
328
  end
320
329
  ]
321
-
330
+
322
331
  on('KeyPress') do |event|
323
332
  if event.keysym == 'Return'
324
333
  find