]> git.gir.st - VimFx.git/blob - extension/packages/button.coffee
Change license to GPLv3
[VimFx.git] / extension / packages / 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 { commands } = require 'commands'
25 utils = require 'utils'
26 { unloader } = require 'unloader'
27 { _ } = require 'l10n'
28
29 KEYSET_ID = 'vimfx-keyset'
30 BUTTON_ID = 'vimfx-toolbar-button'
31 KEY_ID = 'vimfx-key'
32 MENUPOPUP_ID = 'vimfx-menupopup'
33 MENU_ITEM_PREF = 'vimfx-menu-item-preferences'
34 MENU_ITEM_HELP = 'vimfx-menu-item-help'
35 TEXTBOX_BLACKLIST_ID = 'vimfx-textbox-blacklist-id'
36 BUTTON_BLACKLIST_ID = 'vimfx-button-blacklist-id'
37
38 $ = (document, selector) -> document.getElementById(selector)
39 $$ = (document, selector) -> document.querySelectorAll(selector)
40
41 positions = {}
42
43 setButtonInstallPosition = (toolbarId, beforeId) ->
44 positions[BUTTON_ID] = {toolbarId, beforeId}
45
46 addToolbarButton = (vimBucket, window) ->
47 document = window.document
48 win = document.querySelector('window')
49
50 [ button, keyset ] = createButton(vimBucket, window)
51
52 # Namespace to put the VimFx state on, for example.
53 button.VimFx = {}
54
55 restorePosition(document, button)
56
57 if tabWindow = utils.getCurrentTabWindow(window)
58 blacklisted = utils.isBlacklisted(tabWindow.location.href)
59 disabled = getPref('disabled')
60 updateToolbarButton(window, {disabled, blacklisted})
61
62 win.appendChild(keyset)
63
64 unloader.add(->
65 button.remove()
66 keyset.remove()
67 $(document, 'navigator-toolbox').palette.removeChild(button)
68 )
69
70 createButton = (vimBucket, window) ->
71 document = window.document
72
73 button = utils.createElement(document, 'toolbarbutton', {
74 id: BUTTON_ID
75 type: 'menu-button'
76 label: 'VimFx'
77 class: 'toolbarbutton-1'
78 })
79
80 menupopup = createMenupopup(window, button)
81
82 onButtonCommand = (event) ->
83 switch
84 when button.VimFx.blacklisted
85 menupopup.openPopup(button, 'after_start')
86 when button.VimFx.insertMode
87 return unless currentTabWindow = utils.getEventCurrentTabWindow(event)
88 return unless vim = vimBucket.get(currentTabWindow)
89 updateToolbarButton(window, {insertMode: false})
90 vim.enterMode('normal')
91 else
92 disabled = not getPref('disabled')
93 setPref('disabled', disabled)
94 updateToolbarButton(window, {disabled})
95
96 event.stopPropagation()
97
98 button.addEventListener('command', onButtonCommand, false)
99
100 vimkey = utils.createElement(document, 'key', {
101 id: KEY_ID
102 key: 'V'
103 modifiers: 'shift,alt'
104 oncommand: 'void(0);'
105 })
106 vimkey.addEventListener('command', onButtonCommand, false)
107
108 keyset = utils.createElement(document, 'keyset', {id: KEYSET_ID})
109 keyset.appendChild(vimkey)
110
111 return [button, keyset]
112
113 createMenupopup = (window, button) ->
114 document = window.document
115
116 blacklistTextbox = utils.createElement(document, 'textbox', {
117 id: TEXTBOX_BLACKLIST_ID
118 })
119 blacklistButton = utils.createElement(document, 'toolbarbutton', {
120 id: BUTTON_BLACKLIST_ID
121 class: 'toolbarbutton-1'
122 })
123 blacklistControls = utils.createElement(document, 'hbox')
124 blacklistControls.appendChild(blacklistTextbox)
125 blacklistControls.appendChild(blacklistButton)
126
127 itemPreferences = utils.createElement(document, 'menuitem', {
128 id: MENU_ITEM_PREF
129 label: _('item_preferences')
130 })
131
132 itemHelp = utils.createElement(document, 'menuitem', {
133 id: MENU_ITEM_HELP
134 label: _('help_title')
135 })
136
137 menupopup = utils.createElement(document, 'menupopup', {
138 id: MENUPOPUP_ID
139 ignorekeys: true
140 })
141 menupopup.appendChild(blacklistControls)
142 menupopup.appendChild(itemPreferences)
143 menupopup.appendChild(itemHelp)
144
145 onPopupShowing = (event) ->
146 return unless tabWindow = utils.getCurrentTabWindow(window)
147
148 if button.VimFx.blacklisted
149 matchingRules = utils.getMatchingBlacklistRules(tabWindow.location.href)
150 blacklistTextbox.value = matchingRules.join(', ')
151 blacklistTextbox.setAttribute('readonly', true)
152 blacklistButton.setAttribute('tooltiptext',
153 _('item_blacklist_button_inverse_tooltip'))
154 blacklistButton.style.listStyleImage = iconUrl('blacklist_inverse')
155 else
156 blacklistTextbox.value =
157 # In `about:` pages, the `host` property is an empty string. Fall back
158 # to the whole URL.
159 if tabWindow.location.host != ''
160 "*#{ tabWindow.location.host }*"
161 else
162 tabWindow.location.href
163 blacklistTextbox.removeAttribute('readonly')
164 blacklistButton.setAttribute('tooltiptext',
165 _('item_blacklist_button_tooltip'))
166 blacklistButton.style.listStyleImage = iconUrl('blacklist')
167
168 onBlacklistButtonCommand = (event) ->
169 return unless tabWindow = utils.getCurrentTabWindow(window)
170
171 if button.VimFx.blacklisted
172 utils.updateBlacklist({remove: blacklistTextbox.value})
173 else
174 utils.updateBlacklist({add: blacklistTextbox.value})
175
176 menupopup.hidePopup()
177
178 tabWindow.location.reload(false)
179
180 event.stopPropagation()
181
182 onPreferencesCommand = (event) ->
183 id = encodeURIComponent(utils.ADDON_ID)
184 window.BrowserOpenAddonsMgr("addons://detail/#{ id }/preferences")
185
186 event.stopPropagation()
187
188 onHelpCommand = (event) ->
189 if tabWindow = utils.getCurrentTabWindow(window)
190 injectHelp(tabWindow.document, commands)
191
192 event.stopPropagation()
193
194 menupopup.addEventListener('popupshowing', onPopupShowing, false)
195 blacklistButton.addEventListener('command', onBlacklistButtonCommand, false)
196 itemPreferences.addEventListener('command', onPreferencesCommand, false)
197 itemHelp.addEventListener('command', onHelpCommand, false)
198
199 button.appendChild(menupopup)
200 return menupopup
201
202 restorePosition = (document, button) ->
203 $(document, 'navigator-toolbox').palette.appendChild(button)
204
205 for tb in $$(document, 'toolbar')
206 currentset = tb.getAttribute('currentset').split(',')
207 idx = currentset.indexOf(button.id)
208 if idx != -1
209 toolbar = tb
210 break
211
212 # Saved position not found, using the default one, after persisting it.
213 if not toolbar and button.id of positions
214 { toolbarId, beforeId } = positions[button.id]
215 if toolbar = $(document, toolbarId)
216 [ currentset, idx ] = persist(document, toolbar, button.id, beforeId)
217
218 if toolbar and idx != -1
219 # Inserting the button before the first item in `currentset`
220 # after `idx` that is present in the document.
221 for id in currentset[idx+1..]
222 if before = $(document, id)
223 toolbar.insertItem(button.id, before)
224 return
225
226 toolbar.insertItem(button.id)
227
228 persist = (document, toolbar, buttonId, beforeId) ->
229 currentset = toolbar.currentSet.split(',')
230 idx = if beforeId then currentset.indexOf(beforeId) else -1
231 if idx != -1
232 currentset.splice(idx, 0, buttonId)
233 else
234 currentset.push(buttonId)
235
236 toolbar.setAttribute('currentset', currentset.join(','))
237 document.persist(toolbar.id, 'currentset')
238 return [currentset, idx]
239
240 updateToolbarButton = (window, { disabled, blacklisted, insertMode }) ->
241 return unless button = $(window.document, BUTTON_ID)
242
243 button.VimFx.disabled = disabled if disabled?
244 button.VimFx.blacklisted = blacklisted if blacklisted?
245 button.VimFx.insertMode = insertMode if insertMode?
246
247 [ icon, tooltip ] = switch
248 when button.VimFx.disabled
249 ['grey', 'disabled']
250 when button.VimFx.blacklisted
251 ['red', 'blacklisted']
252 when button.VimFx.insertMode
253 ['grey', 'insertMode']
254 else
255 ['normal', 'enabled']
256
257 button.style.listStyleImage = iconUrl(icon)
258 button.setAttribute('tooltiptext', _("button_tooltip_#{ tooltip }"))
259
260 iconUrl = (kind) ->
261 url = utils.getResourceURI("resources/icon16-#{ kind }.png").spec
262 return "url(#{ url })"
263
264 exports.setButtonInstallPosition = setButtonInstallPosition
265 exports.addToolbarButton = addToolbarButton
266 exports.updateToolbarButton = updateToolbarButton
Imprint / Impressum