maccman-bowline 0.3.9 → 0.4.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.
data/README.txt CHANGED
@@ -12,7 +12,24 @@ Ruby desktop application framework
12
12
  * Uses Webkit
13
13
  * View in HTML/JavaScript
14
14
  * Binding between HTML & Ruby
15
- * Will be cross platform (though only OSX atm)
15
+ * Cross platform (osx/linux/windows)
16
+
17
+ = INTRODUCTION
18
+
19
+ If you've ever wished creating a desktop application was as simple
20
+ as creating a Rails website you'll be interested in Bowline.
21
+
22
+ Bowline lets you take your existing skills and apply them to the desktop.
23
+ You can write apps in HTML/JavaScript/Ruby without having to worry about
24
+ different platforms or a complex GUI API.
25
+
26
+ Compared to existing Ruby desktop frameworks, such as Shoes, Bowline's strengths
27
+ are its adherence to MVC and use of HTML/JavaScript. We think that, although Ruby is
28
+ a great language for the backend, the view should be written in languages designed
29
+ for that purpose, HTML and JavaScript.
30
+
31
+ Bowline also takes inspiration from Flex through its binders. Bowline will bind
32
+ up Ruby and HTML - letting you concentrate on the more interesting things.
16
33
 
17
34
  = CONTACT
18
35
 
@@ -20,34 +37,132 @@ info@eribium.org
20
37
  http://eribium.org
21
38
  http://twitter.com/maccman
22
39
 
23
- = Usage - Building a basic Twitter client
40
+ = INSTALLATION
24
41
 
25
42
  Install the Titanium SDK:
26
- http://www.appcelerator.com/products/download-titanium/download/
43
+ http://www.appcelerator.com/products/download-titanium/download/
27
44
 
28
45
  Install the gem:
29
46
  >> sudo gem install maccman-bowline --source http://gems.github.com
30
47
 
31
- Run the app/binder generators:
32
- >> bowline-gen app bowline_twitter
33
- >> cd bowline_twitter
34
- >> bowline-gen binder tweets
48
+ = USAGE
49
+
50
+ See the Twitter example at the end of this document,
51
+ or browse the completed version here:
52
+ http://github.com/maccman/bowline-twitter
35
53
 
36
- Copy tweets.rb from examples to app/binders/tweets.rb
37
- Add your Twitter credentials to tweets.rb - in this simple example they're not dynamic.
54
+ = GENERATING
38
55
 
39
- Copy twitter.html from examples to public/index.html
56
+ Using the bowline-gen binary (installed with Bowline) you can generate the following things:
57
+ app Generates a new application.
58
+ binder Generates a new binder, either a collection one, or a singleton one.
59
+ helper Generates a new helper.
60
+ migration Generates a new database migration.
61
+ model Generates a new model.
62
+
63
+ Run 'bowline-gen --help' for more information.
40
64
 
41
- Install the Twitter gem:
42
- >> sudo gem install twitter
65
+ = COMMANDS
43
66
 
44
- Add the Twitter gem to config/environment.rb:
45
- config.gem "twitter"
67
+ App console:
68
+ >> script/console
46
69
 
47
- run:
70
+ Run application:
48
71
  >> script/run
49
72
 
