forked from brave/browser-laptop
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmenuBar.js
150 lines (122 loc) · 4.57 KB
/
menuBar.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const React = require('react')
// Components
const ReduxComponent = require('../reduxComponent')
const MenuBarItem = require('./menuBarItem')
// Constants
const keyCodes = require('../../../common/constants/keyCodes')
// Actions
const windowActions = require('../../../../js/actions/windowActions')
// State
const contextMenuState = require('../../../common/state/contextMenuState.js')
// Utils
const {separatorMenuItem} = require('../../../common/commonMenu')
const {showContextMenu} = require('../../../common/lib/menuUtil')
const {wrappingClamp} = require('../../../common/lib/formatUtil')
/**
* Menubar that can be optionally be displayed at the top of a window (in favor of the system menu).
* First intended use is with Windows to enable a slim titlebar.
* NOTE: the system menu is still created and used in order to keep the accelerators working.
*/
class MenuBar extends React.Component {
constructor (props) {
super(props)
this.onKeyDown = this.onKeyDown.bind(this)
}
componentWillMount () {
document.addEventListener('keydown', this.onKeyDown)
}
componentWillUnmount () {
document.removeEventListener('keydown', this.onKeyDown)
}
/**
* Get client rect for the MenubarItem controls.
* Used to position the context menu object.
*/
getMenubarItemBounds (index) {
if (typeof index !== 'number') {
index = this.props.selectedIndex
}
const selected = document.querySelectorAll('.menubar .menubarItem[data-index=\'' + index + '\']')
if (selected.length === 1) {
return selected.item(0).getBoundingClientRect()
}
return null
}
onKeyDown (e) {
const selectedIndex = this.props.selectedIndex
const template = this.props.template
const contextMenuIndex = this.props.contextMenuSelectedIndex
if (!template || !template.get(selectedIndex)) {
return
}
switch (e.which) {
case keyCodes.LEFT:
case keyCodes.RIGHT:
if (contextMenuIndex !== null) {
const currentTemplate = template.get(selectedIndex).get('submenu').filter((element) => {
if (element.get('type') === separatorMenuItem.type) return false
if (element.has('visible')) return element.get('visible')
return true
}).get(contextMenuIndex[0])
if (currentTemplate && currentTemplate.has('submenu')) {
break
}
}
e.preventDefault()
e.stopPropagation()
// Regular old menu item
const nextIndex = selectedIndex === null
? 0
: wrappingClamp(
selectedIndex + (e.which === keyCodes.LEFT ? -1 : 1),
0,
this.props.template.size - 1)
windowActions.setMenuBarSelectedIndex(nextIndex)
if (this.props.contextMenuDetail) {
windowActions.setContextMenuSelectedIndex([0])
showContextMenu(this.getMenubarItemBounds(nextIndex), template.get(nextIndex).get('submenu').toJS(), this.props.lastFocusedSelector)
} else {
windowActions.setContextMenuSelectedIndex()
}
break
case keyCodes.DOWN:
case keyCodes.ENTER:
e.preventDefault()
if (contextMenuIndex === null &&
template.get(selectedIndex).has('submenu')) {
e.stopPropagation()
windowActions.setContextMenuSelectedIndex([0])
showContextMenu(this.getMenubarItemBounds(selectedIndex), template.get(selectedIndex).get('submenu').toJS(), this.props.lastFocusedSelector)
}
break
case keyCodes.UP:
e.preventDefault()
}
}
mergeProps (state, ownProps) {
const currentWindow = state.get('currentWindow')
const contextMenuDetail = currentWindow.get('contextMenuDetail')
const props = {}
// used in renderer
props.template = state.getIn(['menu', 'template'])
// used in other functions
props.selectedIndex = currentWindow.getIn(['ui', 'menubar', 'selectedIndex'])
props.contextMenuSelectedIndex = contextMenuState.selectedIndex(currentWindow)
props.contextMenuDetail = !!contextMenuDetail
props.lastFocusedSelector = currentWindow.getIn(['ui', 'menubar', 'lastFocusedSelector'])
return props
}
render () {
return <div className='menubar'>
{
this.props.template.map((item, i) => {
return <MenuBarItem index={i} />
})
}
</div>
}
}
module.exports = ReduxComponent.connect(MenuBar)