menu-motion 0.0.2 → 0.1.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 +4 -4
- data/README.md +63 -11
- data/lib/menu_motion/menu.rb +27 -30
- data/lib/menu_motion/menu_item.rb +106 -0
- data/lib/menu_motion/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 728776dec6261eb85e60dbb1d452dd1605257f62
|
4
|
+
data.tar.gz: 233be399ec008b1eb71af6146684568fc335f521
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f27f0192f9ef7bb1f1c2592873fa5bda6e949410b40bcc2f3d093b79bbeae54b34ce42e69c8a5a0cfe6d29e01bf7893b787e506d5d616cf00bb50d02be529ba
|
7
|
+
data.tar.gz: e57a001a46dc0fc2271f7f1b44fa541e0a247a0de2db09caf75d5891c192c2ba7ac9d37299fcd0108611a8738224dc00554b1ba444fcfd60d1ba0275f3b0b5be
|
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# MenuMotion
|
2
2
|
|
3
|
-
|
3
|
+
[](https://travis-ci.org/codelation/menu-motion)
|
4
|
+
[](https://codeclimate.com/github/codelation/menu-motion)
|
5
|
+
|
6
|
+
MenuMotion is a [RubyMotion](http://www.rubymotion.com) wrapper inspired by [Formotion](https://github.com/clayallsopp/formotion) for creating OS X status bar menus with a syntax that should feel familiar if you've used Formotion.
|
4
7
|
|
5
8
|
## Installation
|
6
9
|
|
@@ -67,12 +70,10 @@ menu = MenuMotion::Menu.new({
|
|
67
70
|
}, {
|
68
71
|
rows: [{
|
69
72
|
title: "About MenuMotion",
|
70
|
-
|
71
|
-
action: "about"
|
73
|
+
action: "orderFrontStandardAboutPanel:"
|
72
74
|
}, {
|
73
75
|
title: "Quit",
|
74
|
-
|
75
|
-
action: "quit"
|
76
|
+
action: "terminate:"
|
76
77
|
}]
|
77
78
|
}]
|
78
79
|
})
|
@@ -137,23 +138,69 @@ def action_with_sender(sender)
|
|
137
138
|
end
|
138
139
|
```
|
139
140
|
|
141
|
+
### Keyboard Shortcuts
|
142
|
+
|
143
|
+
Keyboard shortcuts can be assigned to menu items with a simple string.
|
144
|
+
The string can include multiple modifier keys, followed by the final key to be assigned (`{modifier+}{modifier+}{key}`):
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
menu = MenuMotion::Menu.new({
|
148
|
+
rows: [{
|
149
|
+
title: "Item 1",
|
150
|
+
shortcut: "command+1"
|
151
|
+
}, {
|
152
|
+
title: "Item 2",
|
153
|
+
shortcut: "control+shift+2"
|
154
|
+
}]
|
155
|
+
})
|
156
|
+
```
|
157
|
+
|
158
|
+
#### Modifier Key Options
|
159
|
+
|
160
|
+
- **`shift`**
|
161
|
+
- **`control`**, `ctl`, `ctrl`
|
162
|
+
- **`option`**, `opt`, `alt`, `alternate`
|
163
|
+
- **`command`**, `cmd`
|
164
|
+
|
165
|
+
### Validation
|
166
|
+
|
167
|
+
MenuMotion implements the [NSMenuValidation](https://developer.apple.com/library/mac/documentation/cocoa/reference/applicationkit/Protocols/NSMenuValidation_Protocol/Reference/Reference.html) protocol. Pass a proc to a menu item on `validate`:
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
menu = MenuMotion::Menu.new({
|
171
|
+
rows: [{
|
172
|
+
title: "Menu item",
|
173
|
+
tag: :main_item
|
174
|
+
rows: [{
|
175
|
+
title: "Submenu item 1",
|
176
|
+
tag: :submenu_item1,
|
177
|
+
target: self,
|
178
|
+
action: "do_something:",
|
179
|
+
validate: ->(menu_item) {
|
180
|
+
true # or false
|
181
|
+
}
|
182
|
+
}]
|
183
|
+
}]
|
184
|
+
})
|
185
|
+
```
|
186
|
+
|
140
187
|
### Updating Menu Items
|
141
188
|
|
142
|
-
Assign
|
189
|
+
Assign tags to menu items that will need to be updated.
|
143
190
|
|
144
191
|
```ruby
|
145
192
|
menu = MenuMotion::Menu.new({
|
146
193
|
rows: [{
|
147
194
|
title: "Menu item",
|
148
|
-
|
195
|
+
tag: :main_item
|
149
196
|
rows: [{
|
150
197
|
title: "Submenu item 1",
|
151
|
-
|
198
|
+
tag: :submenu_item1,
|
152
199
|
target: self,
|
153
200
|
action: "do_something:"
|
154
201
|
}, {
|
155
202
|
title: "Submenu item 2",
|
156
|
-
|
203
|
+
tag: :submenu_item2,
|
157
204
|
target: self,
|
158
205
|
action: "do_something:"
|
159
206
|
}]
|
@@ -161,13 +208,13 @@ menu = MenuMotion::Menu.new({
|
|
161
208
|
})
|
162
209
|
|
163
210
|
# Let's update the first item's title:
|
164
|
-
menu.
|
211
|
+
menu.update_item_with_tag(:main_item, {
|
165
212
|
title: "Hello World"
|
166
213
|
})
|
167
214
|
|
168
215
|
# And give the first submenu item a submenu.
|
169
216
|
# The target and action will not be used if a submenu is defined.
|
170
|
-
menu.
|
217
|
+
menu.update_item_with_tag(:submenu_item1, {
|
171
218
|
rows: [{
|
172
219
|
title: "Click me",
|
173
220
|
target: self,
|
@@ -176,6 +223,11 @@ menu.update(:submenu_item1, {
|
|
176
223
|
})
|
177
224
|
```
|
178
225
|
|
226
|
+
## TODO
|
227
|
+
|
228
|
+
- Menu Item Icons
|
229
|
+
- Keyboard Shortcuts
|
230
|
+
|
179
231
|
## Contributing
|
180
232
|
|
181
233
|
1. Fork it
|
data/lib/menu_motion/menu.rb
CHANGED
@@ -2,34 +2,25 @@ module MenuMotion
|
|
2
2
|
|
3
3
|
class Menu < NSMenu
|
4
4
|
|
5
|
-
attr_accessor :menu_items
|
6
|
-
attr_accessor :root_menu
|
5
|
+
attr_accessor :menu_items, :root_menu
|
7
6
|
|
8
7
|
def add_rows_to_menu(menu, rows)
|
9
8
|
rows.each do |row|
|
10
|
-
|
11
|
-
menu_item
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
menu_item.setSubmenu(submenu)
|
19
|
-
elsif row[:rows]
|
20
|
-
submenu = MenuMotion::Menu.new({
|
21
|
-
rows: row[:rows]
|
22
|
-
}, self.root_menu || self)
|
23
|
-
menu_item.setSubmenu(submenu)
|
24
|
-
end
|
9
|
+
row[:root_menu] = WeakRef.new(self.root_menu || self)
|
10
|
+
menu_item = MenuMotion::MenuItem.new(row)
|
11
|
+
menu_item.target = self
|
12
|
+
menu_item.action = "perform_action:"
|
13
|
+
|
14
|
+
if tag = row[:tag]
|
15
|
+
tag = tag.to_sym
|
16
|
+
menu_item.tag = tag
|
25
17
|
|
26
|
-
if row[:key]
|
27
18
|
if self.root_menu
|
28
19
|
self.root_menu.menu_items ||= {}
|
29
|
-
self.root_menu.menu_items[
|
20
|
+
self.root_menu.menu_items[tag] = WeakRef.new(menu_item)
|
30
21
|
else
|
31
22
|
self.menu_items ||= {}
|
32
|
-
self.menu_items[
|
23
|
+
self.menu_items[tag] = WeakRef.new(menu_item)
|
33
24
|
end
|
34
25
|
end
|
35
26
|
|
@@ -59,7 +50,11 @@ module MenuMotion
|
|
59
50
|
end
|
60
51
|
|
61
52
|
def initialize(params = {}, root_menu = nil)
|
62
|
-
|
53
|
+
if params[:title]
|
54
|
+
initWithTitle(params[:title])
|
55
|
+
else
|
56
|
+
super()
|
57
|
+
end
|
63
58
|
|
64
59
|
self.root_menu = root_menu
|
65
60
|
self.build_menu_from_params(self, params)
|
@@ -67,22 +62,24 @@ module MenuMotion
|
|
67
62
|
self
|
68
63
|
end
|
69
64
|
|
70
|
-
def
|
65
|
+
def item_with_tag(tag)
|
71
66
|
@menu_items ||= {}
|
72
|
-
@menu_items[
|
67
|
+
@menu_items[tag.to_sym]
|
73
68
|
end
|
74
69
|
|
75
|
-
def
|
76
|
-
menu_item
|
70
|
+
def perform_action(menu_item)
|
71
|
+
menu_item.perform_action
|
72
|
+
end
|
77
73
|
|
78
|
-
|
79
|
-
menu_item
|
80
|
-
menu_item.
|
74
|
+
def update_item_with_tag(tag, params)
|
75
|
+
menu_item = self.item_with_tag(tag)
|
76
|
+
menu_item.update(params)
|
77
|
+
end
|
81
78
|
|
82
|
-
|
79
|
+
def validateMenuItem(menu_item)
|
80
|
+
menu_item.valid?
|
83
81
|
end
|
84
82
|
|
85
83
|
end
|
86
84
|
|
87
85
|
end
|
88
|
-
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module MenuMotion
|
2
|
+
|
3
|
+
class MenuItem < NSMenuItem
|
4
|
+
|
5
|
+
attr_accessor :item_action, :item_target,
|
6
|
+
:root_menu, :tag, :validate
|
7
|
+
|
8
|
+
def initialize(params = {})
|
9
|
+
super()
|
10
|
+
update(params)
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def perform_action
|
15
|
+
if self.valid? && self.valid_target_and_action?
|
16
|
+
if self.item_action.to_s.end_with?(":")
|
17
|
+
self.item_target.performSelector(self.item_action, withObject: self)
|
18
|
+
else
|
19
|
+
self.item_target.performSelector(self.item_action)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def update(params)
|
25
|
+
self.item_action = params[:action] if params.has_key?(:action)
|
26
|
+
self.item_target = params[:target] if params.has_key?(:target)
|
27
|
+
self.root_menu = params[:root_menu] if params.has_key?(:root_menu)
|
28
|
+
self.title = params[:title] if params.has_key?(:title)
|
29
|
+
self.validate = params[:validate] if params.has_key?(:validate)
|
30
|
+
|
31
|
+
# Set NSApp as the default target if no other target is given
|
32
|
+
if self.item_action && self.item_target.nil?
|
33
|
+
self.item_target = NSApp
|
34
|
+
end
|
35
|
+
|
36
|
+
# Setup submenu and keyboard shortcut
|
37
|
+
set_submenu_from_params(params)
|
38
|
+
set_keyboard_shortcut(params[:shortcut]) if params.has_key?(:shortcut)
|
39
|
+
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def valid?
|
44
|
+
if self.submenu || self.valid_target_and_action?
|
45
|
+
if self.validate.nil?
|
46
|
+
true
|
47
|
+
else
|
48
|
+
self.validate.call(self)
|
49
|
+
end
|
50
|
+
else
|
51
|
+
false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def valid_target_and_action?
|
56
|
+
self.item_target && self.item_action && self.item_target.respond_to?(self.item_action.gsub(":", ""))
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def set_keyboard_shortcut(shortcut)
|
62
|
+
if shortcut
|
63
|
+
keys = shortcut.gsub("-", "+").split("+")
|
64
|
+
key = keys.pop
|
65
|
+
modifier_mask = 0
|
66
|
+
modifier_keys = keys
|
67
|
+
|
68
|
+
modifier_keys.each do |modifier_key|
|
69
|
+
case modifier_key
|
70
|
+
when "alt", "alternate", "opt", "option"
|
71
|
+
modifier_mask |= NSAlternateKeyMask
|
72
|
+
when "cmd", "command"
|
73
|
+
modifier_mask |= NSCommandKeyMask
|
74
|
+
when "ctl", "ctrl", "control"
|
75
|
+
modifier_mask |= NSControlKeyMask
|
76
|
+
when "shift"
|
77
|
+
modifier_mask |= NSShiftKeyMask
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
self.setKeyEquivalent(key)
|
82
|
+
self.setKeyEquivalentModifierMask(modifier_mask)
|
83
|
+
else
|
84
|
+
self.setKeyEquivalent(nil)
|
85
|
+
self.setKeyEquivalentModifierMask(nil)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def set_submenu_from_params(params)
|
90
|
+
if params[:sections]
|
91
|
+
submenu = MenuMotion::Menu.new({
|
92
|
+
sections: params[:sections]
|
93
|
+
}, self.root_menu)
|
94
|
+
self.setSubmenu(submenu)
|
95
|
+
elsif params[:rows]
|
96
|
+
submenu = MenuMotion::Menu.new({
|
97
|
+
rows: params[:rows]
|
98
|
+
}, self.root_menu)
|
99
|
+
self.setSubmenu(submenu)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
data/lib/menu_motion/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: menu-motion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Pattison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -35,6 +35,7 @@ files:
|
|
35
35
|
- README.md
|
36
36
|
- lib/menu_motion.rb
|
37
37
|
- lib/menu_motion/menu.rb
|
38
|
+
- lib/menu_motion/menu_item.rb
|
38
39
|
- lib/menu_motion/version.rb
|
39
40
|
homepage: https://github.com/codelation/menu-motion
|
40
41
|
licenses:
|