50
- That's it
73
+ = BINDERS
74
+
75
+ Binders are the core of Bowline, they're classes that you can bind HTML to.
76
+ This means, if you can data in the class, the HTML also automatically changes.
77
+ It's a one way relationship though.
78
+
79
+ You can think of binders as similar to controllers in Rails.
80
+
81
+ There are two types of binders, singleton and collection.
82
+ Singleton binders are for a single data entity, such as the current logged in user.
83
+ And it goes without saying that collection binders are for an array of data.
84
+
85
+ You can create a collection binder like this:
86
+ >> bowline-gen binder users --type collection
87
+
88
+ Which will generate code a bit like this:
89
+ module Binders
90
+ class Users < Bowline::Collection
91
+ end
92
+ end
93
+
94
+ Now, in the view you can bind HTML to this collection, by
95
+ using the following javascript:
96
+ $('#users').bowline('users');
97
+
98
+ You should probably become familiar with Chain.js (which bowline uses for binding): http://wiki.github.com/raid-ox/chain.js/
99
+
100
+ Suffice to say, the HTML looks a bit like this:
101
+ <div id="users">
102
+ <div class="item">
103
+ <span class="name"></span>
104
+ <span class="email"></span>
105
+ <a href="#" class="destroy">Delete</a>
106
+ </div>
107
+ </div>
108
+
109
+ Now, were you to have a user object, you could do something like
110
+ this to update the HTML.
111
+
112
+ Binders::Users.items = [User.first]
113
+
114
+ = METHODS IN BINDERS
115
+
116
+ You can call both class and instance methods of the binders.
117
+ Following on from the above example with 'users', you could call a class
118
+ method called 'admins' on the users binder like so:
119
+
120
+ $('#users').invoke('admins')
121
+
122
+ It's the same syntax for invoking instance methods, just called
123
+ on one of the individual users:
124
+
125
+ $('#users div:first').invoke('instance_method', 'arg1')
126
+
127
+ = HELPERS
128
+
129
+ Helpers are similar to helpers in Rails - they're helper methods for the view which
130
+ don't need a full blown binder to cater for.
131
+
132
+ You can call helpers with JavaScript like so:
133
+ $.bowline.helper('name', 'arg1', ['arg2'])
134
+
135
+ = MODELS
136
+
137
+ Bowline plans to fully support ActiveRecord and the Sqlite3 database.
138
+ This is still in development though.
139
+
140
+ = THEMES
141
+
142
+ The Cappuccino Aristo theme has been specially customized for Bowline, you can see
143
+ examples of it in the Twitter client, and find it here:
144
+ http://github.com/maccman/aristo
145
+
146
+ = TITANIUM
147
+
148
+ Bowline is built on top of Titanium, an open source cross platform framework for desktop apps.
149
+ You can use any of the Titanium api methods in Ruby and JavaScript, like this:
150
+ Titanium.UI.currentWindow.close
151
+
152
+ Site: http://www.appcelerator.com/products/titanium-desktop/
153
+ API Docs: http://www.codestrong.com/titanium/api/
154
+
155
+ = BUILDING
156
+
157
+ Once your app is complete, you should run the following command
158
+ to make sure all the gems required (including Bowline) have been vendorised:
159
+ rake gems:sync
160
+
161
+ Then, run:
162
+ rake app
163
+
164
+ You can only build distributions for your local platform, but
165
+ using the Titanium Developer app you can build on all three platforms.
51
166
 
52
167
  = EXAMPLES
53
168
 
@@ -137,3 +252,33 @@ Usage for a collection (of users):
137
252
  <a href="#" id="showAdmins">Show admins</a>
138
253
  </body>
139
254
  </html>
255
+
256
+ = Building a basic Twitter client
257
+
258
+ Install the Titanium SDK:
259
+ http://www.appcelerator.com/products/download-titanium/download/
260
+
261
+ Install the gem:
262
+ >> sudo gem install maccman-bowline --source http://gems.github.com
263
+
264
+ Run the app/binder generators:
265
+ >> bowline-gen app bowline_twitter
266
+ >> cd bowline_twitter
267
+ >> bowline-gen binder tweets
268
+
269
+ Copy tweets.rb from examples to app/binders/tweets.rb
270
+ Add your Twitter credentials to tweets.rb - in this simple example they're not dynamic.
271
+
272
+ Copy twitter.html from examples to public/index.html
273
+
274
+ Install the Twitter gem:
275
+ >> sudo gem install twitter
276
+
277
+ Add the Twitter gem to config/environment.rb:
278
+ config.gem "twitter"
279
+
280
+ run:
281
+ >> script/run
282
+
283
+ That's it. You can see a snazzed up version here:
284
+ http://github.com/maccman/bowline-twitter
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.9
1
+ 0.4.0
@@ -1,21 +1,24 @@
1
1
  (function($){
2
2
  var init = false;
3
+ var TI = Titanium;
4
+ var UI = TI.UI;
5
+ var mainWin = UI.mainWindow.window;
3
6
 
4
7
  $.bowline = {
5
8
  setup: function(name, el){
6
- var rb = eval("bowline_" + name + "_setup");
9
+ var rb = mainWin.eval("bowline_" + name + "_setup");
7
10
  if(!rb) throw 'Unknown class';
8
11
  rb(el);
9
12
  },
10
13
 
11
14
  klass: function(name){
12
- var rb = eval("bowline_" + name);
15
+ var rb = mainWin.eval("bowline_" + name);
13
16
  if(!rb) throw 'Unknown class';
14
17
  return rb;
15
18
  },
16
19
 
17
20
  instance: function(name, el){
18
- var rb = eval("bowline_" + name + "_instance");
21
+ var rb = mainWin.eval("bowline_" + name + "_instance");
19
22
  if(!rb) throw 'Unknown class';
20
23
  return rb(el);
21
24
  },
@@ -28,12 +31,43 @@
28
31
  )
29
32
  );
30
33
  },
