appfactory 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,168 @@
1
+ #
2
+ # Code stolen from HotCocoa examples: http://macruby.org
3
+ #
4
+ module Growl
5
+ class Notifier
6
+ VERSION = '1.0.1'
7
+
8
+ GROWL_IS_READY = "Lend Me Some Sugar; I Am Your Neighbor!"
9
+ GROWL_NOTIFICATION_CLICKED = "GrowlClicked!"
10
+ GROWL_NOTIFICATION_TIMED_OUT = "GrowlTimedOut!"
11
+ GROWL_KEY_CLICKED_CONTEXT = "ClickedContext"
12
+
13
+ PRIORITIES = {
14
+ :emergency => 2,
15
+ :high => 1,
16
+ :normal => 0,
17
+ :moderate => -1,
18
+ :very_low => -2,
19
+ }
20
+
21
+ class << self
22
+ # Returns the singleton instance of Growl::Notifier with which you register and send your Growl notifications.
23
+ def sharedInstance
24
+ @sharedInstance ||= alloc.init
25
+ end
26
+ end
27
+
28
+ attr_reader :application_name, :application_icon, :notifications, :default_notifications
29
+ attr_accessor :delegate
30
+
31
+ # Registers the applications metadata and the notifications, that your application might send, to Growl.
32
+ # The +default_notifications+ are notifications that will be enabled by default, the regular +notifications+ are
33
+ # optional and should be enabled by the user in the Growl system preferences.
34
+ #
35
+ # Register the applications name and the notifications that will be used.
36
+ # * +default_notifications+ defaults to the regular +notifications+.
37
+ # * +application_icon+ defaults to NSApplication.sharedApplication.applicationIconImage.
38
+ #
39
+ # Growl::Notifier.sharedInstance.register 'FoodApp', ['YourHamburgerIsReady', 'OhSomeoneElseAteIt']
40
+ #
41
+ # Register the applications name, the notifications plus the default notifications that will be used and the icon that's to be used in the Growl notifications.
42
+ #
43
+ # Growl::Notifier.sharedInstance.register 'FoodApp', ['YourHamburgerIsReady', 'OhSomeoneElseAteIt'], ['DefaultNotification], NSImage.imageNamed('GreasyHamburger')
44
+ def register(application_name, notifications, default_notifications = nil, application_icon = nil)
45
+ @application_name, @application_icon = application_name, (application_icon || NSApplication.sharedApplication.applicationIconImage)
46
+ @notifications, @default_notifications = notifications, (default_notifications || notifications)
47
+ @callbacks = {}
48
+ send_registration!
49
+ end
50
+
51
+ # Sends a Growl notification.
52
+ #
53
+ # * +notification_name+ : the name of one of the notifcations that your apllication registered with Growl. See register for more info.
54
+ # * +title+ : the title that should be used in the Growl notification.
55
+ # * +description+ : the body of the Grow notification.
56
+ # * +options+ : specifies a few optional options:
57
+ # * <tt>:sticky</tt> : indicates if the Grow notification should "stick" to the screen. Defaults to +false+.
58
+ # * <tt>:priority</tt> : sets the priority level of the Growl notification. Defaults to 0.
59
+ # * <tt>:icon</tt> : specifies the icon to be used in the Growl notification. Defaults to the registered +application_icon+, see register for more info.
60
+ #
61
+ # Simple example:
62
+ #
63
+ # name = 'YourHamburgerIsReady'
64
+ # title = 'Your hamburger is ready for consumption!'
65
+ # description = 'Please pick it up at isle 4.'
66
+ #
67
+ # Growl::Notifier.sharedInstance.notify(name, title, description)
68
+ #
69
+ # Example with optional options:
70
+ #
71
+ # Growl::Notifier.sharedInstance.notify(name, title, description, :sticky => true, :priority => 1, :icon => NSImage.imageNamed('SuperBigHamburger'))
72
+ #
73
+ # When you pass notify a block, that block will be used as the callback handler if the Growl notification was clicked. Eg:
74
+ #
75
+ # Growl::Notifier.sharedInstance.notify(name, title, description, :sticky => true) do
76
+ # user_clicked_notification_so_do_something!
77
+ # end
78
+ def notify(notification_name, title, description, options = {}, &callback)
79
+ dict = {
80
+ :ApplicationName => @application_name,
81
+ :ApplicationPID => pid,
82
+ :NotificationName => notification_name,
83
+ :NotificationTitle => title,
84
+ :NotificationDescription => description,
85
+ :NotificationPriority => PRIORITIES[options[:priority]] || options[:priority] || 0
86
+ }
87
+ dict[:NotificationIcon] = options[:icon].TIFFRepresentation if options[:icon]
88
+ dict[:NotificationSticky] = 1 if options[:sticky]
89
+
90
+ context = {}
91
+ context[:user_click_context] = options[:click_context] if options[:click_context]
92
+ if block_given?
93
+ @callbacks[callback.object_id] = callback
94
+ context[:callback_object_id] = callback.object_id.to_s
95
+ end
96
+ dict[:NotificationClickContext] = context unless context.empty?
97
+
98
+ notification_center.postNotificationName :GrowlNotification, object:nil, userInfo:dict, deliverImmediately:true
99
+ end
100
+
101
+ def onReady(notification)
102
+ send_registration!
103
+ end
104
+
105
+ def onClicked(notification)
106
+ user_context = nil
107
+ if context = notification.userInfo[GROWL_KEY_CLICKED_CONTEXT]
108
+ user_context = context[:user_click_context]
109
+ if callback_object_id = context[:callback_object_id]
110
+ @callbacks.delete(callback_object_id.to_i).call
111
+ end
112
+ end
113
+
114
+ @delegate.growlNotifierClicked_context(self, user_context) if @delegate && @delegate.respond_to?(:growlNotifierClicked_context)
115
+ end
116
+
117
+ def onTimeout(notification)
118
+ user_context = nil
119
+ if context = notification.userInfo[GROWL_KEY_CLICKED_CONTEXT]
120
+ @callbacks.delete(context[:callback_object_id].to_i) if context[:callback_object_id]
121
+ user_context = context[:user_click_context]
122
+ end
123
+
124
+ @delegate.growlNotifierTimedOut_context(self, user_context) if @delegate && @delegate.respond_to?(:growlNotifierTimedOut_context)
125
+ end
126
+
127
+ private
128
+
129
+ def pid
130
+ NSProcessInfo.processInfo.processIdentifier.to_i
131
+ end
132
+
133
+ def notification_center
134
+ NSDistributedNotificationCenter.defaultCenter
135
+ end
136
+
137
+ def send_registration!
138
+ add_observer 'onReady:', GROWL_IS_READY, false
139
+ add_observer 'onClicked:', GROWL_NOTIFICATION_CLICKED, true
140
+ add_observer 'onTimeout:', GROWL_NOTIFICATION_TIMED_OUT, true
141
+
142
+ dict = {
143
+ :ApplicationName => @application_name,
144
+ :ApplicationIcon => application_icon.TIFFRepresentation,
145
+ :AllNotifications => @notifications,
146
+ :DefaultNotifications => @default_notifications
147
+ }
148
+
149
+ notification_center.postNotificationName :GrowlApplicationRegistrationNotification, object:nil, userInfo:dict, deliverImmediately:true
150
+ end
151
+
152
+ def add_observer(selector, name, prepend_name_and_pid)
153
+ name = "#{@application_name}-#{pid}-#{name}" if prepend_name_and_pid
154
+ notification_center.addObserver self, selector:selector, name:name, object:nil
155
+ end
156
+ end
157
+
158
+ def self.growl(name, title, description, options = {}, &callback)
159
+ Growl::Notifier.sharedInstance.notify name, title, description, options, &callback
160
+ end
161
+
162
+ # Sends a sticky Growl notification. See Growl::Notifier#notify for more info.
163
+ def self.sticky_growl(name, title, description, options = {}, &callback)
164
+ growl name, title, description, options.merge!(:sticky => true), &callback
165
+ end
166
+
167
+
168
+ end
@@ -0,0 +1,171 @@
1
+ framework 'Cocoa'
2
+ $: << NSBundle.mainBundle.resourcePath.fileSystemRepresentation
3
+ require 'growl'
4
+
5
+ module AppFactory
6
+ def self.resources_dir
7
+ NSBundle.mainBundle.resourcePath.fileSystemRepresentation
8
+ end
9
+
10
+ def self.app_name
11
+ @app_name || 'AppFactory'
12
+ end
13
+
14
+ def self.app_name=(name)
15
+ @app_name = name
16
+ end
17
+
18
+ def self.debug(msg)
19
+ NSLog "DEBUG [#{app_name}]: #{msg}"
20
+ end
21
+
22
+ def register_growl_events(array = [])
23
+ a = array.map { |e| e.to_s }
24
+ Growl::Notifier.sharedInstance.register AppFactory.app_name, array
25
+ end
26
+
27
+ def growl(event_name, title, desc)
28
+ Growl.growl event_name.to_s, title, desc
29
+ end
30
+
31
+ def self.top_menu
32
+ if not @top_menu
33
+ @top_menu = NSMenu.new
34
+ @top_menu.initWithTitle app_name
35
+ @top_menu
36
+ else
37
+ debug 'Meny already initialized...'
38
+ @top_menu
39
+ end
40
+ end
41
+
42
+ def clear_menu(menu)
43
+ menu.itemArray.each do |mi|
44
+ menu.removeItem mi
45
+ end
46
+ end
47
+
48
+ def self.terminate
49
+ @app.terminate(self)
50
+ end
51
+
52
+ def open_url(url)
53
+ NSWorkspace.sharedWorkspace.openURL(NSURL.URLWithString(url))
54
+ end
55
+
56
+ def self.status_bar
57
+ if not @status_bar
58
+ @status_bar = NSStatusBar.systemStatusBar
59
+ @status_item = @status_bar.statusItemWithLength(NSVariableStatusItemLength)
60
+ @status_item.setMenu top_menu
61
+ img = NSImage.new.initWithContentsOfFile "#{AppFactory.resources_dir}/ruby_statusbar.png"
62
+ @status_item.setImage(img)
63
+ Growl.growl 'InitDone', app_name, "Here we go!"
64
+ @status_bar
65
+ else
66
+ debug 'Statusbar already initialized...'
67
+ @status_bar
68
+ end
69
+ end
70
+
71
+ def self.start
72
+ @app = NSApplication.sharedApplication
73
+ status_bar
74
+ @app.run
75
+ end
76
+
77
+ def timer(interval, &block)
78
+ delegate = TimerDelegate.new
79
+ @timer = NSTimer.scheduledTimerWithTimeInterval interval.to_f, :target => delegate, :selector => "runTimer:", :userInfo => nil, :repeats => true
80
+ TimerDelegate.send(:class_eval, "def timerBlock=(blk); @timerBlock = blk; end")
81
+ delegate.send("timerBlock=".to_sym, block)
82
+ end
83
+
84
+ def menu_item(title, &block)
85
+ mi = NSMenuItem.new
86
+ mi.title = title
87
+ dname = "delegate#{rand(999999999)}"
88
+ mi.action = "#{dname}:"
89
+ AppFactoryDelegate.send(:class_eval, "def #{dname}=(blk); @#{dname} = blk; end")
90
+ AppFactoryDelegate.send(:class_eval, "def #{dname}(sender); @#{dname}.call ; end")
91
+ delegate = AppFactory.delegate
92
+ delegate.send("#{dname}=".to_sym, block)
93
+ mi.target = delegate
94
+ if @current_menu
95
+ @current_menu.addItem mi
96
+ else
97
+ AppFactory.menu.addItem mi
98
+ end
99
+ end
100
+
101
+ def menu_separator
102
+ if @current_menu
103
+ @current_menu.addItem NSMenuItem.separatorItem
104
+ else
105
+ puts NSMenuItem.separatorItem
106
+ AppFactory.top_menu.addItem NSMenuItem.separatorItem
107
+ end
108
+ end
109
+
110
+ def menu_quit
111
+ mi = NSMenuItem.new
112
+ mi.title = 'Quit'
113
+ mi.action = 'terminate:'
114
+ mi.target = AppFactory.delegate
115
+ AppFactory.top_menu.addItem mi
116
+ end
117
+
118
+ def menu(title)
119
+ if not @submenues
120
+ AppFactory.debug 'Init submenues collection'
121
+ @submenues = {}
122
+ end
123
+ m = nil
124
+ if @submenues.has_key? title
125
+ #existing menu
126
+ AppFactory.debug "Submenu #{title} already exists"
127
+ m = @submenues[title]
128
+ else
129
+ AppFactory.debug "Creating submenu #{title}"
130
+ m = NSMenu.new
131
+ @submenues[title] = m
132
+ m.initWithTitle title
133
+ mi = NSMenuItem.new
134
+ mi.title = title
135
+ mi.setSubmenu m
136
+ AppFactory.top_menu.addItem mi
137
+ end
138
+ @current_menu = m
139
+ yield m
140
+ @current_menu = nil
141
+ end
142
+
143
+ def self.delegate
144
+ @delegate ||= AppFactoryDelegate.new
145
+ end
146
+
147
+ def self.vendor_libs
148
+ Dir["#{resources_dir}/vendor/gems/gems/*"].each do |d|
149
+ AppFactory.debug "Adding #{d}/lib to RUBYLIB"
150
+ $: << "#{d}/lib"
151
+ end
152
+ end
153
+
154
+ class TimerDelegate
155
+ def runTimer(timer)
156
+ @timerBlock.call
157
+ end
158
+ end
159
+ class AppFactoryDelegate
160
+ def terminate(sender)
161
+ AppFactory.terminate
162
+ end
163
+ end
164
+
165
+ end
166
+
167
+ AppFactory.vendor_libs
168
+ include AppFactory
169
+ require 'dsl'
170
+
171
+ AppFactory.start
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: appfactory
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Sergio Rubio
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-02 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: choice
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.1.3
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: bundler
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0.7"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: hoe
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 2.3.3
44
+ version:
45
+ description: Easily create Status Bar Applications for Mac OS X
46
+ email:
47
+ - sergio@rubio.name
48
+ executables:
49
+ - appfactory
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - History.txt
54
+ - Manifest.txt
55
+ - README.txt
56
+ files:
57
+ - .DS_Store
58
+ - History.txt
59
+ - Manifest.txt
60
+ - README.txt
61
+ - Rakefile
62
+ - bin/appfactory
63
+ - examples/appmain.rb
64
+ - lib/appfactory.rb
65
+ - template/appfactory.app.template/Contents/Info.plist
66
+ - template/appfactory.app.template/Contents/MacOS/appfactory
67
+ - template/appfactory.app.template/Contents/PkgInfo
68
+ - template/appfactory.app.template/Contents/Resources/English.lproj/InfoPlist.strings
69
+ - template/appfactory.app.template/Contents/Resources/English.lproj/MainMenu.nib/designable.nib
70
+ - template/appfactory.app.template/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nib
71
+ - template/appfactory.app.template/Contents/Resources/growl.rb
72
+ - template/appfactory.app.template/Contents/Resources/rb_main.rb
73
+ - template/appfactory.app.template/Contents/Resources/ruby.icns
74
+ - template/appfactory.app.template/Contents/Resources/ruby_statusbar.png
75
+ has_rdoc: true
76
+ homepage: http://appfactory.netcorex.org
77
+ licenses: []
78
+
79
+ post_install_message:
80
+ rdoc_options:
81
+ - --main
82
+ - README.txt
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "0"
90
+ version:
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: "0"
96
+ version:
97
+ requirements: []
98
+
99
+ rubyforge_project: appfactory
100
+ rubygems_version: 1.3.5
101
+ signing_key:
102
+ specification_version: 3
103
+ summary: Mac OS X StatusBar App Builder!
104
+ test_files: []
105
+