menu-motion 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/codelation/menu-motion.svg)](https://travis-ci.org/codelation/menu-motion)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/codelation/menu-motion.png)](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:
|