added Linux arm64 SDK
This commit is contained in:
@@ -1,444 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
WI.NavigationBar = class NavigationBar extends WI.View
|
||||
{
|
||||
constructor(element, {role, sizesToFit, navigationItems} = {})
|
||||
{
|
||||
super(element);
|
||||
|
||||
this.element.classList.add(this.constructor.StyleClassName || "navigation-bar");
|
||||
|
||||
if (role)
|
||||
this.element.setAttribute("role", role);
|
||||
|
||||
this.element.addEventListener("keydown", this._keyDown.bind(this), false);
|
||||
this.element.addEventListener("mousedown", this._mouseDown.bind(this), true);
|
||||
|
||||
this._role = role;
|
||||
this._sizesToFit = sizesToFit || false;
|
||||
this._minimumWidth = NaN;
|
||||
this._navigationItems = [];
|
||||
this._selectedNavigationItem = null;
|
||||
|
||||
this._mouseMovedEventListener = this._mouseMoved.bind(this);
|
||||
this._mouseUpEventListener = this._mouseUp.bind(this);
|
||||
|
||||
if (navigationItems) {
|
||||
for (var i = 0; i < navigationItems.length; ++i)
|
||||
this.addNavigationItem(navigationItems[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Public
|
||||
|
||||
get sizesToFit() { return this._sizesToFit; }
|
||||
|
||||
addNavigationItem(navigationItem, parentElement)
|
||||
{
|
||||
return this.insertNavigationItem(navigationItem, Infinity, parentElement);
|
||||
}
|
||||
|
||||
insertNavigationItem(navigationItem, index, parentElement)
|
||||
{
|
||||
console.assert(navigationItem instanceof WI.NavigationItem);
|
||||
if (!(navigationItem instanceof WI.NavigationItem))
|
||||
return null;
|
||||
|
||||
if (navigationItem.parentNavigationBar)
|
||||
navigationItem.parentNavigationBar.removeNavigationItem(navigationItem);
|
||||
|
||||
navigationItem.didAttach(this);
|
||||
|
||||
console.assert(!isFinite(index) || (index >= 0 && index <= this._navigationItems.length));
|
||||
index = Math.max(0, Math.min(index, this._navigationItems.length));
|
||||
|
||||
this._navigationItems.splice(index, 0, navigationItem);
|
||||
|
||||
if (!parentElement)
|
||||
parentElement = this.element;
|
||||
|
||||
var nextSibling = this._navigationItems[index + 1];
|
||||
var nextSiblingElement = nextSibling ? nextSibling.element : null;
|
||||
if (nextSiblingElement && nextSiblingElement.parentNode !== parentElement)
|
||||
nextSiblingElement = null;
|
||||
|
||||
parentElement.insertBefore(navigationItem.element, nextSiblingElement);
|
||||
|
||||
this._minimumWidth = NaN;
|
||||
|
||||
this.needsLayout();
|
||||
|
||||
return navigationItem;
|
||||
}
|
||||
|
||||
removeNavigationItem(navigationItem)
|
||||
{
|
||||
console.assert(navigationItem instanceof WI.NavigationItem);
|
||||
if (!(navigationItem instanceof WI.NavigationItem))
|
||||
return null;
|
||||
|
||||
if (!navigationItem._parentNavigationBar)
|
||||
return null;
|
||||
|
||||
console.assert(navigationItem._parentNavigationBar === this, "Cannot remove item with unexpected parent bar.", navigationItem);
|
||||
if (navigationItem._parentNavigationBar !== this)
|
||||
return null;
|
||||
|
||||
navigationItem.didDetach();
|
||||
|
||||
if (this._selectedNavigationItem === navigationItem)
|
||||
this.selectedNavigationItem = null;
|
||||
|
||||
this._navigationItems.remove(navigationItem);
|
||||
navigationItem.element.remove();
|
||||
|
||||
this._minimumWidth = NaN;
|
||||
|
||||
this.needsLayout();
|
||||
|
||||
return navigationItem;
|
||||
}
|
||||
|
||||
get selectedNavigationItem()
|
||||
{
|
||||
return this._selectedNavigationItem;
|
||||
}
|
||||
|
||||
set selectedNavigationItem(navigationItem)
|
||||
{
|
||||
let navigationItemHasOtherParent = navigationItem && navigationItem.parentNavigationBar !== this;
|
||||
console.assert(!navigationItemHasOtherParent, "Cannot select item with unexpected parent bar.", navigationItem);
|
||||
if (navigationItemHasOtherParent)
|
||||
return;
|
||||
|
||||
// Only radio navigation items can be selected.
|
||||
if (!(navigationItem instanceof WI.RadioButtonNavigationItem))
|
||||
navigationItem = null;
|
||||
|
||||
if (this._selectedNavigationItem === navigationItem)
|
||||
return;
|
||||
|
||||
if (this._selectedNavigationItem)
|
||||
this._selectedNavigationItem.selected = false;
|
||||
|
||||
this._selectedNavigationItem = navigationItem || null;
|
||||
|
||||
if (this._selectedNavigationItem)
|
||||
this._selectedNavigationItem.selected = true;
|
||||
|
||||
// When the mouse is down don't dispatch the selected event, it will be dispatched on mouse up.
|
||||
// This prevents sending the event while the user is scrubbing the bar.
|
||||
if (!this._mouseIsDown)
|
||||
this.dispatchEventToListeners(WI.NavigationBar.Event.NavigationItemSelected);
|
||||
}
|
||||
|
||||
get navigationItems()
|
||||
{
|
||||
return this._navigationItems;
|
||||
}
|
||||
|
||||
get minimumWidth()
|
||||
{
|
||||
if (isNaN(this._minimumWidth))
|
||||
this._minimumWidth = this._calculateMinimumWidth();
|
||||
return this._minimumWidth;
|
||||
}
|
||||
|
||||
findNavigationItem(identifier)
|
||||
{
|
||||
function matchingSelfOrChild(item) {
|
||||
if (item.identifier === identifier)
|
||||
return item;
|
||||
|
||||
if (item instanceof WI.GroupNavigationItem) {
|
||||
for (let childItem of item.navigationItems) {
|
||||
let result = matchingSelfOrChild(childItem);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
for (let item of this._navigationItems) {
|
||||
let result = matchingSelfOrChild(item);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
layout()
|
||||
{
|
||||
super.layout();
|
||||
|
||||
this._minimumWidth = NaN;
|
||||
|
||||
// Remove the collapsed style class to test if the items can fit at full width.
|
||||
this.element.classList.remove(WI.NavigationBar.CollapsedStyleClassName);
|
||||
|
||||
function forceItemHidden(item, hidden) {
|
||||
item[WI.NavigationBar.ForceHiddenSymbol] = hidden;
|
||||
item.element.classList.toggle("force-hidden", hidden);
|
||||
}
|
||||
|
||||
function isDivider(item) {
|
||||
return item instanceof WI.DividerNavigationItem;
|
||||
}
|
||||
|
||||
// Tell each navigation item to update to full width if needed.
|
||||
for (let item of this._navigationItems) {
|
||||
forceItemHidden(item, false);
|
||||
item.update({expandOnly: true});
|
||||
}
|
||||
|
||||
if (this.sizesToFit)
|
||||
return;
|
||||
|
||||
let visibleNavigationItems = this._visibleNavigationItems;
|
||||
|
||||
function calculateVisibleItemWidth() {
|
||||
return visibleNavigationItems.reduce((total, item) => total + item.width, 0);
|
||||
}
|
||||
|
||||
let totalItemWidth = calculateVisibleItemWidth();
|
||||
|
||||
const barWidth = this.element.realOffsetWidth;
|
||||
|
||||
// Add the collapsed class back if the items are wider than the bar.
|
||||
if (totalItemWidth > barWidth)
|
||||
this.element.classList.add(WI.NavigationBar.CollapsedStyleClassName);
|
||||
|
||||
// Give each navigation item the opportunity to collapse further.
|
||||
for (let item of visibleNavigationItems)
|
||||
item.update();
|
||||
|
||||
totalItemWidth = calculateVisibleItemWidth();
|
||||
|
||||
if (totalItemWidth > barWidth) {
|
||||
if (this.parentView instanceof WI.Sidebar) {
|
||||
this.parentView.width = this.minimumWidth;
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide visible items, starting with the lowest priority item, until
|
||||
// the bar fits the available width.
|
||||
visibleNavigationItems.sort((a, b) => a.visibilityPriority - b.visibilityPriority);
|
||||
|
||||
while (totalItemWidth > barWidth && visibleNavigationItems.length) {
|
||||
let navigationItem = visibleNavigationItems.shift();
|
||||
totalItemWidth -= navigationItem.width;
|
||||
forceItemHidden(navigationItem, true);
|
||||
}
|
||||
|
||||
visibleNavigationItems = this._visibleNavigationItems;
|
||||
}
|
||||
|
||||
// Hide leading, trailing, and consecutive dividers.
|
||||
let previousItem = null;
|
||||
for (let item of visibleNavigationItems) {
|
||||
if (isDivider(item) && (!previousItem || isDivider(previousItem))) {
|
||||
forceItemHidden(item);
|
||||
continue;
|
||||
}
|
||||
|
||||
previousItem = item;
|
||||
}
|
||||
|
||||
if (isDivider(previousItem))
|
||||
forceItemHidden(previousItem);
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
_mouseDown(event)
|
||||
{
|
||||
// Only handle left mouse clicks.
|
||||
if (event.button !== 0)
|
||||
return;
|
||||
|
||||
var itemElement = event.target.closest("." + WI.RadioButtonNavigationItem.StyleClassName);
|
||||
if (!itemElement || !itemElement.navigationItem)
|
||||
return;
|
||||
|
||||
if (this._role === "tablist") {
|
||||
if (this.element.contains(document.activeElement)) {
|
||||
// If clicking on a tab, stop the event from being handled by the button element. Instead,
|
||||
// pass focus to the selected tab. Otherwise, let the button become activated normally.
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
this._previousSelectedNavigationItem = this.selectedNavigationItem;
|
||||
this.selectedNavigationItem = itemElement.navigationItem;
|
||||
|
||||
this._mouseIsDown = true;
|
||||
|
||||
if (typeof this.selectedNavigationItem.dontPreventDefaultOnNavigationBarMouseDown === "function"
|
||||
&& this.selectedNavigationItem.dontPreventDefaultOnNavigationBarMouseDown()
|
||||
&& this._previousSelectedNavigationItem === this.selectedNavigationItem)
|
||||
return;
|
||||
|
||||
// Register these listeners on the document so we can track the mouse if it leaves the navigation bar.
|
||||
document.addEventListener("mousemove", this._mouseMovedEventListener, false);
|
||||
document.addEventListener("mouseup", this._mouseUpEventListener, false);
|
||||
}
|
||||
|
||||
_mouseMoved(event)
|
||||
{
|
||||
console.assert(event.button === 0);
|
||||
console.assert(this._mouseIsDown);
|
||||
if (!this._mouseIsDown)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
var itemElement = event.target.closest("." + WI.RadioButtonNavigationItem.StyleClassName);
|
||||
if (!itemElement || !itemElement.navigationItem || !this.element.contains(itemElement)) {
|
||||
// Find the element that is at the X position of the mouse, even when the mouse is no longer
|
||||
// vertically in the navigation bar.
|
||||
var element = document.elementFromPoint(event.pageX, this.element.totalOffsetTop + (this.element.offsetHeight / 2));
|
||||
if (!element)
|
||||
return;
|
||||
|
||||
itemElement = element.closest("." + WI.RadioButtonNavigationItem.StyleClassName);
|
||||
if (!itemElement || !itemElement.navigationItem || !this.element.contains(itemElement))
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.selectedNavigationItem)
|
||||
this.selectedNavigationItem.active = false;
|
||||
|
||||
this.selectedNavigationItem = itemElement.navigationItem;
|
||||
|
||||
this.selectedNavigationItem.active = true;
|
||||
}
|
||||
|
||||
_mouseUp(event)
|
||||
{
|
||||
console.assert(event.button === 0);
|
||||
console.assert(this._mouseIsDown);
|
||||
if (!this._mouseIsDown)
|
||||
return;
|
||||
|
||||
if (this.selectedNavigationItem)
|
||||
this.selectedNavigationItem.active = false;
|
||||
|
||||
this._mouseIsDown = false;
|
||||
|
||||
document.removeEventListener("mousemove", this._mouseMovedEventListener, false);
|
||||
document.removeEventListener("mouseup", this._mouseUpEventListener, false);
|
||||
|
||||
// Dispatch the selected event here since the selectedNavigationItem setter surpresses it
|
||||
// while the mouse is down to prevent sending it while scrubbing the bar.
|
||||
if (this._previousSelectedNavigationItem !== this.selectedNavigationItem)
|
||||
this.dispatchEventToListeners(WI.NavigationBar.Event.NavigationItemSelected);
|
||||
|
||||
delete this._previousSelectedNavigationItem;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
_keyDown(event)
|
||||
{
|
||||
let isLeftArrow = event.code === "ArrowLeft";
|
||||
if (!isLeftArrow && event.code !== "ArrowRight")
|
||||
return;
|
||||
|
||||
if (this._selectedNavigationItem?.element !== document.activeElement)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
let delta = isLeftArrow ? -1 : 1;
|
||||
if (WI.resolveLayoutDirectionForElement(this._element) === WI.LayoutDirection.RTL)
|
||||
delta *= -1;
|
||||
|
||||
let selectedIndex = this._navigationItems.indexOf(this._selectedNavigationItem);
|
||||
|
||||
if (selectedIndex === -1)
|
||||
selectedIndex = (this._navigationItems.length + delta) % this._navigationItems.length;
|
||||
|
||||
while (true) {
|
||||
selectedIndex += delta;
|
||||
|
||||
if (selectedIndex < 0 || selectedIndex >= this._navigationItems.length)
|
||||
break;
|
||||
|
||||
let selectedItemCandidate = this._navigationItems[selectedIndex];
|
||||
if (selectedItemCandidate instanceof WI.RadioButtonNavigationItem) {
|
||||
this.selectedNavigationItem = selectedItemCandidate;
|
||||
this.selectedNavigationItem.element.focus();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_calculateMinimumWidth()
|
||||
{
|
||||
let visibleNavigationItems = this._visibleNavigationItems;
|
||||
if (!visibleNavigationItems.length)
|
||||
return 0;
|
||||
|
||||
const wasCollapsed = this.element.classList.contains(WI.NavigationBar.CollapsedStyleClassName);
|
||||
|
||||
// Add the collapsed style class to calculate the width of the items when they are collapsed.
|
||||
if (!wasCollapsed)
|
||||
this.element.classList.add(WI.NavigationBar.CollapsedStyleClassName);
|
||||
|
||||
let totalItemWidth = visibleNavigationItems.reduce((total, item) => total + Math.ceil(item.minimumWidth), 0);
|
||||
|
||||
// Remove the collapsed style class if we were not collapsed before.
|
||||
if (!wasCollapsed)
|
||||
this.element.classList.remove(WI.NavigationBar.CollapsedStyleClassName);
|
||||
|
||||
return totalItemWidth;
|
||||
}
|
||||
|
||||
get _visibleNavigationItems()
|
||||
{
|
||||
return this._navigationItems.filter((item) => {
|
||||
if (item instanceof WI.FlexibleSpaceNavigationItem)
|
||||
return false;
|
||||
if (item.hidden || item[WI.NavigationBar.ForceHiddenSymbol])
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
WI.NavigationBar.ForceHiddenSymbol = Symbol("force-hidden");
|
||||
|
||||
WI.NavigationBar.CollapsedStyleClassName = "collapsed";
|
||||
|
||||
WI.NavigationBar.Event = {
|
||||
NavigationItemSelected: "navigation-bar-navigation-item-selected"
|
||||
};
|
||||
Reference in New Issue
Block a user