glimmer-dsl-opal 0.2.0 → 0.3.0

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: 4149153253dd59829bf590c406ff2e5b18c11a62cbbaf7130877f2046a04d2a1
4
- data.tar.gz: f82f4d9c0bff2625f1f4ef8bef4be2703789a72aed847d4c851697d916cf48c4
3
+ metadata.gz: 321f0f4121858de374edacf81772b65ff3bd0ee1e155531b5a04681c1e7f5fa0
4
+ data.tar.gz: 5bfab859f5b96458ca452444253a8fb1fefe5274e2bdbc892e574ab6fcd74ed0
5
5
  SHA512:
6
- metadata.gz: 202c4686ab1a2bf31377cbe4ee6f173c92318460e0758cb74356132323c571b381f3bd69d0d47933ac44c54a79fd24520ce7c2e1ffa1412db903ae2c27ce259b
7
- data.tar.gz: 182085ad652639b3d83b9853bf993702839cb8066074b92e5377b5b8aa1998d659d925ef0d1f5cac0c659241bd97cf7fe109d2008142e0f5b34165f49e93bc67
6
+ metadata.gz: 58ee88fda2ed5729f1c3b58035d6aa252fbb23ac2a12b120e88040aa485d7e34bf9f337c1a8e6f289c73c23528aec4dd735a00c0542c4c120c9499141815cc38
7
+ data.tar.gz: d70d728a4beb4ff5bff63c68b823155ab39b014163698fe875ffacbba09c2e18b91fc3b11fd529876857187fe7aae5e331ecf32b06f4d417a0615bd38d64877a
@@ -1,5 +1,11 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.3.0
4
+
5
+ - Support opening a custom shell in a browser tab/window by passing in query parameters to URL (e.g. ?custom_shell=keyword+option1=value1 etc...)
6
+ - Make custom shells automatically open in a new tab/window (while standard shells continue to open in the same window by replacing its content)
7
+ - Hello, Custom Shell! Sample
8
+
3
9
  ## 0.2.0
4
10
 
5
11
  - Color support