34
+
35
+ load: function(){
36
+ $(function(){
37
+ setTimeout(function(){
38
+ $(document.body).trigger('loading.bowline');
39
+ var script = $("<script />");
40
+ script.attr('type', 'text/ruby');
41
+ script.attr('src', '../script/init');
42
+ $('head').append(script);
43
+ }, 100);
44
+ });
45
+ },
31
46
 
32
47
  ready: function(func){
33
48
  if(init) return func();
34
49
  $(document).bind('loaded.bowline', func);
35
50
  },
36
51
 
52
+ dialog: function(name, options, callback){
53
+ if(!callback && typeof(options) == 'function') {
54
+ callback = options;
55
+ options = {};
56
+ }
57
+ $.extend(options, {
58
+ 'url': 'app://public/' + name + '.html',
59
+ 'height': 200,
60
+ 'width': 350,
61
+ 'transparency': 0.9,
62
+ 'resizable': false,
63
+ 'usingChrome': false,
64
+ 'onclose': function(res){
65
+ if(callback) callback(res);
66
+ }
67
+ });
68
+ return Titanium.UI.showDialog(options);
69
+ },
70
+
37
71
  setupForms: function(){
38
72
  // $('form').bind('submit', function(e){
39
73
  // var src = $(this).attr('src').split('.');
@@ -86,7 +120,16 @@
86
120
  var name = $(this).item('root').data('bowline');
87
121
  var func = $.bowline.instance(name, $(this));
88
122
  }
89
- return func.apply(func, arguments);
123
+ var args = $.makeArray(arguments);
124
+ var opts = args.pop();
125
+ if(typeof(opts) == "object" && opts.async){
126
+ setTimeout(function(){
127
+ func.apply(func, args);
128
+ }, 100);
129
+ } else {
130
+ args.push(opts);
131
+ func.apply(func, args);
132
+ }
90
133
  } else {
91
134
  throw 'Chain not active';
92
135
  }
@@ -106,13 +149,8 @@
106
149
  $(this).trigger('update.bowline');
107
150
  };
108
151
 
109
- $(function(){
110
- setTimeout(function(){
111
- $(document.body).trigger('loading.bowline');
112
- var script = $("<script />");
113
- script.attr('type', 'text/ruby');
114
- script.attr('src', '../script/init');
115
- $('head').append(script);
116
- }, 100);
117
- })
152
+ // main window
153
+ if(UI.getCurrentWindow().isTopMost()){
154
+ $.bowline.load();
155
+ }
118
156
  })(jQuery)
data/bowline.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{bowline}
5
- s.version = "0.3.9"
5
+ s.version = "0.4.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Alex MacCaw"]
9
- s.date = %q{2009-07-15}
9
+ s.date = %q{2009-07-18}
10
10
  s.default_executable = %q{bowline-gen}
11
11
  s.description = %q{Ruby/JS GUI framework}
12
12
  s.email = %q{alex@leadthinking.com}
@@ -30,8 +30,8 @@ module Bowline
30
30
  def params
31
31
  @params
32
32
  end
33
-
34
- def params=(p)
33
+
34
+ def params=(p) #:nodoc:
35
35
  case p
36
36
  when String
37
37
  # Params comes in a string (since it's a
@@ -46,18 +46,35 @@ module Bowline
46
46
  @params = p
47
47
  end
48
48
  end
49
-
50
- def setup(d)
49
+
50
+ def elements
51
+ @elements
52
+ end
53
+
54
+ def setup(d) #:nodoc:
51
55
  @elements ||= []
52
56
  @elements << d
53
57
  self.item_sync!
54
58
  end
