Bug 630759 - Improve attachment list XBL bindings; r=bienvenu, ui-r=bwinton
This commit is contained in:
Родитель
06e79a0050
Коммит
1e059486ab
|
@ -227,7 +227,7 @@ pref("mail.ui.show.migration.on.upgrade", true);
|
|||
pref("mail.showCondensedAddresses", true); // show the friendly display name for people I know
|
||||
|
||||
// hidden pref for changing how we present attachments in the message pane
|
||||
pref("mailnews.attachments.display.largeView", false);
|
||||
pref("mailnews.attachments.display.view", 0);
|
||||
pref("mail.pane_config.dynamic", 0);
|
||||
pref("mailnews.reuse_thread_window2", true);
|
||||
pref("editor.singleLine.pasteNewlines", 4); // substitute commas for new lines in single line text boxes
|
||||
|
|
|
@ -16,17 +16,50 @@
|
|||
<!-- dummy widget to force this file to load -->
|
||||
<binding id="dummy" extends="xul:box"/>
|
||||
|
||||
<!-- temporary holding place for horizontal list -->
|
||||
|
||||
<binding id="extdescription" extends="chrome://global/content/bindings/listbox.xml#listbox-base">
|
||||
<binding id="attachmentlist-base" extends="chrome://global/content/bindings/listbox.xml#listbox-base">
|
||||
<implementation>
|
||||
<constructor><![CDATA[
|
||||
this.children.filter(function(aChild) aChild.getAttribute("selected") == "true")
|
||||
.forEach(this.selectedItems.push, this.selectedItems);
|
||||
this.children.filter(function(aChild) aChild.getAttribute("selected") == "true")
|
||||
.forEach(this.selectedItems.push, this.selectedItems);
|
||||
|
||||
this.children.filter(function(aChild) !aChild.hasAttribute("context"))
|
||||
.forEach(function(aChild) aChild.setAttribute("context",
|
||||
this.getAttribute("itemcontext")), this);
|
||||
|
||||
this.sizes = {small: 16, large: 32, tile: 32};
|
||||
this.messenger = Components.classes["@mozilla.org/messenger;1"]
|
||||
.createInstance(Components.interfaces.nsIMessenger);
|
||||
|
||||
]]></constructor>
|
||||
|
||||
<!-- ///////////////// public members ///////////////// -->
|
||||
|
||||
<property name="view">
|
||||
<getter><![CDATA[
|
||||
return this.getAttribute("view");
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
this.setAttribute("view", val);
|
||||
this._setImageSize();
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="orient">
|
||||
<getter><![CDATA[
|
||||
return this.getAttribute("orient");
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
// The current item can get messed up when changing orientation.
|
||||
let curr = this.currentItem;
|
||||
this.currentItem = null;
|
||||
|
||||
this.setAttribute("orient", val);
|
||||
this.currentItem = curr;
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="itemCount" readonly="true"
|
||||
onget="return this.children.length;"/>
|
||||
|
||||
|
@ -49,20 +82,42 @@
|
|||
</method>
|
||||
<method name="getNumberOfVisibleRows">
|
||||
<body><![CDATA[
|
||||
var firstItem = this.children[0] || null;
|
||||
if (!firstItem)
|
||||
return 0; // nothing to be visible
|
||||
var itemsPerRow = Math.floor(this.boxObject.width / firstItem.boxObject.width);
|
||||
var itemsPerCol = Math.floor(this.boxObject.height / firstItem.boxObject.height);
|
||||
return Math.max(itemsPerRow, 1) * Math.max(itemsPerCol, 1);
|
||||
return this._itemsPerRow() * this._itemsPerCol();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="getIndexOfFirstVisibleRow">
|
||||
<body><![CDATA[
|
||||
//XXXzeniko unimplementable without a way to scroll
|
||||
let children = this.children;
|
||||
if (children.length == 0)
|
||||
return -1;
|
||||
|
||||
// First try to estimate which row is visible, assuming they're all
|
||||
// the same height.
|
||||
let box = this.scrollbox;
|
||||
let estimatedIndex = Math.floor(box.scrollTop /
|
||||
children[0].boxObject.height);
|
||||
let offset = children[estimatedIndex].boxObject.screenY -
|
||||
box.boxObject.screenY;
|
||||
|
||||
if (offset > 0) { // We went too far!
|
||||
for (let i = estimatedIndex - 1; i >= 0; i--) {
|
||||
if (children[i].boxObject.screenY - box.boxObject.screenY <= 0)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = estimatedIndex; i < this.children.length; i++) {
|
||||
if (children[i].boxObject.screenY + children[i].boxObject.height -
|
||||
box.boxObject.screenY > 0)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, something is very wrong.
|
||||
dump("Couldn't get index of first visible row for attachmentlist!");
|
||||
return -1;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="ensureIndexIsVisible">
|
||||
<parameter name="index"/>
|
||||
<body><![CDATA[
|
||||
|
@ -72,48 +127,111 @@
|
|||
<method name="ensureElementIsVisible">
|
||||
<parameter name="item"/>
|
||||
<body><![CDATA[
|
||||
//XXXzeniko unimplementable without a way to scroll
|
||||
let box = this.scrollbox;
|
||||
|
||||
// Are we too far down?
|
||||
if (item.boxObject.screenY < box.boxObject.screenY)
|
||||
box.scrollTop = item.boxObject.y - box.boxObject.y;
|
||||
// ... or not far enough?
|
||||
else if (item.boxObject.screenY + item.boxObject.height >
|
||||
box.boxObject.screenY + box.boxObject.height)
|
||||
box.scrollTop = item.boxObject.y + item.boxObject.height -
|
||||
box.boxObject.y - box.boxObject.height;
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="scrollToIndex">
|
||||
<parameter name="index"/>
|
||||
<body><![CDATA[
|
||||
//XXXzeniko unimplementable without a way to scroll
|
||||
let box = this.scrollbox;
|
||||
let item = this.getItemAtIndex(index);
|
||||
if (!item)
|
||||
return;
|
||||
box.scrollTop = item.boxObject.y - box.boxObject.y;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="appendItem">
|
||||
<parameter name="label"/>
|
||||
<parameter name="value"/>
|
||||
<parameter name="attachment"/>
|
||||
<parameter name="name"/>
|
||||
<body><![CDATA[
|
||||
// -1 appends due to the way getItemAtIndex is implemented
|
||||
return this.insertItemAt(-1, label, value);
|
||||
// -1 appends due to the way getItemAtIndex is implemented.
|
||||
return this.insertItemAt(-1, attachment, name);
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="insertItemAt">
|
||||
<parameter name="index"/>
|
||||
<parameter name="label"/>
|
||||
<parameter name="value"/>
|
||||
<parameter name="attachment"/>
|
||||
<parameter name="name"/>
|
||||
<body><![CDATA[
|
||||
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
var item = document.createElementNS(XULNS, "descriptionitem");
|
||||
item.setAttribute("label", label);
|
||||
let item = this.ownerDocument.createElementNS(XULNS, "attachmentitem");
|
||||
item.setAttribute("name", name || attachment.name);
|
||||
if (attachment.size != null && attachment.size != -1)
|
||||
item.setAttribute("size", this.messenger.formatFileSize(
|
||||
attachment.size));
|
||||
|
||||
// Pick out some nice icons (small and large) for the attachment
|
||||
if (attachment.contentType == "text/x-moz-deleted") {
|
||||
let base = "chrome://messenger/skin/icons/";
|
||||
item.setAttribute("image16", base+"attachment-deleted.png");
|
||||
item.setAttribute("image32", base+"attachment-deleted-large.png");
|
||||
}
|
||||
else {
|
||||
item.setAttribute("image16", "moz-icon://" + attachment.name +
|
||||
"?size=16&contentType=" +
|
||||
attachment.contentType);
|
||||
item.setAttribute("image32", "moz-icon://" + attachment.name +
|
||||
"?size=32&contentType=" +
|
||||
attachment.contentType);
|
||||
}
|
||||
|
||||
item.setAttribute("imagesize", this.sizes[this.getAttribute("view")] || 16);
|
||||
item.setAttribute("context", this.getAttribute("itemcontext"));
|
||||
item.attachment = attachment;
|
||||
|
||||
this.insertBefore(item, this.getItemAtIndex(index));
|
||||
return item;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="scrollOnePage">
|
||||
<parameter name="direction"/>
|
||||
<parameter name="direction"/> <!-- Must be -1 or 1 -->
|
||||
<body><![CDATA[
|
||||
return direction * this.getNumberOfVisibleRows();
|
||||
let pageOffset = this.getNumberOfVisibleRows() * direction;
|
||||
// skip over invisible elements - the user won't care about them
|
||||
for (let i = 0; i != pageOffset; i += direction) {
|
||||
let item = this.getItemAtIndex(this.currentIndex + i);
|
||||
if (item && !this._canUserSelect(item))
|
||||
pageOffset += direction;
|
||||
}
|
||||
let newTop = this.getIndexOfFirstVisibleRow() + pageOffset;
|
||||
if (direction == 1) {
|
||||
let maxTop = this.getRowCount() - this.getNumberOfVisibleRows();
|
||||
for (let i = this.getRowCount(); i >= 0 && i > maxTop; i--) {
|
||||
let item = this.getItemAtIndex(i);
|
||||
if (item && !this._canUserSelect(item))
|
||||
maxTop--;
|
||||
}
|
||||
if (newTop >= maxTop)
|
||||
newTop = maxTop;
|
||||
}
|
||||
if (newTop < 0)
|
||||
newTop = 0;
|
||||
this.scrollToIndex(newTop);
|
||||
return pageOffset;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- Get the preferred height (the height that would allow us to fit
|
||||
everything without scrollbars) of the attachmentlist's boxObject. -->
|
||||
<property name="preferredHeight" readonly="true"
|
||||
onget="return this.scrollbox.scrollHeight - this.scrollbox.clientHeight + this.boxObject.height;"/>
|
||||
|
||||
<!-- ///////////////// private members ///////////////// -->
|
||||
|
||||
<property name="children" readonly="true"
|
||||
onget="return Array.slice(this.getElementsByTagName('descriptionitem'));"/>
|
||||
onget="return Array.slice(this.getElementsByTagName('attachmentitem'));"/>
|
||||
<property name="scrollbox" readonly="true"
|
||||
onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'scrollbox');"/>
|
||||
|
||||
<method name="_fireOnSelect">
|
||||
<body><![CDATA[
|
||||
|
@ -124,17 +242,59 @@
|
|||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_itemsPerRow">
|
||||
<body><![CDATA[
|
||||
let firstItem = this.children[0] || null;
|
||||
if (!firstItem)
|
||||
return 0; // nothing to be visible
|
||||
|
||||
let itemsPerRow = Math.floor(this.scrollbox.clientWidth /
|
||||
firstItem.boxObject.width);
|
||||
return Math.max(itemsPerRow, 1);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_itemsPerCol">
|
||||
<body><![CDATA[
|
||||
let firstItem = this.children[0] || null;
|
||||
if (!firstItem)
|
||||
return 0; // nothing to be visible
|
||||
|
||||
let itemsPerCol = Math.floor(this.scrollbox.clientHeight /
|
||||
firstItem.boxObject.height);
|
||||
return Math.max(itemsPerCol, 1);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_setImageSize">
|
||||
<body><![CDATA[
|
||||
let children = this.children;
|
||||
let size = this.sizes[this.view] || 16;
|
||||
|
||||
for (let i = 0; i < children.length; i++)
|
||||
children[i].imageSize = size;
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="keypress" keycode="VK_LEFT" modifiers="control shift any"
|
||||
action="this.moveByOffset(-1, !event.ctrlKey, event.shiftKey);"
|
||||
phase="target" preventdefault="true"/>
|
||||
<handler event="keypress" keycode="VK_RIGHT" modifiers="control shift any"
|
||||
action="this.moveByOffset(1, !event.ctrlKey, event.shiftKey);"
|
||||
<!-- The spacebar should work just like the arrow keys, except that the
|
||||
focused element doesn't change, so use moveByOffset here. -->
|
||||
<handler event="keypress" key=" " modifiers="control shift any"
|
||||
action="this.moveByOffset(0, !event.ctrlKey, event.shiftKey);"
|
||||
phase="target" preventdefault="true"/>
|
||||
<handler event="keypress" keycode="VK_RETURN"><![CDATA[
|
||||
if (this.currentItem) {
|
||||
this.addItemToSelection(this.currentItem);
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("command", true, true);
|
||||
this.currentItem.dispatchEvent(event);
|
||||
}
|
||||
]]></handler>
|
||||
<handler event="click" button="0" phase="target"><![CDATA[
|
||||
if (this.selType != "multiple" || (!event.ctrlKey && !event.shiftKey && !event.metaKey))
|
||||
if (this.selType != "multiple" || (!event.ctrlKey && !event.shiftKey &&
|
||||
!event.metaKey))
|
||||
this.clearSelection();
|
||||
]]></handler>
|
||||
<!-- make sure we keep the focus... -->
|
||||
|
@ -143,21 +303,93 @@
|
|||
</handlers>
|
||||
</binding>
|
||||
|
||||
<binding id="descriptionitem" extends="chrome://global/content/bindings/listbox.xml#listitem">
|
||||
<binding id="attachmentlist-horizontal" extends="chrome://messenger/content/mailWidgets.xml#attachmentlist-base">
|
||||
<content>
|
||||
<xul:hbox class="attachmentBox" xbl:inherits="orient" align="start">
|
||||
<xul:label class="descriptioncell-label" xbl:inherits="value=label,flex=flexlabel,crop,disabled,context" flex="1" dir="ltr" crop="center"/>
|
||||
</xul:hbox>
|
||||
<xul:scrollbox flex="1" anonid="scrollbox" style="overflow: auto;">
|
||||
<xul:hbox flex="1" class="attachmentlist-wrapper">
|
||||
<children includes="attachmentitem"/>
|
||||
</xul:hbox>
|
||||
</xul:scrollbox>
|
||||
</content>
|
||||
<handlers>
|
||||
<handler event="keypress" keycode="VK_LEFT" modifiers="control shift any"
|
||||
action="this.moveByOffset(-1, !event.ctrlKey, event.shiftKey);"
|
||||
phase="target" preventdefault="true"/>
|
||||
<handler event="keypress" keycode="VK_RIGHT" modifiers="control shift any"
|
||||
action="this.moveByOffset(1, !event.ctrlKey, event.shiftKey);"
|
||||
phase="target" preventdefault="true"/>
|
||||
<handler event="keypress" keycode="VK_UP" modifiers="control shift any"
|
||||
action="this.moveByOffset(-this._itemsPerRow(), !event.ctrlKey, event.shiftKey);"
|
||||
phase="target" preventdefault="true"/>
|
||||
<handler event="keypress" keycode="VK_DOWN" modifiers="control shift any"
|
||||
action="this.moveByOffset(this._itemsPerRow(), !event.ctrlKey, event.shiftKey);"
|
||||
phase="target" preventdefault="true"/>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
<binding id="attachmentlist-vertical" extends="chrome://messenger/content/mailWidgets.xml#attachmentlist-base">
|
||||
<content>
|
||||
<xul:scrollbox orient="vertical" flex="1" anonid="scrollbox"
|
||||
style="overflow: auto;">
|
||||
<children includes="attachmentitem"/>
|
||||
</xul:scrollbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="descriptionitem-iconic" extends="chrome://global/content/bindings/listbox.xml#listitem">
|
||||
<binding id="attachmentitem" extends="chrome://global/content/bindings/listbox.xml#listitem">
|
||||
<implementation>
|
||||
<constructor><![CDATA[
|
||||
this._updateImage();
|
||||
]]></constructor>
|
||||
|
||||
<property name="imageSize">
|
||||
<getter><![CDATA[
|
||||
return this.getAttribute("imagesize");
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
this.setAttribute("imagesize", val);
|
||||
this._updateImage();
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<method name="_updateImage">
|
||||
<body><![CDATA[
|
||||
if (!this.hasAttribute("image")) {
|
||||
let icon = document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"icon");
|
||||
let attr = "image"+this.imageSize;
|
||||
if (this.hasAttribute(attr))
|
||||
icon.setAttribute("src", this.getAttribute(attr));
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
<!-- Below, we want the name label to flex but not be any bigger than
|
||||
necessary, so add a spacer with a huge flex value. -->
|
||||
<content>
|
||||
<xul:hbox class="attachmentBox" xbl:inherits="orient" align="center">
|
||||
<xul:image class="descriptioncell-icon" xbl:inherits="src=image"/>
|
||||
<xul:label class="descriptioncell-label" xbl:inherits="value=label,flex=flexlabel,crop,disabled,context" flex="1" dir="ltr" crop="center"/>
|
||||
<xul:hbox class="attachmentcell-content" flex="1">
|
||||
<xul:hbox align="center">
|
||||
<xul:image class="attachmentcell-icon" anonid="icon"
|
||||
xbl:inherits="src=image"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox class="attachmentcell-text" flex="1">
|
||||
<xul:hbox class="attachmentcell-nameselection" flex="1">
|
||||
<xul:label class="attachmentcell-name" xbl:inherits="value=name"
|
||||
flex="1" crop="center"/>
|
||||
</xul:hbox>
|
||||
<xul:spacer flex="99999"/>
|
||||
<xul:label class="attachmentcell-size" xbl:inherits="value=size"/>
|
||||
</xul:hbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<handlers>
|
||||
<handler event="click" button="0" clickcount="2"><![CDATA[
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("command", true, true);
|
||||
this.dispatchEvent(event);
|
||||
]]></handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
<!-- Message Pane Widgets -->
|
||||
|
|
|
@ -154,6 +154,7 @@
|
|||
</popupset>
|
||||
|
||||
<menupopup id="attachmentListContext"/>
|
||||
<menupopup id="attachmentItemContext"/>
|
||||
<menupopup id="header-toolbar-context-menu"/>
|
||||
<menupopup id="attachment-toolbar-context-menu"/>
|
||||
<menupopup id="copyUrlPopup"/>
|
||||
|
|
|
@ -43,18 +43,69 @@
|
|||
|
||||
/* ::::: mail xbl bindings ::::: */
|
||||
|
||||
description[selectable="true"] {
|
||||
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#extdescription");
|
||||
/* attachment list styles */
|
||||
|
||||
attachmentlist {
|
||||
-moz-appearance: listbox;
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
descriptionitem {
|
||||
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#descriptionitem");
|
||||
attachmentlist[orient="horizontal"] {
|
||||
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#attachmentlist-horizontal");
|
||||
}
|
||||
|
||||
.descriptionitem-iconic {
|
||||
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#descriptionitem-iconic");
|
||||
attachmentlist[orient="vertical"] {
|
||||
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#attachmentlist-vertical");
|
||||
}
|
||||
|
||||
.attachmentlist-wrapper {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
attachmentitem {
|
||||
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#attachmentitem");
|
||||
}
|
||||
|
||||
.attachmentcell-content {
|
||||
-moz-box-orient: horizontal;
|
||||
}
|
||||
|
||||
.attachmentcell-text {
|
||||
-moz-box-orient: horizontal;
|
||||
}
|
||||
|
||||
attachmentitem {
|
||||
width: 15em;
|
||||
}
|
||||
|
||||
attachmentlist[view="large"] .attachmentcell-content {
|
||||
-moz-box-orient: horizontal;
|
||||
}
|
||||
|
||||
attachmentlist[view="large"] .attachmentcell-text {
|
||||
-moz-box-align: start;
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
attachmentlist[view="tile"] .attachmentcell-content {
|
||||
-moz-box-align: center;
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
attachmentlist[view="tile"] .attachmentcell-text {
|
||||
-moz-box-align: center;
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
attachmentlist[view="tile"] > attachmentitem {
|
||||
width: 9em;
|
||||
}
|
||||
|
||||
/* message header widgets */
|
||||
|
||||
mail-messageid {
|
||||
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#mail-messageid");
|
||||
}
|
||||
|
|
|
@ -164,6 +164,7 @@
|
|||
<menupopup id="mailContext"/>
|
||||
<menupopup id="folderPaneContext"/>
|
||||
<menupopup id="attachmentListContext"/>
|
||||
<menupopup id="attachmentItemContext"/>
|
||||
<menupopup id="header-toolbar-context-menu"/>
|
||||
<menupopup id="attachment-toolbar-context-menu"/>
|
||||
<menupopup id="copyUrlPopup"/>
|
||||
|
|
|
@ -1774,98 +1774,83 @@ function ContentTypeIsSMIME(contentType)
|
|||
}
|
||||
|
||||
/**
|
||||
* Set up the attachment context menu, showing or hiding the appropriate menu
|
||||
* items.
|
||||
* Set up the attachment item context menu, showing or hiding the appropriate
|
||||
* menu items.
|
||||
*/
|
||||
function onShowAttachmentContextMenu()
|
||||
function onShowAttachmentItemContextMenu()
|
||||
{
|
||||
var attachmentList = document.getElementById('attachmentList');
|
||||
var attachmentName = document.getElementById('attachmentName');
|
||||
var contextMenu = document.getElementById('attachmentListContext');
|
||||
|
||||
var openMenu = document.getElementById('context-openAttachment');
|
||||
var saveMenu = document.getElementById('context-saveAttachment');
|
||||
var menuSeparator = document.getElementById('context-menu-separator');
|
||||
var detachMenu = document.getElementById('context-detachAttachment');
|
||||
var deleteMenu = document.getElementById('context-deleteAttachment');
|
||||
|
||||
var openAllMenu = document.getElementById('context-openAllAttachments');
|
||||
var saveAllMenu = document.getElementById('context-saveAllAttachments');
|
||||
var menuSeparatorAll = document.getElementById('context-menu-separator-all');
|
||||
var detachAllMenu = document.getElementById('context-detachAllAttachments');
|
||||
var deleteAllMenu = document.getElementById('context-deleteAllAttachments');
|
||||
let attachmentList = document.getElementById("attachmentList");
|
||||
let attachmentName = document.getElementById("attachmentName");
|
||||
let contextMenu = document.getElementById("attachmentItemContext");
|
||||
let openMenu = document.getElementById("context-openAttachment");
|
||||
let saveMenu = document.getElementById("context-saveAttachment");
|
||||
let detachMenu = document.getElementById("context-detachAttachment");
|
||||
let deleteMenu = document.getElementById("context-deleteAttachment");
|
||||
|
||||
// If we opened the context menu from the attachmentName label, just grab
|
||||
// the first (and only) attachment as our "selected" attachments.
|
||||
var selectedAttachments;
|
||||
if (contextMenu.triggerNode == attachmentName) {
|
||||
selectedAttachments = [attachmentList.getItemAtIndex(0).attachment];
|
||||
attachmentName.setAttribute('selected', true);
|
||||
attachmentName.setAttribute("selected", true);
|
||||
}
|
||||
else
|
||||
selectedAttachments = [item.attachment for each([, item] in
|
||||
Iterator(attachmentList.selectedItems))];
|
||||
contextMenu.attachments = selectedAttachments;
|
||||
|
||||
var selectNone = selectedAttachments.length == 0;
|
||||
var allSelectedDetached = selectedAttachments.every(function(attachment) {
|
||||
return attachment.isExternalAttachment;
|
||||
});
|
||||
var allSelectedDeleted = selectedAttachments.every(function(attachment) {
|
||||
return !attachment.hasFile;
|
||||
});
|
||||
var canDetachSelected = CanDetachAttachments() && !allSelectedDetached &&
|
||||
!allSelectedDeleted;
|
||||
|
||||
openMenu.hidden = selectNone;
|
||||
saveMenu.hidden = selectNone;
|
||||
menuSeparator.hidden = selectNone;
|
||||
detachMenu.hidden = selectNone;
|
||||
deleteMenu.hidden = selectNone;
|
||||
|
||||
openAllMenu.hidden = !selectNone;
|
||||
saveAllMenu.hidden = !selectNone;
|
||||
menuSeparatorAll.hidden = !selectNone;
|
||||
detachAllMenu.hidden = !selectNone;
|
||||
deleteAllMenu.hidden = !selectNone;
|
||||
|
||||
if (!selectNone)
|
||||
{
|
||||
var allSelectedDetached = selectedAttachments.every(function(attachment) {
|
||||
return attachment.isExternalAttachment;
|
||||
});
|
||||
var allSelectedDeleted = selectedAttachments.every(function(attachment) {
|
||||
return !attachment.hasFile;
|
||||
});
|
||||
var canDetachSelected = CanDetachAttachments() && !allSelectedDetached &&
|
||||
!allSelectedDeleted;
|
||||
|
||||
openMenu.disabled = allSelectedDeleted;
|
||||
saveMenu.disabled = allSelectedDeleted;
|
||||
detachMenu.disabled = !canDetachSelected;
|
||||
deleteMenu.disabled = !canDetachSelected;
|
||||
}
|
||||
else
|
||||
{
|
||||
var allDetached = currentAttachments.every(function(attachment) {
|
||||
return attachment.isExternalAttachment;
|
||||
});
|
||||
var allDeleted = currentAttachments.every(function(attachment) {
|
||||
return !attachment.hasFile;
|
||||
});
|
||||
var canDetachAll = CanDetachAttachments() && !allDetached && !allDeleted;
|
||||
|
||||
saveAllMenu.disabled = allDeleted;
|
||||
openAllMenu.disabled = allDeleted;
|
||||
detachAllMenu.disabled = !canDetachAll;
|
||||
deleteAllMenu.disabled = !canDetachAll;
|
||||
}
|
||||
openMenu.disabled = allSelectedDeleted;
|
||||
saveMenu.disabled = allSelectedDeleted;
|
||||
detachMenu.disabled = !canDetachSelected;
|
||||
deleteMenu.disabled = !canDetachSelected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the attachment context menu, performing any cleanup as necessary.
|
||||
* Close the attachment item context menu, performing any cleanup as necessary.
|
||||
*/
|
||||
function onHideAttachmentContextMenu()
|
||||
function onHideAttachmentItemContextMenu()
|
||||
{
|
||||
let attachmentName = document.getElementById('attachmentName');
|
||||
let contextMenu = document.getElementById('attachmentListContext');
|
||||
let attachmentName = document.getElementById("attachmentName");
|
||||
let contextMenu = document.getElementById("attachmentListContext");
|
||||
|
||||
// If we opened the context menu from the attachmentName label, we need to
|
||||
// get rid of the "selected" attribute.
|
||||
if (contextMenu.triggerNode == attachmentName)
|
||||
attachmentName.removeAttribute('selected');
|
||||
attachmentName.removeAttribute("selected");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the attachment list context menu, showing or hiding the appropriate
|
||||
* menu items.
|
||||
*/
|
||||
function onShowAttachmentListContextMenu()
|
||||
{
|
||||
var openAllMenu = document.getElementById("context-openAllAttachments");
|
||||
var saveAllMenu = document.getElementById("context-saveAllAttachments");
|
||||
var detachAllMenu = document.getElementById("context-detachAllAttachments");
|
||||
var deleteAllMenu = document.getElementById("context-deleteAllAttachments");
|
||||
|
||||
var allDetached = currentAttachments.every(function(attachment) {
|
||||
return attachment.isExternalAttachment;
|
||||
});
|
||||
var allDeleted = currentAttachments.every(function(attachment) {
|
||||
return !attachment.hasFile;
|
||||
});
|
||||
var canDetachAll = CanDetachAttachments() && !allDetached && !allDeleted;
|
||||
|
||||
saveAllMenu.disabled = allDeleted;
|
||||
openAllMenu.disabled = allDeleted;
|
||||
detachAllMenu.disabled = !canDetachAll;
|
||||
deleteAllMenu.disabled = !canDetachAll;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1923,20 +1908,15 @@ function MessageIdClick(node, event)
|
|||
}
|
||||
}
|
||||
|
||||
// this is our onclick handler for the attachment list.
|
||||
// A double click in a listitem simulates "opening" the attachment....
|
||||
function attachmentListClick(event)
|
||||
/**
|
||||
* This is our oncommand handler for the attachment list items. A double click
|
||||
* or enter press in an attachmentitem simulates "opening" the attachment.
|
||||
*
|
||||
* @param event the event object
|
||||
*/
|
||||
function attachmentItemCommand(event)
|
||||
{
|
||||
// we only care about button 0 (left click) events
|
||||
if (event.button != 0)
|
||||
return;
|
||||
|
||||
if (event.detail == 2) // double click
|
||||
{
|
||||
var target = event.target;
|
||||
if (target.localName == "descriptionitem")
|
||||
target.attachment.open();
|
||||
}
|
||||
HandleSelectedAttachments("open");
|
||||
}
|
||||
|
||||
function createAttachmentDisplayName(aAttachment)
|
||||
|
@ -1949,65 +1929,106 @@ function createAttachmentDisplayName(aAttachment)
|
|||
return aAttachment.name.trimRight();
|
||||
}
|
||||
|
||||
var AttachmentListController =
|
||||
{
|
||||
supportsCommand: function(command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case "cmd_selectAll":
|
||||
case "cmd_delete":
|
||||
case "cmd_shiftDelete":
|
||||
case "button_delete":
|
||||
case "cmd_saveAsFile":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
isCommandEnabled: function(command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case "cmd_selectAll":
|
||||
case "cmd_delete":
|
||||
case "cmd_shiftDelete":
|
||||
case "button_delete":
|
||||
case "cmd_saveAsFile":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
doCommand: function(command)
|
||||
{
|
||||
// If the user invoked a key short cut then it is possible that we got here
|
||||
// for a command which is really disabled. kick out if the command should
|
||||
// be disabled.
|
||||
if (!this.isCommandEnabled(command)) return;
|
||||
|
||||
var attachmentList = document.getElementById('attachmentList');
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case "cmd_selectAll":
|
||||
attachmentList.selectAll();
|
||||
return;
|
||||
case "cmd_delete":
|
||||
case "cmd_shiftDelete":
|
||||
case "button_delete":
|
||||
HandleSelectedAttachments('delete');
|
||||
return;
|
||||
case "cmd_saveAsFile":
|
||||
HandleSelectedAttachments('saveAs');
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
onEvent: function(event)
|
||||
{}
|
||||
};
|
||||
|
||||
function displayAttachmentsForExpandedView()
|
||||
{
|
||||
var bundle = document.getElementById("bundle_messenger");
|
||||
var numAttachments = currentAttachments.length;
|
||||
var totalSize = 0;
|
||||
var attachmentView = document.getElementById('attachmentView');
|
||||
var attachmentSplitter = document.getElementById('attachment-splitter');
|
||||
var attachmentView = document.getElementById("attachmentView");
|
||||
var attachmentSplitter = document.getElementById("attachment-splitter");
|
||||
|
||||
if (numAttachments <= 0)
|
||||
{
|
||||
if (numAttachments <= 0) {
|
||||
attachmentView.collapsed = true;
|
||||
attachmentSplitter.collapsed = true;
|
||||
}
|
||||
else if (!gBuildAttachmentsForCurrentMsg)
|
||||
{
|
||||
else if (!gBuildAttachmentsForCurrentMsg) {
|
||||
attachmentView.collapsed = false;
|
||||
|
||||
var attachmentList = document.getElementById('attachmentList');
|
||||
var attachmentList = document.getElementById("attachmentList");
|
||||
|
||||
var showLargeAttView = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
var viewMode = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch2)
|
||||
.getBoolPref("mailnews.attachments.display.largeView")
|
||||
attachmentList.setAttribute("largeView", showLargeAttView);
|
||||
.getIntPref("mailnews.attachments.display.view");
|
||||
var views = ["small", "large", "tile"];
|
||||
attachmentList.view = views[viewMode];
|
||||
attachmentList.controllers.appendController(AttachmentListController);
|
||||
|
||||
toggleAttachmentList(false);
|
||||
|
||||
var unknownSize = false;
|
||||
for each (let [, attachment] in Iterator(currentAttachments))
|
||||
{
|
||||
for each (let [, attachment] in Iterator(currentAttachments)) {
|
||||
// Create a new attachment widget
|
||||
var displayName = createAttachmentDisplayName(attachment);
|
||||
var item;
|
||||
if (attachment.size != null) {
|
||||
var size = messenger.formatFileSize(attachment.size);
|
||||
var nameAndSize = bundle.getFormattedString("attachmentNameAndSize",
|
||||
[displayName, size]);
|
||||
item = attachmentList.appendItem(nameAndSize);
|
||||
totalSize += attachment.size;
|
||||
}
|
||||
else {
|
||||
if (!attachment.isDeleted)
|
||||
unknownSize = true;
|
||||
item = attachmentList.appendItem(displayName);
|
||||
}
|
||||
|
||||
item.setAttribute("class", "descriptionitem-iconic");
|
||||
|
||||
setApplicationIconForAttachment(attachment, item, showLargeAttView);
|
||||
var item = attachmentList.appendItem(attachment, displayName);
|
||||
item.setAttribute("tooltiptext", attachment.name);
|
||||
item.setAttribute("context", "attachmentListContext");
|
||||
item.addEventListener("command", attachmentItemCommand, false);
|
||||
|
||||
item.attachment = attachment;
|
||||
item.setAttribute("attachmentUrl", attachment.url);
|
||||
item.setAttribute("attachmentContentType", attachment.contentType);
|
||||
item.setAttribute("attachmentUri", attachment.uri);
|
||||
item.setAttribute("attachmentSize", attachment.size);
|
||||
|
||||
attachmentList.appendChild(item);
|
||||
} // for each attachment
|
||||
if (attachment.size !== null)
|
||||
totalSize += attachment.size;
|
||||
else if (!attachment.isDeleted)
|
||||
unknownSize = true;
|
||||
}
|
||||
|
||||
// Show the appropriate toolbar button and label based on the number of
|
||||
// attachments.
|
||||
|
@ -2079,62 +2100,49 @@ function updateSaveAllAttachmentsButton()
|
|||
*/
|
||||
function toggleAttachmentList(expanded)
|
||||
{
|
||||
var attachmentToggle = document.getElementById("attachmentToggle");
|
||||
var attachmentView = document.getElementById("attachmentView");
|
||||
var attachmentSplitter = document.getElementById("attachment-splitter");
|
||||
var attachmentListWrapper = document.getElementById("attachmentListWrapper");
|
||||
var attachmentToggle = document.getElementById("attachmentToggle");
|
||||
var attachmentView = document.getElementById("attachmentView");
|
||||
var attachmentList = document.getElementById("attachmentList");
|
||||
var attachmentSplitter = document.getElementById("attachment-splitter");
|
||||
|
||||
if (expanded === undefined)
|
||||
expanded = !attachmentToggle.checked;
|
||||
attachmentToggle.checked = expanded;
|
||||
|
||||
if (expanded) {
|
||||
attachmentListWrapper.collapsed = false;
|
||||
attachmentList.collapsed = false;
|
||||
attachmentSplitter.collapsed = false;
|
||||
|
||||
var attachmentHeight = attachmentView.boxObject.height;
|
||||
var attachmentHeight = attachmentView.boxObject.height -
|
||||
attachmentList.boxObject.height + attachmentList.preferredHeight;
|
||||
|
||||
// If the attachments box takes up too much of the message pane, downsize:
|
||||
var maxAttachmentHeight = document.getElementById("messagepanebox")
|
||||
.boxObject.height / 4;
|
||||
|
||||
attachmentListWrapper.setAttribute("attachmentOverflow", "true");
|
||||
attachmentView.setAttribute("height", Math.min(attachmentHeight,
|
||||
maxAttachmentHeight));
|
||||
attachmentView.setAttribute("maxheight", attachmentHeight);
|
||||
}
|
||||
else {
|
||||
attachmentListWrapper.collapsed = true;
|
||||
attachmentList.collapsed = true;
|
||||
attachmentSplitter.collapsed = true;
|
||||
attachmentView.removeAttribute("height");
|
||||
attachmentView.removeAttribute("maxheight");
|
||||
|
||||
// Switch overflow off so that when we expand again we can get the
|
||||
// preferred size. (Doing this when expanding hits a race condition.)
|
||||
attachmentListWrapper.setAttribute("attachmentOverflow", "false");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a nice icon next to the attachment.
|
||||
* Pick out a nice icon for the attachment.
|
||||
* @param attachment the nsIMsgAttachment object to show icon for
|
||||
* @param listitem the listitem currently showing the attachment
|
||||
* @param largeView boolean value: 32x32 vs. 16x16 size icon
|
||||
*/
|
||||
function setApplicationIconForAttachment(attachment, listitem, largeView)
|
||||
function getIconForAttachment(attachment)
|
||||
{
|
||||
// Show a nice icon next to it the attachment.
|
||||
if (attachment.isDeleted)
|
||||
{
|
||||
let fn = largeView ? "attachment-deleted-large.png" : "attachment-deleted.png";
|
||||
listitem.setAttribute("image", "chrome://messenger/skin/icons/"+fn);
|
||||
}
|
||||
return "chrome://messenger/skin/icon/attachment-deleted.png";
|
||||
else
|
||||
{
|
||||
let iconSize = largeView ? 32 : 16;
|
||||
listitem.setAttribute("image", "moz-icon://" + attachment.name + "?size=" +
|
||||
iconSize + "&contentType=" + attachment.contentType);
|
||||
}
|
||||
return "moz-icon://" + attachment.name + "?size=16&contentType=" +
|
||||
attachment.contentType;
|
||||
}
|
||||
|
||||
// Public method called when we create the attachments file menu
|
||||
|
@ -2206,7 +2214,7 @@ function addAttachmentToPopup(popup, attachment, attachmentIndex)
|
|||
// Insert the item just before the separator. The separator is the 2nd to
|
||||
// last element in the popup.
|
||||
item.setAttribute('class', 'menu-iconic');
|
||||
setApplicationIconForAttachment(attachment,item, false);
|
||||
item.setAttribute('image', getIconForAttachment(attachment));
|
||||
|
||||
var numItemsInPopup = popup.childNodes.length;
|
||||
// find the separator
|
||||
|
@ -2301,7 +2309,7 @@ function HandleSelectedAttachments(action)
|
|||
/**
|
||||
* Perform an action on multiple attachments (e.g. open or save)
|
||||
*
|
||||
* @param attachments an array of attachment objects to work with
|
||||
* @param attachments an array of AttachmentInfo objects to work with
|
||||
* @param action one of "open", "save", "saveAs", "detach", or "delete"
|
||||
*/
|
||||
function HandleMultipleAttachments(attachments, action)
|
||||
|
@ -2417,7 +2425,7 @@ var attachmentListDNDObserver = {
|
|||
{
|
||||
var target = aEvent.target;
|
||||
|
||||
if (target.localName == "descriptionitem")
|
||||
if (target.localName == "attachmentitem")
|
||||
aAttachmentData.data = CreateAttachmentTransferData(target.attachment);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
]>
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/messageHeader.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/attachmentList.css" type="text/css"?>
|
||||
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript"
|
||||
|
@ -73,9 +74,9 @@
|
|||
CopyMessageId(messageId);"/>
|
||||
</menupopup>
|
||||
|
||||
<menupopup id="attachmentListContext"
|
||||
onpopupshowing="return onShowAttachmentContextMenu();"
|
||||
onpopuphiding="return onHideAttachmentContextMenu();">
|
||||
<menupopup id="attachmentItemContext"
|
||||
onpopupshowing="return onShowAttachmentItemContextMenu();"
|
||||
onpopuphiding="return onHideAttachmentItemContextMenu();">
|
||||
<menuitem id="context-openAttachment"
|
||||
label="&openAttachmentCmd.label;"
|
||||
accesskey="&openAttachmentCmd.accesskey;"
|
||||
|
@ -93,6 +94,10 @@
|
|||
label="&deleteAttachmentCmd.label;"
|
||||
accesskey="&deleteAttachmentCmd.accesskey;"
|
||||
oncommand="HandleMultipleAttachments(this.parentNode.attachments, 'delete');"/>
|
||||
</menupopup>
|
||||
|
||||
<menupopup id="attachmentListContext"
|
||||
onpopupshowing="return onShowAttachmentListContextMenu(event);">
|
||||
<menuitem id="context-openAllAttachments"
|
||||
label="&openAllAttachmentsCmd.label;"
|
||||
accesskey="&openAllAttachmentsCmd.accesskey;"
|
||||
|
@ -512,7 +517,7 @@
|
|||
<image id="attachmentIcon"/>
|
||||
<label id="attachmentCount"/>
|
||||
<label id="attachmentName" crop="center" flex="1"
|
||||
context="attachmentListContext"
|
||||
context="attachmentItemContext"
|
||||
onclick="if (event.button == 0) { HandleAllAttachments('open'); RestoreFocusAfterHdrButton(); }"
|
||||
ondraggesture="nsDragAndDrop.startDrag(event,attachmentNameDNDObserver);"/>
|
||||
<label id="attachmentSize"/>
|
||||
|
@ -593,14 +598,11 @@
|
|||
defaultset="attachmentSaveAll"/>
|
||||
</toolbox>
|
||||
</hbox>
|
||||
<box id="attachmentListWrapper" flex="1" collapsed="true">
|
||||
<description selectable="true" id="attachmentList" flex="1"
|
||||
seltype="multiple" context="attachmentListContext"
|
||||
onclick="attachmentListClick(event);"
|
||||
ondraggesture="nsDragAndDrop.startDrag(event,attachmentListDNDObserver);"
|
||||
ondragover="nsDragAndDrop.dragOver(event, attachmentListDNDObserver);">
|
||||
</description>
|
||||
</box>
|
||||
<attachmentlist orient="horizontal" id="attachmentList" flex="1"
|
||||
seltype="multiple" context="attachmentListContext"
|
||||
itemcontext="attachmentItemContext"
|
||||
ondraggesture="nsDragAndDrop.startDrag(event,attachmentListDNDObserver);"
|
||||
ondragover="nsDragAndDrop.dragOver(event, attachmentListDNDObserver);"/>
|
||||
</vbox>
|
||||
|
||||
</overlay>
|
||||
|
|
|
@ -2936,27 +2936,17 @@ function AddUrlAttachment(attachment)
|
|||
attachment.name = gComposeBundle.getString("partAttachmentSafeName");
|
||||
|
||||
var bucket = document.getElementById("attachmentBucket");
|
||||
var item;
|
||||
var item = bucket.appendItem(attachment);
|
||||
if (attachment.size != -1)
|
||||
{
|
||||
var size = gMessenger.formatFileSize(attachment.size);
|
||||
var nameAndSize = gComposeBundle.getFormattedString(
|
||||
"attachmentNameAndSize", [attachment.name, size]);
|
||||
item = bucket.appendItem(nameAndSize, "");
|
||||
gAttachmentsSize += attachment.size;
|
||||
}
|
||||
else
|
||||
item = bucket.appendItem(attachment.name, "");
|
||||
|
||||
item.attachment = attachment; // Full attachment object stored here.
|
||||
try {
|
||||
item.setAttribute("tooltiptext", decodeURI(attachment.url));
|
||||
}
|
||||
catch(e) {
|
||||
item.setAttribute("tooltiptext", attachment.url);
|
||||
}
|
||||
item.setAttribute("class", "listitem-iconic");
|
||||
item.setAttribute("crop", "center");
|
||||
item.addEventListener("command", OpenSelectedAttachment, false);
|
||||
|
||||
// For local file urls, we are better off using the full file url because
|
||||
// moz-icon will actually resolve the file url and get the right icon from
|
||||
|
@ -3520,13 +3510,9 @@ function subjectKeyPress(event)
|
|||
|
||||
function AttachmentBucketClicked(event)
|
||||
{
|
||||
if (event.button != 0)
|
||||
return;
|
||||
|
||||
if (event.originalTarget.localName == "listboxbody")
|
||||
let boundTarget = document.getBindingParent(event.originalTarget);
|
||||
if (event.button == 0 && boundTarget.localName == "scrollbox")
|
||||
goDoCommand('cmd_attachFile');
|
||||
else if (event.originalTarget.localName == "listitem" && event.detail == 2)
|
||||
OpenSelectedAttachment();
|
||||
}
|
||||
|
||||
// we can drag and drop addresses, files, messages and urls into the compose envelope
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/messengercompose/messengercompose.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/folderMenus.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/attachmentList.css" type="text/css"?>
|
||||
<?xul-overlay href="chrome://editor/content/editorOverlay.xul"?>
|
||||
#ifdef XP_MACOSX
|
||||
<?xul-overlay href="chrome://messenger/content/macMenuOverlay.xul"?>
|
||||
|
@ -312,14 +313,35 @@
|
|||
|
||||
</menupopup>
|
||||
|
||||
<menupopup id="msgComposeAttachmentContext" onpopupshowing="updateEditItems();">
|
||||
<menuitem label="&openAttachment.label;" accesskey="&openAttachment.accesskey;" command="cmd_openAttachment"/>
|
||||
<menuitem label="&removeAttachment.label;" accesskey="&removeAttachment.accesskey;" command="cmd_delete"/>
|
||||
<menuitem label="&renameAttachment.label;" accesskey="&renameAttachment.accesskey;" command="cmd_renameAttachment"/>
|
||||
<menuitem label="&selectAll.label;" accesskey="&selectAll.accesskey;" command="cmd_selectAll"/>
|
||||
<menupopup id="msgComposeAttachmentItemContext"
|
||||
onpopupshowing="updateEditItems();">
|
||||
<menuitem label="&openAttachment.label;"
|
||||
accesskey="&openAttachment.accesskey;"
|
||||
command="cmd_openAttachment"/>
|
||||
<menuitem label="&removeAttachment.label;"
|
||||
accesskey="&removeAttachment.accesskey;"
|
||||
command="cmd_delete"/>
|
||||
<menuitem label="&renameAttachment.label;"
|
||||
accesskey="&renameAttachment.accesskey;"
|
||||
command="cmd_renameAttachment"/>
|
||||
<menuseparator/>
|
||||
<menuitem label="&attachFile.label;" accesskey="&attachFile.accesskey;" command="cmd_attachFile"/>
|
||||
<menuitem label="&attachPage.label;" accesskey="&attachPage.accesskey;" command="cmd_attachPage"/>
|
||||
<menuitem label="&selectAll.label;"
|
||||
accesskey="&selectAll.accesskey;"
|
||||
command="cmd_selectAll"/>
|
||||
</menupopup>
|
||||
|
||||
<menupopup id="msgComposeAttachmentListContext"
|
||||
onpopupshowing="updateEditItems();">
|
||||
<menuitem label="&selectAll.label;"
|
||||
accesskey="&selectAll.accesskey;"
|
||||
command="cmd_selectAll"/>
|
||||
<menuseparator/>
|
||||
<menuitem label="&attachFile.label;"
|
||||
accesskey="&attachFile.accesskey;"
|
||||
command="cmd_attachFile"/>
|
||||
<menuitem label="&attachPage.label;"
|
||||
accesskey="&attachPage.accesskey;"
|
||||
command="cmd_attachPage"/>
|
||||
</menupopup>
|
||||
|
||||
<menupopup id="toolbar-context-menu"
|
||||
|
@ -755,12 +777,13 @@
|
|||
crop="right" accesskey="&attachments.accesskey;"/>
|
||||
<label id="attachmentBucketSize"/>
|
||||
</hbox>
|
||||
<listbox seltype="multiple" id="attachmentBucket" flex="1" rows="4"
|
||||
tabindex="0"
|
||||
context="msgComposeAttachmentContext"
|
||||
onkeypress="if (event.keyCode == 8 || event.keyCode == 46) RemoveSelectedAttachment();"
|
||||
onclick="AttachmentBucketClicked(event);"
|
||||
ondraggesture="nsDragAndDrop.startDrag(event, attachmentBucketDNDObserver);"/>
|
||||
<attachmentlist orient="vertical" id="attachmentBucket"
|
||||
seltype="multiple" flex="1" height="0" tabindex="0"
|
||||
context="msgComposeAttachmentListContext"
|
||||
itemcontext="msgComposeAttachmentItemContext"
|
||||
onkeypress="if (event.keyCode == 8 || event.keyCode == 46) RemoveSelectedAttachment();"
|
||||
onclick="AttachmentBucketClicked(event);"
|
||||
ondraggesture="nsDragAndDrop.startDrag(event, attachmentBucketDNDObserver);"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</toolbar>
|
||||
|
|
|
@ -218,16 +218,16 @@ function setupModule(module) {
|
|||
*/
|
||||
function check_attachment_size(index, expectedSize) {
|
||||
let list = mc.e('attachmentList');
|
||||
let node = list.getElementsByTagName('descriptionitem')[index];
|
||||
let node = list.getElementsByTagName('attachmentitem')[index];
|
||||
|
||||
// First, let's check that the 'attachmentSize' attribute is correct
|
||||
let size = parseInt(node.getAttribute('attachmentSize'));
|
||||
// First, let's check that the attachment size is correct
|
||||
let size = node.attachment.size;
|
||||
if (Math.abs(size - expectedSize) > epsilon)
|
||||
throw new Error('Reported attachment size ('+size+') not within epsilon ' +
|
||||
'of actual attachment size ('+expectedSize+')');
|
||||
|
||||
// Next, make sure that the formatted size in the label is correct
|
||||
let formattedSize = /\((.*?)\)$/.exec(node.getAttribute('label'))[1];
|
||||
let formattedSize = node.getAttribute('size');
|
||||
let expectedFormattedSize = messenger.formatFileSize(size);
|
||||
if (formattedSize != expectedFormattedSize)
|
||||
throw new Error('Formatted attachment size ('+formattedSize+') does not ' +
|
||||
|
@ -240,13 +240,13 @@ function check_attachment_size(index, expectedSize) {
|
|||
*/
|
||||
function check_no_attachment_size(index) {
|
||||
let list = mc.e('attachmentList');
|
||||
let node = list.getElementsByTagName('descriptionitem')[index];
|
||||
let node = list.getElementsByTagName('attachmentitem')[index];
|
||||
|
||||
if (node.getAttribute('attachmentSize') != '')
|
||||
if (node.attachment.size != null)
|
||||
throw new Error('attachmentSize attribute of deleted attachment should ' +
|
||||
'be null!');
|
||||
|
||||
if (/\((.*?)\)$/.exec(node.getAttribute('label')))
|
||||
if (node.getAttribute('size') != '')
|
||||
throw new Error('Attachment size should not be displayed!');
|
||||
}
|
||||
|
||||
|
@ -258,7 +258,7 @@ function check_no_attachment_size(index) {
|
|||
*/
|
||||
function check_total_attachment_size(count, expectedSize, exact) {
|
||||
let list = mc.e('attachmentList');
|
||||
let nodes = list.getElementsByTagName('descriptionitem');
|
||||
let nodes = list.getElementsByTagName('attachmentitem');
|
||||
let sizeNode = mc.e('attachmentSize');
|
||||
|
||||
if (nodes.length != count)
|
||||
|
@ -266,7 +266,7 @@ function check_total_attachment_size(count, expectedSize, exact) {
|
|||
|
||||
let size = 0;
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
let currSize = parseInt(nodes[i].getAttribute('attachmentSize'));
|
||||
let currSize = nodes[i].attachment.size;
|
||||
if (!isNaN(currSize))
|
||||
size += currSize;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,8 @@ const binaryAttachment = textAttachment;
|
|||
var setupModule = function (module) {
|
||||
let fdh = collector.getModule('folder-display-helpers');
|
||||
fdh.installInto(module);
|
||||
let wh = collector.getModule('window-helpers');
|
||||
wh.installInto(module);
|
||||
let composeHelper = collector.getModule('compose-helpers');
|
||||
composeHelper.installInto(module);
|
||||
let wh = collector.getModule('window-helpers');
|
||||
|
@ -137,8 +139,8 @@ function test_attachment_name_click() {
|
|||
|
||||
// Ensure the context menu appears when right-clicking the attachment name
|
||||
mc.rightClick(mc.eid("attachmentName"));
|
||||
wait_for_popup_to_open(mc.e("attachmentListContext"));
|
||||
close_popup(mc, mc.eid("attachmentListContext"));
|
||||
wait_for_popup_to_open(mc.e("attachmentItemContext"));
|
||||
close_popup(mc, mc.eid("attachmentItemContext"));
|
||||
}
|
||||
|
||||
function test_attachment_list_expansion() {
|
||||
|
@ -147,24 +149,28 @@ function test_attachment_list_expansion() {
|
|||
select_click_row(1);
|
||||
assert_selected_and_displayed(1);
|
||||
|
||||
assert_true(mc.e("attachmentListWrapper").collapsed,
|
||||
"Attachment list should start out collapsed!");
|
||||
let attachmentList = mc.e("attachmentList");
|
||||
let attachmentToggle = mc.eid("attachmentToggle");
|
||||
let attachmentBar = mc.eid("attachmentBar");
|
||||
|
||||
mc.click(mc.eid("attachmentToggle"));
|
||||
assert_true(!mc.e("attachmentListWrapper").collapsed,
|
||||
"Attachment list should be expanded after clicking twisty!");
|
||||
assert_true(attachmentList.collapsed, "Attachment list should start out " +
|
||||
"collapsed!");
|
||||
|
||||
mc.click(mc.eid("attachmentToggle"));
|
||||
assert_true(mc.e("attachmentListWrapper").collapsed,
|
||||
"Attachment list should be collapsed after clicking twisty again!");
|
||||
mc.click(attachmentToggle);
|
||||
assert_true(!attachmentList.collapsed, "Attachment list should be expanded " +
|
||||
"after clicking twisty!");
|
||||
|
||||
mc.click(mc.eid("attachmentBar"));
|
||||
assert_true(!mc.e("attachmentListWrapper").collapsed,
|
||||
"Attachment list should be expanded after clicking bar!");
|
||||
mc.click(attachmentToggle);
|
||||
assert_true(attachmentList.collapsed, "Attachment list should be collapsed " +
|
||||
"after clicking twisty again!");
|
||||
|
||||
mc.click(mc.eid("attachmentBar"));
|
||||
assert_true(mc.e("attachmentListWrapper").collapsed,
|
||||
"Attachment list should be collapsed after clicking bar again!");
|
||||
mc.click(attachmentBar);
|
||||
assert_true(!attachmentList.collapsed, "Attachment list should be expanded " +
|
||||
"after clicking bar!");
|
||||
|
||||
mc.click(attachmentBar);
|
||||
assert_true(attachmentList.collapsed, "Attachment list should be collapsed " +
|
||||
"after clicking bar again!");
|
||||
}
|
||||
|
||||
function test_selected_attachments_are_cleared() {
|
||||
|
@ -183,7 +189,7 @@ function test_selected_attachments_are_cleared() {
|
|||
|
||||
// We can just click on the first element, but the second one needs a
|
||||
// ctrl-click (or cmd-click for those Mac-heads among us).
|
||||
mc.click(new elib.Elem(attachmentList.children[0]));
|
||||
mc.click(new elib.Elem(attachmentList.children[0]), 5, 5);
|
||||
EventUtils.synthesizeMouse(attachmentList.children[1], 5, 5,
|
||||
{accelKey: true}, mc.window);
|
||||
|
||||
|
@ -232,10 +238,55 @@ function test_attachment_toolbar_customize() {
|
|||
add_to_toolbar(mc.e("attachment-view-toolbar"), "attachmentSaveAll");
|
||||
}
|
||||
|
||||
function test_select_all_attachments_key() {
|
||||
be_in_folder(folder);
|
||||
|
||||
// First, select the message with two attachments.
|
||||
select_none();
|
||||
select_click_row(3);
|
||||
|
||||
// Expand the attachment list.
|
||||
mc.click(mc.eid("attachmentToggle"));
|
||||
|
||||
let attachmentList = mc.e("attachmentList");
|
||||
mc.keypress(new elib.Elem(attachmentList), "a", {accelKey: true});
|
||||
assert_equals(attachmentList.selectedItems.length, 2,
|
||||
"Should have selected all attachments!");
|
||||
}
|
||||
|
||||
function test_delete_attachment_key() {
|
||||
be_in_folder(folder);
|
||||
|
||||
// First, select the message with two attachments.
|
||||
select_none();
|
||||
select_click_row(3);
|
||||
|
||||
// Expand the attachment list.
|
||||
mc.click(mc.eid("attachmentToggle"));
|
||||
|
||||
let firstAttachment = new elib.Elem(mc.e("attachmentList").firstChild);
|
||||
mc.click(firstAttachment, 5, 5);
|
||||
|
||||
// Try deleting with the delete key
|
||||
plan_for_modal_dialog("commonDialog", function(cdc) {
|
||||
cdc.window.document.documentElement.cancelDialog();
|
||||
});
|
||||
mc.keypress(firstAttachment, "VK_DELETE", {});
|
||||
wait_for_modal_dialog("commonDialog");
|
||||
|
||||
// Try deleting with the shift-delete key combo.
|
||||
plan_for_modal_dialog("commonDialog", function(cdc) {
|
||||
cdc.window.document.documentElement.cancelDialog();
|
||||
});
|
||||
mc.keypress(firstAttachment, "VK_DELETE", {shiftKey: true});
|
||||
wait_for_modal_dialog("commonDialog");
|
||||
}
|
||||
|
||||
function test_attachments_compose_menu() {
|
||||
be_in_folder(folder);
|
||||
|
||||
// First, select the message with two attachments.
|
||||
select_none();
|
||||
select_click_row(3);
|
||||
|
||||
let cwc = open_compose_with_forward();
|
||||
|
|
|
@ -122,16 +122,16 @@ function setupModule(module) {
|
|||
*/
|
||||
function check_attachment_size(controller, index, expectedSize) {
|
||||
let bucket = controller.e('attachmentBucket');
|
||||
let node = bucket.getElementsByTagName('listitem')[index];
|
||||
let node = bucket.getElementsByTagName('attachmentitem')[index];
|
||||
|
||||
// First, let's check that the 'attachmentSize' attribute is correct
|
||||
// First, let's check that the attachment size is correct
|
||||
let size = node.attachment.size;
|
||||
if (Math.abs(size - expectedSize) > epsilon)
|
||||
throw new Error('Reported attachment size ('+size+') not within epsilon ' +
|
||||
'of actual attachment size ('+expectedSize+')');
|
||||
|
||||
// Next, make sure that the formatted size in the label is correct
|
||||
let formattedSize = /\((.*?)\)$/.exec(node.getAttribute('label'))[1];
|
||||
let formattedSize = node.getAttribute('size');
|
||||
let expectedFormattedSize = messenger.formatFileSize(size);
|
||||
if (formattedSize != expectedFormattedSize)
|
||||
throw new Error('Formatted attachment size ('+formattedSize+') does not ' +
|
||||
|
@ -145,12 +145,12 @@ function check_attachment_size(controller, index, expectedSize) {
|
|||
*/
|
||||
function check_no_attachment_size(controller, index) {
|
||||
let bucket = controller.e('attachmentBucket');
|
||||
let node = bucket.getElementsByTagName('listitem')[index];
|
||||
let node = bucket.getElementsByTagName('attachmentitem')[index];
|
||||
|
||||
if (node.attachment.size != -1)
|
||||
throw new Error('attachment.size attribute should be -1!');
|
||||
|
||||
if (/\((.*?)\)$/.exec(node.getAttribute('label')))
|
||||
if (node.getAttribute('size') != '')
|
||||
throw new Error('Attachment size should not be displayed!');
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ function check_no_attachment_size(controller, index) {
|
|||
*/
|
||||
function check_total_attachment_size(controller, count) {
|
||||
let bucket = controller.e("attachmentBucket");
|
||||
let nodes = bucket.getElementsByTagName("listitem");
|
||||
let nodes = bucket.getElementsByTagName("attachmentitem");
|
||||
let sizeNode = controller.e("attachmentBucketSize");
|
||||
|
||||
if (nodes.length != count)
|
||||
|
@ -252,7 +252,7 @@ function test_rename_attachment() {
|
|||
|
||||
// Now, rename the attachment.
|
||||
let bucket = cwc.e("attachmentBucket");
|
||||
let node = bucket.getElementsByTagName("listitem")[0];
|
||||
let node = bucket.getElementsByTagName("attachmentitem")[0];
|
||||
cwc.click(new elib.Elem(node));
|
||||
plan_for_modal_dialog("commonDialog", subtest_rename_attachment);
|
||||
cwc.window.RenameSelectedAttachment();
|
||||
|
|
|
@ -268,7 +268,7 @@ function add_attachment(aComposeWindow, aUrl, aSize) {
|
|||
*/
|
||||
function delete_attachment(aComposeWindow, aIndex) {
|
||||
let bucket = aComposeWindow.e('attachmentBucket');
|
||||
let node = bucket.getElementsByTagName('listitem')[aIndex];
|
||||
let node = bucket.getElementsByTagName('attachmentitem')[aIndex];
|
||||
|
||||
aComposeWindow.click(new elib.Elem(node));
|
||||
aComposeWindow.window.RemoveSelectedAttachment();
|
||||
|
|
|
@ -19,6 +19,8 @@ classic.jar:
|
|||
skin/classic/messenger/messageBody.css (mail/messageBody.css)
|
||||
skin/classic/messenger/messageQuotes.css (mail/messageQuotes.css)
|
||||
skin/classic/messenger/messenger.css (mail/messenger.css)
|
||||
skin/classic/messenger/attachmentList.css (mail/attachmentList.css)
|
||||
skin/classic/messenger/imageFilters.svg (mail/imageFilters.svg)
|
||||
skin/classic/messenger/mailWindow1.css (mail/mailWindow1.css)
|
||||
skin/classic/messenger/tagColors.css (mail/tagColors.css)
|
||||
skin/classic/messenger/messageWindow.css (mail/messageWindow.css)
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Thunderbird
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Messaging
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jim Porter <squibblyflabbetydoo@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* styles for the attachment list */
|
||||
|
||||
.attachmentcell-icon {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.attachmentcell-name,
|
||||
.attachmentcell-size {
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.attachmentcell-size {
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
attachmentlist[orient="horizontal"] > attachmentitem {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
attachmentlist[orient="horizontal"] .attachmentcell-icon,
|
||||
attachmentlist[orient="horizontal"] .attachmentcell-nameselection {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[selected="true"][current="true"] .attachmentcell-nameselection {
|
||||
outline: 1px dotted #F3D982;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[current="true"] .attachmentcell-nameselection {
|
||||
outline: 1px dotted;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
attachmentitem[selected="true"] .attachmentcell-nameselection {
|
||||
background-color: -moz-CellHighlight;
|
||||
color: -moz-CellHighlightText;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[selected="true"] .attachmentcell-nameselection {
|
||||
background-color: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
attachmentitem[selected="true"] .attachmentcell-icon {
|
||||
filter: url("chrome://messenger/skin/imageFilters.svg#selected");
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[selected="true"] .attachmentcell-icon {
|
||||
filter: url("chrome://messenger/skin/imageFilters.svg#selected-focus");
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is Mozilla Thunderbird.
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- Mozilla Messaging.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2011
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Jim Porter <squibblyflabbetydoo@gmail.com>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<filter id="selected-focus">
|
||||
<feFlood flood-color="Highlight" flood-opacity="0.7" result="color"/>
|
||||
<feComposite in="color" in2="SourceAlpha" operator="in" result="mask"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
<feMergeNode in="mask"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
|
||||
<filter id="selected">
|
||||
<feFlood flood-color="-moz-CellHighlight" flood-opacity="0.7" result="color"/>
|
||||
<feComposite in="color" in2="SourceAlpha" operator="in" result="mask"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
<feMergeNode in="mask"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</svg>
|
|
@ -119,7 +119,7 @@
|
|||
/* ::::: attachment view ::::: */
|
||||
|
||||
#attachmentList {
|
||||
margin: 0px;
|
||||
margin: 0;
|
||||
background-color: -moz-Field;
|
||||
color: -moz-FieldText;
|
||||
}
|
||||
|
@ -176,47 +176,10 @@
|
|||
list-style-image: url("moz-icon://stock/gtk-save?size=menu");
|
||||
}
|
||||
|
||||
/* XXX: Move all of the description attributes to the toolkit */
|
||||
|
||||
description[selectable="true"] {
|
||||
margin: 1px 5px 4px;
|
||||
}
|
||||
|
||||
descriptionitem {
|
||||
border: 1px solid transparent;
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
description[selectable="true"]:focus > descriptionitem[current="true"] {
|
||||
border: 1px dotted #F5DB95;
|
||||
}
|
||||
|
||||
descriptionitem[selected="true"] {
|
||||
background-color: -moz-Dialog;
|
||||
color: -moz-DialogText;
|
||||
}
|
||||
|
||||
description[selectable="true"]:focus > descriptionitem[selected="true"] {
|
||||
background-color: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
.attachmentBox {
|
||||
width: 15em;
|
||||
}
|
||||
|
||||
#attachmentList[largeView="true"] .attachmentBox {
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
#attachmentView {
|
||||
border-top: 1px solid ThreeDShadow;
|
||||
}
|
||||
|
||||
#attachmentListWrapper[attachmentOverflow="true"] {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* ::::: msg header captions ::::: */
|
||||
|
||||
#msgHeaderView {
|
||||
|
|
|
@ -21,6 +21,7 @@ classic.jar:
|
|||
skin/classic/messenger/messageHeader.css (mail/messageHeader.css)
|
||||
skin/classic/messenger/messageWindow.css (mail/messageWindow.css)
|
||||
skin/classic/messenger/messageBody.css (mail/messageBody.css)
|
||||
skin/classic/messenger/attachmentList.css (mail/attachmentList.css)
|
||||
skin/classic/messenger/msgSelectOffline.css (mail/msgSelectOffline.css)
|
||||
skin/classic/messenger/mailWindow1.css (mail/mailWindow1.css)
|
||||
skin/classic/messenger/searchBox.css (mail/searchBox.css)
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Thunderbird
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Messaging
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jim Porter <squibblyflabbetydoo@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* styles for the attachment list */
|
||||
|
||||
/* ::::: attachment list ::::: */
|
||||
|
||||
.attachmentcell-icon {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.attachmentcell-name,
|
||||
.attachmentcell-size {
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.attachmentcell-size {
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[selected="true"][current="true"] {
|
||||
outline: 1px dotted #F3D982;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[current="true"] {
|
||||
outline: 1px dotted;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
attachmentitem[selected="true"] {
|
||||
background-color: -moz-CellHighlight;
|
||||
color: -moz-CellHighlightText;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[selected="true"] {
|
||||
background-color: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
attachmentitem[selected="true"] .attachmentcell-size {
|
||||
color: -moz-CellHighlightText;
|
||||
}
|
||||
|
||||
attachmentlist:focus >attachmentitem[selected="true"] .attachmentcell-size {
|
||||
color: HighlightText;
|
||||
}
|
|
@ -145,6 +145,8 @@
|
|||
|
||||
#attachmentList {
|
||||
margin: 0px;
|
||||
background-color: -moz-Field;
|
||||
color: -moz-FieldText;
|
||||
}
|
||||
|
||||
#attachmentToggle {
|
||||
|
@ -203,56 +205,8 @@
|
|||
padding-bottom: 0px !important;
|
||||
}
|
||||
|
||||
/* XXX: Move all of the description attributes to the toolkit */
|
||||
|
||||
description {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
descriptionitem {
|
||||
padding: 0px;
|
||||
margin: 1px;
|
||||
text-decoration: underline;
|
||||
color: blue;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
description[selectable="true"]:focus > descriptionitem[selected="true"][current="true"] {
|
||||
border: 1px solid #B8B8B8;
|
||||
background-color: #C8C8C8;
|
||||
}
|
||||
|
||||
descriptionitem[selected="true"] {
|
||||
border: 1px solid #B8B8B8;
|
||||
background-color: #C8C8C8;
|
||||
}
|
||||
|
||||
description[selectable="true"]:focus > descriptionitem[selected="true"] {
|
||||
border: 1px solid #B8B8B8;
|
||||
background-color: #C8C8C8;
|
||||
}
|
||||
|
||||
.descriptioncell-icon {
|
||||
}
|
||||
|
||||
.attachmentBox {
|
||||
width: 15em;
|
||||
}
|
||||
|
||||
#attachmentView[largeView="true"] .attachmentBox{
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
#attachmentView {
|
||||
background-color: #E6E6E6;
|
||||
border: 1px solid #C8C8C8;
|
||||
border-radius: 7px;
|
||||
margin: 4px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
#attachmentListWrapper[attachmentOverflow="true"] {
|
||||
overflow: auto;
|
||||
border-top: 1px solid ThreeDShadow;
|
||||
}
|
||||
|
||||
#attachment-splitter {
|
||||
|
@ -261,6 +215,48 @@ description[selectable="true"]:focus > descriptionitem[selected="true"] {
|
|||
background-color: #E6E6E6;
|
||||
}
|
||||
|
||||
/* ::::: attachment list ::::: */
|
||||
|
||||
.attachmentcell-icon {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.attachmentcell-name,
|
||||
.attachmentcell-size {
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.attachmentcell-size {
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[selected="true"][current="true"] {
|
||||
outline: 1px dotted #F3D982;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[current="true"] {
|
||||
outline: 1px dotted;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
attachmentitem[selected="true"] {
|
||||
background-color: -moz-CellHighlight;
|
||||
color: -moz-CellHighlightText;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[selected="true"] {
|
||||
background-color: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
attachmentitem[selected="true"] .attachmentcell-size {
|
||||
color: -moz-CellHighlightText;
|
||||
}
|
||||
|
||||
attachmentlist:focus >attachmentitem[selected="true"] .attachmentcell-size {
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
/* ::::: msg header captions ::::: */
|
||||
|
||||
#msgHeaderView {
|
||||
|
|
|
@ -59,6 +59,8 @@ classic.jar:
|
|||
skin/classic/messenger/messageBody.css (mail/messageBody.css)
|
||||
skin/classic/messenger/messageQuotes.css (mail/messageQuotes.css)
|
||||
skin/classic/messenger/messenger.css (mail/messenger.css)
|
||||
skin/classic/messenger/attachmentList.css (mail/attachmentList.css)
|
||||
skin/classic/messenger/imageFilters.svg (mail/imageFilters.svg)
|
||||
skin/classic/messenger/mailWindow1.css (mail/mailWindow1.css)
|
||||
skin/classic/messenger/tagColors.css (mail/tagColors.css)
|
||||
skin/classic/messenger/messageWindow.css (mail/messageWindow.css)
|
||||
|
@ -293,6 +295,8 @@ classic.jar:
|
|||
skin/classic/aero/messenger/messageBody.css (mail/messageBody.css)
|
||||
skin/classic/aero/messenger/messageQuotes.css (mail/messageQuotes.css)
|
||||
* skin/classic/aero/messenger/messenger.css (mail/messenger-aero.css)
|
||||
skin/classic/aero/messenger/attachmentList.css (mail/attachmentList.css)
|
||||
skin/classic/aero/messenger/imageFilters.svg (mail/imageFilters.svg)
|
||||
* skin/classic/aero/messenger/mailWindow1.css (mail/mailWindow1-aero.css)
|
||||
skin/classic/aero/messenger/tagColors.css (mail/tagColors.css)
|
||||
skin/classic/aero/messenger/messageWindow.css (mail/messageWindow.css)
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Thunderbird
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Messaging
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jim Porter <squibblyflabbetydoo@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* styles for the attachment list */
|
||||
|
||||
.attachmentcell-icon {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.attachmentcell-name,
|
||||
.attachmentcell-size {
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.attachmentcell-size {
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
attachmentlist[orient="horizontal"] > attachmentitem {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
attachmentlist[orient="horizontal"] .attachmentcell-icon,
|
||||
attachmentlist[orient="horizontal"] .attachmentcell-nameselection {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[selected="true"][current="true"] .attachmentcell-nameselection {
|
||||
outline: 1px dotted #F3D982;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[current="true"] .attachmentcell-nameselection {
|
||||
outline: 1px dotted;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
attachmentitem[selected="true"] .attachmentcell-nameselection {
|
||||
background-color: -moz-CellHighlight;
|
||||
color: -moz-CellHighlightText;
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[selected="true"] .attachmentcell-nameselection {
|
||||
background-color: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
attachmentitem[selected="true"] .attachmentcell-icon {
|
||||
filter: url("chrome://messenger/skin/imageFilters.svg#selected");
|
||||
}
|
||||
|
||||
attachmentlist:focus > attachmentitem[selected="true"] .attachmentcell-icon {
|
||||
filter: url("chrome://messenger/skin/imageFilters.svg#selected-focus");
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is Mozilla Thunderbird.
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- Mozilla Messaging.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2011
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Jim Porter <squibblyflabbetydoo@gmail.com>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<filter id="selected-focus">
|
||||
<feFlood flood-color="Highlight" flood-opacity="0.7" result="color"/>
|
||||
<feComposite in="color" in2="SourceAlpha" operator="in" result="mask"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
<feMergeNode in="mask"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
|
||||
<filter id="selected">
|
||||
<feFlood flood-color="-moz-CellHighlight" flood-opacity="0.7" result="color"/>
|
||||
<feComposite in="color" in2="SourceAlpha" operator="in" result="mask"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
<feMergeNode in="mask"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</svg>
|
|
@ -211,47 +211,10 @@
|
|||
list-style-image: url("chrome://messenger/skin/icons/download.png");
|
||||
}
|
||||
|
||||
/* XXX: Move all of the description attributes to the toolkit */
|
||||
|
||||
description[selectable="true"] {
|
||||
margin: 1px 5px 4px;
|
||||
}
|
||||
|
||||
descriptionitem {
|
||||
border: 1px solid transparent;
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
description[selectable="true"]:focus > descriptionitem[current="true"] {
|
||||
border: 1px dotted #F5DB95;
|
||||
}
|
||||
|
||||
descriptionitem[selected="true"] {
|
||||
background-color: -moz-Dialog;
|
||||
color: -moz-DialogText;
|
||||
}
|
||||
|
||||
description[selectable="true"]:focus > descriptionitem[selected="true"] {
|
||||
background-color: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
.attachmentBox {
|
||||
width: 15em;
|
||||
}
|
||||
|
||||
#attachmentView[largeView="true"] .attachmentBox {
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
#attachmentView {
|
||||
border-top: 1px solid ThreeDShadow;
|
||||
}
|
||||
|
||||
#attachmentListWrapper[attachmentOverflow="true"] {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* ::::: msg header captions ::::: */
|
||||
|
||||
#msgHeaderView {
|
||||
|
|
|
@ -193,47 +193,10 @@
|
|||
-moz-image-region: rect(0px 192px 16px 176px);
|
||||
}
|
||||
|
||||
/* XXX: Move all of the description attributes to the toolkit */
|
||||
|
||||
description[selectable="true"] {
|
||||
margin: 1px 5px 4px;
|
||||
}
|
||||
|
||||
descriptionitem {
|
||||
border: 1px solid transparent;
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
description[selectable="true"]:focus > descriptionitem[current="true"] {
|
||||
border: 1px dotted #F5DB95;
|
||||
}
|
||||
|
||||
descriptionitem[selected="true"] {
|
||||
background-color: -moz-Dialog;
|
||||
color: -moz-DialogText;
|
||||
}
|
||||
|
||||
description[selectable="true"]:focus > descriptionitem[selected="true"] {
|
||||
background-color: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
.attachmentBox {
|
||||
width: 15em;
|
||||
}
|
||||
|
||||
#attachmentView[largeView="true"] .attachmentBox {
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
#attachmentView {
|
||||
border-top: 1px solid ThreeDShadow;
|
||||
}
|
||||
|
||||
#attachmentListWrapper[attachmentOverflow="true"] {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* ::::: msg header captions ::::: */
|
||||
|
||||
#msgHeaderView {
|
||||
|
|
Загрузка…
Ссылка в новой задаче