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