glimmer-dsl-gtk 0.0.5 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,11 +1,11 @@
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 GTK 0.0.5
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 GTK 0.0.9
2
2
  ## Ruby-GNOME Desktop Development GUI Library
3
3
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-gtk.svg)](http://badge.fury.io/rb/glimmer-dsl-gtk)
4
4
  [![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)
5
5
 
6
- [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [GTK](https://www.gtk.org/) enables building desktop applications with [Ruby-GNOME](https://github.com/ruby-gnome/ruby-gnome).
6
+ [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [GTK](https://www.gtk.org/) enables building desktop applications with [Ruby-GNOME](https://github.com/ruby-gnome/ruby-gnome) (including [Cairo graphics](#declarative-cairo-graphics)) using [MRI Ruby](https://www.ruby-lang.org).
7
7
 
8
- [GTK](https://www.gtk.org/) (aka GIMP-Toolkit or [incorrectly] GNOME-Toolkit) is the premiere desktop GUI toolkit on [Linux](https://www.gtk.org/docs/installations/linux/), which also runs on [Mac](https://www.gtk.org/docs/installations/macos/) ([Quartz GTK+](https://wiki.gnome.org/Projects/GTK/OSX)) and [Windows](https://www.gtk.org/docs/installations/windows).
8
+ [GTK](https://www.gtk.org/) (aka GIMP-Toolkit or [incorrectly] GNOME-Toolkit) is the premiere desktop GUI toolkit on [Linux](https://www.gtk.org/docs/installations/linux/) (included in [GNOME flavors of Linux](https://www.gnome.org/getting-gnome/), where [Glimmer DSL for GTK](https://rubygems.org/gems/glimmer-dsl-gtk)'s forte is), which also runs on [Mac](https://www.gtk.org/docs/installations/macos/) ([Quartz GTK+](https://wiki.gnome.org/Projects/GTK/OSX)) and [Windows](https://www.gtk.org/docs/installations/windows).
9
9
 
10
10
  [Glimmer DSL for GTK](https://rubygems.org/gems/glimmer-dsl-gtk) aims to supercharge productivity and maintainability in developing [Ruby-GNOME](https://github.com/ruby-gnome/ruby-gnome) applications by providing a DSL similar to [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) having:
11
11
  - Declarative DSL syntax that visually maps to the GUI widget hierarchy
@@ -32,19 +32,25 @@ Linux | Mac | Windows
32
32
 
33
33
  NOTE: Glimmer DSL for GTK is currently in early alpha mode (incomplete proof-of-concept). If you want it developed faster, then [open an issue report](https://github.com/AndyObtiva/glimmer-dsl-gtk/issues/new). I have completed some GitHub project features much faster before due to [issue reports](https://github.com/AndyObtiva/glimmer-dsl-gtk/issues) and [pull requests](https://github.com/AndyObtiva/glimmer-dsl-gtk/pulls). Please help make better by contributing, adopting for small or low risk projects, and providing feedback. It is still an early alpha, so the more feedback and issues you report the better.
34
34
 
35
- Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interested in:
36
- - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
37
- - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)
38
- - [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
39
- - [glimmer-dsl-libui](https://github.com/AndyObtiva/glimmer-dsl-libui): Glimmer DSL for Tk (Prerequisite-Free Ruby Desktop Development GUI Library)
40
- - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
41
- - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS
35
+ **[Glimmer](https://rubygems.org/gems/glimmer) DSL Comparison Table:**
36
+ DSL | Platforms | Native? | Vector Graphics? | Pros | Cons | Prereqs
37
+ ----|-----------|---------|------------------|------|------|--------
38
+ [Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)](https://github.com/AndyObtiva/glimmer-dsl-swt) | Mac / Windows / Linux | Yes | Yes (Canvas Shape DSL) | Very Mature / Scaffolding / Native Executable Packaging / Custom Widgets | Slow JRuby Startup Time / Heavy Memory Footprint | Java / JRuby
39
+ [Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)](https://github.com/AndyObtiva/glimmer-dsl-opal) | All Web Browsers | No | Yes (Canvas Shape DSL) | Simpler than All JavaScript Technologies / Auto-Webify Desktop Apps | Setup Process / Only Rails 5 Support for Now | Rails
40
+ [Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-libui) | Mac / Windows / Linux | Yes | Yes (Area API) | Fast Startup Time / Light Memory Footprint | LibUI is an Incomplete Mid-Alpha Only | None Other Than MRI Ruby
41
+ [Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-tk) | Mac / Windows / Linux | Some Native-Themed Widgets (Not Truly Native) | Yes (Canvas) | Fast Startup Time / Light Memory Footprint | Widgets Do Not Look Truly Native, Espcially on Linux | ActiveTcl / MRI Ruby
42
+ [Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-gtk) | Mac / Windows / Linux | Only on Linux | Yes (Cairo) | Complete Access to GNOME Features on Linux (Forte) | Not Native on Mac and Windows | None Other Than MRI Ruby on Linux / Brew Packages on Mac / MSYS & MING Toolchains on Windows / MRI Ruby
43
+ [Glimmer DSL for FX (FOX Toolkit Ruby Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-fx) | Mac (requires XQuartz) / Windows / Linux | No | Yes (Canvas) | No Prerequisites on Windows (Forte Since Binaries Are Included Out of The Box) | Widgets Do Not Look Native / Mac Usage Obtrusively Starts XQuartz | None Other Than MRI Ruby on Windows / XQuarts on Mac / MRI Ruby
44
+ [Glimmer DSL for JFX (JRuby JavaFX Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-jfx) | Mac / Windows / Linux | No | Yes (javafx.scene.shape and javafx.scene.canvas) | Rich in Custom Widgets | Slow JRuby Startup Time / Heavy Memory Footprint / Widgets Do Not Look Native | Java / JRuby / JavaFX SDK
45
+ [Glimmer DSL for Swing (JRuby Swing Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-swing) | Mac / Windows / Linux | No | Yes (Java2D) | Very Mature | Slow JRuby Startup Time / Heavy Memory Footprint / Widgets Do Not Look Native | Java / JRuby
46
+ [Glimmer DSL for XML (& HTML)](https://github.com/AndyObtiva/glimmer-dsl-xml) | All Web Browsers | No | Yes (SVG) | Programmable / Lighter-weight Than Actual XML | XML Elements Are Sometimes Not Well-Named (Many Types of Input) | None
47
+ [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css) | All Web Browsers | No | Yes | Programmable | CSS Is Over-Engineered / Too Many Features To Learn | None
42
48
 
43
49
  ## Prerequisites
44
50
 
45
51
  ### Linux
46
52
 
47
- GNOME-based Linux installations do not need any pre-requisites since they have GTK built-in, so you can skip to [Setup](#setup) right away.
53
+ GNOME-based Linux installations do not need any prerequisites since they have GTK built-in, so you can skip to [Setup](#setup) right away.
48
54
 
49
55
  Still, if you run into issues installing the GTK gem in [Setup](#setup), you may try these commands first:
50
56
  ```
@@ -80,7 +86,7 @@ gem install glimmer-dsl-gtk
80
86
 
81
87
  Add the following to `Gemfile`:
82
88
  ```
83
- gem 'glimmer-dsl-gtk', '~> 0.0.5'
89
+ gem 'glimmer-dsl-gtk', '~> 0.0.9'
84
90
  ```
85
91
 
86
92
  And, then run:
@@ -152,13 +158,13 @@ Note that it is usually recommended to observe external model objects (not `self
152
158
 
153
159
  [Cairo](https://www.cairographics.org/) is the engine behind drawing arbitrary 2D geometric shapes in [GTK](https://www.gtk.org/).
154
160
 
155
- In [Glimmer DSL for GTK](https://rubygems.org/gems/glimmer-dsl-gtk), you can draw Cairo shapes declaratively in a way similar to how SVG works, but using one language; Ruby, thus being able to utilize Ruby logic (e.g. if statement or each loop) with it effortlessly when needed.
161
+ In [Glimmer DSL for GTK](https://rubygems.org/gems/glimmer-dsl-gtk), you can draw Cairo shapes declaratively in a way similar to how SVG works, but using one language; Ruby, thus being able to utilize Ruby logic (e.g. if statement or each loop) with it effortlessly when needed. Declarative syntax also yields less code that is simpler, not dependent on ordering of nested properties, and more understandable/maintainable.
156
162
 
157
163
  Below is a quick tutorial consisting of samples inspired and ported from [Mohit Sindhwani's blog post "Cairo with Ruby - Samples using RCairo"](https://notepad.onghu.com/2021/cairo-samples-in-ruby/).
158
164
 
159
- ### Arc
165
+ #### Arc
160
166
 
161
- Example (you may copy/paste in [`girb`](#girb-glimmer-irb))
167
+ [samples/cairo/arc.rb](/samples/cairo/arc.rb)
162
168
 
163
169
  ```ruby
164
170
  require 'glimmer-dsl-gtk'
@@ -166,7 +172,7 @@ require 'glimmer-dsl-gtk'
166
172
  include Glimmer
167
173
 
168
174
  window {
169
- title 'Hello, Drawing Area!'
175
+ title 'Arc'
170
176
  default_size 256, 256
171
177
 
172
178
  drawing_area {
@@ -209,9 +215,9 @@ window {
209
215
 
210
216
  ![Arc](/screenshots/glimmer-dsl-gtk-mac-cairo-arc.png)
211
217
 
212
- ### Arc Negative
218
+ #### Arc Negative
213
219
 
214
- Example (you may copy/paste in [`girb`](#girb-glimmer-irb))
220
+ [samples/cairo/arc_negative.rb](/samples/cairo/arc_negative.rb)
215
221
 
216
222
  ```ruby
217
223
  require 'glimmer-dsl-gtk'
@@ -262,9 +268,9 @@ window {
262
268
 
263
269
  ![Arc Negative](/screenshots/glimmer-dsl-gtk-mac-cairo-arc-negative.png)
264
270
 
265
- ### Clip
271
+ #### Clip
266
272
 
267
- Example (you may copy/paste in [`girb`](#girb-glimmer-irb))
273
+ [samples/cairo/clip.rb](/samples/cairo/clip.rb)
268
274
 
269
275
  ```ruby
270
276
  require 'glimmer-dsl-gtk'
@@ -305,6 +311,591 @@ window {
305
311
 
306
312
  ![Clip](/screenshots/glimmer-dsl-gtk-mac-cairo-clip.png)
307
313
 
314
+ #### Clip Image
315
+
316
+ [samples/cairo/clip_image.rb](/samples/cairo/clip_image.rb)
317
+
318
+ ```ruby
319
+ require 'glimmer-dsl-gtk'
320
+ require 'net/http'
321
+
322
+ image_content = Net::HTTP.get(URI('https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-gtk/master/images/breaking-blue-wave.png'))
323
+ image_file = File.join(Dir.home, 'breaking-blue-wave.png')
324
+ File.write(image_file, image_content)
325
+
326
+ include Glimmer
327
+
328
+ window {
329
+ title 'Clip Image'
330
+ default_size 256, 256
331
+
332
+ drawing_area {
333
+ paint 242.25, 242.25, 242.25
334
+
335
+ arc(128.0, 128.0, 76.8, 0, 2 * Math::PI) {
336
+ clip true # designate arc as the clipping area
337
+ }
338
+
339
+ rectangle(0, 0, 256, 256) {
340
+ # Source image is from:
341
+ # - https://www.publicdomainpictures.net/en/view-image.php?image=7683&picture=breaking-blue-wave
342
+ # Converted to PNG before using it
343
+ image = Cairo::ImageSurface.from_png(image_file)
344
+ w = image.width
345
+ h = image.height
346
+
347
+ scale 256.0/w, 256.0/h, exclude: :shape # applies scale to fill source image only
348
+ fill image, 0, 0
349
+ }
350
+ }
351
+ }.show
352
+ ```
353
+
354
+ ![Clip Image](/screenshots/glimmer-dsl-gtk-mac-cairo-clip-image.png)
355
+
356
+ #### Curve to
357
+
358
+ [samples/cairo/curve_to.rb](/samples/cairo/curve_to.rb)
359
+
360
+ ```ruby
361
+ require 'glimmer-dsl-gtk'
362
+
363
+ include Glimmer
364
+
365
+ window {
366
+ title 'Curve to'
367
+ default_size 256, 256
368
+
369
+ drawing_area {
370
+ paint 242.25, 242.25, 242.25
371
+
372
+ x=25.6
373
+ y=128.0
374
+ x1=102.4
375
+ y1=230.4
376
+ x2=153.6
377
+ y2=25.6
378
+ x3=230.4
379
+ y3=128.0
380
+
381
+ path {
382
+ move_to x, y
383
+ curve_to x1, y1, x2, y2, x3, y3
384
+
385
+ line_width 10
386
+ stroke 0, 0, 0
387
+ }
388
+
389
+ path {
390
+ move_to x,y
391
+ line_to x1,y1
392
+ move_to x2,y2
393
+ line_to x3,y3
394
+
395
+ line_width 6
396
+ stroke 255, 51, 51, 0.6
397
+ }
398
+ }
399
+ }.show
400
+ ```
401
+
402
+ ![Curve to](/screenshots/glimmer-dsl-gtk-mac-cairo-curve-to.png)
403
+
404
+ #### Dashes
405
+
406
+ [samples/cairo/dashes.rb](/samples/cairo/dashes.rb)
407
+
408
+ ```ruby
409
+ require 'glimmer-dsl-gtk'
410
+
411
+ include Glimmer
412
+
413
+ window {
414
+ title 'Dashes'
415
+ default_size 256, 256
416
+
417
+ drawing_area {
418
+ paint 242.25, 242.25, 242.25
419
+
420
+ dashes = [ 50.0, # ink
421
+ 10.0, # skip
422
+ 10.0, # ink
423
+ 10.0 # skip
424
+ ]
425
+ offset = -50.0
426
+
427
+ path {
428
+ move_to 128.0, 25.6
429
+ line_to 230.4, 230.4
430
+ rel_line_to -102.4, 0.0
431
+ curve_to 51.2, 230.4, 51.2, 128.0, 128.0, 128.0
432
+
433
+ line_width 10
434
+ dash dashes, offset
435
+ stroke 0, 0, 0
436
+ }
437
+ }
438
+ }.show
439
+ ```
440
+
441
+ ![Dashes](/screenshots/glimmer-dsl-gtk-mac-cairo-dashes.png)
442
+
443
+ #### Fill and Stroke 2
444
+
445
+ (note: there is no Fill and Stroke 1; this was adopted from [Mohit's blog post](https://notepad.onghu.com/2021/cairo-samples-in-ruby/), which only mentioned Fill and Stroke 2)
446
+
447
+ [samples/cairo/fill_and_stroke2.rb](/samples/cairo/fill_and_stroke2.rb)
448
+
449
+ ```ruby
450
+ require 'glimmer-dsl-gtk'
451
+
452
+ include Glimmer
453
+
454
+ window {
455
+ title 'Fill and Stroke 2'
456
+ default_size 256, 256
457
+
458
+ drawing_area {
459
+ paint 242.25, 242.25, 242.25
460
+
461
+ path {
462
+ move_to 128.0, 25.6
463
+ line_to 230.4, 230.4
464
+ rel_line_to -102.4, 0.0
465
+ curve_to 51.2, 230.4, 51.2, 128.0, 128.0, 128.0
466
+ close_path
467
+
468
+ fill 0, 0, 255
469
+ stroke 0, 0, 0
470
+ line_width 10
471
+ }
472
+
473
+ path {
474
+ move_to 64.0, 25.6
475
+ rel_line_to 51.2, 51.2
476
+ rel_line_to -51.2, 51.2
477
+ rel_line_to -51.2, -51.2
478
+ close_path
479
+
480
+ fill 0, 0, 255
481
+ stroke 0, 0, 0
482
+ line_width 10
483
+ }
484
+ }
485
+ }.show
486
+ ```
487
+
488
+ ![Fill and Stroke 2](/screenshots/glimmer-dsl-gtk-mac-cairo-fill-and-stroke2.png)
489
+
490
+ #### Fill Style
491
+
492
+ [samples/cairo/fill_style.rb](/samples/cairo/fill_style.rb)
493
+
494
+ ```ruby
495
+ require 'glimmer-dsl-gtk'
496
+
497
+ include Glimmer
498
+
499
+ window {
500
+ title 'Fill Style'
501
+ default_size 256, 256
502
+
503
+ drawing_area {
504
+ paint 242.25, 242.25, 242.25
505
+
506
+ path {
507
+ rectangle 12, 12, 232, 70
508
+ path { # sub-path
509
+ arc 64, 64, 40, 0, 2*Math::PI
510
+ }
511
+ path { # sub-path
512
+ arc_negative 192, 64, 40, 0, -2*Math::PI
513
+ }
514
+
515
+ fill_rule Cairo::FILL_RULE_EVEN_ODD
516
+ line_width 6
517
+ fill 0, 178.5, 0
518
+ stroke 0, 0, 0
519
+ }
520
+
521
+ path {
522
+ rectangle 12, 12, 232, 70
523
+ path { # sub-path
524
+ arc 64, 64, 40, 0, 2*Math::PI
525
+ }
526
+ path { # sub-path
527
+ arc_negative 192, 64, 40, 0, -2*Math::PI
528
+ }
529
+
530
+ translate 0, 128
531
+ fill_rule Cairo::FILL_RULE_WINDING
532
+ line_width 6
533
+ fill 0, 0, 229.5
534
+ stroke 0, 0, 0
535
+ }
536
+ }
537
+ }.show
538
+ ```
539
+
540
+ ![Fill Style](/screenshots/glimmer-dsl-gtk-mac-cairo-fill-style.png)
541
+
542
+ #### Gradient
543
+
544
+ [samples/cairo/gradient.rb](/samples/cairo/gradient.rb)
545
+
546
+ ```ruby
547
+ require 'glimmer-dsl-gtk'
548
+
549
+ include Glimmer
550
+
551
+ window {
552
+ title 'Gradient'
553
+ default_size 256, 256
554
+
555
+ drawing_area {
556
+ paint 242.25, 242.25, 242.25
557
+
558
+ # Create the Linear Pattern
559
+ rectangle(0, 0, 256, 256) {
560
+ pat = Cairo::LinearPattern.new(0.0, 0.0, 0.0, 256.0)
561
+ pat.add_color_stop_rgba(1, 0, 0, 0, 1)
562
+ pat.add_color_stop_rgba(0, 1, 1, 1, 1)
563
+
564
+ fill pat
565
+ }
566
+
567
+ # Create the radial pattern
568
+ arc(128.0, 128.0, 76.8, 0, 2 * Math::PI) {
569
+ pat = Cairo::RadialPattern.new(115.2, 102.4, 25.6,
570
+ 102.4, 102.4, 128.0)
571
+ pat.add_color_stop_rgba(0, 1, 1, 1, 1)
572
+ pat.add_color_stop_rgba(1, 0, 0, 0, 1)
573
+
574
+ fill pat
575
+ }
576
+ }
577
+ }.show
578
+ ```
579
+
580
+ ![Gradient](/screenshots/glimmer-dsl-gtk-mac-cairo-gradient.png)
581
+
582
+ #### Image
583
+
584
+ [samples/cairo/image.rb](/samples/cairo/image.rb)
585
+
586
+ ```ruby
587
+ require 'glimmer-dsl-gtk'
588
+ require 'net/http'
589
+
590
+ image_content = Net::HTTP.get(URI('https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-gtk/master/images/breaking-blue-wave.png'))
591
+ image_file = File.join(Dir.home, 'breaking-blue-wave.png')
592
+ File.write(image_file, image_content)
593
+
594
+ include Glimmer
595
+
596
+ window {
597
+ title 'Image'
598
+ default_size 256, 256
599
+
600
+ drawing_area {
601
+ paint 242.25, 242.25, 242.25
602
+
603
+ image = Cairo::ImageSurface.from_png(image_file)
604
+ w = image.width
605
+ h = image.height
606
+
607
+ translate 128.0, 128.0
608
+ rotate 45*Math::PI/180
609
+ scale 256.0/w, 256.0/h
610
+ translate -0.5*w, -0.5*h
611
+
612
+ paint image, 0, 0
613
+ }
614
+ }.show
615
+ ```
616
+
617
+ ![Image](/screenshots/glimmer-dsl-gtk-mac-cairo-image.png)
618
+
619
+ #### Image Gradient
620
+
621
+ [samples/cairo/image_gradient.rb](/samples/cairo/image_gradient.rb)
622
+
623
+ ```ruby
624
+ require 'glimmer-dsl-gtk'
625
+ require 'net/http'
626
+
627
+ image_content = Net::HTTP.get(URI('https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-gtk/master/images/breaking-blue-wave.png'))
628
+ image_file = File.join(Dir.home, 'breaking-blue-wave.png')
629
+ File.write(image_file, image_content)
630
+
631
+ include Glimmer
632
+
633
+ window {
634
+ title 'Image Gradient'
635
+ default_size 256, 256
636
+
637
+ drawing_area {
638
+ paint 242.25, 242.25, 242.25
639
+
640
+ image = Cairo::ImageSurface.from_png(image_file)
641
+ w = image.width
642
+ h = image.height
643
+
644
+ # Load the image as a surface pattern
645
+ pattern = Cairo::SurfacePattern.new(image)
646
+ pattern.extend = Cairo::EXTEND_REPEAT
647
+
648
+ # Set up the scale matrix
649
+ pattern.matrix = Cairo::Matrix.scale(w/256.0 * 5.0, h/256.0 * 5.0)
650
+
651
+ rectangle(0, 0, 256, 256) {
652
+ translate 128.0, 128.0
653
+ rotate Math::PI / 4
654
+ scale 1/Math.sqrt(2), 1/Math.sqrt(2)
655
+ translate -128.0, -128.0
656
+
657
+ fill pattern
658
+ }
659
+ }
660
+ }.show
661
+ ```
662
+
663
+ ![Image Gradient](/screenshots/glimmer-dsl-gtk-mac-cairo-image-gradient.png)
664
+
665
+ #### Multi Segment Caps
666
+
667
+ [samples/cairo/multi_segment_caps.rb](/samples/cairo/multi_segment_caps.rb)
668
+
669
+ ```ruby
670
+ require 'glimmer-dsl-gtk'
671
+
672
+ include Glimmer
673
+
674
+ window {
675
+ title 'Multi Segment Caps'
676
+ default_size 256, 256
677
+
678
+ drawing_area {
679
+ paint 242.25, 242.25, 242.25
680
+
681
+ path {
682
+ move_to 50.0, 75.0
683
+ line_to 200.0, 75.0
684
+
685
+ move_to 50.0, 125.0
686
+ line_to 200.0, 125.0
687
+
688
+ move_to 50.0, 175.0
689
+ line_to 200.0, 175.0
690
+
691
+ line_width 30
692
+ line_cap Cairo::LINE_CAP_ROUND
693
+ stroke 0, 0, 0
694
+ }
695
+ }
696
+ }.show
697
+ ```
698
+
699
+ ![Multi Segment Caps](/screenshots/glimmer-dsl-gtk-mac-cairo-multi-segment-caps.png)
700
+
701
+ #### Rounded Rectangle
702
+
703
+ [samples/cairo/rounded_rectangle.rb](/samples/cairo/rounded_rectangle.rb)
704
+
705
+ ```ruby
706
+ require 'glimmer-dsl-gtk'
707
+
708
+ include Glimmer
709
+
710
+ window {
711
+ title 'Rounded Rectangle'
712
+ default_size 256, 256
713
+
714
+ drawing_area {
715
+ paint 242.25, 242.25, 242.25
716
+
717
+ path {
718
+ rounded_rectangle(25.6, 25.6, 204.8, 204.8, 20)
719
+
720
+ fill 127.5, 127.5, 255
721
+ line_width 10.0
722
+ stroke 127.5, 0, 0, 0.5
723
+ }
724
+ }
725
+ }.show
726
+ ```
727
+
728
+ ![Rounded Rectangle](/screenshots/glimmer-dsl-gtk-mac-cairo-rounded-rectangle.png)
729
+
730
+ #### Set line cap
731
+
732
+ [samples/cairo/set_line_cap.rb](/samples/cairo/set_line_cap.rb)
733
+
734
+ ```ruby
735
+ require 'glimmer-dsl-gtk'
736
+
737
+ include Glimmer
738
+
739
+ window {
740
+ title 'Set line cap'
741
+ default_size 256, 256
742
+
743
+ drawing_area {
744
+ paint 242.25, 242.25, 242.25
745
+
746
+ # The main code
747
+ path {
748
+ move_to 64.0, 50.0
749
+ line_to 64.0, 200.0
750
+
751
+ line_cap Cairo::LINE_CAP_BUTT # default
752
+ line_width 30
753
+ stroke 0, 0, 0
754
+ }
755
+
756
+ path {
757
+ move_to 128.0, 50.0
758
+ line_to 128.0, 200.0
759
+
760
+ line_cap Cairo::LINE_CAP_ROUND
761
+ line_width 30
762
+ stroke 0, 0, 0
763
+ }
764
+
765
+ path {
766
+ move_to 192.0, 50.0
767
+ line_to 192.0, 200.0
768
+
769
+ line_cap Cairo::LINE_CAP_SQUARE
770
+ line_width 30
771
+ stroke 0, 0, 0
772
+ }
773
+
774
+ # draw helping lines */
775
+ path {
776
+ move_to 64.0, 50.0
777
+ line_to 64.0, 200.0
778
+ move_to 128.0, 50.0
779
+ line_to 128.0, 200.0
780
+ move_to 192.0, 50.0
781
+ line_to 192.0, 200.0
782
+
783
+ line_width 2.56
784
+ stroke 255, 51, 51
785
+ }
786
+ }
787
+ }.show
788
+ ```
789
+
790
+ ![Set line cap](/screenshots/glimmer-dsl-gtk-mac-cairo-set-line-cap.png)
791
+
792
+ #### Set line join
793
+
794
+ [samples/cairo/set_line_join.rb](/samples/cairo/set_line_join.rb)
795
+
796
+ ```ruby
797
+ require 'glimmer-dsl-gtk'
798
+
799
+ include Glimmer
800
+
801
+ window {
802
+ title 'Set line join'
803
+ default_size 256, 256
804
+
805
+ drawing_area {
806
+ paint 242.25, 242.25, 242.25
807
+
808
+ # The main code
809
+ path {
810
+ move_to 76.8, 84.48
811
+ rel_line_to 51.2, -51.2
812
+ rel_line_to 51.2, 51.2
813
+
814
+ line_join Cairo::LINE_JOIN_MITER # default
815
+ line_width 40.96
816
+ stroke 0, 0, 0
817
+ }
818
+
819
+ path {
820
+ move_to 76.8, 161.28
821
+ rel_line_to 51.2, -51.2
822
+ rel_line_to 51.2, 51.2
823
+
824
+ line_join Cairo::LINE_JOIN_BEVEL
825
+ line_width 40.96
826
+ stroke 0, 0, 0
827
+ }
828
+
829
+ path {
830
+ move_to 76.8, 238.08
831
+ rel_line_to 51.2, -51.2
832
+ rel_line_to 51.2, 51.2
833
+
834
+ line_join Cairo::LINE_JOIN_ROUND
835
+ line_width 40.96
836
+ stroke 0, 0, 0
837
+ }
838
+ }
839
+ }.show
840
+ ```
841
+
842
+ ![Set line join](/screenshots/glimmer-dsl-gtk-mac-cairo-set-line-join.png)
843
+
844
+ #### Text
845
+
846
+ [samples/cairo/text.rb](/samples/cairo/text.rb)
847
+
848
+ ```ruby
849
+ require 'glimmer-dsl-gtk'
850
+
851
+ include Glimmer
852
+
853
+ window {
854
+ title 'Text'
855
+ default_size 256, 256
856
+
857
+ drawing_area {
858
+ paint 242.25, 242.25, 242.25
859
+
860
+ font_family = OS.linux? ? 'Sans' : (OS.mac? ? 'Helvetica' : 'Arial')
861
+
862
+ # The main code
863
+ path {
864
+ move_to 10.0, 135.0
865
+ show_text 'Hello'
866
+
867
+ font_face font_family, Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_BOLD
868
+ font_size 90.0
869
+ line_width 2.56
870
+ fill 0, 0, 0
871
+ stroke 0, 0, 0
872
+ }
873
+
874
+ path {
875
+ move_to 70.0, 165.0
876
+ text_path 'void'
877
+
878
+ font_face font_family, Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_BOLD
879
+ font_size 90.0
880
+ line_width 2.56
881
+ fill 127.5, 127.5, 255
882
+ stroke 0, 0, 0
883
+ }
884
+
885
+ # draw helping lines
886
+ path {
887
+ arc 10.0, 135.0, 5.12, 0, 2*Math::PI
888
+ close_path
889
+ arc 70.0, 165.0, 5.12, 0, 2*Math::PI
890
+
891
+ fill 255, 51, 51, 0.6
892
+ }
893
+ }
894
+ }.show
895
+ ```
896
+
897
+ ![Text](/screenshots/glimmer-dsl-gtk-mac-cairo-text.png)
898
+
308
899
  ## Girb (Glimmer IRB)
309
900
 
310
901
  You can run the `girb` command (`bin/girb` if you cloned the project locally):
@@ -431,9 +1022,9 @@ include Glimmer
431
1022
  window { |w|
432
1023
  title 'Hello, Button!'
433
1024
 
434
- button('Button') {
1025
+ button(label: 'Button') {
435
1026
  on(:clicked) do
436
- message_dialog(w) { |md|
1027
+ message_dialog(parent: w) { |md|
437
1028
  title 'Information'
438
1029
  text 'You clicked the button'
439
1030
 
@@ -485,9 +1076,9 @@ window { |w|
485
1076
  end
486
1077
  }
487
1078
 
488
- button('Button') {
1079
+ button(label: 'Button') {
489
1080
  on(:clicked) do
490
- message_dialog(w) { |md|
1081
+ message_dialog(parent: w) { |md|
491
1082
  title 'You entered'
492
1083
  text e.text
493
1084
 
@@ -809,7 +1400,7 @@ include Glimmer
809
1400
 
810
1401
  application('org.glimmer.hello-application') {
811
1402
  on(:activate) do |app|
812
- application_window(app) {
1403
+ application_window(app) { |aw|
813
1404
  title 'Widget Gallery'
814
1405
 
815
1406
  notebook { |n|
@@ -851,13 +1442,24 @@ application('org.glimmer.hello-application') {
851
1442
  spacing 10
852
1443
 
853
1444
  label('Button')
854
- button('Push Me')
1445
+ button(label: 'Push Me') {
1446
+ on(:clicked) do
1447
+ message_dialog(parent: aw) { |md|
1448
+ title 'Information'
1449
+ text 'You clicked the button'
1450
+
1451
+ on(:response) do
1452
+ md.destroy
1453
+ end
1454
+ }.show
1455
+ end
1456
+ }
855
1457
 
856
1458
  label('Radio Button')
857
1459
  box(:horizontal) {
858
- rb = radio_button('One')
859
- radio_button(rb, 'Two')
860
- radio_button(rb, 'Three')
1460
+ rb = radio_button(label: 'One')
1461
+ radio_button(label: 'Two', member: rb)
1462
+ radio_button(label: 'Three', member: rb)
861
1463
  }
862
1464
 
863
1465
  label('Check Button')
@@ -879,12 +1481,12 @@ application('org.glimmer.hello-application') {
879
1481
  spacing 10
880
1482
 
881
1483
  label('Horizontal Scale')
882
- h_scale(1, 100, 1) {
1484
+ scale(:horizontal, 1, 100, 1) {
883
1485
  visible true
884
1486
  }
885
1487
 
886
1488
  label('Vertical Scale')
887
- v_scale(1, 100, 1) {
1489
+ scale(:vertical, 1, 100, 1) {
888
1490
  visible true
889
1491
  height_request 200
890
1492
  }
@@ -1065,17 +1667,32 @@ class Tetris
1065
1667
 
1066
1668
  Model::Game::PREVIEW_PLAYFIELD_HEIGHT.times do |row|
1067
1669
  Model::Game::PREVIEW_PLAYFIELD_WIDTH.times do |column|
1068
- observe(@game.preview_playfield[row][column], :color) do |new_color|
1069
- color = new_color
1670
+ preview_updater = proc do
1070
1671
  block = @preview_playfield_blocks[row][column]
1071
- block[:background_square].fill = color
1072
- block[:top_bevel_edge].fill = [color[0] + 4*BEVEL_CONSTANT, color[1] + 4*BEVEL_CONSTANT, color[2] + 4*BEVEL_CONSTANT]
1073
- block[:right_bevel_edge].fill = [color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT]
1074
- block[:bottom_bevel_edge].fill = [color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT]
1075
- block[:left_bevel_edge].fill = [color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT]
1076
- block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : color
1672
+ if @game.show_preview_tetromino?
1673
+ new_color = @game.preview_playfield[row][column].color
1674
+ block[:background_square].fill = new_color
1675
+ block[:top_bevel_edge].fill = [new_color[0] + 4*BEVEL_CONSTANT, new_color[1] + 4*BEVEL_CONSTANT, new_color[2] + 4*BEVEL_CONSTANT]
1676
+ block[:right_bevel_edge].fill = [new_color[0] - BEVEL_CONSTANT, new_color[1] - BEVEL_CONSTANT, new_color[2] - BEVEL_CONSTANT]
1677
+ block[:bottom_bevel_edge].fill = [new_color[0] - BEVEL_CONSTANT, new_color[1] - BEVEL_CONSTANT, new_color[2] - BEVEL_CONSTANT]
1678
+ block[:left_bevel_edge].fill = [new_color[0] - BEVEL_CONSTANT, new_color[1] - BEVEL_CONSTANT, new_color[2] - BEVEL_CONSTANT]
1679
+ block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : new_color
1680
+ @next_label.text = 'Next'
1681
+ else
1682
+ transparent_color = [0, 0, 0, 0]
1683
+ block[:background_square].fill = transparent_color
1684
+ block[:top_bevel_edge].fill = transparent_color
1685
+ block[:right_bevel_edge].fill = transparent_color
1686
+ block[:bottom_bevel_edge].fill = transparent_color
1687
+ block[:left_bevel_edge].fill = transparent_color
1688
+ block[:border_square].stroke = transparent_color
1689
+ @next_label.text = ''
1690
+ end
1077
1691
  block[:drawing_area].queue_draw
1078
1692
  end
1693
+
1694
+ observe(@game.preview_playfield[row][column], :color, &preview_updater)
1695
+ observe(@game, :show_preview_tetromino, &preview_updater)
1079
1696
  end
1080
1697
  end
1081
1698
 
@@ -1121,6 +1738,16 @@ class Tetris
1121
1738
 
1122
1739
  menu_item(label: 'View') { |mi|
1123
1740
  m = menu {
1741
+ check_menu_item(label: 'Show Next Block Preview') {
1742
+ active @game.show_preview_tetromino?
1743
+
1744
+ on(:activate) do
1745
+ @game.show_preview_tetromino = !@game.show_preview_tetromino?
1746
+ end
1747
+ }
1748
+
1749
+ separator_menu_item
1750
+
1124
1751
  menu_item(label: 'Show High Scores') {
1125
1752
  on(:activate) do
1126
1753
  show_high_score_dialog
@@ -1136,6 +1763,27 @@ class Tetris
1136
1763
  mi.submenu = m.gtk
1137
1764
  }
1138
1765
 
1766
+ menu_item(label: 'Speed') { |mi|
1767
+ m = menu {
1768
+ rmi = radio_menu_item(nil, Model::Game::SPEEDS.first.to_s.capitalize) {
1769
+ active true
1770
+
1771
+ on(:activate) do
1772
+ @game.send("speed_#{Model::Game::SPEEDS.first}=", true)
1773
+ end
1774
+ }
1775
+
1776
+ Model::Game::SPEEDS.drop(1).each do |speed|
1777
+ radio_menu_item(rmi.group, speed.to_s.capitalize) {
1778
+ on(:activate) do
1779
+ @game.send("speed_#{speed}=", true)
1780
+ end
1781
+ }
1782
+ end
1783
+ }
1784
+ mi.submenu = m.gtk
1785
+ }
1786
+
1139
1787
  menu_item(label: 'Options') { |mi|
1140
1788
  m = menu {
1141
1789
  rmi = radio_menu_item(nil, 'Instant Down on Up') {
@@ -1160,7 +1808,7 @@ class Tetris
1160
1808
  mi.submenu = m.gtk
1161
1809
  }
1162
1810
 
1163
- menu_item(label: 'Options') { |mi|
1811
+ menu_item(label: 'Help') { |mi|
1164
1812
  m = menu {
1165
1813
  menu_item(label: 'About') {
1166
1814
  on(:activate) do
@@ -1176,6 +1824,7 @@ class Tetris
1176
1824
  def score_board
1177
1825
  box(:vertical) {
1178
1826
  label
1827
+ @next_label = label('Next')
1179
1828
  @preview_playfield_blocks = playfield(playfield_width: Model::Game::PREVIEW_PLAYFIELD_WIDTH, playfield_height: Model::Game::PREVIEW_PLAYFIELD_HEIGHT, block_size: BLOCK_SIZE)
1180
1829
 
1181
1830
  label
@@ -1249,29 +1898,29 @@ class Tetris
1249
1898
  def start_moving_tetrominos_down
1250
1899
  unless @tetrominos_start_moving_down
1251
1900
  @tetrominos_start_moving_down = true
1252
- GLib::Timeout.add(@game.delay*1000) do
1901
+ tetromino_move = proc do
1253
1902
  @game.down! if !@game.game_over? && !@game.paused?
1254
- true
1903
+ GLib::Timeout.add(@game.delay*1000, &tetromino_move)
1904
+ false # do not repeat
1255
1905
  end
1906
+ GLib::Timeout.add(@game.delay*1000, &tetromino_move)
1256
1907
  end
1257
1908
  end
1258
1909
 
1259
1910
  def show_game_over_dialog
1260
- message_dialog(@main_window) { |md|
1911
+ @game.paused = true
1912
+ message_dialog(parent: @main_window) { |md|
1261
1913
  title 'Game Over!'
1262
1914
  text "Score: #{@game.high_scores.first.score}\nLines: #{@game.high_scores.first.lines}\nLevel: #{@game.high_scores.first.level}"
1263
1915
 
1264
1916
  on(:response) do
1917
+ @game.restart!
1265
1918
  md.destroy
1266
1919
  end
1267
1920
  }.show
1268
-
1269
- @game.restart!
1270
- false
1271
1921
  end
1272
1922
 
1273
1923
  def show_high_score_dialog
1274
- game_paused = !!@game.paused
1275
1924
  @game.paused = true
1276
1925
 
1277
1926
  if @game.high_scores.empty?
@@ -1282,20 +1931,19 @@ class Tetris
1282
1931
  end.join("\n")
1283
1932
  end
1284
1933
 
1285
- message_dialog(@main_window) { |md|
1934
+ message_dialog(parent: @main_window) { |md|
1286
1935
  title 'High Scores'
1287
1936
  text high_scores_string
1288
1937
 
1289
1938
  on(:response) do
1939
+ @game.paused = false
1290
1940
  md.destroy
1291
1941
  end
1292
1942
  }.show
1293
-
1294
- @game.paused = game_paused
1295
1943
  end
1296
1944
 
1297
1945
  def show_about_dialog
1298
- message_dialog(@main_window) { |md|
1946
+ message_dialog(parent: @main_window) { |md|
1299
1947
  title 'About'
1300
1948
  text "Glimmer Tetris\n\nGlimmer DSL for GTK\n\nElaborate Sample\n\nCopyright (c) 2021-2022 Andy Maleh"
1301
1949