glimmer-dsl-tk 0.0.28 → 0.0.32

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.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Tk 0.0.28
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Tk 0.0.32
2
2
  ## MRI Ruby Desktop Development GUI Library
3
3
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-tk.svg)](http://badge.fury.io/rb/glimmer-dsl-tk)
4
4
  [![Ruby](https://github.com/AndyObtiva/glimmer-dsl-tk/actions/workflows/ruby.yml/badge.svg)](https://github.com/AndyObtiva/glimmer-dsl-tk/actions/workflows/ruby.yml)
@@ -75,6 +75,7 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
75
75
  - [Common Attributes](#common-attributes)
76
76
  - [Common Themed Widget States](#common-themed-widget-states)
77
77
  - [Text API](#text-api)
78
+ - [Drag and Drop API](#drag-and-drop-api)
78
79
  - [Smart Defaults and Conventions](#smart-defaults-and-conventions)
79
80
  - [Grid Layout](#grid-layout)
80
81
  - [Image Attribute](#image-attribute)
@@ -90,6 +91,7 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
90
91
  - [List Single Selection Data-Binding](#list-single-selection-data-binding)
91
92
  - [List Multi Selection Data-Binding](#list-multi-selection-data-binding)
92
93
  - [Entry Data-Binding](#entry-data-binding)
94
+ - [Text Data-Binding](#text-data-binding)
93
95
  - [Spinbox Data-Binding](#spinbox-data-binding)
94
96
  - [Checkbutton Data-Binding](#checkbutton-data-binding)
95
97
  - [Radiobutton Data-Binding](#radiobutton-data-binding)
@@ -113,10 +115,17 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
113
115
  - [Hello, Spinbox!](#hello-spinbox)
114
116
  - [Hello, Computed!](#hello-computed)
115
117
  - [Hello, Drag and Drop!](#hello-drag-and-drop)
118
+ - [Hello, Built-in Dialog!](#hello-built-in-dialog)
119
+ - [Hello, Separator!](#hello-separator)
120
+ - [Applications](#applications)
121
+ - [Glimmer Tk Calculator](#glimmer-tk-calculator)
122
+ - [Y3network Ruby UI](#y3network-ruby-ui)
123
+ - [CryptoPunks GUI](#cryptopunks-gui)
124
+ - [Process](#process)
125
+ - [Resources](#resources)
116
126
  - [Help](#help)
117
127
  - [Issues](#issues)
118
128
  - [Chat](#chat)
119
- - [Process](#process)
120
129
  - [Planned Features and Feature Suggestions](#planned-features-and-feature-suggestions)
121
130
  - [Change Log](#change-log)
122
131
  - [Contributing](#contributing)
@@ -149,7 +158,7 @@ gem install glimmer-dsl-tk
149
158
 
150
159
  Add the following to `Gemfile`:
151
160
  ```
152
- gem 'glimmer-dsl-tk', '~> 0.0.28'
161
+ gem 'glimmer-dsl-tk', '~> 0.0.32'
153
162
  ```
154
163
 
155
164
  And, then run:
@@ -191,7 +200,7 @@ The Glimmer GUI DSL follows these simple concepts in mapping from Tk syntax:
191
200
  - **Widget Keyword**: Any Tk widget (e.g. `Tk::Tile::Label`) or toplevel window (e.g. `TkRoot`) may be declared by its lower-case underscored name without the namespace (e.g. `label` or `root`). This is called a keyword and is represented in the Glimmer GUI DSL by a Ruby method behind the scenes.
192
201
  - **Args**: Any keyword method may optionally take arguments surrounded by parentheses (e.g. a `frame` nested under a `notebook` may receive tab options like `frame(text: 'Users')`, which gets used behind the scenes by Tk code such as `notebook.add tab, text: 'Users'`)
193
202
  - **Content/Options Block**: Any keyword may optionally be followed by a Ruby curly-brace block containing nested widgets (content) and attributes (options). Attributes are simply Tk option keywords followed by arguments and no block (e.g. `title 'Hello, World!'` under a `root`)
194
- - **Event Binding Block**: `on(event) {}` keyword receiving a Tk binding event name (e.g. `KeyPress` or `ComboboxSelected`). No need to surround event by `<>` as [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) takes care of that automatically.
203
+ - **Event Binding Block**: `on(event) {}` keyword receiving a Tk binding event name (e.g. `KeyPress` or `ComboboxSelected`). Surrounding event by `<>` is optional as [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) can take care of that automatically.
195
204
 
196
205
  Example of an app written in [Tk](https://www.tcl.tk/) imperative syntax:
197
206
 
@@ -260,8 +269,14 @@ keyword(args) | attributes | event bindings & callbacks
260
269
  ------------- | ---------- | ---------
261
270
  `button` | `text`, `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `default` (`'active', 'normal'`) | `command {}`
262
271
  `checkbutton` | `text`, `variable` (Boolean), `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `onvalue` (default: `1`), `offvalue` (default: `0`) | `command {}`
272
+ `choose_color(options = nil)` | None | None
273
+ `choose_directory(options = nil)` | None | None
274
+ `choose_font(options = nil) {|font| ... }` | None | None
263
275
  `combobox` | `state`, `text` | `'ComboboxSelected'`
264
276
  `entry` | `width`, `text`, `validate`, `show` (`'none', 'focus', 'focusin', 'focusout', 'key', or 'all'`) | `'validate'`, `'invalid'`, `'change'`, `validatecommand {}`, `invalidcommand {}`
277
+ `get_multiple_open_file(options = nil)` | None | None
278
+ `get_open_file(options = nil)` | None | None
279
+ `get_save_file(options = nil)` | None | None
265
280
  `spinbox` | `text`, `from`, `to`, `increment`, `format`, [more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `command {}`, `'increment'`, `'decrement'`
266
281
  `frame(text: nil)` | `width`, `height`, `borderwidth`, `relief` (`'flat' (default), 'raised', 'sunken', 'solid', 'ridge', 'groove'`) | None
267
282
  `label` | `text`, `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `font` (`'default', 'text', 'fixed', 'menu', 'heading', 'caption', 'small_caption', 'icon', 'tooltip'`), `relief` (`'flat' (default), 'raised', 'sunken', 'solid', 'ridge', 'groove'`), `justify` (`'left', 'center', 'right'`), `foreground`, `background` | None
@@ -270,7 +285,11 @@ keyword(args) | attributes | event bindings & callbacks
270
285
  `notebook` | None | None
271
286
  `radiobutton` | `text`, `variable` (Boolean), `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `value` (default: `text`) | `command {}`
272
287
  `root` | `title`, `iconphoto`, `background`, `alpha`, `fullscreen?`, `topmost?`, `transparent?`, `stackorder`, `winfo_screendepth`, `winfo_screenvisual`, `winfo_screenwidth`, `winfo_screenheight`, `winfo_pixels('li')`, `winfo_screen`, `wm_maxsize`, `state` (`'normal', 'iconic', 'withdrawn', 'icon', 'zoomed'`) | `'DELETE_WINDOW'`, `'OPEN_WINDOW'`
273
- `text` | `text`, [many more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `'modified'`, `'selection'`
288
+ `separator` | `orient` (`'horizontal' (default) or 'vertical'`) | None
289
+ `text` | `value`, [many more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `'modified'`, `'selection'`
290
+
291
+ Options for `get_open_file` and `get_multiple_open_file` include:
292
+ - `filetypes`: `Hash` of `'Group Name' => '.ext'` entries (e.g. `filetypes: {'PNG Images' => '.png'}`
274
293
 
275
294
  #### Common Attributes
276
295
 
@@ -322,9 +341,7 @@ keyword(args) | attributes | event bindings & callbacks
322
341
 
323
342
  #### Text API
324
343
 
325
- [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) automatically provides a `text` attribute for the `text` widget that enables updating its content simply without worrying about whether to manually insert by index, delete, or append.
326
-
327
- Also, the `text` widget is enhanced by [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) to enable simpler manipulation of text options without dealing with [tags](https://tkdocs.com/tutorial/text.html) directly. Simply specify region to mutate and option/value or font_option/value, and [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) takes care of the rest by automating work of adding/removing [tags](https://tkdocs.com/tutorial/text.html) behind the scenes.
344
+ The `text` widget is enhanced by [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) to enable simpler manipulation of text options without dealing with [tags](https://tkdocs.com/tutorial/text.html) directly. Simply specify region to mutate and option/value or font_option/value, and [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) takes care of the rest by automating work of adding/removing [tags](https://tkdocs.com/tutorial/text.html) behind the scenes.
328
345
 
329
346
  - `add_format(region_start, region_end, option, value)`
330
347
  - `remove_format(region_start, region_end, option, value)`
@@ -338,6 +355,8 @@ Also, the `text` widget is enhanced by [Glimmer DSL for Tk](https://rubygems.org
338
355
  - `add_selection_font_format(region_start, region_end, font_option, value)`
339
356
  - `remove_selection_font_format(region_start, region_end, font_option, value)`
340
357
  - `toggle_selection_font_format(region_start, region_end, font_option, value)`
358
+ - `text#insert_image(text_index, *image_args)`: inserts image into `text` `value` content at `text_index` location (e.g. `'insert'`)
359
+ - `text#get_open_file_to_insert_image(text_index = 'insert')`: opens a file dialog to select one of the available image formats and then inserts image into `text` `value` content
341
360
 
342
361
  Available options:
343
362
 
@@ -381,6 +400,19 @@ Other useful built-in API methods:
381
400
 
382
401
  Check out the [Hello, Text!](#hello-text) sample for a good demonstration of the `text` widget features.
383
402
 
403
+ #### Drag and Drop API
404
+
405
+ Drag and drop works by simply designating a widget as a drag source with attribute `drag_source true`
406
+
407
+ Alternatively, add listeners:
408
+ - `on_drag_start {|event| ...}`: fires on drag start receiving an `event` arg to set `data` and configure `source`
409
+ - `on_drag_motion {|event| ...}`: fires on drag motion receiving an `event` arg to check `event#drop_accepted`, and configure `source` and `tooltip`
410
+
411
+ On the drop target, you simply define:
412
+ - `on_drop { |event| ...}`: fires on drop, receiving an `event` arg with `event#target` and `event#data` (set during drag). You can even destroy the `event#source` if you want to get rid of the dragged widget.
413
+
414
+ Learn more at the [Hello, Drag and Drop!](#hello-drag-and-drop) sample.
415
+
384
416
  ### Smart Defaults and Conventions
385
417
 
386
418
  #### Event Bindings
@@ -466,6 +498,8 @@ Example:
466
498
  ```
467
499
 
468
500
  Extra convenience options may be passed to `grid` when using [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk):
501
+ - `column_span`: alias for `columnspan` keyword arg
502
+ - `row_span`: alias for `rowspan` keyword arg
469
503
  - `min_width`: alias for `columnminsize` being called on `TkGrid.columnconfigure`
470
504
  - `min_height`: alias for `rowminsize` being called on `TkGrid.rowconfigure`
471
505
  - `column_weight`: alias for `columnweight` being called on `TkGrid.columnconfigure`
@@ -578,6 +612,24 @@ It automatically handles all the Tk plumbing behind the scenes.
578
612
 
579
613
  More details can be found in [Hello, Entry!](#hello-entry) and [Hello, Computed!](#hello-computed) samples below.
580
614
 
615
+ ### Text Data-Binding
616
+
617
+ Example:
618
+
619
+ This assumes a `Person` model with a `biography` attribute.
620
+
621
+ ```ruby
622
+ text {
623
+ value <=> [person, :biography]
624
+ }
625
+ ```
626
+
627
+ That code binds the `value` of `text` to the `biography` attribute on the `person` model.
628
+
629
+ It automatically handles all the Tk plumbing behind the scenes.
630
+
631
+ More details can be found in [Hello, Text!](#hello-text) sample below.
632
+
581
633
  ### Spinbox Data-Binding
582
634
 
583
635
  Example:
@@ -698,6 +750,128 @@ ruby -r ./lib/glimmer-dsl-tk.rb samples/elaborate/meta_sample.rb
698
750
 
699
751
  ![glimmer dsl tk screenshot sample meta sample](images/glimmer-dsl-tk-screenshot-sample-elaborate-meta-sample.png)
700
752
 
753
+ Code:
754
+
755
+ ```ruby
756
+ require 'glimmer-dsl-tk'
757
+ require 'facets'
758
+ require 'fileutils'
759
+
760
+ class MetaSample
761
+ include Glimmer
762
+
763
+ attr_accessor :selected_sample_index
764
+
765
+ def initialize
766
+ @selected_sample_index = 0
767
+ end
768
+
769
+ def samples
770
+ if @samples.nil?
771
+ sample_files = Dir.glob(File.join(File.expand_path('../hello', __dir__), '**', 'hello_*.rb'))
772
+ sample_file_names = sample_files.map { |f| File.basename(f, '.rb') }
773
+ sample_file_names = sample_file_names.reject { |f| f == 'meta_sample' || f.match(/\d$/) }
774
+ @samples = sample_file_names.map { |f| f.underscore.titlecase }
775
+ end
776
+ @samples
777
+ end
778
+
779
+ def file_path_for(sample)
780
+ File.join(File.expand_path('../hello', __dir__), "#{sample.underscore}.rb")
781
+ end
782
+
783
+ def glimmer_dsl_tk_file
784
+ File.expand_path('../../lib/glimmer-dsl-tk', __dir__)
785
+ end
786
+
787
+ def selected_sample
788
+ samples[@selected_sample_index]
789
+ end
790
+
791
+ def run_sample(sample)
792
+ Thread.new do
793
+ command = "ruby -r #{glimmer_dsl_tk_file} #{sample} 2>&1"
794
+ result = ''
795
+ IO.popen(command) do |f|
796
+ f.each_line do |line|
797
+ result << line
798
+ puts line
799
+ $stdout.flush
800
+ end
801
+ end
802
+ ::Tk.after(100) do
803
+ message_box(parent: @root, title: 'Error Running Sample', message: result) if result.downcase.include?('error')
804
+ end
805
+ end
806
+ end
807
+
808
+ def launch
809
+ @root = root {
810
+ title 'Glimmer Meta-Sample'
811
+ width 1280
812
+ height 720
813
+
814
+ frame {
815
+ grid row: 0, column: 0, column_weight: 0, row_weight: 1
816
+
817
+ samples.each_with_index do |sample, index|
818
+ radiobutton {
819
+ text sample
820
+ variable <=> [self, :selected_sample_index, on_write: ->(v) {v ? index : selected_sample_index}, on_read: ->(v) {v == index}]
821
+
822
+ on('command') do
823
+ @selected_sample_index = index
824
+ @code_text.value = File.read(file_path_for(selected_sample))
825
+ end
826
+ }
827
+ end
828
+
829
+ frame {
830
+ button {
831
+ grid row: 0, column: 0
832
+ text 'Launch'
833
+
834
+ on('command') do
835
+ begin
836
+ parent_dir = File.join(Dir.home, '.glimmer-dsl-tk', 'samples', 'hello')
837
+ FileUtils.mkdir_p(parent_dir)
838
+ sample_file = File.join(parent_dir, "#{selected_sample.underscore}.rb")
839
+ File.write(sample_file, @code_text.value)
840
+ FileUtils.cp_r(File.expand_path('../../icons', __dir__), File.dirname(File.dirname(parent_dir)))
841
+ FileUtils.cp_r(File.expand_path('../hello/images', __dir__), parent_dir)
842
+ sample_namespace_directory = File.expand_path("../hello/#{selected_sample.underscore}", __dir__)
843
+ FileUtils.cp_r(sample_namespace_directory, parent_dir) if Dir.exist?(sample_namespace_directory)
844
+ run_sample(sample_file)
845
+ rescue => e
846
+ puts e.full_message
847
+ puts 'Unable to write code changes! Running original sample...'
848
+ run_sample(file_path_for(selected_sample))
849
+ end
850
+ end
851
+ }
852
+ button {
853
+ grid row: 0, column: 1
854
+ text 'Reset'
855
+
856
+ on('command') do
857
+ @code_text.value = File.read(file_path_for(selected_sample))
858
+ end
859
+ }
860
+ }
861
+ }
862
+
863
+ @code_text = text {
864
+ grid row: 0, column: 1, column_weight: 1
865
+ value File.read(file_path_for(selected_sample))
866
+ }
867
+ }
868
+ @root.open
869
+ end
870
+ end
871
+
872
+ MetaSample.new.launch
873
+ ```
874
+
701
875
  ### Hello, World!
702
876
 
703
877
  Glimmer code (from [samples/hello/hello_world.rb](samples/hello/hello_world.rb)):
@@ -1389,8 +1563,6 @@ root { |r|
1389
1563
  title 'Hello, Message Box!'
1390
1564
 
1391
1565
  frame {
1392
- grid sticky: 'nsew', padx: 15, pady: 15
1393
-
1394
1566
  button {
1395
1567
  text 'Please Click To Win a Surprise'
1396
1568
 
@@ -1442,8 +1614,6 @@ root { |r|
1442
1614
  }
1443
1615
 
1444
1616
  frame {
1445
- grid sticky: 'nsew', padx: 15, pady: 15
1446
-
1447
1617
  label {
1448
1618
  grid row: 0, column: 0
1449
1619
  text 'Result:'
@@ -1471,7 +1641,6 @@ ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_message_box.rb
1471
1641
  Glimmer app:
1472
1642
 
1473
1643
  ![glimmer dsl tk screenshot sample hello message box](images/glimmer-dsl-tk-screenshot-sample-hello-message-box.png)
1474
- ![glimmer dsl tk screenshot sample hello message box open](images/glimmer-dsl-tk-screenshot-sample-hello-message-box-open.png)
1475
1644
 
1476
1645
  ### Hello, Combobox!
1477
1646
 
@@ -1700,6 +1869,8 @@ Glimmer app:
1700
1869
 
1701
1870
  ### Hello, Text!
1702
1871
 
1872
+ You may use the META+F shortcut to bring up the Find Dialog.
1873
+
1703
1874
  Icons used in this sample were made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon"> www.flaticon.com</a>
1704
1875
 
1705
1876
  Glimmer code (from [samples/hello/hello_text.rb](samples/hello/hello_text.rb)):
@@ -1711,14 +1882,47 @@ class HelloText
1711
1882
  include Glimmer
1712
1883
 
1713
1884
  COLOR_OPTIONS = %w[black purple blue green orange yellow red white].map(&:capitalize)
1714
- FOREGROUND_PROMPT = '<select foreground>'
1715
- BACKGROUND_PROMPT = '<select background>'
1885
+ FONT_FAMILY_OPTIONS = ::TkFont.families
1886
+ FOREGROUND_PROMPT = '<foreground>'
1887
+ BACKGROUND_PROMPT = '<background>'
1888
+ FONT_FAMILY_PROMPT = '<font family>'
1889
+ FONT_SIZE_PROMPT = '<font size>'
1716
1890
 
1717
1891
  def initialize
1718
1892
  @foreground = FOREGROUND_PROMPT
1719
1893
  @background = BACKGROUND_PROMPT
1894
+ @font_family = FONT_FAMILY_PROMPT
1895
+ @font_size = FONT_SIZE_PROMPT
1896
+ @document = <<~MULTI_LINE_STRING
1897
+ According to the National Post, a heavy metal-loving high school principal in Canada will be allowed to keep her job, days after a public campaign to oust her made headlines around the globe.
1898
+
1899
+ Parents at Eden High School in St. Catharines, Ontario launched a petition to remove principal Sharon Burns after discovering she's an IRON MAIDEN fan.
1900
+
1901
+ The petition, titled "Eden High School Principal, Sharon Burns, Needs to Be Transferred Immediately!" read, "We are deeply disturbed that the principal assigned to the school blatantly showed Satanic symbols and her allegiance to Satanic practices on her public social media platforms where all the students can see them under @edenprincipal (not her personal account)."
1902
+
1903
+ More than 500 people signed the petition to transfer Burns after she posted a picture of herself flashing the "devil horns" hand sign with a doll of the MAIDEN zombie mascot Eddie behind her as well as a personalized license plate reading "IRNMADEN" and a handwritten note that reads "Eddie 666" on a car's dashboard.
1904
+
1905
+
1906
+ The number 666 is used to represent the devil, and is featured prominently in MAIDEN's artwork by the band, whose classic third album is titled "The Number Of The Beast".
1907
+
1908
+ The petition was later updated to state that the demand for her transfer is not because of her love for metal, but for "openly displaying her own handmade sign with the 666 clearly displayed on it".
1909
+
1910
+ The creator of the original petition wrote: "Sharon knows full well what she did was simply inappropriate, unnecessary and not professional but has yet to publicly admit so and is willing to allow people to believe a completely different story, making very real concerns seem petty."
1911
+
1912
+ Meanwhile, a counter-petition supporting Burns garnered over 20,000 signatures.
1913
+
1914
+ "It is ridiculous that a couple of parents judge her role as a principal only based on an Instagram post. (About liking the band IRON MAIDEN. That's it.) Eden High School is a public school. Not a Christian school," the petition titled "We need Mrs Burns" stated. "She has made Eden a safe space for so many people. She spreads nothing but love and kindness."
1915
+
1916
+ After the complaints were aired, the District School Board of Niagara spoke with Burns and the parents who launched the petition, and the issue is over as far as the board is concerned, Kim Sweeney, the board's chief communications officer, told the National Post. No disciplinary action or policy changes were needed.
1917
+
1918
+ "Our belief is that taste in music is subjective and we support that both students and staff enjoy a wide variety of genres," Sweeney said.
1919
+
1920
+ The original petition has since been removed.
1921
+ MULTI_LINE_STRING
1720
1922
  end
1721
1923
 
1924
+ attr_accessor :document
1925
+
1722
1926
  attr_accessor :foreground
1723
1927
 
1724
1928
  def foreground_options
@@ -1731,15 +1935,65 @@ class HelloText
1731
1935
  [BACKGROUND_PROMPT] + COLOR_OPTIONS
1732
1936
  end
1733
1937
 
1938
+ attr_accessor :font_family
1939
+
1940
+ def font_family_options
1941
+ [FONT_FAMILY_PROMPT] + FONT_FAMILY_OPTIONS
1942
+ end
1943
+
1944
+ attr_accessor :font_size
1945
+
1946
+ def font_size_options
1947
+ [FONT_SIZE_PROMPT] + (9..64).to_a.map(&:to_s)
1948
+ end
1949
+
1734
1950
  def launch
1735
1951
  root {
1736
1952
  title 'Hello, Text!'
1953
+ width 1280
1954
+ height 800
1737
1955
 
1738
1956
  frame {
1739
1957
  grid row: 0, column: 0
1740
1958
 
1959
+ label {
1960
+ grid row: 0, column: 0, columnspan: 17
1961
+ text 'Select a region of text and then apply formatting from the toolbar'
1962
+ }
1963
+
1964
+ column_index = -1
1965
+
1966
+ combobox {
1967
+ grid row: 1, column: column_index += 1, column_weight: 1
1968
+ readonly true
1969
+ text <=> [self, :font_family, after_write: ->(value) { @text.toggle_selection_font_format('family', value == FONT_FAMILY_PROMPT ? 'Courier New' : value) }]
1970
+ }
1971
+
1972
+ combobox {
1973
+ grid row: 1, column: column_index += 1, column_weight: 1
1974
+ readonly true
1975
+ text <=> [self, :font_size, after_write: ->(value) { @text.toggle_selection_font_format('size', value == FONT_SIZE_PROMPT ? 13 : value) }]
1976
+ }
1977
+
1978
+ combobox {
1979
+ grid row: 1, column: column_index += 1, column_weight: 1
1980
+ readonly true
1981
+ text <=> [self, :foreground, after_write: ->(value) { @text.add_selection_format('foreground', value == FOREGROUND_PROMPT ? 'black' : value) }]
1982
+ }
1983
+
1984
+ combobox {
1985
+ grid row: 1, column: column_index += 1, column_weight: 1
1986
+ readonly true
1987
+ text <=> [self, :background, after_write: ->(value) { @text.add_selection_format('background', value == BACKGROUND_PROMPT ? 'white' : value) }]
1988
+ }
1989
+
1990
+ separator {
1991
+ grid row: 1, column: column_index += 1, column_weight: 0
1992
+ orient 'vertical'
1993
+ }
1994
+
1741
1995
  button {
1742
- grid row: 0, column: 0, column_weight: 0
1996
+ grid row: 1, column: column_index += 1, column_weight: 0
1743
1997
  text 'B'
1744
1998
  style font: {weight: 'bold'}
1745
1999
 
@@ -1749,7 +2003,7 @@ class HelloText
1749
2003
  }
1750
2004
 
1751
2005
  button {
1752
- grid row: 0, column: 1, column_weight: 0
2006
+ grid row: 1, column: column_index += 1, column_weight: 0
1753
2007
  text 'I'
1754
2008
  style font: {slant: 'italic'}
1755
2009
 
@@ -1759,7 +2013,7 @@ class HelloText
1759
2013
  }
1760
2014
 
1761
2015
  button {
1762
- grid row: 0, column: 2, column_weight: 0
2016
+ grid row: 1, column: column_index += 1, column_weight: 0
1763
2017
  text 'U'
1764
2018
  style font: {underline: true}
1765
2019
 
@@ -1768,48 +2022,113 @@ class HelloText
1768
2022
  end
1769
2023
  }
1770
2024
 
1771
- combobox {
1772
- grid row: 0, column: 4, column_weight: 1
1773
- readonly true
1774
- text <=> [self, :foreground, after_write: ->(value) { @text.add_selection_format('foreground', value == FOREGROUND_PROMPT ? 'black' : value) }]
2025
+ separator {
2026
+ grid row: 1, column: column_index += 1, column_weight: 0
2027
+ orient 'vertical'
1775
2028
  }
1776
2029
 
1777
- combobox {
1778
- grid row: 0, column: 5, column_weight: 1
1779
- readonly true
1780
- text <=> [self, :background, after_write: ->(value) { @text.add_selection_format('background', value == BACKGROUND_PROMPT ? 'black' : value) }]
1781
- }
1782
- }
1783
-
1784
- @text = text {
1785
- grid row: 1, column: 0, row_weight: 1
1786
- wrap 'word'
1787
- text <<~MULTI_LINE_STRING
1788
- According to the National Post, a heavy metal-loving high school principal in Canada will be allowed to keep her job, days after a public campaign to oust her made headlines around the globe.
1789
-
1790
- Parents at Eden High School in St. Catharines, Ontario launched a petition to remove principal Sharon Burns after discovering she's an IRON MAIDEN fan.
1791
-
1792
- The petition, titled "Eden High School Principal, Sharon Burns, Needs to Be Transferred Immediately!" read, "We are deeply disturbed that the principal assigned to the school blatantly showed Satanic symbols and her allegiance to Satanic practices on her public social media platforms where all the students can see them under @edenprincipal (not her personal account)."
1793
-
1794
- More than 500 people signed the petition to transfer Burns after she posted a picture of herself flashing the "devil horns" hand sign with a doll of the MAIDEN zombie mascot Eddie behind her as well as a personalized license plate reading "IRNMADEN" and a handwritten note that reads "Eddie 666" on a car's dashboard.
2030
+ button {
2031
+ grid row: 1, column: column_index += 1, column_weight: 0
2032
+ image File.expand_path("images/cut.png", __dir__), subsample: 32
1795
2033
 
2034
+ on('command') do
2035
+ @text.text_cut
2036
+ end
2037
+ }
2038
+
2039
+ button {
2040
+ grid row: 1, column: column_index += 1, column_weight: 0
2041
+ image File.expand_path("images/copy.png", __dir__), subsample: 32
1796
2042
 
1797
- The number 666 is used to represent the devil, and is featured prominently in MAIDEN's artwork by the band, whose classic third album is titled "The Number Of The Beast".
2043
+ on('command') do
2044
+ @text.text_copy
2045
+ end
2046
+ }
2047
+
2048
+ button {
2049
+ grid row: 1, column: column_index += 1, column_weight: 0
2050
+ image File.expand_path("images/paste.png", __dir__), subsample: 32
1798
2051
 
1799
- The petition was later updated to state that the demand for her transfer is not because of her love for metal, but for "openly displaying her own handmade sign with the 666 clearly displayed on it".
2052
+ on('command') do
2053
+ @text.text_paste
2054
+ end
2055
+ }
2056
+
2057
+ separator {
2058
+ grid row: 1, column: column_index += 1, column_weight: 0
2059
+ orient 'vertical'
2060
+ }
2061
+
2062
+ button {
2063
+ grid row: 1, column: column_index += 1, column_weight: 0
2064
+ image File.expand_path("images/align-left.png", __dir__), subsample: 32
1800
2065
 
1801
- The creator of the original petition wrote: "Sharon knows full well what she did was simply inappropriate, unnecessary and not professional but has yet to publicly admit so and is willing to allow people to believe a completely different story, making very real concerns seem petty."
2066
+ on('command') do
2067
+ @text.add_selection_format('justify', 'left')
2068
+ end
2069
+ }
2070
+
2071
+ button {
2072
+ grid row: 1, column: column_index += 1, column_weight: 0
2073
+ image File.expand_path("images/align-center.png", __dir__), subsample: 32
1802
2074
 
1803
- Meanwhile, a counter-petition supporting Burns garnered over 20,000 signatures.
2075
+ on('command') do
2076
+ @text.add_selection_format('justify', 'center')
2077
+ end
2078
+ }
2079
+
2080
+ button {
2081
+ grid row: 1, column: column_index += 1, column_weight: 0
2082
+ image File.expand_path("images/align-right.png", __dir__), subsample: 32
1804
2083
 
1805
- "It is ridiculous that a couple of parents judge her role as a principal only based on an Instagram post. (About liking the band IRON MAIDEN. That's it.) Eden High School is a public school. Not a Christian school," the petition titled "We need Mrs Burns" stated. "She has made Eden a safe space for so many people. She spreads nothing but love and kindness."
2084
+ on('command') do
2085
+ @text.add_selection_format('justify', 'right')
2086
+ end
2087
+ }
2088
+
2089
+ separator {
2090
+ grid row: 1, column: column_index += 1, column_weight: 0
2091
+ orient 'vertical'
2092
+ }
2093
+
2094
+ button {
2095
+ grid row: 1, column: column_index += 1, column_weight: 0
2096
+ image File.expand_path("images/undo.png", __dir__), subsample: 32
1806
2097
 
1807
- After the complaints were aired, the District School Board of Niagara spoke with Burns and the parents who launched the petition, and the issue is over as far as the board is concerned, Kim Sweeney, the board's chief communications officer, told the National Post. No disciplinary action or policy changes were needed.
2098
+ on('command') do
2099
+ @text.edit_undo
2100
+ end
2101
+ }
2102
+
2103
+ button {
2104
+ grid row: 1, column: column_index += 1, column_weight: 0
2105
+ image File.expand_path("images/redo.png", __dir__), subsample: 32
1808
2106
 
1809
- "Our belief is that taste in music is subjective and we support that both students and staff enjoy a wide variety of genres," Sweeney said.
2107
+ on('command') do
2108
+ @text.edit_redo
2109
+ end
2110
+ }
2111
+
2112
+ separator {
2113
+ grid row: 1, column: column_index += 1, column_weight: 0
2114
+ orient 'vertical'
2115
+ }
2116
+
2117
+ button {
2118
+ grid row: 1, column: column_index += 1, column_weight: 0
2119
+ image File.expand_path("images/picture.png", __dir__), subsample: 32
1810
2120
 
1811
- The original petition has since been removed.
1812
- MULTI_LINE_STRING
2121
+ on('command') do
2122
+ @text.get_open_file_to_insert_image
2123
+ end
2124
+ }
2125
+ }
2126
+
2127
+ @text = text {
2128
+ grid row: 1, column: 0, row_weight: 1
2129
+ wrap 'word'
2130
+ undo true
2131
+ value <=> [self, :document]
1813
2132
  }
1814
2133
  }.open
1815
2134
  end
@@ -1834,6 +2153,8 @@ Glimmer app:
1834
2153
 
1835
2154
  ![glimmer dsl tk screenshot sample hello text](images/glimmer-dsl-tk-screenshot-sample-hello-text.png)
1836
2155
 
2156
+ ![glimmer dsl tk screenshot sample hello text find dialog](images/glimmer-dsl-tk-screenshot-sample-hello-text-find-dialog.png)
2157
+
1837
2158
  ### Hello, Spinbox!
1838
2159
 
1839
2160
  Glimmer code (from [samples/hello/hello_spinbox.rb](samples/hello/hello_spinbox.rb)):
@@ -2152,22 +2473,195 @@ Glimmer app:
2152
2473
 
2153
2474
  ![glimmer dsl tk screenshot sample hello drag and drop](images/glimmer-dsl-tk-screenshot-sample-hello-drag-and-drop.png)
2154
2475
 
2155
- ## Help
2476
+ ### Hello, Built-in Dialog!
2156
2477
 
2157
- ### Issues
2478
+ Glimmer code (from [samples/hello/hello_built_in_dialog.rb](samples/hello/hello_built_in_dialog.rb)):
2158
2479
 
2159
- You may submit [issues](https://github.com/AndyObtiva/glimmer/issues) on [GitHub](https://github.com/AndyObtiva/glimmer/issues).
2480
+ ```ruby
2481
+ require 'glimmer-dsl-tk'
2160
2482
 
2161
- [Click here to submit an issue.](https://github.com/AndyObtiva/glimmer/issues)
2483
+ include Glimmer
2162
2484
 
2163
- ### Chat
2485
+ root { |w|
2486
+ title 'Hello, Built-in Dialog!'
2487
+ width 400
2488
+ height 400
2489
+ x 150
2490
+ y 150
2491
+
2492
+ frame {
2493
+ %w[get_open_file get_multiple_open_file get_save_file choose_directory choose_color].each do |dialog|
2494
+ button {
2495
+ text dialog.split('_').map(&:capitalize).join(' ')
2496
+
2497
+ on('command') do
2498
+ result = send(dialog, parent: w)
2499
+ @result_label.text = [result].flatten.join("\n")
2500
+ end
2501
+ }
2502
+ end
2503
+
2504
+ button {
2505
+ text 'Choose Font'
2506
+
2507
+ on('command') do
2508
+ choose_font(family: 'Courier New', size: '30', weight: 'bold') do |chosen_font|
2509
+ @result_label.text = chosen_font
2510
+ end
2511
+ end
2512
+ }
2513
+ }
2514
+
2515
+ frame {
2516
+ grid sticky: 'nsew', padx: 15, pady: 15
2517
+
2518
+ label {
2519
+ grid row: 0, column: 0
2520
+ text 'Result:'
2521
+ }
2522
+
2523
+ @result_label = label {
2524
+ grid row: 0, column: 1
2525
+ }
2526
+ }
2527
+ }.open
2528
+ ```
2164
2529
 
2165
- If you need live help, try to [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
2530
+ Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
2531
+
2532
+ ```
2533
+ ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_built_in_dialog'"
2534
+ ```
2535
+
2536
+ Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
2537
+
2538
+ ```
2539
+ ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_built_in_dialog.rb
2540
+ ```
2541
+
2542
+ Glimmer app:
2543
+
2544
+ ![glimmer dsl tk screenshot sample hello built in dialog 1](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-get-open-file.png)
2545
+ ![glimmer dsl tk screenshot sample hello built in dialog 2](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-get-open-file-done.png)
2546
+
2547
+ ![glimmer dsl tk screenshot sample hello built in dialog 3](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-choose-color.png)
2548
+ ![glimmer dsl tk screenshot sample hello built in dialog 4](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-choose-color-done.png)
2549
+
2550
+ ![glimmer dsl tk screenshot sample hello built in dialog 5](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-choose-font.png)
2551
+ ![glimmer dsl tk screenshot sample hello built in dialog 6](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-choose-font-done.png)
2552
+
2553
+ ### Hello, Separator!
2554
+
2555
+ Glimmer code (from [samples/hello/hello_separator.rb](samples/hello/hello_separator.rb)):
2556
+
2557
+ ```ruby
2558
+ require 'glimmer-dsl-tk'
2559
+
2560
+ include Glimmer
2561
+
2562
+ root {
2563
+ title 'Hello, Separator!'
2564
+ width 200
2565
+ height 200
2566
+
2567
+ label {
2568
+ grid row: 0, column: 0, min_width: 100, min_height: 100, column_weight: 0, sticky: 'nsew'
2569
+ text 'Label 1'
2570
+ anchor 'center'
2571
+ }
2572
+
2573
+ separator {
2574
+ grid row: 0, column: 1
2575
+ orient 'vertical'
2576
+ }
2577
+
2578
+ label {
2579
+ grid row: 0, column: 2, min_width: 100, min_height: 100, sticky: 'nsew'
2580
+ text 'Label 2'
2581
+ anchor 'center'
2582
+ }
2583
+
2584
+ separator {
2585
+ grid row: 1, column: 0, column_span: 3
2586
+ # orient 'horizontal' # default
2587
+ }
2588
+
2589
+ label {
2590
+ grid row: 2, column: 0, min_width: 100, min_height: 100, sticky: 'nsew'
2591
+ text 'Label 3'
2592
+ anchor 'center'
2593
+ }
2594
+
2595
+ separator {
2596
+ grid row: 2, column: 1
2597
+ orient 'vertical'
2598
+ }
2599
+
2600
+ label {
2601
+ grid row: 2, column: 2, min_width: 100, min_height: 100, sticky: 'nsew'
2602
+ text 'Label 4'
2603
+ anchor 'center'
2604
+ }
2605
+ }.open
2606
+ ```
2607
+
2608
+ Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
2609
+
2610
+ ```
2611
+ ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_separator'"
2612
+ ```
2613
+
2614
+ Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
2615
+
2616
+ ```
2617
+ ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_separator.rb
2618
+ ```
2619
+
2620
+ Glimmer app:
2621
+
2622
+ ![glimmer dsl tk screenshot sample hello separator](images/glimmer-dsl-tk-screenshot-sample-hello-separator.png)
2623
+
2624
+ ## Applications
2625
+
2626
+ ### Glimmer Tk Calculator
2627
+
2628
+ "I wanted to try how it feels to write an UI in glimmer-dsl-tk so I decided to write an alternative version of the [Glimmer Calculator](https://github.com/AndyObtiva/glimmer-cs-calculator) that uses [Tk]([Tk](https://www.tcl.tk/)) and runs in the regular [MRI Ruby interpreter](https://www.ruby-lang.org/en/)." - [Ancor Gonzalez Sosa](https://github.com/ancorgs)
2629
+
2630
+ https://github.com/ancorgs/glimmer-tk-calculator
2631
+
2632
+ ![Glimmer Tk Calculator Screenshot](https://raw.githubusercontent.com/ancorgs/glimmer-tk-calculator/master/screenshot.png)
2633
+
2634
+ ### Y3network Ruby UI
2635
+
2636
+ https://github.com/ancorgs/y3network-ruby-ui
2637
+
2638
+ ### CryptoPunks GUI
2639
+
2640
+ This is a Graphical User Interface for the famous [cryptopunks Ruby gem](https://github.com/cryptopunksnotdead/cryptopunks/tree/master/cryptopunks).
2641
+
2642
+ https://github.com/AndyObtiva/cryptopunks-gui
2643
+
2644
+ ![CryptoPunks GUI Screenshot](https://raw.githubusercontent.com/AndyObtiva/cryptopunks-gui/master/screenshots/cryptopunks-gui-screenshot.png)
2166
2645
 
2167
2646
  ## Process
2168
2647
 
2169
2648
  [Glimmer Process](https://github.com/AndyObtiva/glimmer/blob/master/PROCESS.md)
2170
2649
 
2650
+ ## Resources
2651
+
2652
+ - [Tk Tutorial](https://tkdocs.com/tutorial/index.html)
2653
+ - [Code Master Blog](https://andymaleh.blogspot.com/search/label/Tk)
2654
+
2655
+ ## Help
2656
+
2657
+ ### Issues
2658
+
2659
+ If you encounter [issues](https://github.com/AndyObtiva/glimmer-dsl-tk/issues) that are not reported, discover missing features that are not mentioned in [TODO.md](TODO.md), or think up better ways to use [Tk](https://www.tcl.tk/) than what is possible with [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk), you may submit an [issue](https://github.com/AndyObtiva/glimmer-dsl-tk/issues/new) or [pull request](https://github.com/AndyObtiva/glimmer-dsl-tk/compare) on [GitHub](https://github.com).
2660
+
2661
+ ### Chat
2662
+
2663
+ If you need live help, try to [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
2664
+
2171
2665
  ## Planned Features and Feature Suggestions
2172
2666
 
2173
2667
  These features have been planned or suggested. You might see them in a future version of [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk). You are welcome to contribute more feature suggestions.