everyday-menu 0.1.0 → 0.1.1
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 +4 -4
- data/.gitignore +23 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +24 -0
- data/README.md +75 -0
- data/Rakefile +24 -0
- data/everyday-menu.gemspec +22 -0
- data/examples/basic_main_menu/app_delegate.rb +24 -0
- data/examples/basic_main_menu/main_menu.rb +20 -0
- data/lib/everyday-menu.rb +9 -0
- data/lib/everyday-menu/menu.rb +152 -0
- data/lib/everyday-menu/menu_builder.rb +70 -0
- data/lib/everyday-menu/menu_item.rb +123 -0
- data/lib/everyday-menu/version.rb +3 -0
- data/spec/menu_builder_spec.rb +105 -0
- data/spec/menu_item_spec.rb +38 -0
- data/spec/menu_spec.rb +70 -0
- metadata +24 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8629e47d2c83c578b36c97f19929b19510a2f109
|
4
|
+
data.tar.gz: 33d50f3c20d86ade4efb059ca5c540ec8fc3fd5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d52d5545f858e73378246066a05eb524fab4363eacc03cba1876d80e9c5b6f58a86342c2736884b9313a85d0a3ce49645da321bb7df7f1a45c3ae52199e8e2e3
|
7
|
+
data.tar.gz: 4cfac1436396e77297c61d1745eab23bbb455baa64b184146fa73310b1c599de978887be0ed59f62ab10a7a04e05a8d5f9103ddc213440474019bba0aed4cdcc
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
build
|
19
|
+
vendor
|
20
|
+
|
21
|
+
/.idea/
|
22
|
+
|
23
|
+
/projectFilesBackup/
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Here is the copyright from drink-menu, which I based a lot of my code on:
|
2
|
+
|
3
|
+
Copyright (c) 2013 Joe Fiorini
|
4
|
+
|
5
|
+
MIT License
|
6
|
+
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
8
|
+
a copy of this software and associated documentation files (the
|
9
|
+
"Software"), to deal in the Software without restriction, including
|
10
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
11
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
12
|
+
permit persons to whom the Software is furnished to do so, subject to
|
13
|
+
the following conditions:
|
14
|
+
|
15
|
+
The above copyright notice and this permission notice shall be
|
16
|
+
included in all copies or substantial portions of the Software.
|
17
|
+
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
20
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
21
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
22
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
23
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
24
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# EverydayMenu
|
2
|
+
|
3
|
+
## Credit
|
4
|
+
Please note that this gem is strongly based off of Joe Fiorini's `drink-menu` gem (with a little code copy-paste and lots of test and readme copy-paste), which I couldn't get to work for me.
|
5
|
+
|
6
|
+
You can find his gem at <https://github.com/joefiorini/drink-menu>. He doesn't get all of the credit, but he gets a lot of it.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'everyday-menu'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install everyday-menu
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
Everyday Menu separates menu layout from menu definition. Menu definition looks like:
|
25
|
+
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
class MainMenu
|
29
|
+
extend EverydayMenu::MenuBuilder
|
30
|
+
|
31
|
+
menuItem :create_site, 'Create Site'
|
32
|
+
menuItem :export, 'Export to Folder...'
|
33
|
+
menuItem :import, 'Import Folder as Site...'
|
34
|
+
menuItem :force_rebuild, 'Force Rebuild'
|
35
|
+
menuItem :about, 'About Staticly'
|
36
|
+
menuItem :quit, 'Quit', key_equivalent: 'q'
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
and then layout is as simple as:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
|
44
|
+
class MainMenu
|
45
|
+
extend EverydayMenu::MenuBuilder
|
46
|
+
|
47
|
+
mainMenu :main_menu, 'Main Menu' do
|
48
|
+
create_site
|
49
|
+
___
|
50
|
+
export
|
51
|
+
import
|
52
|
+
force_rebuild
|
53
|
+
___
|
54
|
+
about
|
55
|
+
quit
|
56
|
+
end
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
## Running the Examples
|
61
|
+
|
62
|
+
To run our example apps:
|
63
|
+
|
64
|
+
1. Clone this repo
|
65
|
+
2. From within your clone's root, run `platform=osx example=basic_main_menu rake`
|
66
|
+
|
67
|
+
You can replace the value of `example` with any folder under the `examples` directory to run that example.
|
68
|
+
|
69
|
+
## Contributing
|
70
|
+
|
71
|
+
1. Fork it
|
72
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
73
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
74
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
75
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$:.unshift('/Library/RubyMotion/lib')
|
2
|
+
|
3
|
+
if ENV['platform'] == 'osx'
|
4
|
+
require 'motion/project/template/osx'
|
5
|
+
else
|
6
|
+
raise 'The everyday-menu gem must be used within an OSX project.'
|
7
|
+
end
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'bundler'
|
11
|
+
Bundler.require
|
12
|
+
rescue LoadError
|
13
|
+
# ignored
|
14
|
+
end
|
15
|
+
|
16
|
+
Motion::Project::App.setup do |app|
|
17
|
+
app.name = 'everyday-menu'
|
18
|
+
app.identifier = 'us.myepg.everyday-menu'
|
19
|
+
app.specs_dir = 'spec/'
|
20
|
+
|
21
|
+
if ENV['example']
|
22
|
+
app.files << Dir["examples/#{ENV['example']}/**/*.rb"]
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'everyday-menu/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'everyday-menu'
|
8
|
+
spec.version = EverydayMenu::VERSION
|
9
|
+
spec.authors = ['Eric Henderson']
|
10
|
+
spec.email = ['henderea@gmail.com']
|
11
|
+
spec.description = %q{An easy way to define menu items and visually lay out menus for your OSX apps. Based strongly on the drink-menu gem that I couldn't get to work for me.}
|
12
|
+
spec.summary = %q{A more ruby way to create OS X menus in RubyMotion}
|
13
|
+
spec.homepage = 'https://github.com/henderea/everyday-menu'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
21
|
+
spec.add_development_dependency 'rake', '~> 10.0.0'
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class AppDelegate
|
2
|
+
|
3
|
+
def applicationDidFinishLaunching(notification)
|
4
|
+
MainMenu.build!
|
5
|
+
|
6
|
+
MainMenu[:app].subscribe :quit do |_|
|
7
|
+
NSApp.terminate(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
MainMenu[:file].subscribe :new do |_|
|
11
|
+
puts 'new'
|
12
|
+
end
|
13
|
+
|
14
|
+
MainMenu[:file].subscribe :close do |_|
|
15
|
+
puts 'close'
|
16
|
+
end
|
17
|
+
|
18
|
+
MainMenu[:file].subscribe :open do |_|
|
19
|
+
puts 'open'
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class MainMenu
|
2
|
+
extend EverydayMenu::MenuBuilder
|
3
|
+
|
4
|
+
menuItem :quit, 'Quit', key_equivalent: 'q'
|
5
|
+
menuItem :open, 'Open', key_equivalent: 'o'
|
6
|
+
menuItem :new, 'New'
|
7
|
+
|
8
|
+
menuItem :close, 'Close', key_equivalent: 'w'
|
9
|
+
|
10
|
+
mainMenu :app, 'Blah' do
|
11
|
+
quit
|
12
|
+
end
|
13
|
+
|
14
|
+
mainMenu :file, 'File' do
|
15
|
+
new
|
16
|
+
open
|
17
|
+
___
|
18
|
+
close
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
unless defined?(Motion::Project::Config)
|
2
|
+
raise 'The everyday-menu gem must be required within a RubyMotion project Rakefile.'
|
3
|
+
end
|
4
|
+
|
5
|
+
Motion::Project::App.setup do |app|
|
6
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'everyday-menu/**/*.rb')).each do |file|
|
7
|
+
app.files.unshift(file)
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module EverydayMenu
|
2
|
+
class Menu
|
3
|
+
attr_reader :needsMenuItem
|
4
|
+
|
5
|
+
def self.create(label, title, options = {}, &block)
|
6
|
+
new(label, &block).tap { |menu|
|
7
|
+
menu[:label] = label
|
8
|
+
menu[:title] = title
|
9
|
+
options.each { |option| menu[option[0]] = option[1] }
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(label, &block)
|
14
|
+
@label = label
|
15
|
+
@builder = block
|
16
|
+
@menu = NSMenu.alloc.init
|
17
|
+
@menuItems = MenuItemList.new(@menu)
|
18
|
+
@needsMenuItem = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def menuItemFromMenu!
|
22
|
+
@mainMenuItem ||= MenuItem.create(self[:label], self[:title], submenu: self)
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
alias :menu_item_for_menu! :menuItemFromMenu!
|
27
|
+
|
28
|
+
def menuItem
|
29
|
+
@mainMenuItem.item
|
30
|
+
end
|
31
|
+
|
32
|
+
alias :menu_item :menuItem
|
33
|
+
|
34
|
+
def subscribe(label, &block)
|
35
|
+
self.items[label].subscribe(&block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def <<(item)
|
39
|
+
@menuItems << item
|
40
|
+
end
|
41
|
+
|
42
|
+
def has(key)
|
43
|
+
name = key_to_name(key, 'has')
|
44
|
+
begin
|
45
|
+
self.send(name)
|
46
|
+
rescue NoMethodError
|
47
|
+
@menu.send(name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def is(key)
|
52
|
+
name = key_to_name(key, 'is')
|
53
|
+
begin
|
54
|
+
self.send(name)
|
55
|
+
rescue NoMethodError
|
56
|
+
@menu.send(name)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def [](key)
|
61
|
+
name = key_to_name(key)
|
62
|
+
begin
|
63
|
+
self.send(name)
|
64
|
+
rescue NoMethodError
|
65
|
+
@menu.send(name)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def []=(key, value)
|
70
|
+
name = key_to_name(key, 'set')
|
71
|
+
begin
|
72
|
+
self.send(name, value)
|
73
|
+
rescue NoMethodError
|
74
|
+
@menu.send(name, value)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def key_to_name(key, prefix = nil)
|
79
|
+
rval = key.to_s.gsub(/_(\w)/) { |_| $1.upcase }
|
80
|
+
prefix.nil? ? rval : "#{prefix}#{rval[0].upcase}#{rval[1..-1]}"
|
81
|
+
end
|
82
|
+
|
83
|
+
def label
|
84
|
+
@label ||= nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def setLabel(label)
|
88
|
+
@label = label
|
89
|
+
end
|
90
|
+
|
91
|
+
alias :label= :setLabel
|
92
|
+
|
93
|
+
def items
|
94
|
+
@menuItems
|
95
|
+
end
|
96
|
+
|
97
|
+
def menu
|
98
|
+
@menu
|
99
|
+
end
|
100
|
+
|
101
|
+
def builder
|
102
|
+
@builder
|
103
|
+
end
|
104
|
+
|
105
|
+
def isMainMenu
|
106
|
+
@needsMenuItem
|
107
|
+
end
|
108
|
+
|
109
|
+
alias :mainMenu :isMainMenu
|
110
|
+
alias :main_menu? :isMainMenu
|
111
|
+
|
112
|
+
def setMainMenu(value)
|
113
|
+
@needsMenuItem = value
|
114
|
+
end
|
115
|
+
|
116
|
+
alias :main_menu= :setMainMenu
|
117
|
+
end
|
118
|
+
|
119
|
+
class MenuItemList
|
120
|
+
def initialize(menu)
|
121
|
+
@menuItems = {}
|
122
|
+
@menu = menu
|
123
|
+
end
|
124
|
+
|
125
|
+
def <<(item)
|
126
|
+
previousItemTag = @menuItems.keys.last || 0
|
127
|
+
item[:tag] = previousItemTag + 1
|
128
|
+
@menuItems[item[:tag]] = item
|
129
|
+
@menu.addItem item.menuItem
|
130
|
+
end
|
131
|
+
|
132
|
+
def [](labelOrTag)
|
133
|
+
(labelOrTag.is_a? Fixnum) ? @menuItems[labelOrTag] : @menuItems.values.find { |item| item.label == labelOrTag }
|
134
|
+
end
|
135
|
+
|
136
|
+
def selectItem(label)
|
137
|
+
item = self[label]
|
138
|
+
item.execute
|
139
|
+
end
|
140
|
+
|
141
|
+
alias :select_item :selectItem
|
142
|
+
|
143
|
+
def selectItemByMember(member)
|
144
|
+
item = @menuItems.values.find do |i|
|
145
|
+
i[:represented_object] == member
|
146
|
+
end
|
147
|
+
item.execute
|
148
|
+
end
|
149
|
+
|
150
|
+
alias :select_item_by_member :selectItemByMember
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module EverydayMenu
|
2
|
+
module MenuBuilder
|
3
|
+
class Context < BasicObject
|
4
|
+
def initialize(menu, menuItems={})
|
5
|
+
@menu = menu
|
6
|
+
@menuItems = menuItems
|
7
|
+
end
|
8
|
+
|
9
|
+
def ___
|
10
|
+
@menu << MenuItem.separator
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing(meth, *args)
|
14
|
+
if @menuItems.key?(meth)
|
15
|
+
@menu << @menuItems[meth]
|
16
|
+
else
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def <<(item)
|
23
|
+
@menuItems ||= {}
|
24
|
+
@menuItems[item.label] = item
|
25
|
+
end
|
26
|
+
|
27
|
+
def menuItem(label, title, options = {})
|
28
|
+
options[:submenu] = @menus[options[:submenu]] if options.has_key?(:submenu)
|
29
|
+
self << MenuItem.create(label, title, options)
|
30
|
+
end
|
31
|
+
|
32
|
+
alias :menu_item :menuItem
|
33
|
+
|
34
|
+
def mainMenu(label, title, options = {}, &block)
|
35
|
+
options[:main_menu] = true
|
36
|
+
@menus ||= {}
|
37
|
+
@menus[label] = Menu.create(label, title, options, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
alias :main_menu :mainMenu
|
41
|
+
|
42
|
+
def menu(label, title, options = {}, &block)
|
43
|
+
options[:main_menu] = false
|
44
|
+
@menus ||= {}
|
45
|
+
@menus[label] = Menu.create(label, title, options, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
def [](label)
|
49
|
+
@menus[label]
|
50
|
+
end
|
51
|
+
|
52
|
+
def build!
|
53
|
+
@menus.values.each do |menu|
|
54
|
+
context = Context.new(menu, @menuItems.dup)
|
55
|
+
context.instance_eval(&menu.builder) if menu.builder
|
56
|
+
if menu.is :main_menu
|
57
|
+
@mainMenu ||= NSMenu.new
|
58
|
+
@mainMenu.addItem menu.menuItemFromMenu!.menuItem
|
59
|
+
end
|
60
|
+
end
|
61
|
+
setupMainMenu if @mainMenu
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def setupMainMenu
|
67
|
+
NSApp.mainMenu = @mainMenu
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module EverydayMenu
|
2
|
+
class MenuItem
|
3
|
+
def self.create(label, title, options = {})
|
4
|
+
new.tap { |item|
|
5
|
+
item[:label] = label
|
6
|
+
item[:title] = title
|
7
|
+
options.each { |option| item[option[0]] = option[1] }
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.separator
|
12
|
+
@@separatorId ||= 0
|
13
|
+
@@separatorId += 1
|
14
|
+
label = :"separator#{@@separatorId}"
|
15
|
+
new(NSMenuItem.separatorItem).tap do |item|
|
16
|
+
item.label = label
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.separatorItem
|
21
|
+
self.separator
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(menuItem=nil)
|
25
|
+
@menuItem = menuItem || NSMenuItem.alloc.init
|
26
|
+
end
|
27
|
+
|
28
|
+
def has(key)
|
29
|
+
name = key_to_name(key, 'has')
|
30
|
+
begin
|
31
|
+
self.send(name)
|
32
|
+
rescue NoMethodError
|
33
|
+
@menuItem.send(name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def is(key)
|
38
|
+
name = key_to_name(key, 'is')
|
39
|
+
begin
|
40
|
+
self.send(name)
|
41
|
+
rescue NoMethodError
|
42
|
+
@menuItem.send(name)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def [](key)
|
47
|
+
name = key_to_name(key)
|
48
|
+
begin
|
49
|
+
self.send(name)
|
50
|
+
rescue NoMethodError
|
51
|
+
@menuItem.send(name)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def []=(key, value)
|
56
|
+
name = key_to_name(key, 'set')
|
57
|
+
begin
|
58
|
+
self.send(name, value)
|
59
|
+
rescue NoMethodError
|
60
|
+
@menuItem.send(name, value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def key_to_name(key, prefix = nil)
|
65
|
+
rval = key.to_s.gsub(/_(\w)/) { |_| $1.upcase }
|
66
|
+
prefix.nil? ? rval : "#{prefix}#{rval[0].upcase}#{rval[1..-1]}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def setSubmenu(menu)
|
70
|
+
@menuItem.submenu = menu.menu
|
71
|
+
end
|
72
|
+
|
73
|
+
def menuItem
|
74
|
+
@menuItem
|
75
|
+
end
|
76
|
+
|
77
|
+
alias :menu_item :menuItem
|
78
|
+
alias :item :menuItem
|
79
|
+
|
80
|
+
def label
|
81
|
+
@label ||= nil
|
82
|
+
end
|
83
|
+
|
84
|
+
def setLabel(label)
|
85
|
+
@label = label
|
86
|
+
end
|
87
|
+
|
88
|
+
alias :label= :setLabel
|
89
|
+
|
90
|
+
def tag
|
91
|
+
@menuItem.tag
|
92
|
+
end
|
93
|
+
|
94
|
+
def setTag(tag)
|
95
|
+
@menuItem.tag = tag
|
96
|
+
end
|
97
|
+
|
98
|
+
alias :tag= :setTag
|
99
|
+
|
100
|
+
def subscribe(&block)
|
101
|
+
@menuItem.subscribe(&block)
|
102
|
+
end
|
103
|
+
|
104
|
+
def execute
|
105
|
+
@menuItem.runBlock(self)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class NSMenuItem
|
111
|
+
def subscribe(&block)
|
112
|
+
@blocks ||= []
|
113
|
+
@blocks << block
|
114
|
+
return if (self.target = self && self.action == :'runBlocks:')
|
115
|
+
@original_target = self.target
|
116
|
+
self.target = self
|
117
|
+
self.action = :'runBlock:'
|
118
|
+
end
|
119
|
+
|
120
|
+
def runBlock(sender)
|
121
|
+
@blocks.each { |block| block.call(sender) } unless @blocks.nil?
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
class TestMenu;
|
2
|
+
extend EverydayMenu::MenuBuilder;
|
3
|
+
end
|
4
|
+
class TestMenu2;
|
5
|
+
include EverydayMenu::MenuBuilder;
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'sugar for creating menus' do
|
9
|
+
|
10
|
+
it 'supports defining menu items' do
|
11
|
+
menuItem = TestMenu.menuItem :create_site, 'Create Site'
|
12
|
+
menuItem[:label].should.equal :create_site
|
13
|
+
menuItem[:title].should.equal 'Create Site'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'builds gives access to menu instance' do
|
17
|
+
TestMenu.menuItem :create_site, 'Create Site'
|
18
|
+
TestMenu.menu :main_menu, 'Main'
|
19
|
+
menu = TestMenu[:main_menu]
|
20
|
+
menu.should.be.an.instance_of EverydayMenu::Menu
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'allows creating a top-level menu' do
|
24
|
+
menu = TestMenu.menu :main_menu, 'Blah'
|
25
|
+
menu.menu.should.be.an.instance_of NSMenu
|
26
|
+
menu[:title].should.equal 'Blah'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'evaluates menu\'s block to add items to menu' do
|
30
|
+
builder = TestMenu2.new
|
31
|
+
item1 = builder.menuItem :test_item1, 'Blah'
|
32
|
+
item2 = builder.menuItem :test_item2, 'Blah'
|
33
|
+
|
34
|
+
builder.menu :main_menu, 'Main' do
|
35
|
+
test_item1
|
36
|
+
___
|
37
|
+
test_item2
|
38
|
+
end
|
39
|
+
|
40
|
+
builder.build!
|
41
|
+
|
42
|
+
builder[:main_menu][:test_item1].should.equal item1
|
43
|
+
builder[:main_menu][:test_item2].should.equal item2
|
44
|
+
|
45
|
+
builder[:main_menu][2].is(:separator_item).should.be.true
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'supports generating an NSApp\'s mainMenu items' do
|
49
|
+
builder = TestMenu2.new
|
50
|
+
testItem1 = builder.menuItem :test_item1, 'Blah 1'
|
51
|
+
testItem2 = builder.menuItem :test_item2, 'Blah 2'
|
52
|
+
|
53
|
+
menu1 = builder.mainMenu :menu1, 'Menu 1' do
|
54
|
+
test_item1
|
55
|
+
end
|
56
|
+
|
57
|
+
menu2 = builder.mainMenu :menu2, 'Menu 2' do
|
58
|
+
test_item2
|
59
|
+
end
|
60
|
+
|
61
|
+
builder.build!
|
62
|
+
|
63
|
+
mainMenu = NSApp.mainMenu
|
64
|
+
|
65
|
+
menuItem = mainMenu.itemArray[0]
|
66
|
+
puts "menu1 title: #{menu1.title.inspect}"
|
67
|
+
puts "menuItem title: #{menuItem.title.inspect}"
|
68
|
+
menuItem.title.should.equal menu1[:title]
|
69
|
+
menuItem.submenu.title.should.equal menu1[:title]
|
70
|
+
menuItem.submenu.itemArray[0].title.should.equal('Blah 1')
|
71
|
+
|
72
|
+
menuItem = mainMenu.itemArray[1]
|
73
|
+
menuItem.title.should.equal menu2[:title]
|
74
|
+
menuItem.submenu.title.should.equal menu2[:title]
|
75
|
+
menuItem.submenu.itemArray[0].title.should.equal('Blah 2')
|
76
|
+
end
|
77
|
+
|
78
|
+
describe 'builder\'s context class' do
|
79
|
+
|
80
|
+
Context = EverydayMenu::MenuBuilder::Context
|
81
|
+
|
82
|
+
it 'adds item to menu by calling method named after item\'s label' do
|
83
|
+
menu = EverydayMenu::Menu.create :test, 'Test'
|
84
|
+
item = EverydayMenu::MenuItem.create :test_item, 'Blah'
|
85
|
+
context = Context.new(menu, { test_item: item })
|
86
|
+
|
87
|
+
menu[:test_item].should.be.nil
|
88
|
+
|
89
|
+
context.test_item
|
90
|
+
|
91
|
+
menu[:test_item].should.equal item
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'creates separators from ___' do
|
95
|
+
menu = EverydayMenu::Menu.create :test, 'Test'
|
96
|
+
|
97
|
+
menu[1].should.be.nil
|
98
|
+
|
99
|
+
Context.new(menu).__send__ :'___'
|
100
|
+
|
101
|
+
menu[1].is[:separator_item].should.be.true
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
describe 'creating menu items' do
|
2
|
+
|
3
|
+
it 'keeps the title and label' do
|
4
|
+
m = EverydayMenu::MenuItem.create :create_site, 'Create Site'
|
5
|
+
m[:label].should.equal :create_site
|
6
|
+
m[:title].should.equal 'Create Site'
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'has an instance of NSMenuItem' do
|
10
|
+
m = EverydayMenu::MenuItem.create :create_site, 'Create Site'
|
11
|
+
m.menuItem.should.be.a.instance_of NSMenuItem
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'allows extra options to create method' do
|
15
|
+
m = EverydayMenu::MenuItem.create :create_site, 'Create Site', enabled: false, tag: 1, state: NSOnState
|
16
|
+
m.menuItem.title.should.equal m.title
|
17
|
+
m.menuItem.isEnabled.should.equal m.isEnabled
|
18
|
+
m.menuItem.tag.should.equal m.tag
|
19
|
+
m.menuItem.image.should.equal m.image
|
20
|
+
m.menuItem.state.should.equal m.state
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'allows creating separator items' do
|
24
|
+
item = EverydayMenu::MenuItem.separatorItem
|
25
|
+
item.is(:separator_item).should.be.true
|
26
|
+
end
|
27
|
+
|
28
|
+
def separator_id(item)
|
29
|
+
item.label[/\d+$/].to_i
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'generates unique label for separators' do
|
33
|
+
item1 = EverydayMenu::MenuItem.separatorItem
|
34
|
+
item2 = EverydayMenu::MenuItem.separatorItem
|
35
|
+
separator_id(item2).should.equal separator_id(item1) + 1
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/spec/menu_spec.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
describe 'creating menus' do
|
2
|
+
|
3
|
+
|
4
|
+
it 'creates an NSMenu instance' do
|
5
|
+
menu = EverydayMenu::Menu.create :test, 'Test'
|
6
|
+
menu.menu.should.be.an.instance_of NSMenu
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'sets title on NSMenu instance' do
|
10
|
+
menu = EverydayMenu::Menu.create :test_menu, 'title'
|
11
|
+
menu[:title].should.equal 'title'
|
12
|
+
menu.menu.title.should.equal menu[:title]
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'automatically adds NSMenuItem instance to NSMenu' do
|
16
|
+
menu = EverydayMenu::Menu.create :test, 'Test'
|
17
|
+
item = EverydayMenu::MenuItem.create :test_item, 'Blah'
|
18
|
+
menu << item
|
19
|
+
|
20
|
+
menu[:item_array].should.include item.menuItem
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'sets a unique tag on each menu item as it is added' do
|
25
|
+
menu = EverydayMenu::Menu.create :test, 'Test'
|
26
|
+
item1 = EverydayMenu::MenuItem.create :test_item1, 'Blah'
|
27
|
+
item2 = EverydayMenu::MenuItem.create :test_item2, 'Diddy'
|
28
|
+
|
29
|
+
menu << item1
|
30
|
+
menu << item2
|
31
|
+
|
32
|
+
item1.menuItem.tag.should.equal 1
|
33
|
+
item2.menuItem.tag.should.equal 2
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'allows looking up menu items by label' do
|
38
|
+
menu = EverydayMenu::Menu.create :test, 'Test'
|
39
|
+
item = EverydayMenu::MenuItem.create :test_item, 'Blah'
|
40
|
+
|
41
|
+
menu << item
|
42
|
+
|
43
|
+
menu[item.label].should.equal item
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'allows selecting an item by its label' do
|
47
|
+
handled = false
|
48
|
+
menu = EverydayMenu::Menu.create :test, 'Test'
|
49
|
+
item = EverydayMenu::MenuItem.create :test_item, 'Blah'
|
50
|
+
|
51
|
+
menu << item
|
52
|
+
|
53
|
+
menu.subscribe :test_item do |_|
|
54
|
+
handled = true
|
55
|
+
end
|
56
|
+
|
57
|
+
menu.selectItem :test_item
|
58
|
+
|
59
|
+
handled.should.be.true
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'allows looking up menu items by tag' do
|
63
|
+
menu = EverydayMenu::Menu.create :test, 'Test'
|
64
|
+
item = EverydayMenu::MenuItem.create :test_item, 'Blah'
|
65
|
+
|
66
|
+
menu << item
|
67
|
+
|
68
|
+
menu[1].should.equal item
|
69
|
+
end
|
70
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: everyday-menu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Henderson
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 10.0.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 10.0.0
|
41
41
|
description: An easy way to define menu items and visually lay out menus for your
|
42
42
|
OSX apps. Based strongly on the drink-menu gem that I couldn't get to work for me.
|
43
43
|
email:
|
@@ -45,7 +45,23 @@ email:
|
|
45
45
|
executables: []
|
46
46
|
extensions: []
|
47
47
|
extra_rdoc_files: []
|
48
|
-
files:
|
48
|
+
files:
|
49
|
+
- ".gitignore"
|
50
|
+
- Gemfile
|
51
|
+
- LICENSE.txt
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- everyday-menu.gemspec
|
55
|
+
- examples/basic_main_menu/app_delegate.rb
|
56
|
+
- examples/basic_main_menu/main_menu.rb
|
57
|
+
- lib/everyday-menu.rb
|
58
|
+
- lib/everyday-menu/menu.rb
|
59
|
+
- lib/everyday-menu/menu_builder.rb
|
60
|
+
- lib/everyday-menu/menu_item.rb
|
61
|
+
- lib/everyday-menu/version.rb
|
62
|
+
- spec/menu_builder_spec.rb
|
63
|
+
- spec/menu_item_spec.rb
|
64
|
+
- spec/menu_spec.rb
|
49
65
|
homepage: https://github.com/henderea/everyday-menu
|
50
66
|
licenses:
|
51
67
|
- MIT
|
@@ -70,5 +86,8 @@ rubygems_version: 2.2.0
|
|
70
86
|
signing_key:
|
71
87
|
specification_version: 4
|
72
88
|
summary: A more ruby way to create OS X menus in RubyMotion
|
73
|
-
test_files:
|
89
|
+
test_files:
|
90
|
+
- spec/menu_builder_spec.rb
|
91
|
+
- spec/menu_item_spec.rb
|
92
|
+
- spec/menu_spec.rb
|
74
93
|
has_rdoc:
|