shenmegui 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cc17fa7f8f6c46479ee3911e123e3a1695bb1e35
4
+ data.tar.gz: 3064fa81b892c8547595cf50bffcd81e7baccb12
5
+ SHA512:
6
+ metadata.gz: 1bc7fa600054cdf7b63829eb1cea9a4704cf3996829ba78a956a53b20edbb04aa4bb5073d56d1a9fa59f11f189eaff3f7b8e4303f9d63115f132b27175a383f8
7
+ data.tar.gz: bf49c7234618ea340f252d46411e6db30345f5eed597d678ac18e7949f89ce3680feef92e5419a8927b37d34a78c974008eeb113930c44a6be5f2948f603c012
data/lib/shenmegui.rb ADDED
@@ -0,0 +1,153 @@
1
+ require 'erb'
2
+ require 'json'
3
+ require 'em-websocket'
4
+
5
+ module ShenmeGUI
6
+
7
+ class << self
8
+ attr_accessor :elements, :socket
9
+ attr_reader :temp_stack
10
+
11
+ %w{stack flow button radio checkbox image select textline textarea}.each do |x|
12
+ define_method "#{x}" do |value=nil, &block|
13
+ params = {value: value}
14
+ el = Control.new(x.to_sym, params)
15
+ temp_stack.last.children << el
16
+ el.parent = temp_stack.last
17
+ temp_stack << el
18
+ instance_eval &block unless block.nil?
19
+ temp_stack.pop
20
+ el
21
+ end
22
+ private x.to_sym
23
+ end
24
+
25
+ end
26
+
27
+ @elements = []
28
+ @temp_stack = []
29
+
30
+ def self.app(params={}, &block)
31
+ el = Control.new(:body, params)
32
+ temp_stack << el
33
+ instance_eval &block unless block.nil?
34
+ temp_stack.pop
35
+ File.open('index.html', 'w'){ |f| f.write el.render }
36
+ el
37
+ end
38
+
39
+ class Control
40
+ attr_accessor :id, :type, :properties, :events, :children, :parent
41
+
42
+ @available_events = %w{click input}.collect(&:to_sym)
43
+ @available_properties = {
44
+ body: %i{style},
45
+ button: %i{value},
46
+ input: %i{value},
47
+ textarea: %i{value cursor},
48
+ textline: %i{value cursor},
49
+ stack: %i{style},
50
+ flow: %i{style}
51
+ }
52
+
53
+ def self.available_properties
54
+ @available_properties
55
+ end
56
+
57
+ def inspect
58
+ "##{@type}.#{@id} #{@properties}"
59
+ end
60
+
61
+ def update
62
+ msg = "update:#{@id}->#{@properties.to_json}"
63
+ ::ShenmeGUI.socket.send(msg)
64
+ end
65
+
66
+ def initialize(type, params={})
67
+ self.type = type
68
+ self.properties = params
69
+ self.id = ::ShenmeGUI.elements.size
70
+ ::ShenmeGUI.elements << self
71
+ self.children = []
72
+ self.events = {}
73
+ self.class.available_properties[type].each do |x|
74
+ define_singleton_method(x) do
75
+ @properties[x]
76
+ end
77
+
78
+ define_singleton_method("#{x}=") do |v|
79
+ @properties[x] = v
80
+ update
81
+ end
82
+ end
83
+ end
84
+
85
+ def render
86
+ lib_path = $LOADED_FEATURES.grep(/.*\/lib\/shenmegui.rb/)[0]
87
+ template_path = lib_path.match(/(.*)\/lib/)[1] + "/templates"
88
+ if type == :body
89
+ static_path = lib_path.match(/(.*)\/lib/)[1] + "/static"
90
+ style = File.open("#{static_path}/style.css", 'r'){ |f| f.read }
91
+ script = File.open("#{static_path}/script.js", 'r'){ |f| f.read }
92
+ end
93
+ template = ::ERB.new File.open("#{template_path}/#{type}.erb", 'r') { |f| f.read }
94
+ content = self.children.collect{|x| x.render}.join("\n")
95
+ template.result(binding)
96
+ end
97
+
98
+ @available_events.each do |x|
99
+ define_method("on#{x}") do |&block|
100
+ return events[x] if block.nil?
101
+ events[x] = lambda &block
102
+ end
103
+ self
104
+ end
105
+
106
+ end
107
+
108
+ def self.handle(msg)
109
+ match_data = msg.match(/(.+?):(\d+)(?:->)?({.+?})?/)
110
+ command = match_data[1].to_sym
111
+ id = match_data[2].to_i
112
+ data = JSON.parse(match_data[3]) unless match_data[3].nil?
113
+ target = elements[id]
114
+ case command
115
+ when :update
116
+ data.each do |k,v|
117
+ target.properties[k.to_sym] = v
118
+ end
119
+ else
120
+ event_lambda = elements[id].events[command]
121
+ ShenmeGUI.instance_exec(&event_lambda) if event_lambda
122
+ end
123
+ target
124
+ end
125
+
126
+ module Server
127
+ def self.start!
128
+ ws_thread = Thread.new do
129
+ EM.run do
130
+ EM::WebSocket.run(:host => "0.0.0.0", :port => 80) do |ws|
131
+ ws.onopen { puts "WebSocket connection open" }
132
+
133
+ ws.onclose { puts "Connection closed" }
134
+
135
+ ws.onmessage do |msg|
136
+ puts "Recieved message: #{msg}"
137
+ ShenmeGUI.handle msg
138
+ end
139
+
140
+ ShenmeGUI.socket = ws
141
+ end
142
+ end
143
+ end
144
+
145
+ index_path = "#{Dir.pwd}/index.html"
146
+ `start file:///#{index_path}`
147
+
148
+ ws_thread.join
149
+ end
150
+
151
+ end
152
+
153
+ end
data/static/script.js ADDED
@@ -0,0 +1,49 @@
1
+ var wsUrl = "ws://localhost/";
2
+
3
+ websocket = new WebSocket(wsUrl);
4
+ websocket.onopen = function(evt){ console.log("Connected."); };
5
+ websocket.onmessage = function(evt){ console.log(evt.data); handleMessage(evt.data); };
6
+ websocket.onclose = function(evt){
7
+ console.log("Closed.");
8
+ };
9
+
10
+ function handleMessage(msg){
11
+ var match_data = msg.match(/(.+?):(\d+)(?:->)?({.+?})?/);
12
+ var command = match_data[1];
13
+ var target = document.getElementById('item-' + match_data[2]);
14
+ var data = JSON.parse(match_data[3]);
15
+ switch (command){
16
+ case 'update':
17
+ target.properties = data;
18
+ target.value = data.value;
19
+ }
20
+ }
21
+
22
+ function getId(obj){
23
+ return obj.id.match(/item-(\d+)/)[1];
24
+ }
25
+
26
+ var buttons = document.getElementsByTagName('input');
27
+ var i;
28
+ for(i=0; i<buttons.length; i++){
29
+ buttons[i].addEventListener('click', function(){
30
+ websocket.send("click:" + getId(this));
31
+ });
32
+ }
33
+
34
+ var inputs = document.getElementsByTagName('input');
35
+ for(i=0; i<inputs.length; i++){
36
+ inputs[i].addEventListener('input', function(){
37
+ var value = {value: this.value};
38
+ websocket.send("update:" + getId(this) + "->" + JSON.stringify(value));
39
+ websocket.send("input:" + getId(this));
40
+ });
41
+ }
42
+
43
+ var textareas = document.getElementsByTagName('textarea');
44
+ for(i=0; i<textareas.length; i++){
45
+ textareas[i].addEventListener('change', function(){
46
+ var value = {value: this.value};
47
+ websocket.send("change:" + getId(this) + "->" + JSON.stringify(value));
48
+ });
49
+ }
data/static/style.css ADDED
@@ -0,0 +1,11 @@
1
+ body {
2
+ margin: 50px;
3
+ width: 600px; }
4
+
5
+ .stack * {
6
+ display: block; }
7
+
8
+ .flow * {
9
+ display: inline; }
10
+
11
+ /*# sourceMappingURL=style.css.map */
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Document</title>
6
+ <link rel="stylesheet" type="text/css" href="http://cdn.amazeui.org/amazeui/2.2.1/css/amazeui.min.css">
7
+ <style>
8
+ <%= style %>
9
+ </style>
10
+ </head>
11
+ <body id="item-<%= id %>">
12
+ <%= content %>
13
+ <script>
14
+ <%= script %>
15
+ </script>
16
+ </body>
17
+ </html>
@@ -0,0 +1 @@
1
+ <input id="item-<%= id %>" type="button" class="am-btn am-btn-primary" value="<%= properties[:value] %>" />
@@ -0,0 +1 @@
1
+ <div id="item-<%= id %>" class="flow"><%= content %></div>
@@ -0,0 +1 @@
1
+ <div id="item-<%= id %>" class="stack"><%= content %></div>
@@ -0,0 +1 @@
1
+ <div class="am-form"><textarea id="item-<%= id %>"><%= properties[:value] %></textarea></div>
@@ -0,0 +1 @@
1
+ <input id="item-<%= id %>" class="am-form-field" type="text" value="<%= properties[:value] %>"/>
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shenmegui
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - CicholGricenchos
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: em-websocket
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: a simple HTML GUI for Ruby
28
+ email: cichol@live.cn
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/shenmegui.rb
34
+ - static/style.css
35
+ - static/script.js
36
+ - templates/body.erb
37
+ - templates/button.erb
38
+ - templates/flow.erb
39
+ - templates/stack.erb
40
+ - templates/textarea.erb
41
+ - templates/textline.erb
42
+ homepage: https://github.com/CicholGricenchos/shenmegui
43
+ licenses: []
44
+ metadata: {}
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project:
61
+ rubygems_version: 2.0.14
62
+ signing_key:
63
+ specification_version: 4
64
+ summary: "什么鬼!"
65
+ test_files: []