data/README.md CHANGED
@@ -1,14 +1,14 @@
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 Opal 0.2.0 (Webify Desktop Apps)
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 Opal 0.3.0 (Webify 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
 
5
- ### You can finally live in pure Ruby land even on the web!
5
+ ### You can finally live in pure Ruby land on the web!
6
6
 
7
7
  [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [Opal](https://opalrb.com/) is an experimental proof-of-concept web GUI adapter for [Glimmer](https://github.com/AndyObtiva/glimmer) desktop apps (i.e. apps built with [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt)). It webifies them via [Rails](https://rubyonrails.org/), allowing Ruby desktop apps to run on the web via [Opal Ruby](https://opalrb.com/) without changing a line of code. Apps may then be custom-styled for the web with standard CSS by web designers.
8
8
 
9
- Glimmer DSL for Opal webifier successfully reuses the entire [Glimmer](https://github.com/AndyObtiva/glimmer) core DSL engine in [Opal Ruby](https://opalrb.com/) inside a web browser, and as such inherits the full range of powerful Glimmer desktop [data-binding](https://github.com/AndyObtiva/glimmer#data-binding) capabilities for the web.
9
+ Glimmer DSL for Opal successfully reuses the entire [Glimmer](https://github.com/AndyObtiva/glimmer) core DSL engine in [Opal Ruby](https://opalrb.com/) inside a web browser, and as such inherits the full range of powerful Glimmer desktop [data-binding](https://github.com/AndyObtiva/glimmer#data-binding) capabilities for the web.
10
10
 
11
- NOTE: Alpha Version 0.2.0 only supports bare-minimum capabilities for the following [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) [samples](https://github.com/AndyObtiva/glimmer#samples):
11
+ NOTE: Alpha Version 0.3.0 only supports bare-minimum capabilities for the following [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) [samples](https://github.com/AndyObtiva/glimmer#samples):
12
12
  - [Hello, World!](#hello-world)
13
13
  - [Hello, Combo!](#hello-combo)
14
14
  - [Hello, Computed!](#hello-computed)
@@ -17,6 +17,7 @@ NOTE: Alpha Version 0.2.0 only supports bare-minimum capabilities for the follow
17
17
  - [Hello, Browser!](#hello-browser)
18
18
  - [Hello, Tab!](#hello-tab)
19
19
  - [Hello, Custom Widget!](#hello-custom-widget)
20
+ - [Hello, Custom Shell!](#hello-custom-shell)
20
21
  - [Login](#login)
21
22
  - [Tic Tac Toe](#tic-tac-toe)
22
23
  - [Contact Manager](#contact-manager)
@@ -44,10 +45,8 @@ Widgets:
44
45
  - `table`
45
46
  - `table_column`
46
47
  - `message_box`
47
-
48
- Graphics:
49
- - `color`
50
- - `font`
48
+ - CustomWidget (ability to define any keyword as a custom widget)
49
+ - CustomShell (ability to define any keyword as a custom shell (aka custom window) that opens in a new browser window)
51
50
 
52
51
  Layouts:
53
52
  - `grid_layout`
@@ -55,6 +54,10 @@ Layouts:
55
54
  - `fill_layout`
56
55
  - `layout_data`
57
56
 
57
+ Graphics:
58
+ - `color`
59
+ - `font`
60
+
58
61
  Data-Binding/Observers:
59
62
  - `bind`
60
63
  - `observe`
@@ -86,11 +89,11 @@ Add the following to `Gemfile`:
86
89
 
87
90
  ```
88
91
  gem 'opal-rails', '~> 1.1.2'
89
- gem 'opal-async', '~> 1.1.1'
92
+ gem 'opal-async', '~> 1.2.0'
90
93
  gem 'opal-jquery', '~> 0.4.4'
91
- gem 'glimmer-dsl-opal', '~> 0.2.0', require: false
92
- gem 'glimmer-dsl-xml', '~> 1.0.0', require: false
93
- gem 'glimmer-dsl-css', '~> 1.0.0', require: false
94
+ gem 'glimmer-dsl-opal', '~> 0.3.0', require: false
95
+ gem 'glimmer-dsl-xml', '~> 1.1.0', require: false
96
+ gem 'glimmer-dsl-css', '~> 1.1.0', require: false
94
97
 
95
98
  ```
96
99
 
@@ -688,6 +691,175 @@ You should see "Hello, Custom Widget!"
688
691
 
689
692
  ![Glimmer DSL for Opal Hello Custom Widget](images/glimmer-dsl-opal-hello-custom-widget.gif)
690
693
 
694
+ #### Hello, Custom Shell!
695
+
696
+ Add the following require statement to `app/assets/javascripts/application.rb`
697
+
698
+ ```ruby
699
+ require 'glimmer-dsl-opal/samples/hello/hello_custom_shell'
700
+ ```
701
+
702
+ Or add the Glimmer code directly if you prefer to play around with it:
703
+
704
+ ```ruby
705
+ require 'date'
706
+
707
+ # This class declares an `email_shell` custom shell, aka custom window (by convention)
708
+ # Used to view an email message
709
+ class EmailShell
710
+ include Glimmer::UI::CustomShell
711
+
712
+ # multiple options without default values
713
+ options :date, :subject, :from, :message
714
+
715
+ # single option with default value
716
+ option :to, default: '"John Irwin" <john.irwin@example.com>'
717
+
718
+ before_body {
719
+ @swt_style |= swt(:shell_trim, :modeless)
720
+ }
721
+
722
+ body {
723
+ # pass received swt_style through to shell to customize it (e.g. :dialog_trim for a blocking shell)
724
+ shell(swt_style) {
725
+ grid_layout(2, false)
726
+
727
+ text subject
728
+
729
+ label {
730
+ text 'Date:'
731
+ }
732
+ label {
733
+ text date
734
+ }
735
+
736
+ label {
737
+ text 'From:'
738
+ }
739
+ label {
740
+ text from
741
+ }
742
+
743
+ label {
744
+ text 'To:'
745
+ }
746
+ label {
747
+ text to
748
+ }
749
+
750
+ label {
751
+ text 'Subject:'
752
+ }
753
+ label {
754
+ text subject
755
+ }
756
+
757
+ label {
758
+ layout_data(:fill, :fill, true, true) {
759
+ horizontal_span 2 #TODO implement
760
+ vertical_indent 10
761
+ }
762
+
763
+ background :white
764
+ text message
765
+ }
766
+ }
767
+ }
768
+
769
+ end
770
+
771
+ class HelloCustomShell
772
+ # including Glimmer enables the Glimmer DSL syntax, including auto-discovery of the `email_shell` custom widget
773
+ include Glimmer
774
+
775
+ Email = Struct.new(:date, :subject, :from, :message, keyword_init: true)
776
+ EmailSystem = Struct.new(:emails, keyword_init: true)
777
+
778
+ def initialize
779
+ @email_system = EmailSystem.new(
780
+ emails: [
781
+ Email.new(date: DateTime.new(2029, 10, 22, 11, 3, 0).strftime('%F %I:%M %p'), subject: '3rd Week Report', from: '"Dianne Tux" <dianne.tux@example.com>', message: "Hello,\n\nI was wondering if you'd like to go over the weekly report sometime this afternoon.\n\nDianne"),
782
+ Email.new(date: DateTime.new(2029, 10, 21, 8, 1, 0).strftime('%F %I:%M %p'), subject: 'Glimmer Upgrade v100.0', from: '"Robert McGabbins" <robert.mcgabbins@example.com>', message: "Team,\n\nWe are upgrading to Glimmer version 100.0.\n\nEveryone pull the latest code!\n\nRegards,\n\nRobert McGabbins"),
783
+ Email.new(date: DateTime.new(2029, 10, 19, 16, 58, 0).strftime('%F %I:%M %p'), subject: 'Christmas Party', from: '"Lisa Ferreira" <lisa.ferreira@example.com>', message: "Merry Christmas,\n\nAll office Christmas Party arrangements have been set\n\nMake sure to bring a Secret Santa gift\n\nBest regards,\n\nLisa Ferreira"),
784
+ Email.new(date: DateTime.new(2029, 10, 16, 9, 43, 0).strftime('%F %I:%M %p'), subject: 'Glimmer Upgrade v99.0', from: '"Robert McGabbins" <robert.mcgabbins@example.com>', message: "Team,\n\nWe are upgrading to Glimmer version 99.0.\n\nEveryone pull the latest code!\n\nRegards,\n\nRobert McGabbins"),
785
+ Email.new(date: DateTime.new(2029, 10, 15, 11, 2, 0).strftime('%F %I:%M %p'), subject: '2nd Week Report', from: '"Dianne Tux" <dianne.tux@example.com>', message: "Hello,\n\nI was wondering if you'd like to go over the weekly report sometime this afternoon.\n\nDianne"),
786
+ Email.new(date: DateTime.new(2029, 10, 2, 10, 34, 0).strftime('%F %I:%M %p'), subject: 'Glimmer Upgrade v98.0', from: '"Robert McGabbins" <robert.mcgabbins@example.com>', message: "Team,\n\nWe are upgrading to Glimmer version 98.0.\n\nEveryone pull the latest code!\n\nRegards,\n\nRobert McGabbins"),
787
+ ]
788
+ )
789
+ end
790
+
791
+ def launch
792
+ shell {
793
+ grid_layout
794
+
795
+ text 'Hello, Custom Shell!'
796
+
797
+ label {
798
+ font height: 24, style: :bold
799
+ text 'Emails:'
800
+ }
801
+
802
+ label {
803
+ font height: 18
804
+ text 'Click an email to view its message'
805
+ }
806
+
807
+ table {
808
+ layout_data :fill, :fill, true, true
809
+
810
+ table_column {
811
+ text 'Date:'
812
+ width 180
813
+ }
814
+ table_column {
815
+ text 'Subject:'
816
+ width 180
817
+ }
818
+ table_column {
819
+ text 'From:'
820
+ width 360
821
+ }
822
+
823
+ items bind(@email_system, :emails), column_properties(:date, :subject, :from)
824
+
825
+ on_mouse_up { |event|
826
+ email = event.table_item.get_data
827
+ Thread.new do
828
+ async_exec {
829
+ email_shell(date: email.date, subject: email.subject, from: email.from, message: email.message).open
830
+ }
831
+ end
832
+ }
833
+ }
834
+ }.open
835
+ end
836
+ end
837
+
838
+ HelloCustomShell.new.launch
839
+ ```
840
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
841
+
842
+ ![Glimmer DSL for SWT Hello Custom Shell](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-custom-shell.png)
843
+ ![Glimmer DSL for SWT Hello Custom Shell Email1](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-custom-shell-email1.png)
844
+ ![Glimmer DSL for SWT Hello Custom Shell Email2](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-custom-shell-email2.png)
845
+ ![Glimmer DSL for SWT Hello Custom Shell Email3](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-custom-shell-email3.png)
846
+
847
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
848
+
849
+ Start the Rails server:
850
+ ```
851
+ rails s
852
+ ```
853
+
854
+ Visit `http://localhost:3000`
855
+
856
+ You should see "Hello, Custom Widget!"
857
+
858
+ ![Glimmer DSL for Opal Hello Custom Shell](images/glimmer-dsl-opal-hello-custom-shell.png)
859
+ ![Glimmer DSL for Opal Hello Custom Shell Email1](images/glimmer-dsl-opal-hello-custom-shell-email1.png)
860
+ ![Glimmer DSL for Opal Hello Custom Shell Email2](images/glimmer-dsl-opal-hello-custom-shell-email2.png)
861
+ ![Glimmer DSL for Opal Hello Custom Shell Email3](images/glimmer-dsl-opal-hello-custom-shell-email3.png)
862
+
691
863
  ### Elaborate Samples
692
864
 
693
865
  #### Login
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
@@ -8,6 +8,7 @@ if RUBY_PLATFORM == 'opal'
8
8
  $LOAD_PATH.unshift(GLIMMER_DSL_OPAL_LIB)
9
9
  $LOAD_PATH.unshift(GLIMMER_DSL_OPAL_MISSING) # missing Ruby classes/methods
10
10
 
11
+ require 'opal-parser'
11
12
  require 'native' # move this to opal-async
12
13
  require 'opal-async'
13
14
  require 'async/ext'
@@ -16,6 +17,8 @@ if RUBY_PLATFORM == 'opal'
16
17
  require 'glimmer'
17
18
  require 'facets/hash/symbolize_keys'
18
19
  require 'glimmer-dsl-opal/ext/exception'
20
+ require 'glimmer-dsl-opal/ext/date'
21
+ require 'glimmer-dsl-opal/missing/uri'
19
22
 
20
23
  # Spiking async logging
21
24
  # logger = Glimmer::Config.logger
@@ -0,0 +1,13 @@
1
+ require 'date'
2
+ require 'time'
3
+
4
+ class DateTime < Date
5
+ def initialize(*args, &block)
6
+ @time = Time.new(*args, &block)
7
+ @time.methods.each do |method|
8
+ singleton_class.define_method(method) do |*args, &block|
9
+ @time.send(method, *args, &block)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -16,9 +16,47 @@ module URI
16
16
 
17
17
  def to_s
18
18
  url
19
+ end
20
+ end
21
+
22
+ TBLENCWWWCOMP_ = {"\u0000"=>"%00", "\u0001"=>"%01", "\u0002"=>"%02", "\u0003"=>"%03", "\u0004"=>"%04", "\u0005"=>"%05", "\u0006"=>"%06", "\a"=>"%07", "\b"=>"%08", "\t"=>"%09", "\n"=>"%0A", "\v"=>"%0B", "\f"=>"%0C", "\r"=>"%0D", "\u000E"=>"%0E", "\u000F"=>"%0F", "\u0010"=>"%10", "\u0011"=>"%11", "\u0012"=>"%12", "\u0013"=>"%13", "\u0014"=>"%14", "\u0015"=>"%15", "\u0016"=>"%16", "\u0017"=>"%17", "\u0018"=>"%18", "\u0019"=>"%19", "\u001A"=>"%1A", "\e"=>"%1B", "\u001C"=>"%1C", "\u001D"=>"%1D", "\u001E"=>"%1E", "\u001F"=>"%1F", " "=>"+", "!"=>"%21", "\""=>"%22", "#"=>"%23", "$"=>"%24", "%"=>"%25", "&"=>"%26", "'"=>"%27", "("=>"%28", ")"=>"%29", "*"=>"%2A", "+"=>"%2B", ","=>"%2C", "-"=>"%2D", "."=>"%2E", "/"=>"%2F", "0"=>"%30", "1"=>"%31", "2"=>"%32", "3"=>"%33", "4"=>"%34", "5"=>"%35", "6"=>"%36", "7"=>"%37", "8"=>"%38", "9"=>"%39", ":"=>"%3A", ";"=>"%3B", "<"=>"%3C", "="=>"%3D", ">"=>"%3E", "?"=>"%3F", "@"=>"%40", "A"=>"%41", "B"=>"%42", "C"=>"%43", "D"=>"%44", "E"=>"%45", "F"=>"%46", "G"=>"%47", "H"=>"%48", "I"=>"%49", "J"=>"%4A", "K"=>"%4B", "L"=>"%4C", "M"=>"%4D", "N"=>"%4E", "O"=>"%4F", "P"=>"%50", "Q"=>"%51", "R"=>"%52", "S"=>"%53", "T"=>"%54", "U"=>"%55", "V"=>"%56", "W"=>"%57", "X"=>"%58", "Y"=>"%59", "Z"=>"%5A", "["=>"%5B", "\\"=>"%5C", "]"=>"%5D", "^"=>"%5E", "_"=>"%5F", "`"=>"%60", "a"=>"%61", "b"=>"%62", "c"=>"%63", "d"=>"%64", "e"=>"%65", "f"=>"%66", "g"=>"%67", "h"=>"%68", "i"=>"%69", "j"=>"%6A", "k"=>"%6B", "l"=>"%6C", "m"=>"%6D", "n"=>"%6E", "o"=>"%6F", "p"=>"%70", "q"=>"%71", "r"=>"%72", "s"=>"%73", "t"=>"%74", "u"=>"%75", "v"=>"%76", "w"=>"%77", "x"=>"%78", "y"=>"%79", "z"=>"%7A", "{"=>"%7B", "|"=>"%7C", "}"=>"%7D", "~"=>"%7E", "\u007F"=>"%7F", "\u0080"=>"%80", "\u0081"=>"%81", "\u0082"=>"%82", "\u0083"=>"%83", "\u0084"=>"%84", "\u0085"=>"%85", "\u0086"=>"%86", "\u0087"=>"%87", "\u0088"=>"%88", "\u0089"=>"%89", "\u008A"=>"%8A", "\u008B"=>"%8B", "\u008C"=>"%8C", "\u008D"=>"%8D", "\u008E"=>"%8E", "\u008F"=>"%8F", "\u0090"=>"%90", "\u0091"=>"%91", "\u0092"=>"%92", "\u0093"=>"%93", "\u0094"=>"%94", "\u0095"=>"%95", "\u0096"=>"%96", "\u0097"=>"%97", "\u0098"=>"%98", "\u0099"=>"%99", "\u009A"=>"%9A", "\u009B"=>"%9B", "\u009C"=>"%9C", "\u009D"=>"%9D", "\u009E"=>"%9E", "\u009F"=>"%9F", "\u00A0"=>"%A0", "\u00A1"=>"%A1", "\u00A2"=>"%A2", "\u00A3"=>"%A3", "\u00A4"=>"%A4", "\u00A5"=>"%A5", "\u00A6"=>"%A6", "\u00A7"=>"%A7", "\u00A8"=>"%A8", "\u00A9"=>"%A9", "\u00AA"=>"%AA", "\u00AB"=>"%AB", "\u00AC"=>"%AC", "\u00AD"=>"%AD", "\u00AE"=>"%AE", "\u00AF"=>"%AF", "\u00B0"=>"%B0", "\u00B1"=>"%B1", "\u00B2"=>"%B2", "\u00B3"=>"%B3", "\u00B4"=>"%B4", "\u00B5"=>"%B5", "\u00B6"=>"%B6", "\u00B7"=>"%B7", "\u00B8"=>"%B8", "\u00B9"=>"%B9", "\u00BA"=>"%BA", "\u00BB"=>"%BB", "\u00BC"=>"%BC", "\u00BD"=>"%BD", "\u00BE"=>"%BE", "\u00BF"=>"%BF", "\u00C0"=>"%C0", "\u00C1"=>"%C1", "\u00C2"=>"%C2", "\u00C3"=>"%C3", "\u00C4"=>"%C4", "\u00C5"=>"%C5", "\u00C6"=>"%C6", "\u00C7"=>"%C7", "\u00C8"=>"%C8", "\u00C9"=>"%C9", "\u00CA"=>"%CA", "\u00CB"=>"%CB", "\u00CC"=>"%CC", "\u00CD"=>"%CD", "\u00CE"=>"%CE", "\u00CF"=>"%CF", "\u00D0"=>"%D0", "\u00D1"=>"%D1", "\u00D2"=>"%D2", "\u00D3"=>"%D3", "\u00D4"=>"%D4", "\u00D5"=>"%D5", "\u00D6"=>"%D6", "\u00D7"=>"%D7", "\u00D8"=>"%D8", "\u00D9"=>"%D9", "\u00DA"=>"%DA", "\u00DB"=>"%DB", "\u00DC"=>"%DC", "\u00DD"=>"%DD", "\u00DE"=>"%DE", "\u00DF"=>"%DF", "\u00E0"=>"%E0", "\u00E1"=>"%E1", "\u00E2"=>"%E2", "\u00E3"=>"%E3", "\u00E4"=>"%E4", "\u00E5"=>"%E5", "\u00E6"=>"%E6", "\u00E7"=>"%E7", "\u00E8"=>"%E8", "\u00E9"=>"%E9", "\u00EA"=>"%EA", "\u00EB"=>"%EB", "\u00EC"=>"%EC", "\u00ED"=>"%ED", "\u00EE"=>"%EE", "\u00EF"=>"%EF", "\u00F0"=>"%F0", "\u00F1"=>"%F1", "\u00F2"=>"%F2", "\u00F3"=>"%F3", "\u00F4"=>"%F4", "\u00F5"=>"%F5", "\u00F6"=>"%F6", "\u00F7"=>"%F7", "\u00F8"=>"%F8", "\u00F9"=>"%F9", "\u00FA"=>"%FA", "\u00FB"=>"%FB", "\u00FC"=>"%FC", "\u00FD"=>"%FD", "\u00FE"=>"%FE", "\u00FF"=>"%FF"}.freeze
23
+ TBLDECWWWCOMP_ = TBLENCWWWCOMP_.invert.freeze
24
+
25
+ # Encodes given +str+ to URL-encoded form data.
26
+ #
27
+ # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
28
+ # (ASCII space) to + and converts others to %XX.
29
+ #
30
+ # If +enc+ is given, convert +str+ to the encoding before percent encoding.
31
+ #
32
+ # This is an implementation of
33
+ # https://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data.
34
+ #
35
+ # See URI.decode_www_form_component, URI.encode_www_form.
36
+ def self.encode_www_form_component(str, enc=nil)
37
+ str = str.to_s.dup
38
+ if str.encoding != Encoding::ASCII_8BIT
39
+ if enc && enc != Encoding::ASCII_8BIT
40
+ str.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace)
41
+ str.encode!(enc, fallback: ->(x){"&##{x.ord};"})
42
+ end
43
+ str.force_encoding(Encoding::ASCII_8BIT)
19
44
  end
45
+ str = str.gsub(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_)
46
+ str.force_encoding(Encoding::US_ASCII)
20
47
  end
48
+
49
+ # Decodes given +str+ of URL-encoded form data.
50
+ #
51
+ # This decodes + to SP.
52
+ #
53
+ # See URI.encode_www_form_component, URI.decode_www_form.
54
+ def self.decode_www_form_component(str, enc=Encoding::UTF_8)
55
+ raise ArgumentError, "invalid %-encoding (#{str})" if /%(?![0-9a-fA-F][0-9a-fA-F])/ =~ str
56
+ str.b.gsub(/\+|%[0-9a-fA-F][0-9a-fA-F]/, TBLDECWWWCOMP_).force_encoding(enc)
57
+ end
21
58
  end
59
+
22
60
  module Kernel
23
61
  def URI(url)
24
62
  URI::HTTP.new(url)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2020 Andy Maleh
1
+ # Copyright (c) 2020 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -73,8 +73,8 @@ class EmailShell
73
73
 
74
74
  label {
75
75
  layout_data(:fill, :fill, true, true) {
76
- horizontal_span 2
77
- verticalIndent 10
76
+ horizontal_span 2 #TODO implement
77
+ vertical_indent 10
78
78
  }
79
79
 
80
80
  background :white
@@ -39,11 +39,31 @@ module Glimmer
39
39
  end
40
40
 
41
41
  def interpret(parent, keyword, *args, &block)
42
- options = args.last.is_a?(Hash) ? args.pop : {}
43
- UI::CustomWidget.for(keyword).new(parent, *args, options, &block)
42
+ custom_widget_class = UI::CustomWidget.for(keyword)
43
+ # TODO clean code by extracting methods into CustomShell
44
+ if !Glimmer::UI::CustomShell.requested? && custom_widget_class.ancestors.include?(Glimmer::UI::CustomShell)
45
+ options = args.last.is_a?(Hash) ? args.pop : {}
46
+ options = options.merge('swt_style' => args.join(',')) unless args.join(',').empty?
47
+ params = {
48
+ 'custom_shell' => keyword
49
+ }.merge(options)
50
+ param_string = params.to_a.map {|k, v| "#{k}=#{URI.encode_www_form_component(v)}"}.join('&')
51
+ url = "#{`document.location.href`}?#{param_string}"
52
+ `window.open(#{url})`
53
+ # just a placeholder that has an open method # TODO return an actual CustomShell in the future that does the work happening above in the #open method
54
+ Struct.new(:open).new(true)
55
+ else
56
+ custom_widget_class.new(parent, *args, options, &block)
57
+ end
58
+ end
59
+
60
+ def add_content(parent, &content)
61
+ content.call(parent) if parent.is_a?(Glimmer::SWT::ShellProxy) || parent.is_a?(Glimmer::UI::CustomShell)
44
62
  end
63
+
45
64
 
46
65
  def add_content(parent, &block)
66
+ return unless parent.is_a?(Glimmer::UI::CustomWidget)
47
67
  # TODO consider avoiding source_location
48
68
  if block.source_location == parent.content&.__getobj__.source_location
49
69
  parent.content.call(parent) unless parent.content.called?
@@ -20,6 +20,7 @@ require 'glimmer/dsl/opal/color_expression'
20
20
  require 'glimmer/dsl/opal/rgb_expression'
21
21
  require 'glimmer/dsl/opal/rgba_expression'
22
22
  require 'glimmer/dsl/opal/custom_widget_expression'
23
+ require 'glimmer/dsl/opal/swt_expression'
23
24
 
24
25
  module Glimmer
25
26
  module DSL
@@ -9,7 +9,7 @@ module Glimmer
9
9
  include ParentExpression
10
10
 
11
11
  def can_interpret?(parent, keyword, *args, &block)
12
- parent.is_a?(Glimmer::SWT::CompositeProxy) &&
12
+ (parent.is_a?(Glimmer::SWT::CompositeProxy) or (parent.is_a?(Glimmer::UI::CustomWidget) and parent.body_root.is_a?(Glimmer::SWT::CompositeProxy))) and
13
13
  Glimmer::SWT::LayoutProxy.layout_exists?(keyword)
14
14
  end
15
15
 
@@ -2,6 +2,8 @@ require 'glimmer/dsl/static_expression'
2
2
  require 'glimmer/dsl/top_level_expression'
3
3
  require 'glimmer/dsl/parent_expression'
4
4
  require 'glimmer/swt/shell_proxy'
5
+ require 'glimmer/ui/custom_shell'
6
+ require 'glimmer/dsl/opal/custom_widget_expression'
5
7
 
6
8
  module Glimmer
7
9
  module DSL
@@ -11,7 +13,21 @@ module Glimmer
11
13
  include ParentExpression
12
14
 
13
15
  def interpret(parent, keyword, *args, &block)
14
- Glimmer::SWT::ShellProxy.new(*args)
16
+ if Glimmer::UI::CustomShell.requested_and_not_handled?
17
+ parameters = Glimmer::UI::CustomShell.request_parameter_string.split("&").map {|str| str.split("=")}.to_h
18
+ `history.pushState(#{parameters.merge('custom_shell_handled' => 'true')}, document.title, #{"?#{Glimmer::UI::CustomShell.encoded_request_parameter_string}&custom_shell_handled=true"})`
19
+ custom_shell_keyword = parameters.delete('custom_shell')
20
+ CustomWidgetExpression.new.interpret(nil, custom_shell_keyword, *[parameters])
21
+ `history.pushState(#{parameters.reject {|k,v| k == 'custom_shell_handled'}}, document.title, #{"?#{Glimmer::UI::CustomShell.encoded_request_parameter_string.sub('&custom_shell_handled=true', '')}"})`
22
+ # just a placeholder that has an open method # TODO return an actual CustomShell in the future that does the work happening above in the #open method
23
+ Struct.new(:open).new(true)
24
+ else
25
+ Glimmer::SWT::ShellProxy.new(*args)
26
+ end
27
+ end
28
+
29
+ def add_content(parent, &content)
30
+ content.call(parent) if parent.is_a?(Glimmer::SWT::ShellProxy)
15
31
  end
16
32
  end
17
33
  end
@@ -33,7 +33,7 @@ module Glimmer
33
33
  # discovers quickly by convention
34
34
  class SwtExpression < StaticExpression
35
35
  def can_interpret?(parent, keyword, *args, &block)
36
- block.nil? &&
36
+ block.nil? and
37
37
  args.size > 0
38
38
  end
39
39
 
@@ -8,6 +8,10 @@ module Glimmer
8
8
  :args,
9
9
  :horizontal_alignment,
10
10
  :vertical_alignment,
11
+ :horizontal_span,
12
+ :vertical_span,
13
+ :horizontal_indent,
14
+ :vertical_indent,
11
15
  :grab_excess_horizontal_space,
12
16
  :grab_excess_vertical_space,
13
17
  :height_hint
@@ -15,31 +19,62 @@ module Glimmer
15
19
  def initialize(parent, args)
16
20
  @parent = parent
17
21
  @args = args
22
+ # TODO spread args correctly
23
+ # TODO avoid using reapply
18
24
  reapply
19
25
  end
20
26
 
21
27
  def height_hint=(height_hint)
22
28
  @height_hint = height_hint
29
+ # TODO
23
30
  reapply
24
31
  end
25
32
 
26
33
  def horizontal_alignment=(horizontal_alignment)
27
34
  @horizontal_alignment = horizontal_alignment
35
+ # TODO
28
36
  reapply
29
37
  end
30
38
 
31
39
  def vertical_alignment=(vertical_alignment)
32
40
  @vertical_alignment = vertical_alignment
41
+ # TODO
42
+ reapply
43
+ end
44
+
45
+ def horizontal_span=(value)
46
+ @horizontal_span = value
47
+ @parent.dom_element.css('grid-column-start', "span #{@horizontal_span}")
48
+ reapply
49
+ end
50
+
51
+ def vertical_span=(value)
52
+ @vertical_span = value
53
+ @parent.dom_element.css('grid-row-start', "span #{@horizontal_span}")
54
+ reapply
55
+ end
56
+
57
+ def horizontal_indent=(value)
58
+ @horizontal_indent = value
59
+ @parent.dom_element.css('padding-left', @horizontal_indent)
60
+ reapply
61
+ end
62
+
63
+ def vertical_indent=(value)
64
+ @vertical_indent = value
65
+ @parent.dom_element.css('padding-top', @vertical_indent)
33
66
  reapply
34
67
  end
35
68
 
36
69
  def grab_excess_horizontal_space=(grab_excess_horizontal_space)
37
70
  @grab_excess_horizontal_space = grab_excess_horizontal_space
71
+ # TODO
38
72
  reapply
39
73
  end
40
74
 
41
75
  def grab_excess_vertical_space=(grab_excess_vertical_space)
42
76
  @grab_excess_vertical_space = grab_excess_vertical_space
77
+ # TODO
43
78
  reapply
44
79
  end
45
80
 
@@ -29,8 +29,9 @@ module Glimmer
29
29
 
30
30
  attr_reader :parent, :args
31
31
 
32
- def initialize(parent, args)
32
+ def initialize(parent, args)
33
33
  @parent = parent
34
+ @parent = parent.body_root if @parent.is_a?(Glimmer::UI::CustomWidget)
34
35
  @parent.css_classes.each do |css_class|
35
36
  @parent.remove_css_class(css_class) if css_class.include?('layout')
36
37
  end
@@ -93,7 +93,7 @@ module Glimmer
93
93
  }
94
94
  .modal-content {
95
95
  background-color: #fefefe;
96
- margin: auto;
96
+ padding-bottom: 15px;
97
97
  border: 1px solid #888;
98
98
  display: inline-block;
99
99
  min-width: 200px;
@@ -9,7 +9,7 @@ module Glimmer
9
9
 
10
10
  WIDTH_MIN = 130
11
11
  HEIGHT_MIN = 0
12
-
12
+
13
13
  def initialize(args)
14
14
  @args = args
15
15
  @children = []
@@ -238,6 +238,7 @@ module Glimmer
238
238
  end
239
239
 
240
240
  def open
241
+ # TODO consider the idea of delaying rendering till the open method
241
242
  # TODO make it start as hidden and show shell upon open
242
243
  end
243
244
  end
@@ -19,6 +19,7 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
+ require 'glimmer/ui/custom_widget'
22
23
  require 'glimmer/error'
23
24
 
24
25
  module Glimmer
@@ -32,15 +33,32 @@ module Glimmer
32
33
  klass.include(Glimmer)
33
34
  Glimmer::UI::CustomWidget.add_custom_widget_namespaces_for(klass)
34
35
  end
36
+
37
+ def request_parameter_string
38
+ URI.decode_www_form_component(`document.location.href`.match(/\?(.*)$/).to_a[1].to_s)
39
+ end
40
+
41
+ def encoded_request_parameter_string
42
+ `document.location.href`.match(/\?(.*)$/).to_a[1].to_s
43
+ end
44
+
45
+ def requested_and_not_handled?
46
+ requested? && !request_parameter_string.include?('custom_shell_handled=true')
47
+ end
48
+
49
+ def requested?
50
+ request_parameter_string.include?('custom_shell=')
51
+ end
35
52
  end
36
53
 
37
54
  def initialize(parent, args, options, &content)
38
- super
55
+ super(parent, args, options, &content)
39
56
  raise Error, 'Invalid custom shell body root! Must be a shell or another custom shell.' unless body_root.is_a?(Glimmer::SWT::ShellProxy)
40
57
  end
41
58
 
42
59
  # Classes may override
43
60
  def open
61
+ # TODO consider the idea of delaying rendering till the open method
44
62
  body_root.open
45
63
  end
46
64
 
@@ -152,13 +152,14 @@ module Glimmer
152
152
 
153
153
  def initialize(parent, args, options, &content)
154
154
  @parent = parent
155
- options = args.delete_at(-1) if args.is_a?(Array) && args.last.is_a?(Hash)
155
+ options = args.delete_at(-1) if options.nil? && args.is_a?(Array) && args.last.is_a?(Hash)
156
156
  if args.is_a?(Hash)
157
157
  options = args
158
158
  args = []
159
159
  end
160
+ args = options.delete('swt_style').split(',').map(&:to_sym) if options['swt_style']
160
161
  @args = args
161
- @swt_style = SWT::SWTProxy[*args]
162
+ @swt_style = SWT::SWTProxy[*@args]
162
163
  options ||= {}
163
164
  @options = self.class.options.merge(options)
164
165
  @content = Util::ProcTracker.new(content) if content
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.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-12 00:00:00.000000000 Z
11
+ date: 2020-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -210,6 +210,7 @@ files:
210
210
  - README.md
211
211
  - VERSION
212
212
  - lib/glimmer-dsl-opal.rb
213
+ - lib/glimmer-dsl-opal/ext/date.rb
213
214
  - lib/glimmer-dsl-opal/ext/exception.rb
214
215
  - lib/glimmer-dsl-opal/missing/net/http.rb
215
216
  - lib/glimmer-dsl-opal/missing/uri.rb