glimmer-dsl-opal 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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