glimmer-dsl-opal 0.0.6 → 0.0.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbf51689c9728f9af6a7670f703584c79def82be3f74085556f91cbc9f02cd51
4
- data.tar.gz: e73b3c81aa113ca61e080a5c0fce7299c0812c04883aaf8864bdec5dc80fad00
3
+ metadata.gz: b1e27d44e69248f9febb6c2b8ce6d58d5f6a876d451b09d293769e3296e8c1ff
4
+ data.tar.gz: 30f77e89b509c325d8e609a2b6cda35425acb2b3e6f48ed8113c724208a1c0e9
5
5
  SHA512:
6
- metadata.gz: 98c27b51a8de0e218ed4e888660fb6dbf110deda9b1444b7fd75dc72d5477a5eaa277d2a64d92f223bcf0d3b8c398bf2da369a26e000c2544c34952c9fd7f8ad
7
- data.tar.gz: 05725471322ba4a5e55115360fa2a970e69c6f076c36480b3354c86968ac796e63c0e0c1250ca2639f100a329363c51fc7a0254b66a918aa7ed4130f538c2ce4
6
+ metadata.gz: 6ee6ca73fef3795d270cf4980fd4392beb39bc2a4f240f5a0fe10014772206aa5da1ca502559a13da2abb3191f681d5f76041003d207736c4469be2709476d73
7
+ data.tar.gz: 381fde33081fca87a978babb4e3048acfacf70a56de249eb5ea44be9dd0c6f60139b278601d929110eb6f687f3dd65c31287458d8c98c0fc1e31c59c3b842d71
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=65 /> Glimmer DSL for Opal 0.0.6 (Web GUI for Desktop Apps)
1
+ # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=65 /> Glimmer DSL for Opal 0.0.7 (Web GUI for Desktop Apps)
2
2
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-opal.svg)](http://badge.fury.io/rb/glimmer-dsl-opal)
3
3
  [![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)
4
4
 
@@ -6,7 +6,9 @@
6
6
 
7
7
  It enables running [Glimmer](https://github.com/AndyObtiva/glimmer) desktop apps on the web via [Rails](https://rubyonrails.org/) 5 and [Opal](https://opalrb.com/) 1.
8
8
 
9
- NOTE: Alpha Version 0.0.6 only supports Hello sample capabilities (detailed under [Examples](#examples)):
9
+ NOTE: Alpha Version 0.0.7 only supports capabilities for the following [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) [samples](https://github.com/AndyObtiva/glimmer#samples):
10
+
11
+ Hello Samples:
10
12
  - [Hello, World!](#hello-world)
11
13
  - [Hello, Combo!](#hello-combo)
12
14
  - [Hello, Computed!](#hello-computed)
@@ -15,6 +17,10 @@ NOTE: Alpha Version 0.0.6 only supports Hello sample capabilities (detailed unde
15
17
  - [Hello, Browser!](#hello-browser)
16
18
  - [Hello, Tab!](#hello-tab)
17
19
 
20
+ Elaborate Samples:
21
+ - [Login](#login)
22
+ - [Tic Tac Toe](#tic-tac-toe)
23
+
18
24
  Other Glimmer DSL gems:
19
25
  - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (Desktop GUI)
20
26
  - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
@@ -57,9 +63,10 @@ Follow instructions to setup opal with a rails application: config/initializers/
57
63
 
58
64
  Add the following to `Gemfile` (NOTE: if you run into issues, they are probably fixed in master or development/wip branch, you may check out instead):
59
65
  ```
60
- gem 'opal-rails'
61
- gem 'opal-browser'
62
- gem 'glimmer-dsl-opal', '~> 0.0.6', require: false
66
+ gem 'opal-rails', '~> 1.1.2'
67
+ gem 'opal-async', '~> 1.1.0'
68
+ gem 'opal-browser', '~> 0.2.0'
69
+ gem 'glimmer-dsl-opal', '~> 0.0.7', require: false
63
70
  ```
64
71
 
65
72
  Edit `config/initializers/assets.rb` and add:
@@ -73,9 +80,11 @@ Add the following line to the top of an empty `app/assets/javascripts/applicatio
73
80
  require 'glimmer-dsl-opal' # brings opal and opal browser too
74
81
  ```
75
82
 
76
- ## Examples
83
+ ## Samples
84
+
85
+ ### Hello Samples
77
86
 
78
- ### Hello, World!
87
+ #### Hello, World!
79
88
 
80
89
  Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
81
90
 
@@ -107,7 +116,7 @@ You should see "Hello, World!"
107
116
 
108
117
  ![Glimmer DSL for Opal Hello World](images/glimmer-dsl-opal-hello-world.png)
109
118
 
110
- ### Hello, Combo!
119
+ #### Hello, Combo!
111
120
 
112
121
  Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
113
122
 
@@ -164,7 +173,7 @@ You should see "Hello, Combo!"
164
173
 
165
174
  ![Glimmer DSL for Opal Hello Combo](images/glimmer-dsl-opal-hello-combo.png)
166
175
 
167
- ### Hello, Computed!
176
+ #### Hello, Computed!
168
177
 
169
178
  Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
170
179
 
@@ -276,7 +285,7 @@ You should see "Hello, Computed!"
276
285
 
277
286
  ![Glimmer DSL for Opal Hello Computed](images/glimmer-dsl-opal-hello-computed.png)
278
287
 
279
- ### Hello, List Single Selection!
288
+ #### Hello, List Single Selection!
280
289
 
281
290
  Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
282
291
 
@@ -333,7 +342,7 @@ You should see "Hello, List Single Selection!"
333
342
 
334
343
  ![Glimmer DSL for Opal Hello List Single Selection](images/glimmer-dsl-opal-hello-list-single-selection.png)
335
344
 
336
- ### Hello, List Multi Selection!
345
+ #### Hello, List Multi Selection!
337
346
 
338
347
  Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
339
348
 
@@ -400,7 +409,7 @@ You should see "Hello, List Multi Selection!"
400
409
 
401
410
  ![Glimmer DSL for Opal Hello List Multi Selection](images/glimmer-dsl-opal-hello-list-multi-selection.png)
402
411
 
403
- ### Hello, Browser!
412
+ #### Hello, Browser!
404
413
 
405
414
  Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
406
415
 
@@ -431,7 +440,7 @@ You should see "Hello, Browser!"
431
440
 
432
441
  ![Glimmer DSL for Opal Hello Browser](images/glimmer-dsl-opal-hello-browser.png)
433
442
 
434
- ### Hello, Tab!
443
+ #### Hello, Tab!
435
444
 
436
445
  Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
437
446
 
@@ -480,6 +489,351 @@ You should see "Hello, Tab!"
480
489
  ![Glimmer DSL for Opal Hello Tab English](images/glimmer-dsl-opal-hello-tab-english.png)
481
490
  ![Glimmer DSL for Opal Hello Tab French](images/glimmer-dsl-opal-hello-tab-french.png)
482
491
 
492
+ ### Elaborate Samples
493
+
494
+ #### Login
495
+
496
+ Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
497
+
498
+ ```ruby
499
+ require "observer"
500
+
501
+ #Presents login screen data
502
+ class LoginPresenter
503
+
504
+ attr_accessor :user_name
505
+ attr_accessor :password
506
+ attr_accessor :status
507
+
508
+ def initialize
509
+ @user_name = ""
510
+ @password = ""
511
+ @status = "Logged Out"
512
+ end
513
+
514
+ def status=(status)
515
+ @status = status
516
+
517
+ #TODO add feature to bind dependent properties to master property (2017-07-25 nested data binding)
518
+ notify_observers("logged_in")
519
+ notify_observers("logged_out")
520
+ end
521
+
522
+ def logged_in
523
+ self.status == "Logged In"
524
+ end
525
+
526
+ def logged_out
527
+ !self.logged_in
528
+ end
529
+
530
+ def login
531
+ self.status = "Logged In"
532
+ end
533
+
534
+ def logout
535
+ self.user_name = ""
536
+ self.password = ""
537
+ self.status = "Logged Out"
538
+ end
539
+
540
+ end
541
+
542
+ #Login screen
543
+ class Login
544
+ include Glimmer
545
+
546
+ def launch
547
+ presenter = LoginPresenter.new
548
+ @shell = shell {
549
+ text "Login"
550
+ composite {
551
+ grid_layout 2, false #two columns with differing widths
552
+
553
+ label { text "Username:" } # goes in column 1
554
+ text { # goes in column 2
555
+ text bind(presenter, :user_name)
556
+ enabled bind(presenter, :logged_out)
557
+ }
558
+
559
+ label { text "Password:" }
560
+ text(:password, :border) {
561
+ text bind(presenter, :password)
562
+ enabled bind(presenter, :logged_out)
563
+ }
564
+
565
+ label { text "Status:" }
566
+ label { text bind(presenter, :status) }
567
+
568
+ button {
569
+ text "Login"
570
+ enabled bind(presenter, :logged_out)
571
+ on_widget_selected { presenter.login }
572
+ }
573
+
574
+ button {
575
+ text "Logout"
576
+ enabled bind(presenter, :logged_in)
577
+ on_widget_selected { presenter.logout }
578
+ }
579
+ }
580
+ }
581
+ @shell.open
582
+ end
583
+ end
584
+
585
+ Login.new.launch
586
+ ```
587
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
588
+
589
+ ![Glimmer DSL for SWT Login](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-login.png)
590
+ ![Glimmer DSL for SWT Login Filled In](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-login-filled-in.png)
591
+ ![Glimmer DSL for SWT Login Logged In](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-login-logged-in.png)
592
+
593
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
594
+
595
+ Start the Rails server:
596
+ ```
597
+ rails s
598
+ ```
599
+
600
+ Visit `http://localhost:3000`
601
+
602
+ You should see "Login" dialog
603
+
604
+ ![Glimmer DSL for Opal Login](images/glimmer-dsl-opal-login.png)
605
+ ![Glimmer DSL for Opal Login Filled In](images/glimmer-dsl-opal-login-filled-in.png)
606
+ ![Glimmer DSL for Opal Login Logged In](images/glimmer-dsl-opal-login-logged-in.png)
607
+
608
+ #### Tic Tac Toe
609
+
610
+ Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
611
+
612
+ ```ruby
613
+ class TicTacToe
614
+ class Cell
615
+ EMPTY = ""
616
+ attr_accessor :sign, :empty
617
+
618
+ def initialize
619
+ reset
620
+ end
621
+
622
+ def mark(sign)
623
+ self.sign = sign
624
+ end
625
+
626
+ def reset
627
+ self.sign = EMPTY
628
+ end
629
+
630
+ def sign=(sign_symbol)
631
+ @sign = sign_symbol
632
+ self.empty = sign == EMPTY
633
+ end
634
+
635
+ def marked
636
+ !empty
637
+ end
638
+ end
639
+ end
640
+
641
+ class TicTacToe
642
+ class Board
643
+ DRAW = :draw
644
+ IN_PROGRESS = :in_progress
645
+ WIN = :win
646
+ attr :winning_sign
647
+ attr_accessor :game_status
648
+
649
+ def initialize
650
+ @sign_state_machine = {nil => "X", "X" => "O", "O" => "X"}
651
+ build_grid
652
+ @winning_sign = Cell::EMPTY
653
+ @game_status = IN_PROGRESS
654
+ end
655
+
656
+ #row and column numbers are 1-based
657
+ def mark(row, column)
658
+ self[row, column].mark(current_sign)
659
+ game_over? #updates winning sign
660
+ end
661
+
662
+ def current_sign
663
+ @current_sign = @sign_state_machine[@current_sign]
664
+ end
665
+
666
+ def [](row, column)
667
+ @grid[row-1][column-1]
668
+ end
669
+
670
+ def game_over?
671
+ win? or draw?
672
+ end
673
+
674
+ def win?
675
+ win = (row_win? or column_win? or diagonal_win?)
676
+ self.game_status=WIN if win
677
+ win
678
+ end
679
+
680
+ def reset
681
+ (1..3).each do |row|
682
+ (1..3).each do |column|
683
+ self[row, column].reset
684
+ end
685
+ end
686
+ @winning_sign = Cell::EMPTY
687
+ @current_sign = nil
688
+ self.game_status=IN_PROGRESS
689
+ end
690
+
691
+ private
692
+
693
+ def build_grid
694
+ @grid = []
695
+ 3.times do |row_index| #0-based
696
+ @grid << []
697
+ 3.times { @grid[row_index] << Cell.new }
698
+ end
699
+ end
700
+
701
+ def row_win?
702
+ (1..3).each do |row|
703
+ if row_has_same_sign(row)
704
+ @winning_sign = self[row, 1].sign
705
+ return true
706
+ end
707
+ end
708
+ false
709
+ end
710
+
711
+ def column_win?
712
+ (1..3).each do |column|
713
+ if column_has_same_sign(column)
714
+ @winning_sign = self[1, column].sign
715
+ return true
716
+ end
717
+ end
718
+ false
719
+ end
720
+
721
+ #needs refactoring if we ever decide to make the board size dynamic
722
+ def diagonal_win?
723
+ if (self[1, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[3, 3].sign) and self[1, 1].marked
724
+ @winning_sign = self[1, 1].sign
725
+ return true
726
+ end
727
+ if (self[3, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[1, 3].sign) and self[3, 1].marked
728
+ @winning_sign = self[3, 1].sign
729
+ return true
730
+ end
731
+ false
732
+ end
733
+
734
+ def draw?
735
+ @board_full = true
736
+ 3.times do |x|
737
+ 3.times do |y|
738
+ @board_full = false if self[x, y].empty
739
+ end
740
+ end
741
+ self.game_status = DRAW if @board_full
742
+ @board_full
743
+ end
744
+
745
+ def row_has_same_sign(number)
746
+ row_sign = self[number, 1].sign
747
+ [2, 3].each do |column|
748
+ return false unless row_sign == (self[number, column].sign)
749
+ end
750
+ true if self[number, 1].marked
751
+ end
752
+
753
+ def column_has_same_sign(number)
754
+ column_sign = self[1, number].sign
755
+ [2, 3].each do |row|
756
+ return false unless column_sign == (self[row, number].sign)
757
+ end
758
+ true if self[1, number].marked
759
+ end
760
+
761
+ end
762
+ end
763
+
764
+ class TicTacToe
765
+ include Glimmer
766
+
767
+ def initialize
768
+ @tic_tac_toe_board = Board.new
769
+ @shell = shell {
770
+ text "Tic-Tac-Toe"
771
+ composite {
772
+ grid_layout 3, true
773
+ (1..3).each { |row|
774
+ (1..3).each { |column|
775
+ button {
776
+ layout_data :fill, :fill, true, true
777
+ text bind(@tic_tac_toe_board[row, column], :sign)
778
+ enabled bind(@tic_tac_toe_board[row, column], :empty)
779
+ on_widget_selected {
780
+ @tic_tac_toe_board.mark(row, column)
781
+ }
782
+ }
783
+ }
784
+ }
785
+ }
786
+ }
787
+ observe(@tic_tac_toe_board, :game_status) { |game_status|
788
+ display_win_message if game_status == Board::WIN
789
+ display_draw_message if game_status == Board::DRAW
790
+ }
791
+ end
792
+
793
+ def display_win_message
794
+ display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
795
+ end
796
+
797
+ def display_draw_message
798
+ display_game_over_message("Draw!")
799
+ end
800
+
801
+ def display_game_over_message(message_text)
802
+ message_box(@shell) {
803
+ text 'Game Over'
804
+ message message_text
805
+ }.open
806
+ @tic_tac_toe_board.reset
807
+ end
808
+
809
+ def open
810
+ @shell.open
811
+ end
812
+ end
813
+
814
+ TicTacToe.new.open
815
+ ```
816
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
817
+
818
+ ![Glimmer DSL for SWT Tic Tac Toe](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-tic-tac-toe.png)
819
+ ![Glimmer DSL for SWT Tic Tac Toe In Progress](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-tic-tac-toe-in-progress.png)
820
+ ![Glimmer DSL for SWT Tic Tac Toe Game Over](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-tic-tac-toe-game-over.png)
821
+
822
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
823
+
824
+ Start the Rails server:
825
+ ```
826
+ rails s
827
+ ```
828
+
829
+ Visit `http://localhost:3000`
830
+
831
+ You should see "Tic Tac Toe"
832
+
833
+ ![Glimmer DSL for Opal Tic Tac Toe](images/glimmer-dsl-opal-tic-tac-toe.png)
834
+ ![Glimmer DSL for Opal Tic Tac Toe In Progress](images/glimmer-dsl-opal-tic-tac-toe-in-progress.png)
835
+ ![Glimmer DSL for Opal Tic Tac Toe Game Over](images/glimmer-dsl-opal-tic-tac-toe-game-over.png)
836
+
483
837
  ## Help
484
838
 
485
839
  ### Issues
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.6
1
+ 0.0.7
@@ -1,5 +1,5 @@
1
1
  require 'opal'
2
- require 'opal-parser'
2
+ require 'opal-async'
3
3
  require 'glimmer'
4
4
 
5
5
  GLIMMER_DSL_OPAL_ROOT = File.expand_path('../..', __FILE__)
@@ -7,4 +7,5 @@ GLIMMER_DSL_OPAL_LIB = File.join(GLIMMER_DSL_OPAL_ROOT, 'lib')
7
7
 
8
8
  $LOAD_PATH.unshift(GLIMMER_DSL_OPAL_LIB)
9
9
 
10
- require 'glimmer/dsl/opal/dsl'
10
+ require 'glimmer/dsl/opal/dsl'
11
+ require 'glimmer/data_binding/ext/observable_model'
@@ -0,0 +1,40 @@
1
+ require 'glimmer/data_binding/observable'
2
+ require 'glimmer/data_binding/observer'
3
+ require 'glimmer/opal/display_proxy'
4
+
5
+ # This ensures all data-binding events happen async and block on modal display
6
+
7
+ module Glimmer
8
+ module DataBinding
9
+ # TODO prefix utility methods with double-underscore
10
+ module ObservableModel
11
+ include Observable
12
+ include Glimmer
13
+
14
+ def add_property_writer_observers(property_name)
15
+ property_writer_name = "#{property_name}="
16
+ method(property_writer_name)
17
+ ensure_array_object_observer(property_name, send(property_name))
18
+ begin
19
+ method("__original_#{property_writer_name}")
20
+ rescue
21
+ old_method = self.class.instance_method(property_writer_name)
22
+ define_singleton_method("__original_#{property_writer_name}", old_method)
23
+ define_singleton_method(property_writer_name) do |value|
24
+ old_value = self.send(property_name)
25
+ unregister_dependent_observers(property_name, old_value)
26
+ self.send("__original_#{property_writer_name}", value)
27
+ Glimmer::Opal::DisplayProxy.instance.async_exec do
28
+ notify_observers(property_name)
29
+ ensure_array_object_observer(property_name, value, old_value)
30
+ end
31
+ end
32
+ end
33
+ rescue => e
34
+ # ignore writing if no property writer exists
35
+ Glimmer::Config.logger&.debug "No need to observe property writer: #{property_writer_name}\n#{e.message}\n#{e.backtrace.join("\n")}"
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/top_level_expression'
3
+ require 'glimmer/opal/display_proxy'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Opal
8
+ class AsyncExecExpression < StaticExpression
9
+ include TopLevelExpression
10
+
11
+ def interpret(parent, keyword, *args, &block)
12
+ Glimmer::Opal::DisplayProxy.instance.async_exec(&block)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -19,6 +19,9 @@ require 'glimmer/dsl/opal/list_expression'
19
19
  require 'glimmer/dsl/opal/browser_expression'
20
20
  require 'glimmer/dsl/opal/tab_folder_expression'
21
21
  require 'glimmer/dsl/opal/tab_item_expression'
22
+ require 'glimmer/dsl/opal/message_box_expression'
23
+ require 'glimmer/dsl/opal/async_exec_expression'
24
+ require 'glimmer/dsl/opal/observe_expression'
22
25
  require 'glimmer/dsl/opal/layout_data_expression'
23
26
  require 'glimmer/dsl/opal/list_selection_data_binding_expression'
24
27
 
@@ -0,0 +1,20 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/top_level_expression'
3
+ require 'glimmer/dsl/parent_expression'
4
+ require 'glimmer/opal/modal'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module Opal
9
+ class MessageBoxExpression < StaticExpression
10
+ include TopLevelExpression
11
+ include ParentExpression
12
+
13
+ def interpret(parent, keyword, *args, &block)
14
+ parent = args.delete_at(0)
15
+ Glimmer::Opal::Modal.new(parent, args)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/top_level_expression'
3
+ require 'glimmer/data_binding/observer'
4
+ require 'glimmer/data_binding/model_binding'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module Opal
9
+ class ObserveExpression < StaticExpression
10
+ include TopLevelExpression
11
+
12
+ REGEX_NESTED_OR_INDEXED_PROPERTY = /([^\[]+)(\[[^\]]+\])?/
13
+
14
+ def can_interpret?(parent, keyword, *args, &block)
15
+ keyword == 'observe' and
16
+ block_given? and
17
+ (args.size == 2) and
18
+ textual?(args[1])
19
+ end
20
+
21
+ def interpret(parent, keyword, *args, &block)
22
+ observer = DataBinding::Observer.proc(&block)
23
+ if args[1].to_s.match(REGEX_NESTED_OR_INDEXED_PROPERTY)
24
+ observer.observe(DataBinding::ModelBinding.new(args[0], args[1]))
25
+ else
26
+ observer.observe(args[0], args[1])
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ module Glimmer
2
+ module Opal
3
+ class DisplayProxy
4
+ class << self
5
+ def instance
6
+ @instance ||= new
7
+ end
8
+ end
9
+
10
+ def async_exec(&block)
11
+ executer = lambda do
12
+ if $document.at_css('.modal')
13
+ sleep(0.05)
14
+ Async::Task.new(&executer)
15
+ else
16
+ block.call
17
+ end
18
+ end
19
+ Async::Task.new(&executer)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -104,6 +104,56 @@ module Glimmer
104
104
  .hide {
105
105
  display: none !important;
106
106
  }
107
+
108
+ /* The Modal (background) */
109
+ .modal {
110
+ position: fixed; /* Stay in place */
111
+ z-index: 1; /* Sit on top */
112
+ padding-top: 100px; /* Location of the box */
113
+ left: 0;
114
+ top: 0;
115
+ width: 100%; /* Full width */
116
+ height: 100%; /* Full height */
117
+ overflow: auto; /* Enable scroll if needed */
118
+ background-color: rgb(0,0,0); /* Fallback color */
119
+ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
120
+ text-align: center;
121
+ }
122
+
123
+ /* Modal Content */
124
+ .modal-content {
125
+ background-color: #fefefe;
126
+ margin: auto;
127
+ border: 1px solid #888;
128
+ display: inline-block;
129
+ min-width: 200px;
130
+ }
131
+
132
+ .modal-content .text {
133
+ background: rgb(80, 116, 211);
134
+ color: white;
135
+ padding: 5px;
136
+ }
137
+
138
+ .modal-content .message {
139
+ padding: 20px;
140
+ }
141
+
142
+ /* The Close Button */
143
+ .close {
144
+ color: #aaaaaa;
145
+ float: right;
146
+ # font-size: 18px;
147
+ font-weight: bold;
148
+ margin: 5px;
149
+ }
150
+
151
+ .close:hover,
152
+ .close:focus {
153
+ color: #000;
154
+ text-decoration: none;
155
+ cursor: pointer;
156
+ }
107
157
  </style>
108
158
  CSS
109
159
  }
@@ -5,7 +5,7 @@ module Glimmer
5
5
  class ElementProxy
6
6
  include Glimmer
7
7
  include PropertyOwner
8
- attr_reader :parent, :args, :css_classes, :css, :children
8
+ attr_reader :parent, :args, :css_classes, :css, :children, :enabled
9
9
 
10
10
  def initialize(parent, args)
11
11
  @parent = parent
@@ -13,14 +13,20 @@ module Glimmer
13
13
  @children = Set.new
14
14
  @css_classes = Set.new
15
15
  @css = ''
16
+ @enabled = true
16
17
  @parent.add_child(self)
17
18
  end
18
19
 
19
20
  def add_child(child)
20
- # return if @children.include?(child)
21
+ # return if @children.include?(child) # TODO consider adding an option to enable this if needed to prevent dom repetition
21
22
  @children << child
22
23
  dom << child.dom
23
24
  end
25
+
26
+ def enabled=(value)
27
+ @enabled = value
28
+ redraw
29
+ end
24
30
 
25
31
  def redraw
26
32
  if @dom
@@ -189,7 +195,7 @@ module Glimmer
189
195
  # },
190
196
  InputProxy => {
191
197
  :text => lambda do |observer|
192
- on_modify_text { |modify_event|
198
+ on_modify_text { |modify_event|
193
199
  observer.call(text)
194
200
  }
195
201
  end,
@@ -10,8 +10,9 @@ module Glimmer
10
10
  @parent = parent
11
11
  @args = args
12
12
  @parent.add_css_class('grid-layout')
13
+ @horizontal_spacing = 10
13
14
  @vertical_spacing = 10
14
- @num_columns = 1
15
+ @num_columns = @args.first || 1
15
16
  reapply
16
17
  end
17
18
 
@@ -19,8 +19,10 @@ module Glimmer
19
19
  event: 'keyup',
20
20
  event_handler: -> (event_listener) {
21
21
  -> (event) {
22
- @text = event.target.value
23
- event_listener.call(event)
22
+ if args.last[:type] == 'text'
23
+ @text = event.target.value
24
+ event_listener.call(event)
25
+ end
24
26
  }
25
27
  }
26
28
  }
@@ -32,8 +34,10 @@ module Glimmer
32
34
  input_id = id
33
35
  input_style = css
34
36
  input_args = @args.last
37
+ input_disabled = @enabled ? {} : {'disabled': 'disabled'}
38
+ input_args = input_args.merge(type: 'password') if has_style?(:password)
35
39
  @dom ||= DOM {
36
- input input_args.merge(id: input_id, style: input_style, value: input_text)
40
+ input input_args.merge(id: input_id, style: input_style, value: input_text, style: 'min-width: 27px;').merge(input_disabled)
37
41
  }
38
42
  end
39
43
  end
@@ -0,0 +1,94 @@
1
+ require 'glimmer/opal/element_proxy'
2
+
3
+ module Glimmer
4
+ module Opal
5
+ class Modal < ElementProxy
6
+ attr_reader :text, :message
7
+
8
+ def initialize(parent, args)
9
+ i = 0
10
+ @parent = parent
11
+ @args = args
12
+ @children = Set.new
13
+ @css_classes = Set.new(['modal'])
14
+ @css = ''
15
+ @enabled = true
16
+ content do
17
+ on_widget_selected {
18
+ hide
19
+ }
20
+ end
21
+ end
22
+
23
+ def text=(txt)
24
+ @text = txt
25
+ redraw if @dom
26
+ end
27
+
28
+ def message=(msg)
29
+ @message = msg
30
+ redraw if @dom
31
+ end
32
+
33
+ def document
34
+ element = self
35
+ begin
36
+ element = element.parent
37
+ end while(element.parent)
38
+ element
39
+ end
40
+
41
+ def open
42
+ document.add_child(self)
43
+ end
44
+
45
+ def hide
46
+ dom.remove
47
+ end
48
+
49
+ def content(&block)
50
+ Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Opal::MessageBoxExpression.new, &block)
51
+ end
52
+
53
+ def name
54
+ 'div'
55
+ end
56
+
57
+ def selector
58
+ super + ' .close'
59
+ end
60
+
61
+ def observation_request_to_event_mapping
62
+ {
63
+ 'on_widget_selected' => {
64
+ event: 'click'
65
+ },
66
+ }
67
+ end
68
+
69
+ def dom
70
+ modal_id = id
71
+ modal_style = css
72
+ modal_text = text
73
+ modal_message = message
74
+ modal_css_classes = css_classes
75
+ modal_class = modal_css_classes.to_a.join(' ')
76
+ @dom ||= DOM {
77
+ div(id: modal_id, style: modal_style, class: modal_class) {
78
+ div(class: 'modal-content') {
79
+ header.text {
80
+ modal_text
81
+ }
82
+ p.message {
83
+ modal_message
84
+ }
85
+ input(type: 'button', class: 'close', autofocus: 'autofocus', value: 'OK')
86
+ }
87
+ }
88
+ }
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ require 'glimmer/dsl/opal/message_box_expression'
@@ -1,4 +1,3 @@
1
- require "java"
2
1
  require "observer"
3
2
 
4
3
  #Presents login screen data
@@ -37,11 +37,11 @@ class TicTacToe
37
37
  display_game_over_message("Draw!")
38
38
  end
39
39
 
40
- def display_game_over_message(message)
41
- message_box = MessageBox.new(@shell.swt_widget)
42
- message_box.setText("Game Over")
43
- message_box.setMessage(message)
44
- message_box.open
40
+ def display_game_over_message(message_text)
41
+ message_box(@shell) {
42
+ text 'Game Over'
43
+ message message_text
44
+ }.open
45
45
  @tic_tac_toe_board.reset
46
46
  end
47
47
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-opal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-19 00:00:00.000000000 Z
11
+ date: 2020-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -170,11 +170,13 @@ files:
170
170
  - lib/glimmer-dsl-opal.rb
171
171
  - lib/glimmer/config.rb
172
172
  - lib/glimmer/data_binding/element_binding.rb
173
+ - lib/glimmer/data_binding/ext/observable_model.rb
173
174
  - lib/glimmer/data_binding/list_selection_binding.rb
174
175
  - lib/glimmer/data_binding/observable_element.rb
175
176
  - lib/glimmer/dsl/engine.rb
176
177
  - lib/glimmer/dsl/expression.rb
177
178
  - lib/glimmer/dsl/expression_handler.rb
179
+ - lib/glimmer/dsl/opal/async_exec_expression.rb
178
180
  - lib/glimmer/dsl/opal/bind_expression.rb
179
181
  - lib/glimmer/dsl/opal/browser_expression.rb
180
182
  - lib/glimmer/dsl/opal/button_expression.rb
@@ -188,6 +190,8 @@ files:
188
190
  - lib/glimmer/dsl/opal/layout_data_expression.rb
189
191
  - lib/glimmer/dsl/opal/list_expression.rb
190
192
  - lib/glimmer/dsl/opal/list_selection_data_binding_expression.rb
193
+ - lib/glimmer/dsl/opal/message_box_expression.rb
194
+ - lib/glimmer/dsl/opal/observe_expression.rb
191
195
  - lib/glimmer/dsl/opal/property_expression.rb
192
196
  - lib/glimmer/dsl/opal/shell_expression.rb
193
197
  - lib/glimmer/dsl/opal/tab_folder_expression.rb
@@ -199,6 +203,7 @@ files:
199
203
  - lib/glimmer/dsl/top_level_expression.rb
200
204
  - lib/glimmer/error.rb
201
205
  - lib/glimmer/invalid_keyword_error.rb
206
+ - lib/glimmer/opal/display_proxy.rb
202
207
  - lib/glimmer/opal/div_proxy.rb
203
208
  - lib/glimmer/opal/document_proxy.rb
204
209
  - lib/glimmer/opal/element_proxy.rb
@@ -209,6 +214,7 @@ files:
209
214
  - lib/glimmer/opal/label_proxy.rb
210
215
  - lib/glimmer/opal/layout_data_proxy.rb
211
216
  - lib/glimmer/opal/list_proxy.rb
217
+ - lib/glimmer/opal/modal.rb
212
218
  - lib/glimmer/opal/point.rb
213
219
  - lib/glimmer/opal/property_owner.rb
214
220
  - lib/glimmer/opal/select_proxy.rb