| 1 | <?xml version="1.0"?>\r |
| 2 | \r |
| 3 | <bindings id="mailBindings"\r |
| 4 | xmlns="http://www.mozilla.org/xbl"\r |
| 5 | xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">\r |
| 6 | \r |
| 7 | <!-- Message Pane Widgets -->\r |
| 8 | <binding id="mail-emailaddress" extends="chrome://global/content/xulBindings.xml#basetext">\r |
| 9 | <content excludes="observes,template">\r |
| 10 | <xul:box inherits="orient" autostretch="never" flex="1">\r |
| 11 | <xul:box orient="vertical" autostretch="never" flex="1">\r |
| 12 | <xul:text class="emailDisplayButton" context="emailAddressPopup" inherits="value,accesskey,crop"/>\r |
| 13 | </xul:box>\r |
| 14 | <xul:image class="emailDisplayImage" inherits="src"/>\r |
| 15 | </xul:box>\r |
| 16 | </content>\r |
| 17 | \r |
| 18 | <interface> \r |
| 19 | <method name="setTextAttribute">\r |
| 20 | <argument name="attributeName"/>\r |
| 21 | <argument name="attributeValue"/>\r |
| 22 | <body>\r |
| 23 | <![CDATA[ \r |
| 24 | var textNode = document.getAnonymousNodes(this)[0].firstChild.firstChild;\r |
| 25 | textNode.setAttribute(attributeName, attributeValue);\r |
| 26 | ]]>\r |
| 27 | </body>\r |
| 28 | </method>\r |
| 29 | \r |
| 30 | <method name="getTextAttribute">\r |
| 31 | <argument name="attributeName"/>\r |
| 32 | <argument name="attributeValue"/>\r |
| 33 | <body>\r |
| 34 | <![CDATA[ \r |
| 35 | var textNode = document.getAnonymousNodes(this)[0].firstChild.firstChild;\r |
| 36 | return textNode.getAttribute(attributeName, attributeValue);\r |
| 37 | ]]>\r |
| 38 | </body>\r |
| 39 | </method>\r |
| 40 | </interface>\r |
| 41 | </binding>\r |
| 42 | \r |
| 43 | <binding id="search-menulist-abstract" extends="xul:box">\r |
| 44 | <content>\r |
| 45 | <xul:menulist inherits="flex" oncommand="this.parentNode.onSelect(event)">\r |
| 46 | <xul:menupopup/>\r |
| 47 | </xul:menulist>\r |
| 48 | </content>\r |
| 49 | \r |
| 50 | <interface>\r |
| 51 | <property readonly="true" name="validityManager">\r |
| 52 | <![CDATA[\r |
| 53 | Components.classes['mozilla.mail.search.validityManager.1'].getService(Components.interfaces.nsIMsgSearchValidityManager);\r |
| 54 | ]]>\r |
| 55 | </property>\r |
| 56 | <property name="searchScope" onget="return this.internalScope;">\r |
| 57 | <!-- scope ID - retrieve the table -->\r |
| 58 | <setter>\r |
| 59 | <![CDATA[\r |
| 60 | // if scope isn't changing this is a noop\r |
| 61 | if (this.internalScope == val) return;\r |
| 62 | \r |
| 63 | this.internalScope = val;\r |
| 64 | this.refreshList();\r |
| 65 | var targets = this.targets;\r |
| 66 | if (targets) {\r |
| 67 | for (var i=0; i< targets.length; i++) {\r |
| 68 | targets[i].searchScope = val;\r |
| 69 | }\r |
| 70 | }\r |
| 71 | ]]>\r |
| 72 | </setter>\r |
| 73 | </property>\r |
| 74 | \r |
| 75 | <property name="validityTable" readonly="true" onget="return this.validityManager.getTable(this.searchScope)"/>\r |
| 76 | \r |
| 77 | <property name="valueStrings" readonly="true">\r |
| 78 | <getter>\r |
| 79 | <![CDATA[\r |
| 80 | var strings = new Array;\r |
| 81 | var ids = this.valueIds;\r |
| 82 | var bundle = this.stringBundle;\r |
| 83 | for (var i=0; i<ids.length; i++)\r |
| 84 | strings[i] = this.stringBundle.GetStringFromID(ids[i]);\r |
| 85 | return strings;\r |
| 86 | ]]>\r |
| 87 | </getter>\r |
| 88 | </property>\r |
| 89 | <property name="targets" readonly="true">\r |
| 90 | <getter>\r |
| 91 | <![CDATA[\r |
| 92 | var forAttrs = this.getAttribute("for");\r |
| 93 | if (!forAttrs) return null;\r |
| 94 | var targetIds = forAttrs.split(",");\r |
| 95 | if (targetIds.length == 0) return null;\r |
| 96 | \r |
| 97 | var targets = new Array;\r |
| 98 | var j=0;\r |
| 99 | for (var i=0; i<targetIds.length;i++) {\r |
| 100 | var target = document.getElementById(targetIds[i]);\r |
| 101 | if (target) targets[j++] = target;\r |
| 102 | }\r |
| 103 | return targets;\r |
| 104 | ]]>\r |
| 105 | </getter>\r |
| 106 | </property>\r |
| 107 | \r |
| 108 | <!-- value forwards to the internal menulist's "data" attribute -->\r |
| 109 | <property name="value" onget="return document.getAnonymousNodes(this)[0].selectedItem.getAttribute('data');">\r |
| 110 | <setter>\r |
| 111 | <![CDATA[\r |
| 112 | var menulist = document.getAnonymousNodes(this)[0];\r |
| 113 | var dataItems = menulist.getElementsByAttribute("data", val);\r |
| 114 | if (dataItems.length > 0)\r |
| 115 | menulist.selectedItem = dataItems[0];\r |
| 116 | ]]>\r |
| 117 | </setter>\r |
| 118 | </property>\r |
| 119 | <method name="refreshList">\r |
| 120 | <body>\r |
| 121 | <![CDATA[\r |
| 122 | var menuItemIds = this.valueIds;\r |
| 123 | var menuItemStrings = this.valueStrings;\r |
| 124 | \r |
| 125 | var menulist = document.getAnonymousNodes(this)[0];\r |
| 126 | var popup = menulist.firstChild;\r |
| 127 | \r |
| 128 | // save our old "data" so we can restore it later\r |
| 129 | var oldData = menulist.data;\r |
| 130 | \r |
| 131 | // remove the old popup children\r |
| 132 | while (popup.hasChildNodes())\r |
| 133 | popup.removeChild(popup.lastChild);\r |
| 134 | \r |
| 135 | var newSelection;\r |
| 136 | for (var i=0; i<menuItemIds.length; i++) {\r |
| 137 | // create the menuitem\r |
| 138 | var menuitem = document.createElement("menuitem");\r |
| 139 | menuitem.setAttribute("value", menuItemStrings[i]);\r |
| 140 | menuitem.setAttribute("data", menuItemIds[i]);\r |
| 141 | popup.appendChild(menuitem);\r |
| 142 | \r |
| 143 | // try to restore the selection\r |
| 144 | if (!newSelection || oldData == menuItemIds[i].toString()) {\r |
| 145 | newSelection = menuitem;\r |
| 146 | }\r |
| 147 | }\r |
| 148 | \r |
| 149 | // now restore the selection\r |
| 150 | menulist.selectedItem = newSelection\r |
| 151 | ]]>\r |
| 152 | </body>\r |
| 153 | </method>\r |
| 154 | <method name="onSelect">\r |
| 155 | <argument name="event"/>\r |
| 156 | <body>\r |
| 157 | <![CDATA[\r |
| 158 | var menulist = document.getAnonymousNodes(this)[0];\r |
| 159 | \r |
| 160 | // notify targets\r |
| 161 | var targets = this.targets;\r |
| 162 | if (targets) {\r |
| 163 | for (var i=0; i< targets.length; i++) {\r |
| 164 | targets[i].parentValue = menulist.data;\r |
| 165 | }\r |
| 166 | }\r |
| 167 | ]]>\r |
| 168 | </body>\r |
| 169 | </method>\r |
| 170 | </interface>\r |
| 171 | </binding>\r |
| 172 | \r |
| 173 | <!-- searchattribute - Subject, Sender, To, CC, etc. -->\r |
| 174 | <binding id="searchattribute"\r |
| 175 | extends="chrome://messenger/skin/mailWidgets.xml#search-menulist-abstract">\r |
| 176 | <interface>\r |
| 177 | <property name="stringBundle">\r |
| 178 | <![CDATA[\r |
| 179 | srGetStrBundle("chrome://messenger/locale/search-attributes.properties");\r |
| 180 | ]]>\r |
| 181 | </property>\r |
| 182 | <property name="valueIds" readonly="true">\r |
| 183 | <getter>\r |
| 184 | <![CDATA[\r |
| 185 | var length = new Object;\r |
| 186 | return this.validityTable.getAvailableAttributes(length);\r |
| 187 | ]]>\r |
| 188 | </getter>\r |
| 189 | </property>\r |
| 190 | </interface>\r |
| 191 | </binding>\r |
| 192 | \r |
| 193 | <!-- searchoperator - Contains, Is Less than, etc -->\r |
| 194 | <binding id="searchoperator"\r |
| 195 | extends="chrome://messenger/skin/mailWidgets.xml#search-menulist-abstract">\r |
| 196 | <interface>\r |
| 197 | <property name="stringBundle">\r |
| 198 | <![CDATA[\r |
| 199 | srGetStrBundle("chrome://messenger/locale/search-operators.properties");\r |
| 200 | ]]>\r |
| 201 | </property>\r |
| 202 | <property name="valueIds" readonly="true">\r |
| 203 | <getter>\r |
| 204 | <![CDATA[\r |
| 205 | var length = new Object;\r |
| 206 | return this.validityTable.getAvailableOperators(this.searchAttribute,length);\r |
| 207 | ]]>\r |
| 208 | </getter>\r |
| 209 | </property>\r |
| 210 | <property name="parentValue">\r |
| 211 | <setter>\r |
| 212 | <![CDATA[\r |
| 213 | if (this.searchAttribute == val) return;\r |
| 214 | this.searchAttribute = val;\r |
| 215 | this.refreshList();\r |
| 216 | ]]>\r |
| 217 | </setter>\r |
| 218 | <getter>\r |
| 219 | <![CDATA[\r |
| 220 | return this.searchAttribute;\r |
| 221 | ]]>\r |
| 222 | </getter>\r |
| 223 | </property>\r |
| 224 | </interface>\r |
| 225 | </binding>\r |
| 226 | \r |
| 227 | <!-- searchvalue - a widget which dynamically changes it's user interface\r |
| 228 | depending on what type of data it's supposed to be showing\r |
| 229 | currently handles arbitrary text entry, and menulists for priority and\r |
| 230 | status\r |
| 231 | -->\r |
| 232 | <binding id="searchvalue" extends="xul:deck">\r |
| 233 | <!-- yeah yeah, this stuff needs to be localized. I'm working on it! -->\r |
| 234 | <content>\r |
| 235 | <xul:textfield flex="1" />\r |
| 236 | <xul:menulist flex="1" >\r |
| 237 | <xul:menupopup>\r |
| 238 | <xul:menuitem value="Lowest"/>\r |
| 239 | <xul:menuitem value="Low"/>\r |
| 240 | <xul:menuitem value="Normal"/>\r |
| 241 | <xul:menuitem value="High"/>\r |
| 242 | <xul:menuitem value="Highest"/>\r |
| 243 | </xul:menupopup>\r |
| 244 | </xul:menulist>\r |
| 245 | <xul:menulist flex="1" >\r |
| 246 | <xul:menupopup>\r |
| 247 | <xul:menuitem value="read"/>\r |
| 248 | <xul:menuitem value="replied"/>\r |
| 249 | </xul:menupopup>\r |
| 250 | </xul:menulist>\r |
| 251 | </content>\r |
| 252 | <interface>\r |
| 253 | <!-- parentValue forwards to the attribute -->\r |
| 254 | <property name="parentValue" onset="this.searchAttribute=val;"\r |
| 255 | onget="return this.searchAttribute;"/>\r |
| 256 | <property name="searchAttribute" onget="return this.internalAttribute;">\r |
| 257 | <setter>\r |
| 258 | <![CDATA[\r |
| 259 | // noop if we're not changing it\r |
| 260 | if (this.internalAttribute == val) return;\r |
| 261 | this.internalAttribute = val;\r |
| 262 | // we inherit from a deck, so just use it's index attribute\r |
| 263 | // to hide/show widgets\r |
| 264 | if (val == Components.interfaces.nsMsgSearchAttrib.Priority)\r |
| 265 | this.setAttribute("index", "1");\r |
| 266 | else if (val == Components.interfaces.nsMsgSearchAttrib.MsgStatus)\r |
| 267 | this.setAttribute("index", "2");\r |
| 268 | else\r |
| 269 | this.setAttribute("index", "0");\r |
| 270 | ]]>\r |
| 271 | </setter>\r |
| 272 | </property>\r |
| 273 | <property name="value" onget="return this.internalValue;">\r |
| 274 | <setter>\r |
| 275 | <![CDATA[\r |
| 276 | // val is a nsIMsgSearchValue object\r |
| 277 | this.internalValue = val;\r |
| 278 | var attrib = val.attrib;\r |
| 279 | this.searchAttribute = attrib;\r |
| 280 | if (attrib == Components.interfaces.nsMsgSearchAttrib.Priority)\r |
| 281 | document.getAnonymousNodes(this)[1].data=val.priority;\r |
| 282 | else if (attrib == Components.interfaces.nsMsgSearchAttrib.MsgStatus)\r |
| 283 | document.getAnonymousNodes(this)[2].data=val.status;\r |
| 284 | else\r |
| 285 | document.getAnonymousNodes(this)[0].value = val.str;\r |
| 286 | ]]>\r |
| 287 | </setter>\r |
| 288 | </property>\r |
| 289 | <method name="save">\r |
| 290 | <body>\r |
| 291 | <![CDATA[\r |
| 292 | var searchValue = this.value;\r |
| 293 | var searchAttribute = this.searchAttribute;\r |
| 294 | var nsMsgSearchAttrib = Components.interfaces.nsMsgSearchAttrib;\r |
| 295 | \r |
| 296 | searchValue.attrib = searchAttribute;\r |
| 297 | if (searchAttribute == nsMsgSearchAttrib.Priority)\r |
| 298 | searchValue.priority = document.getAnonymousNodes(this)[1].selectedItem.data;\r |
| 299 | else if (searchAttribute == nsMsgSearchAttrib.MsgStatus)\r |
| 300 | searchValue.status = document.getAnonymousNodes(this)[2].selectedItem.data;\r |
| 301 | else\r |
| 302 | searchValue.str = document.getAnonymousNodes(this)[0].value;\r |
| 303 | ]]>\r |
| 304 | </body>\r |
| 305 | </method>\r |
| 306 | <method name="saveTo">\r |
| 307 | <argument name="searchValue"/>\r |
| 308 | <body>\r |
| 309 | <![CDATA[\r |
| 310 | this.internalValue = searchValue;\r |
| 311 | this.save();\r |
| 312 | ]]>\r |
| 313 | </body>\r |
| 314 | </method>\r |
| 315 | </interface>\r |
| 316 | </binding>\r |
| 317 | <binding id="searchterm" extends="xul:box">\r |
| 318 | <interface>\r |
| 319 | <!-- the actual nsIMsgSearchTerm object -->\r |
| 320 | <property name="searchTerm" onget="return this.internalSearchTerm">\r |
| 321 | <setter>\r |
| 322 | <![CDATA[\r |
| 323 | this.internalSearchTerm = val;\r |
| 324 | \r |
| 325 | var term = val;\r |
| 326 | // val is a nsIMsgSearchTerm\r |
| 327 | var searchAttribute=this.searchattribute;\r |
| 328 | var searchOperator=this.searchoperator;\r |
| 329 | var searchValue=this.searchvalue;\r |
| 330 | \r |
| 331 | // now reflect all attributes of the searchterm into the widgets\r |
| 332 | if (searchAttribute) searchAttribute.value = term.attrib;\r |
| 333 | if (searchOperator) searchOperator.value = val.op;\r |
| 334 | if (searchValue) searchValue.value = term.value;\r |
| 335 | \r |
| 336 | this.booleanAnd = val.booleanAnd;\r |
| 337 | ]]>\r |
| 338 | </setter>\r |
| 339 | </property>\r |
| 340 | \r |
| 341 | <property name="searchScope">\r |
| 342 | <getter>\r |
| 343 | <![CDATA[\r |
| 344 | var searchAttribute = this.searchattribute;\r |
| 345 | if (searchAttribute)\r |
| 346 | return searchAttribute.searchScope;\r |
| 347 | return undefined;\r |
| 348 | ]]>\r |
| 349 | </getter>\r |
| 350 | <setter>\r |
| 351 | <![CDATA[\r |
| 352 | var searchAttribute = this.searchattribute;\r |
| 353 | if (searchAttribute) searchAttribute.searchScope=val;\r |
| 354 | ]]>\r |
| 355 | </setter>\r |
| 356 | </property>\r |
| 357 | <!-- the three tags that make up a term - to use, set the\r |
| 358 | attribute in the XUL to the ID of the term.\r |
| 359 | -->\r |
| 360 | <property name="searchattribute" \r |
| 361 | onget="return document.getElementById(this.getAttribute('searchattribute'));"\r |
| 362 | onset="this.setAttribute('searchattribute',val.id)"/>\r |
| 363 | \r |
| 364 | <property name="searchoperator" \r |
| 365 | onget="return document.getElementById(this.getAttribute('searchoperator'));"\r |
| 366 | onset="this.setAttribute('searchoperator',val.id)"/>\r |
| 367 | \r |
| 368 | <property name="searchvalue" \r |
| 369 | onget="return document.getElementById(this.getAttribute('searchvalue'));"\r |
| 370 | onset="this.setAttribute('searchvalue',val.id)"/>\r |
| 371 | <property name="booleanNodes">\r |
| 372 | <![CDATA[\r |
| 373 | null;\r |
| 374 | ]]>\r |
| 375 | </property>\r |
| 376 | <property name="stringBundle">\r |
| 377 | <![CDATA[\r |
| 378 | srGetStrBundle("chrome://messenger/locale/search.properties");\r |
| 379 | ]]>\r |
| 380 | </property>\r |
| 381 | <property name="booleanAnd" onget="return this.internalBooleanAnd">\r |
| 382 | <setter>\r |
| 383 | <![CDATA[\r |
| 384 | // whenever you set this, all nodes in booleanNodes\r |
| 385 | // are updated to reflect the string\r |
| 386 | \r |
| 387 | if (this.internalBooleanAnd == val) return;\r |
| 388 | this.internalBooleanAnd = val;\r |
| 389 | \r |
| 390 | var booleanNodes = this.booleanNodes;\r |
| 391 | if (!booleanNodes) return;\r |
| 392 | \r |
| 393 | var stringBundle = this.stringBundle;\r |
| 394 | var andString = val ? "And" : "Or";\r |
| 395 | for (var i=0; i<booleanNodes.length; i++) {\r |
| 396 | try { \r |
| 397 | var staticString =\r |
| 398 | stringBundle.GetStringFromName("search" + andString + i);\r |
| 399 | if (staticString && staticString.length>0)\r |
| 400 | booleanNodes[i].setAttribute("value", staticString);\r |
| 401 | } catch (ex) { /* no error, means string not found */}\r |
| 402 | }\r |
| 403 | ]]>\r |
| 404 | </setter>\r |
| 405 | </property>\r |
| 406 | <method name="save">\r |
| 407 | <body>\r |
| 408 | <![CDATA[\r |
| 409 | var searchTerm = this.searchTerm;\r |
| 410 | searchTerm.attrib = this.searchattribute.value;\r |
| 411 | searchTerm.op = this.searchoperator.value;\r |
| 412 | if (this.searchvalue.value)\r |
| 413 | this.searchvalue.save();\r |
| 414 | else\r |
| 415 | this.searchvalue.saveTo(searchTerm.value);\r |
| 416 | searchTerm.value = this.searchvalue.value;\r |
| 417 | searchTerm.booleanAnd = this.booleanAnd;\r |
| 418 | ]]>\r |
| 419 | </body>\r |
| 420 | </method>\r |
| 421 | <!-- if you have a search term element with no search term -->\r |
| 422 | <method name="saveTo">\r |
| 423 | <argument name="searchTerm"/>\r |
| 424 | <body>\r |
| 425 | <![CDATA[\r |
| 426 | this.internalSearchTerm = searchTerm;\r |
| 427 | this.save();\r |
| 428 | ]]>\r |
| 429 | </body>\r |
| 430 | </method>\r |
| 431 | </interface>\r |
| 432 | </binding>\r |
| 433 | </bindings>\r |