59
+
60
+ def trigger(event, data = nil)
61
+ @elements ||= []
62
+ @elements.map {|e|
63
+ e.trigger(format_event(event), data)
64
+ }
65
+ end
66
+
67
+ def loading(&block)
68
+ trigger(:loading, true)
69
+ yield
70
+ trigger(:loading, false)
71
+ end
55
72
 
56
- def instance(el)
73
+ def instance(el) #:nodoc:
57
74
  self.new(el).method(:send)
58
75
  end
59
76
 
60
- def inherited(child)
77
+ def inherited(child) #:nodoc:
61
78
  return if self == Bowline::Binders::Base
62
79
  return if child == Bowline::Binders::Singleton
63
80
  return if child == Bowline::Binders::Collection
@@ -66,7 +83,13 @@ module Bowline
66
83
  js.send("bowline_#{name}_setup=", child.method(:setup))
67
84
  js.send("bowline_#{name}_instance=", child.method(:instance))
68
85
  js.send("bowline_#{name}=", child.method(:send))
69
- end
86
+ end
87
+
88
+ def format_event(name) #:nodoc:
89
+ name.is_a?(Array) ?
90
+ name.join('.') :
91
+ name.to_s
92
+ end
70
93
  end
71
94
 
72
95
  attr_reader :element
@@ -93,7 +116,10 @@ module Bowline
93
116
 
94
117
  # Trigger jQuery events on this element
95
118
  def trigger(event, data = nil)
96
- self.element.trigger(event, data)
119
+ self.element.trigger(
120
+ self.class.format_event(event),
121
+ data
122
+ )
97
123
  end
98
124
 
99
125
  # Raw DOM element
@@ -57,6 +57,8 @@ module Bowline::Generators
57
57
  }
58
58
 
59
59
  empty_directory :initializers, "config/initializers"
60
+
61
+ file :readme, "../README.txt", "README"
60
62
  end
61
63
 
62
64
  add :app, ApplicationGenerator
@@ -1,8 +1,7 @@
1
1
  require 'fileutils'
2
2
  namespace :app do
3
3
  task :configure => :environment do
4
- build_path = File.join(APP_ROOT, 'build')
5
-
4
+ config_path = File.join(APP_ROOT, 'config')
6
5
  conf = Bowline.configuration
7
6
 
8
7
  # Titanium complains about whitespace
@@ -66,8 +65,7 @@ tiprocess:0.4.4
66
65
  </ti:app>
67
66
  EOF
68
67
 
69
- FileUtils.makedirs(build_path)
70
- FileUtils.cd(build_path) do
68
+ FileUtils.cd(config_path) do
71
69
  File.open('manifest', 'w+') {|f| f.write manifest }
72
70
  File.open('tiapp.xml', 'w+') {|f| f.write tiapp }
73
71
  end
@@ -75,14 +73,19 @@ tiprocess:0.4.4
75
73
 
76
74
  desc "Bundles up app into executables"
77
75
  task :bundle do
78
- build_path = File.join(APP_ROOT, 'build')
79
- app_path = File.join(build_path, 'app')
80
-
81
- tiapp = File.join(build_path, 'tiapp.xml')
82
- manifest = File.join(build_path, 'manifest')
76
+ build_path = File.join(APP_ROOT, 'build')
77
+ app_path = File.join(build_path, 'app')
78
+ config_path = File.join(APP_ROOT, 'config')
83
79
 
84
- if !File.exists?(tiapp) || !File.exists?(manifest)
80
+ tiapp = File.join(config_path, 'tiapp.xml')
81
+ manifest = File.join(config_path, 'manifest')
82
+ env = File.join(config_path, 'environment.rb')
83
+
84
+ if !File.exists?(tiapp) ||
85
+ !File.exists?(manifest)
85
86
  Rake::Task['app:configure'].invoke
87
+ elsif File.mtime(tiapp) < File.mtime(env)
88
+ puts "You may need to run 'rake app:configure'"
86
89
  end
87
90
 
88
91
  FileUtils.rm_rf(app_path)
@@ -1,8 +1,8 @@
1
1
  module Bowline
2
2
  module Version #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 3
5
- TINY = 9
4
+ MINOR = 4
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maccman-bowline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.9
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex MacCaw
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-15 00:00:00 -07:00
12
+ date: 2009-07-18 00:00:00 -07:00
13
13
  default_executable: bowline-gen
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency