1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 /** 24 * @overview 25 * This file defines a Zimlet tree controller. 26 * 27 */ 28 29 /** 30 * Creates a Zimlet tree controller. 31 * @class 32 * This class represents a Zimlet tree controller. 33 * 34 * @extends ZmTreeController 35 */ 36 ZmZimletTreeController = function() { 37 38 ZmTreeController.call(this, ZmOrganizer.ZIMLET); 39 40 this._eventMgrs = {}; 41 42 // don't select zimlet items via arrow shortcut since selection pops up dialog 43 this._treeSelectionShortcutDelay = 0; 44 }; 45 46 ZmZimletTreeController.prototype = new ZmTreeController; 47 ZmZimletTreeController.prototype.constructor = ZmZimletTreeController; 48 49 ZmZimletTreeController.prototype.isZmZimletTreeController = true; 50 ZmZimletTreeController.prototype.toString = function() { return "ZmZimletTreeController"; }; 51 52 // Public methods 53 54 /** 55 * Adds a selection listener. 56 * 57 * @param {constant} overviewId the overview id 58 * @param {AjxListener} listener the listener to add 59 */ 60 ZmZimletTreeController.prototype.addSelectionListener = 61 function(overviewId, listener) { 62 // Each overview gets its own event manager 63 if (!this._eventMgrs[overviewId]) { 64 this._eventMgrs[overviewId] = new AjxEventMgr; 65 // Each event manager has its own selection event to avoid 66 // multi-threaded collisions 67 this._eventMgrs[overviewId]._selEv = new DwtSelectionEvent(true); 68 } 69 this._eventMgrs[overviewId].addListener(DwtEvent.SELECTION, listener); 70 }; 71 72 ZmZimletTreeController.prototype._createTreeView = 73 function(params) { 74 params.actionSupported = false; 75 return new ZmTreeView(params); 76 }; 77 78 /** 79 * Removes the selection listener. 80 * 81 * @param {constant} overviewId the overview id 82 * @param {AjxListener} listener the listener to remove 83 */ 84 ZmZimletTreeController.prototype.removeSelectionListener = 85 function(overviewId, listener) { 86 if (this._eventMgrs[overviewId]) { 87 this._eventMgrs[overviewId].removeListener(DwtEvent.SELECTION, listener); 88 } 89 }; 90 91 // Protected methods 92 93 /** 94 * @private 95 */ 96 ZmZimletTreeController.prototype._postSetup = 97 function(overviewId) { 98 var treeView = this.getTreeView(overviewId); 99 var root = treeView.getItems()[0]; 100 if (root) { 101 var items = root.getItems(); 102 for (var i = 0; i < items.length; i++) { 103 this.setToolTipText(items[i]); 104 } 105 } 106 }; 107 108 /** 109 * Sets the tool tip text. 110 * 111 * @param {object} item the item 112 */ 113 ZmZimletTreeController.prototype.setToolTipText = 114 function (item) { 115 var zimlet = item.getData(Dwt.KEY_OBJECT); 116 if (zimlet) zimlet.setToolTipText(item); 117 }; 118 119 /** 120 * ZmTreeController removes existing DwtTreeItem object then add a new one on ZmEvent.E_MODIFY, 121 * wiping out any properties set on the object. 122 * 123 * @private 124 */ 125 ZmZimletTreeController.prototype._changeListener = 126 function(ev, treeView, overviewId) { 127 ZmTreeController.prototype._changeListener.call(this, ev, treeView, overviewId); 128 var organizers = ev.getDetail("organizers"); 129 if (!organizers && ev.source) 130 organizers = [ev.source]; 131 132 for (var i = 0; i < organizers.length; i++) { 133 var organizer = organizers[i]; 134 var id = organizer.id; 135 var item = treeView.getTreeItemById(id); 136 this.setToolTipText(item); 137 } 138 }; 139 140 /** 141 * @private 142 */ 143 ZmZimletTreeController.prototype._getDataTree = 144 function() { 145 return appCtxt.getZimletTree(); 146 }; 147 148 /** 149 * Returns a list of desired header action menu operations. 150 * 151 * @private 152 */ 153 ZmZimletTreeController.prototype._getHeaderActionMenuOps = function() { 154 return null; 155 }; 156 157 /** 158 * Returns a list of desired action menu operations. 159 * 160 * @private 161 */ 162 ZmZimletTreeController.prototype._getActionMenuOps = function() { 163 return null; 164 }; 165 166 /** 167 * @private 168 */ 169 ZmZimletTreeController.prototype._getActionMenu = function(ev) { 170 var z = ev.item.getData(Dwt.KEY_OBJECT); 171 // z is here a ZmZimlet 172 z = z.getZimletContext(); 173 if(z) { 174 return z.getPanelActionMenu(); 175 } 176 }; 177 178 /** 179 * Gets the tree style. 180 * 181 * @return {constant} the style 182 * @see DwtTree.SINGLE_STYLE 183 */ 184 ZmZimletTreeController.prototype.getTreeStyle = function() { 185 return DwtTree.SINGLE_STYLE; 186 }; 187 188 /** 189 * Method that is run when a tree item is left-clicked. 190 * 191 * @private 192 */ 193 ZmZimletTreeController.prototype._itemClicked = function(z) { 194 if (z.id == ZmZimlet.ID_ZIMLET_ROOT) { return; } 195 196 // to allow both click and dbl-click, we should use a timeout here, as 197 // this function gets called twice in the case of a dbl-click. If the 198 // timeout already exists, we do nothing since _itemDblClicked will be 199 // called (the timeout is cleared there). 200 if (!z.__dbl_click_timeout) { 201 z.__dbl_click_timeout = setTimeout(function() { 202 z.__dbl_click_timeout = null; 203 z.getZimletContext().callHandler("_dispatch", [ "singleClicked" ]); 204 }, 350); 205 } 206 }; 207 208 /** 209 * @private 210 */ 211 ZmZimletTreeController.prototype._itemDblClicked = function(z) { 212 if (z.id == ZmZimlet.ID_ZIMLET_ROOT) { return; } 213 214 if (z.__dbl_click_timeout) { 215 // click will never happen 216 clearTimeout(z.__dbl_click_timeout); 217 z.__dbl_click_timeout = null; 218 } 219 z.getZimletContext().callHandler("_dispatch", [ "doubleClicked" ]); 220 }; 221 222 /** 223 * Handles a drop event. 224 * 225 * @private 226 */ 227 ZmZimletTreeController.prototype._dropListener = function(ev) { 228 var z = ev.targetControl.getData(Dwt.KEY_OBJECT); 229 if (!z) { 230 ev.doIt = false; 231 return; 232 } 233 if (z.id == ZmZimlet.ID_ZIMLET_ROOT) { 234 ev.doIt = false; 235 return; 236 } 237 if (z.getZimletContext) { 238 try { 239 z = z.getZimletContext(); 240 } catch(ex) { 241 ev.doIt = false; 242 return; 243 } 244 } else { 245 ev.doIt = false; 246 return; 247 } 248 var srcData = ev.srcData.data; 249 if (!z || !srcData) { 250 ev.doIt = false; 251 return; 252 } 253 var dragSrc = z.zimletPanelItem.dragSource; 254 if (dragSrc && ev.action == DwtDropEvent.DRAG_DROP) { 255 z.callHandler("_dispatch", 256 [ "doDrop", 257 ZmZimletContext._translateZMObject(srcData), 258 dragSrc ]); 259 } 260 }; 261 262 /** 263 * Handles a drag event. 264 * 265 * @private 266 */ 267 ZmZimletTreeController.prototype._dragListener = function(ev) { 268 // for now there's nothing defined in the spec to allow this 269 ev.operation = Dwt.DND_DROP_NONE; 270 }; 271