Bug 1531296 - [de-xbl] convert task progress and priority menupopup bindings to custom elements. r=philipp

--HG--
rename : calendar/base/content/calendar-menus.xml => calendar/base/content/calendar-menus.js
This commit is contained in:
Paul Morris 2019-04-16 10:18:55 +02:00
Родитель 3e499f4807
Коммит aafd50f175
10 изменённых файлов: 203 добавлений и 215 удалений

Просмотреть файл

@ -25,14 +25,8 @@ calendar-task-tree {
-moz-binding: url(chrome://calendar/content/calendar-task-tree.xml#calendar-task-tree);
}
menupopup[type="task-progress"] > arrowscrollbox {
-moz-binding: url(chrome://calendar/content/calendar-menus.xml#task-progress-menupopup);
}
menupopup[type="task-priority"] > arrowscrollbox {
-moz-binding: url(chrome://calendar/content/calendar-menus.xml#task-priority-menupopup);
}
task-menupopup {
-moz-binding: url(chrome://calendar/content/calendar-menus.xml#task-menupopup);
/* Needed until menupopup is fully converted to a custom element (see bug 1531296). */
menupopup[is="calendar-task-progress-menupopup"],
menupopup[is="calendar-task-priority-menupopup"] {
-moz-binding: none;
}

Просмотреть файл

@ -487,14 +487,14 @@
accesskey="&calendar.context.progress.accesskey;"
command="calendar_general-progress_command"
observes="calendar_general-progress_command">
<menupopup id="progress-menupopup" type="task-progress"/>
<menupopup is="calendar-task-progress-menupopup"/>
</menu>
<menu id="task-context-menu-priority"
label="&calendar.context.priority.label;"
accesskey="&calendar.context.priority.accesskey;"
command="calendar_general-priority_command"
observes="calendar_general-priority_command">
<menupopup id="priority-menupopup" type="task-priority"/>
<menupopup is="calendar-task-priority-menupopup"/>
</menu>
<menu id="task-context-menu-postpone"
label="&calendar.context.postpone.label;"

Просмотреть файл

@ -0,0 +1,169 @@
/* 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/. */
/* globals gConfig getSelectedTasks gTabmail MozElements MozXULElement
setAttributeOnChildrenOrTheirCommands */
"use strict";
// Wrap in a block and use const to define functions to prevent leaking to window scope.
{
/**
* Get a property value for a group of tasks. If all the tasks have the same property value
* then return that value, otherwise return null.
*
* @param {string} propertyKey The property key.
* @param {Object[]} tasks The tasks.
* @returns {string|null} The property value or null.
*/
const getPropertyValue = (propertyKey, tasks) => {
let propertyValue = null;
const tasksSelected = (tasks != null) && (tasks.length > 0);
if (tasksSelected && tasks.every(task => task[propertyKey] == tasks[0][propertyKey])) {
propertyValue = tasks[0][propertyKey];
}
return propertyValue;
};
/**
* Updates the 'checked' state of menu items so they reflect the state of the relevant task(s),
* for example, tasks currently selected in the task list, or a task being edited in the
* current tab. It operates on commands that are named using the following pattern:
*
* 'calendar_' + propertyKey + ' + '-' + propertyValue + '_command'
*
* When the propertyValue part of a command's name matches the propertyValue of the tasks,
* set the command to 'checked=true', as long as the tasks all have the same propertyValue.
*
* @param parent {Element} Parent element that contains the menu items as direct children.
* @param propertyKey {string} The property key, for example "priority" or "percentComplete".
*/
const updateMenuItemsState = (parent, propertyKey) => {
setAttributeOnChildrenOrTheirCommands("checked", false, parent);
const inSingleTaskTab = gTabmail &&
gTabmail.currentTabInfo &&
gTabmail.currentTabInfo.mode.type == "calendarTask";
const propertyValue = inSingleTaskTab
? gConfig[propertyKey]
: getPropertyValue(propertyKey, getSelectedTasks());
if (propertyValue || propertyValue === 0) {
const commandName = "calendar_" + propertyKey + "-" + propertyValue + "_command";
const command = document.getElementById(commandName);
if (command) {
command.setAttribute("checked", "true");
}
}
};
/**
* A menu for changing the "progress" (percent complete) status for a task or tasks. It
* indicates the current status by displaying a checkmark next to the menu item for that status.
* @extends MozElements.MozMenuPopup
*/
class CalendarTaskProgressMenupopup extends MozElements.MozMenuPopup {
connectedCallback() {
if (this.delayConnectedCallback() || this.hasConnected) {
return;
}
// this.hasConnected is set to true in super.connectedCallback
super.connectedCallback();
const scrollbox = this.querySelector(".popup-internal-box");
scrollbox.appendChild(MozXULElement.parseXULToFragment(`
<menuitem class="percent-0-menuitem"
type="checkbox"
label="&progress.level.0;"
accesskey="&progress.level.0.accesskey;"
observes="calendar_percentComplete-0_command"
command="calendar_percentComplete-0_command"/>
<menuitem class="percent-25-menuitem"
type="checkbox"
label="&progress.level.25;"
accesskey="&progress.level.25.accesskey;"
observes="calendar_percentComplete-25_command"
command="calendar_percentComplete-25_command"/>
<menuitem class="percent-50-menuitem"
type="checkbox"
label="&progress.level.50;"
accesskey="&progress.level.50.accesskey;"
observes="calendar_percentComplete-50_command"
command="calendar_percentComplete-50_command"/>
<menuitem class="percent-75-menuitem"
type="checkbox"
label="&progress.level.75;"
accesskey="&progress.level.75.accesskey;"
observes="calendar_percentComplete-75_command"
command="calendar_percentComplete-75_command"/>
<menuitem class="percent-100-menuitem"
type="checkbox"
label="&progress.level.100;"
accesskey="&progress.level.100.accesskey;"
observes="calendar_percentComplete-100_command"
command="calendar_percentComplete-100_command"/>
`,
["chrome://calendar/locale/calendar.dtd"]
));
this.addEventListener("popupshowing",
updateMenuItemsState.bind(null, scrollbox, "percentComplete"), true);
}
}
customElements.define("calendar-task-progress-menupopup",
CalendarTaskProgressMenupopup, { "extends": "menupopup" });
/**
* A menu for changing the "priority" status for a task or tasks. It indicates the current
* status by displaying a checkmark next to the menu item for that status.
* @extends MozElements.MozMenuPopup
*/
class CalendarTaskPriorityMenupopup extends MozElements.MozMenuPopup {
connectedCallback() {
if (this.delayConnectedCallback() || this.hasConnected) {
return;
}
// this.hasConnected is set to true in super.connectedCallback
super.connectedCallback();
const scrollbox = this.querySelector(".popup-internal-box");
scrollbox.appendChild(MozXULElement.parseXULToFragment(`
<menuitem class="priority-0-menuitem"
type="checkbox"
label="&priority.level.none;"
accesskey="&priority.level.none.accesskey;"
command="calendar_priority-0_command"
observes="calendar_priority-0_command"/>
<menuitem class="priority-9-menuitem"
type="checkbox"
label="&priority.level.low;"
accesskey="&priority.level.low.accesskey;"
command="calendar_priority-9_command"
observes="calendar_priority-9_command"/>
<menuitem class="priority-5-menuitem"
type="checkbox"
label="&priority.level.normal;"
accesskey="&priority.level.normal.accesskey;"
command="calendar_priority-5_command"
observes="calendar_priority-5_command"/>
<menuitem class="priority-1-menuitem"
type="checkbox"
label="&priority.level.high;"
accesskey="&priority.level.high.accesskey;"
command="calendar_priority-1_command"
observes="calendar_priority-1_command"/>
`,
["chrome://calendar/locale/calendar.dtd"]
));
this.addEventListener("popupshowing",
updateMenuItemsState.bind(null, scrollbox, "priority"), true);
}
}
customElements.define("calendar-task-priority-menupopup",
CalendarTaskPriorityMenupopup, { "extends": "menupopup" });
}

Просмотреть файл

@ -1,168 +0,0 @@
<?xml version="1.0"?>
<!-- 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/. -->
<!-- import-globals-from calendar-task-tree.js -->
<!DOCTYPE bindings SYSTEM "chrome://calendar/locale/calendar.dtd">
<bindings id="calendar-menu-bindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="task-menupopup">
<implementation>
<field name="mType">null</field>;
<field name="mPopupHandler">null</field>
<field name="mParentMenuPopup">null</field>
<constructor><![CDATA[
const { cal } = ChromeUtils.import("resource://calendar/modules/calUtils.jsm");
this.mPopupHandler = () => { this.changeMenuByPropertyName(); };
this.mParentMenuPopup = cal.view.getParentNodeOrThis(this, "menupopup");
this.mParentMenuPopup.addEventListener("popupshowing", this.mPopupHandler, true);
]]></constructor>
<destructor><![CDATA[
this.mParentMenuPopup.removeEventListener("popupshowing", this.mPopupHandler, true);
]]></destructor>
<!-- This method checks a command which naming follows
the notation 'calendar_' + mType + ' + '-' + propertyValue + 'command',
when its propertyValue part matches the propertyValue of the selected tasks
as long as the selected tasks share common propertyValues. -->
<method name="changeMenuByPropertyName">
<body><![CDATA[
let liveList = document.getAnonymousNodes(this);
for (let item of liveList) {
let commandName = item.getAttribute("command");
let command = document.getElementById(commandName);
if (command) {
command.setAttribute("checked", "false");
item.setAttribute("checked", "false");
}
}
let propertyValue;
// eslint-disable-next-line no-undef
if (gTabmail && gTabmail.currentTabInfo.mode.type == "calendarTask") {
// We are in a task tab (editing a single task).
propertyValue = gConfig[this.mType]; // eslint-disable-line no-undef
} else {
// We are in the Tasks tab.
let tasks = getSelectedTasks();
let tasksSelected = (tasks != null) && (tasks.length > 0);
if (tasksSelected) {
if (tasks.every(task => task[this.mType] == tasks[0][this.mType])) {
propertyValue = tasks[0][this.mType];
}
} else {
let sibling = this.firstChild;
while (sibling) {
let domObject = sibling;
if (domObject.hasAttribute("command")) {
let commandName = domObject.getAttribute("command");
let command = document.getElementById(commandName);
if (command) {
domObject = command;
}
}
domObject.setAttribute("disabled", false);
sibling = sibling.nextSibling;
}
}
}
if (propertyValue || propertyValue == 0) {
let command = document.getElementById("calendar_" + this.mType + "-" + propertyValue + "_command");
if (command) {
command.setAttribute("checked", "true");
}
}
]]></body>
</method>
</implementation>
</binding>
<binding id="task-progress-menupopup" extends="chrome://calendar/content/calendar-menus.xml#task-menupopup">
<content>
<xul:menuitem anonid="percent-0-menuitem"
type="checkbox"
label="&progress.level.0;"
accesskey="&progress.level.0.accesskey;"
observes="calendar_percentComplete-0_command"
command="calendar_percentComplete-0_command"/>
<xul:menuitem anonid="percent-25-menuitem"
type="checkbox"
label="&progress.level.25;"
accesskey="&progress.level.25.accesskey;"
observes="calendar_percentComplete-25_command"
command="calendar_percentComplete-25_command"/>
<xul:menuitem anonid="percent-50-menuitem"
type="checkbox"
label="&progress.level.50;"
accesskey="&progress.level.50.accesskey;"
observes="calendar_percentComplete-50_command"
command="calendar_percentComplete-50_command"/>
<xul:menuitem anonid="percent-75-menuitem"
type="checkbox"
label="&progress.level.75;"
accesskey="&progress.level.75.accesskey;"
observes="calendar_percentComplete-75_command"
command="calendar_percentComplete-75_command"/>
<xul:menuitem anonid="percent-100-menuitem"
type="checkbox"
label="&progress.level.100;"
accesskey="&progress.level.100.accesskey;"
observes="calendar_percentComplete-100_command"
command="calendar_percentComplete-100_command"/>
<children/>
</content>
<implementation>
<constructor><![CDATA[
this.mType = "percentComplete";
this.changeMenuByPropertyName();
]]></constructor>
</implementation>
</binding>
<binding id="task-priority-menupopup" extends="chrome://calendar/content/calendar-menus.xml#task-menupopup">
<content>
<xul:menuitem id="priority-0-menuitem"
type="checkbox"
label="&priority.level.none;"
accesskey="&priority.level.none.accesskey;"
command="calendar_priority-0_command"
observes="calendar_priority-0_command"/>
<xul:menuitem id="priority-9-menuitem"
type="checkbox"
label="&priority.level.low;"
accesskey="&priority.level.low.accesskey;"
command="calendar_priority-9_command"
observes="calendar_priority-9_command"/>
<xul:menuitem id="priority-5-menuitem"
type="checkbox"
label="&priority.level.normal;"
accesskey="&priority.level.normal.accesskey;"
command="calendar_priority-5_command"
observes="calendar_priority-5_command"/>
<xul:menuitem id="priority-1-menuitem"
type="checkbox"
label="&priority.level.high;"
accesskey="&priority.level.high.accesskey;"
command="calendar_priority-1_command"
observes="calendar_priority-1_command"/>
<children/>
</content>
<implementation>
<constructor><![CDATA[
this.mType = "priority";
this.changeMenuByPropertyName();
]]></constructor>
</implementation>
</binding>
</bindings>

Просмотреть файл

@ -11,6 +11,8 @@
/* import-globals-from calendar-common-sets.js */
/* import-globals-from calendar-dnd-listener.js */
/* globals gTabmail editToDoStatus editConfigState postponeTask */
var { cal } = ChromeUtils.import("resource://calendar/modules/calUtils.jsm");
/**
@ -38,29 +40,20 @@ function addCalendarNames(aEvent) {
}
/**
* Applies a value to all children of a menu. If the respective child nodes define
* a command the value is applied to the disabled attribute of the command of the
* child node.
* For each child of an element (for example all menuitems in a menu), if it defines a command
* set an attribute on the command, otherwise set it on the child node itself.
*
* @param aElement The parent node of the elements
* @param aValue The value of the attribute
* @param aAttribute {string} The attribute to set.
* @param aValue {boolean|string} The value to set.
* @param aElement {Element} The parent node.
*/
function applyDisabledAttributeToMenuChildren(aElement, aValue) {
let sibling = aElement.firstChild;
function setAttributeOnChildrenOrTheirCommands(aAttribute, aValue, aElement) {
for (let child of aElement.children) {
const commandName = child.getAttribute("command");
const command = commandName && document.getElementById(commandName);
while (sibling) {
let domObject = sibling;
if (domObject.hasAttribute("command")) {
let commandName = domObject.getAttribute("command");
let command = document.getElementById(commandName);
if (command) {
domObject = command;
}
}
domObject.setAttribute("disabled", aValue);
sibling = sibling.nextSibling;
const domObject = command || child;
domObject.setAttribute(aAttribute, aValue);
}
}
@ -88,7 +81,8 @@ function changeContextMenuForTask(aEvent) {
(idnode == "calendar-task-tree");
let tasksSelected = (items.length > 0);
applyDisabledAttributeToMenuChildren(aEvent.target, !tasksSelected);
setAttributeOnChildrenOrTheirCommands("disabled", !tasksSelected, aEvent.target);
if (calendarController.isCommandEnabled("calendar_new_todo_command") &&
calendarController.isCommandEnabled("calendar_new_todo_todaypane_command")) {
@ -105,10 +99,9 @@ function changeContextMenuForTask(aEvent) {
// make sure the filter menu is enabled
document.getElementById("task-context-menu-filter-todaypane").removeAttribute("disabled");
applyDisabledAttributeToMenuChildren(
document.getElementById("task-context-menu-filter-todaypane-popup"),
false
);
setAttributeOnChildrenOrTheirCommands("disabled", false,
document.getElementById("task-context-menu-filter-todaypane-popup"));
changeMenuForTask(aEvent);

Просмотреть файл

@ -22,6 +22,7 @@
<script type="application/javascript" src="chrome://calendar/content/calendar-item-bindings.js"/>
<script type="application/javascript" src="chrome://calendar/content/calFilter.js"/>
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="application/javascript" src="chrome://calendar/content/calendar-menus.js"/>
<vbox id="calendarDisplayDeck">
<vbox id="calendar-task-box" flex="1"
@ -140,7 +141,7 @@
command="calendar_toggle_completed_command"
observes="calendar_toggle_completed_command"
class="toolbarbutton-1 msgHeaderView-button">
<menupopup id="task-actions-markcompleted-menupopup" type="task-progress"/>
<menupopup is="calendar-task-progress-menupopup" id="task-actions-markcompleted-menupopup"/>
</toolbarbutton>
<toolbarbutton id="task-actions-priority"
type="menu"
@ -149,7 +150,7 @@
command="calendar_general-priority_command"
observes="calendar_general-priority_command"
class="toolbarbutton-1 msgHeaderView-button">
<menupopup id="task-actions-priority-menupopup" type="task-priority"/>
<menupopup is="calendar-task-priority-menupopup" id="task-actions-priority-menupopup"/>
</toolbarbutton>
<toolbarbutton id="calendar-delete-task-button"
class="toolbarbutton-1 msgHeaderView-button"

Просмотреть файл

@ -23,7 +23,7 @@ calendar.jar:
content/calendar/calendar-item-editing.js (content/calendar-item-editing.js)
content/calendar/calendar-item-bindings.js (content/calendar-item-bindings.js)
content/calendar/calendar-management.js (content/calendar-management.js)
content/calendar/calendar-menus.xml (content/calendar-menus.xml)
content/calendar/calendar-menus.js (content/calendar-menus.js)
content/calendar/calendar-views.xul (content/calendar-views.xul)
content/calendar/calendar-month-view.xml (content/calendar-month-view.xml)
content/calendar/calendar-multiday-view.xml (content/calendar-multiday-view.xml)

Просмотреть файл

@ -807,8 +807,7 @@ function editToDoStatus(aPercentComplete) {
/**
* Check or uncheck the "Mark updated" menu item in "Events and Tasks"
* menu based on the percent complete value. (The percent complete menu
* items are updated by changeMenuByPropertyName in calendar-menus.xml)
* menu based on the percent complete value.
*
* @param {Object} aArg Container
* @param {short} aArg.percentComplete The percent complete value

Просмотреть файл

@ -406,14 +406,14 @@
accesskey="&calendar.context.priority.accesskey;"
command="calendar_general-priority_command"
observes="calendar_general-priority_command">
<menupopup type="task-priority"/>
<menupopup is="calendar-task-priority-menupopup"/>
</menu>
<menu id="ltnTaskActionsProgressMenuitem"
label="&calendar.context.progress.label;"
accesskey="&calendar.context.progress.accesskey;"
command="calendar_general-progress_command"
observes="calendar_general-progress_command">
<menupopup type="task-progress"/>
<menupopup is="calendar-task-progress-menupopup"/>
</menu>
<menu id="ltnTaskActionsPostponeMenuitem"
label="&calendar.context.postpone.label;"
@ -768,13 +768,13 @@
label="&calendar.context.priority.label;"
command="calendar_general-priority_command"
observes="calendar_general-priority_command">
<menupopup type="task-priority"/>
<menupopup is="calendar-task-priority-menupopup"/>
</menu>
<menu id="appmenu_ltnTaskActionsProgressMenuitem"
label="&calendar.context.progress.label;"
command="calendar_general-progress_command"
observes="calendar_general-progress_command">
<menupopup type="task-progress"/>
<menupopup is="calendar-task-progress-menupopup"/>
</menu>
<menu id="appmenu_ltnTaskActionsPostponeMenuitem"
label="&calendar.context.postpone.label;"

Просмотреть файл

@ -124,7 +124,7 @@ function testTaskView() {
id("calendar-task-details-priority-row")/{"flex":"1"}/
id("other-actions-box")/id("task-actions-toolbox")/id("task-actions-toolbar")/
id("task-actions-priority")/id("task-actions-priority-menupopup")/
anon({"class":"popup-internal-box"})/anon({"id":"priority-1-menuitem"})`));
{"class":"popup-internal-box"}/{"class":"priority-1-menuitem"}`));
sleep();
let priorityNode = eid("calendar-task-details-priority-high");
controller.assertNotDOMProperty(priorityNode, "hidden");