<?xml version="1.0"?>

<!-- This Source Code Form is subject to the terms of the Mozilla Public
  - License, v. 2.0. If a copy of the MPL was not distributed with this
  - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<!DOCTYPE window [
<!ENTITY % messengerDTD SYSTEM "chrome://messenger/locale/messenger.dtd" >
%messengerDTD;
]>

<bindings id="threadPaneColumnPickerBindings"
          xmlns="http://www.mozilla.org/xbl"
          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
          xmlns:xbl="http://www.mozilla.org/xbl">

  <!--
    - Because the columnpicker is implicitly created by the treecols binding
    - and it does not pass anything in, we are compelled to override the binding
    - (via CSS rules in messenger.css) in order to add custom menu options to
    - the list.
    -
    - This is now a cut-paste-modify of the original tree.xml#columnpicker
    - since we had to override everything save for the accessibleType anyways.
    -->
  <binding id="threadPaneColumnPicker" display="xul:button" role="xul:button"
           extends="chrome://global/content/bindings/tree.xml#tree-base">
    <content>
      <xul:image class="tree-columnpicker-icon"/>
      <xul:menupopup anonid="popup">
        <xul:menuseparator anonid="menuseparator"/>
        <xul:menuitem anonid="reset" label="&columnPicker.resetToInbox.label;"/>
        <xul:menu anonid="applyTo-menu"
                  label="&columnPicker.applyTo.label;">
          <xul:menupopup>
            <xul:menu anonid="applyToFolder-menu"
                      label="&columnPicker.applyToFolder.label;">
              <xul:menupopup anonid="applyToFolder"
                             type="folder"
                             showFileHereLabel="true"
                             position="start_before"
                             />
            </xul:menu>
            <xul:menu anonid="applyToFolderAndChildren-menu"
                      label="&columnPicker.applyToFolderAndChildren.label;">
              <xul:menupopup anonid="applyToFolderAndChildren"
                             type="folder"
                             showFileHereLabel="true"
                             showAccountsFileHere="true"
                             position="start_before"/>
            </xul:menu>
          </xul:menupopup>
        </xul:menu>
      </xul:menupopup>
    </content>

    <implementation>
      <method name="buildPopup">
        <parameter name="aPopup"/>
        <body><![CDATA[
          while (aPopup.childNodes.length > 3)
            aPopup.firstChild.remove();

          let refChild = aPopup.firstChild;

          let tree = this.parentNode.parentNode;
          for (let currCol = tree.columns.getFirstColumn(); currCol;
               currCol = currCol.getNext()) {
            // Construct an entry for each column in the row, unless
            // it is not being shown.
            let currElement = currCol.element;
            if (!currElement.hasAttribute("ignoreincolumnpicker")) {
              let popupChild = document.createElement("menuitem");
              popupChild.setAttribute("type", "checkbox");
              let columnName = currElement.getAttribute("display") ||
                               currElement.getAttribute("label");
              popupChild.setAttribute("label", columnName);
              popupChild.setAttribute("colindex", currCol.index);
              if (currElement.getAttribute("hidden") != "true")
                popupChild.setAttribute("checked", "true");
              if (currCol.primary)
                popupChild.setAttribute("disabled", "true");
              aPopup.insertBefore(popupChild, refChild);
            }
          }
        ]]></body>
      </method>

      <method name="_showPopup">
        <body><![CDATA[
          let popup = document.getAnonymousElementByAttribute(
            this, "anonid", "popup"
          );
          this.buildPopup(popup);
          popup.showPopup(this, -1, -1, "popup", "bottomright", "topright");
        ]]></body>
      </method>

      <method name="_toggleColumn">
        <parameter name="aColIndex"/>
        <body><![CDATA[
          let tree = this.parentNode.parentNode;
          let column = tree.columns[aColIndex];
          if (column) {
            let element = column.element;
            if (element.getAttribute("hidden") == "true")
              element.setAttribute("hidden", "false");
            else
              element.setAttribute("hidden", "true");
          }
        ]]></body>
      </method>

      <method name="_resetColumns">
        <body><![CDATA[
          let columnStates =
            gFolderDisplay._getDefaultColumnsForCurrentFolder();
          gFolderDisplay.setColumnStates(columnStates, true);
        ]]></body>
      </method>

      <method name="_useChildren">
        <parameter name="aTarget"/>
        <body><![CDATA[
          // Let's figure out which of the actions they chose by walking the
          // parent chain until we find one of them.
          let noChildrenPopup = document.getAnonymousElementByAttribute(
            this, "anonid", "applyToFolder"
          );
          let yesChildrenPopup = document.getAnonymousElementByAttribute(
            this, "anonid", "applyToFolderAndChildren"
          );

          let parent = aTarget.parentNode;
          while (parent != noChildrenPopup && parent != yesChildrenPopup) {
            parent = parent.parentNode;
          }
          return parent == yesChildrenPopup;
        ]]></body>
      </method>

      <method name="_applyColumns">
        <parameter name="aDestFolder"/>
        <parameter name="aUseChildren"/>
        <body><![CDATA[
          // Get the current folder's column state, plus the "swapped" column
          // state, which swaps "From" and "Recipient" if only one is shown.
          // This is useful for copying an incoming folder's columns to an
          // outgoing folder, or vice versa.
          let colState = gFolderDisplay.getColumnStates();

          let myColStateString = JSON.stringify(colState);
          let swappedColStateString;
          if (colState.senderCol.visible != colState.recipientCol.visible) {
            let tmp = colState.senderCol;
            colState.senderCol = colState.recipientCol;
            colState.recipientCol = tmp;
            swappedColStateString = JSON.stringify(colState);
          } else {
            swappedColStateString = myColStateString;
          }

          function isOutgoing(folder) {
            return folder.isSpecialFolder(
              DBViewWrapper.prototype.OUTGOING_FOLDER_FLAGS, true
            );
          }

          let amIOutgoing = isOutgoing(gFolderDisplay.displayedFolder);
          function colStateString(folder) {
            return (isOutgoing(folder) == amIOutgoing ? myColStateString :
                    swappedColStateString);
          }

          // Now propagate appropriately...
          const propName = gFolderDisplay.PERSISTED_COLUMN_PROPERTY_NAME;
          if (aUseChildren) {
            // Generate an observer notification when we have finished
            // configuring all folders.  This is currently done for the benefit
            // of our mozmill tests.
            let observerCallback = function() {
              Services.obs.notifyObservers(gFolderDisplay.displayedFolder,
                                           "msg-folder-columns-propagated", "");
            };
            MailUtils.setStringPropertyOnFolderAndDescendents(
              propName, colStateString, aDestFolder, observerCallback
            );
          } else {
            aDestFolder.setStringProperty(propName,
                                          colStateString(aDestFolder));
            // null out to avoid memory bloat
            aDestFolder.msgDatabase = null;
          }
        ]]></body>
      </method>
    </implementation>
    <handlers>
      <handler event="command"><![CDATA[
        Components.utils.import("resource://gre/modules/Services.jsm");

        // Are they clicking on our header to get us to show the column list?
        if (event.originalTarget == this) {
          this._showPopup();
          return;
        }

        // Are they clicking on one of the columns in the list?
        if (event.originalTarget.hasAttribute("colindex")) {
          this._toggleColumn(event.originalTarget.getAttribute("colindex"));
          return;
        }

        // Did they click the reset button?
        let resetMenu = document.getAnonymousElementByAttribute(
                          this, "anonid", "reset");
        if (event.originalTarget == resetMenu) {
          this._resetColumns();
          return;
        }

        // Otherwise an exciting action has occurred!
        let destFolder = event.originalTarget._folder;
        let useChildren = this._useChildren(event.originalTarget);

        // Confirm the action with the user.
        let bundle = document.getElementById("bundle_messenger");
        let stringBase = "threadPane.columnPicker.confirmFolder." +
          (useChildren ? "withChildren." : "noChildren.");
        let confirmed = Services.prompt.confirm(null,
          bundle.getString(stringBase + "title"),
          bundle.getFormattedString(stringBase + "message",
                                    [destFolder.prettiestName]));
        if (!confirmed)
          return;

        this._applyColumns(destFolder, useChildren);
      ]]></handler>
    </handlers>
  </binding>

</bindings>
