]> git.gir.st - VimFx.git/blob - extension/lib/button.coffee
Merge branch 'master' into develop
[VimFx.git] / extension / lib / button.coffee
1 ###
2 # Copyright Anton Khodakivskiy 2012, 2013, 2014.
3 # Copyright Simon Lydell 2013, 2014.
4 #
5 # This file is part of VimFx.
6 #
7 # VimFx is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # VimFx is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with VimFx. If not, see <http://www.gnu.org/licenses/>.
19 ###
20
21 { getPref
22 , setPref } = require('./prefs')
23 { injectHelp } = require('./help')
24 utils = require('./utils')
25 _ = require('./l10n')
26
27 BUTTON_ID = 'vimfx-toolbar-button'
28 MENUPOPUP_ID = 'vimfx-menupopup'
29 MENU_ITEM_PREF = 'vimfx-menu-item-preferences'
30 MENU_ITEM_HELP = 'vimfx-menu-item-help'
31 TEXTBOX_BLACKLIST_ID = 'vimfx-textbox-blacklist-id'
32 BUTTON_BLACKLIST_ID = 'vimfx-button-blacklist-id'
33
34 $ = (document, selector) -> document.getElementById(selector)
35 $$ = (document, selector) -> document.querySelectorAll(selector)
36
37 positions = {}
38
39 setButtonInstallPosition = (toolbarId, beforeId) ->
40 positions[BUTTON_ID] = {toolbarId, beforeId}
41
42 addToolbarButton = (vimBucket, window) ->
43 document = window.document
44 win = document.querySelector('window')
45
46 button = createButton(vimBucket, window)
47
48 # Namespace to put the VimFx state on, for example.
49 button.VimFx = {}
50
51 restorePosition(document, button)
52
53 if tabWindow = utils.getCurrentTabWindow(window)
54 blacklisted = utils.isBlacklisted(tabWindow.location.href)
55 disabled = getPref('disabled')
56 updateToolbarButton(window, {disabled, blacklisted})
57
58 module.onShutdown(->
59 button.remove()
60 $(document, 'navigator-toolbox').palette.removeChild(button)
61 )
62
63 createButton = (vimBucket, window) ->
64 document = window.document
65
66 button = utils.createElement(document, 'toolbarbutton', {
67 id: BUTTON_ID
68 type: 'menu-button'
69 label: 'VimFx'
70 class: 'toolbarbutton-1'
71 })
72
73 menupopup = createMenupopup(window, button)
74
75 onButtonCommand = (event) ->
76 switch
77 when button.VimFx.blacklisted
78 menupopup.openPopup(button, 'after_start')
79 when button.VimFx.insertMode
80 return unless currentTabWindow = utils.getEventCurrentTabWindow(event)
81 return unless vim = vimBucket.get(currentTabWindow)
82 updateToolbarButton(window, {insertMode: false})
83 vim.enterMode('normal')
84 else
85 disabled = not getPref('disabled')
86 setPref('disabled', disabled)
87 updateToolbarButton(window, {disabled})
88
89 event.stopPropagation()
90
91 button.addEventListener('command', onButtonCommand, false)
92
93 return button
94
95 createMenupopup = (window, button) ->
96 document = window.document
97
98 blacklistTextbox = utils.createElement(document, 'textbox', {
99 id: TEXTBOX_BLACKLIST_ID
100 })
101 blacklistButton = utils.createElement(document, 'toolbarbutton', {
102 id: BUTTON_BLACKLIST_ID
103 class: 'toolbarbutton-1'
104 })
105 blacklistControls = utils.createElement(document, 'hbox')
106 blacklistControls.appendChild(blacklistTextbox)
107 blacklistControls.appendChild(blacklistButton)
108
109 itemPreferences = utils.createElement(document, 'menuitem', {
110 id: MENU_ITEM_PREF
111 label: _('item_preferences')
112 })
113
114 itemHelp = utils.createElement(document, 'menuitem', {
115 id: MENU_ITEM_HELP
116 label: _('help_title')
117 })
118
119 menupopup = utils.createElement(document, 'menupopup', {
120 id: MENUPOPUP_ID
121 ignorekeys: true
122 })
123 menupopup.appendChild(blacklistControls)
124 menupopup.appendChild(itemPreferences)
125 menupopup.appendChild(itemHelp)
126
127 onPopupShowing = (event) ->
128 return unless tabWindow = utils.getCurrentTabWindow(window)
129
130 if button.VimFx.blacklisted
131 matchingRules = utils.getMatchingBlacklistRules(tabWindow.location.href)
132 blacklistTextbox.value = matchingRules.join(', ')
133 blacklistTextbox.setAttribute('readonly', true)
134 blacklistButton.setAttribute('tooltiptext',
135 _('item_blacklist_button_inverse_tooltip'))
136 blacklistButton.style.listStyleImage = iconUrl('blacklist_inverse')
137 else
138 blacklistTextbox.value =
139 # In `about:` pages, the `host` property is an empty string. Fall back
140 # to the whole URL.
141 if tabWindow.location.host != ''
142 "*#{ tabWindow.location.host }*"
143 else
144 tabWindow.location.href
145 blacklistTextbox.removeAttribute('readonly')
146 blacklistButton.setAttribute('tooltiptext',
147 _('item_blacklist_button_tooltip'))
148 blacklistButton.style.listStyleImage = iconUrl('blacklist')
149
150 onBlacklistButtonCommand = (event) ->
151 return unless tabWindow = utils.getCurrentTabWindow(window)
152
153 if button.VimFx.blacklisted
154 utils.updateBlacklist({remove: blacklistTextbox.value})
155 else
156 utils.updateBlacklist({add: blacklistTextbox.value})
157
158 menupopup.hidePopup()
159
160 tabWindow.location.reload(false)
161
162 event.stopPropagation()
163
164 onPreferencesCommand = (event) ->
165 id = encodeURIComponent(utils.ADDON_ID)
166 window.BrowserOpenAddonsMgr("addons://detail/#{ id }/preferences")
167
168 event.stopPropagation()
169
170 onHelpCommand = (event) ->
171 if tabWindow = utils.getCurrentTabWindow(window)
172 injectHelp(tabWindow.document, require('./modes'))
173
174 event.stopPropagation()
175
176 menupopup.addEventListener('popupshowing', onPopupShowing, false)
177 blacklistButton.addEventListener('command', onBlacklistButtonCommand, false)
178 itemPreferences.addEventListener('command', onPreferencesCommand, false)
179 itemHelp.addEventListener('command', onHelpCommand, false)
180
181 button.appendChild(menupopup)
182 return menupopup
183
184 restorePosition = (document, button) ->
185 $(document, 'navigator-toolbox').palette.appendChild(button)
186
187 for tb in $$(document, 'toolbar')
188 currentset = tb.getAttribute('currentset').split(',')
189 idx = currentset.indexOf(button.id)
190 if idx != -1
191 toolbar = tb
192 break
193
194 # Saved position not found, using the default one, after persisting it.
195 if not toolbar and button.id of positions
196 { toolbarId, beforeId } = positions[button.id]
197 if toolbar = $(document, toolbarId)
198 [ currentset, idx ] = persist(document, toolbar, button.id, beforeId)
199
200 if toolbar and idx != -1
201 # Inserting the button before the first item in `currentset`
202 # after `idx` that is present in the document.
203 for id in currentset[idx + 1..]
204 if before = $(document, id)
205 toolbar.insertItem(button.id, before)
206 return
207
208 toolbar.insertItem(button.id)
209
210 persist = (document, toolbar, buttonId, beforeId) ->
211 currentset = toolbar.currentSet.split(',')
212 idx = if beforeId then currentset.indexOf(beforeId) else -1
213 if idx != -1
214 currentset.splice(idx, 0, buttonId)
215 else
216 currentset.push(buttonId)
217
218 toolbar.setAttribute('currentset', currentset.join(','))
219 document.persist(toolbar.id, 'currentset')
220 return [currentset, idx]
221
222 updateToolbarButton = (window, { disabled, blacklisted, insertMode }) ->
223 return unless button = $(window.document, BUTTON_ID)
224
225 button.VimFx.disabled = disabled if disabled?
226 button.VimFx.blacklisted = blacklisted if blacklisted?
227 button.VimFx.insertMode = insertMode if insertMode?
228
229 [ icon, tooltip ] = switch
230 when button.VimFx.disabled
231 ['grey', _('button_tooltip_disabled')]
232 when button.VimFx.blacklisted
233 ['red', _('button_tooltip_blacklisted')]
234 when button.VimFx.insertMode
235 keys = require('./modes')['insert'].commands['exit'].keys().join(', ')
236 ['grey', _('button_tooltip_insertMode', keys)]
237 else
238 ['normal', _('button_tooltip_enabled')]
239
240 button.style.listStyleImage = iconUrl(icon)
241 button.setAttribute('tooltiptext', tooltip)
242
243 iconUrl = (kind) ->
244 url = utils.getResourceURI("resources/icon16-#{ kind }.png").spec
245 return "url(#{ url })"
246
247 exports.setButtonInstallPosition = setButtonInstallPosition
248 exports.addToolbarButton = addToolbarButton
249 exports.updateToolbarButton = updateToolbarButton
Imprint / Impressum