Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 cr.define('ntp4', function() { | 5 cr.define('ntp4', function() { |
| 6 'use strict'; | 6 'use strict'; |
| 7 | 7 |
| 8 var TilePage = ntp4.TilePage; | 8 var localStrings = new LocalStrings; |
| 9 | |
| 10 var APP_LAUNCH = { | |
| 11 // The histogram buckets (keep in sync with extension_constants.h). | |
| 12 NTP_APPS_MAXIMIZED: 0, | |
| 13 NTP_APPS_COLLAPSED: 1, | |
| 14 NTP_APPS_MENU: 2, | |
| 15 NTP_MOST_VISITED: 3, | |
| 16 NTP_RECENTLY_CLOSED: 4, | |
| 17 NTP_APP_RE_ENABLE: 16 | |
| 18 }; | |
| 19 | |
| 20 /** | |
| 21 * App context menu. The class is designed to be used as a singleton with | |
| 22 * the app that is currently showing a context menu stored in this.app_. | |
| 23 * @constructor | |
| 24 */ | |
| 25 function AppContextMenu() { | |
| 26 this.__proto__ = AppContextMenu.prototype; | |
| 27 this.initialize(); | |
| 28 }; | |
| 29 cr.addSingletonGetter(AppContextMenu); | |
| 30 | |
| 31 AppContextMenu.prototype = { | |
| 32 initialize: function() { | |
| 33 var menu = new cr.ui.Menu; | |
| 34 cr.ui.decorate(menu, cr.ui.Menu); | |
| 35 menu.classList.add('app-context-menu'); | |
| 36 this.menu = menu; | |
| 37 | |
| 38 this.launch_ = this.appendMenuItem_(); | |
| 39 menu.appendChild(cr.ui.MenuItem.createSeparator()); | |
| 40 this.launchRegularTab_ = this.appendMenuItem_('applaunchtyperegular'); | |
| 41 this.launchPinnedTab_ = this.appendMenuItem_('applaunchtypepinned'); | |
| 42 this.launchNewWindow_ = this.appendMenuItem_('applaunchtypewindow'); | |
|
csilv
2011/06/22 21:21:30
launchNewWindow is not supported on Mac. the apps
| |
| 43 this.launchFullscreen_ = this.appendMenuItem_('applaunchtypefullscreen'); | |
| 44 menu.appendChild(cr.ui.MenuItem.createSeparator()); | |
| 45 this.options_ = this.appendMenuItem_('appoptions'); | |
| 46 this.uninstall_ = this.appendMenuItem_('appuninstall'); | |
| 47 menu.appendChild(cr.ui.MenuItem.createSeparator()); | |
| 48 this.createShortcut_ = this.appendMenuItem_('appcreateshortcut'); | |
|
csilv
2011/06/22 21:21:30
createShortcut is not support on Mac and ChromeOS.
| |
| 49 | |
| 50 this.launch_.addEventListener('activate', this.onLaunch_.bind(this)); | |
| 51 | |
| 52 var self = this; | |
| 53 this.forAllLaunchTypes_(function(launchTypeButton, id) { | |
| 54 launchTypeButton.addEventListener('activate', | |
| 55 self.onLaunchTypeChanged_.bind(self)); | |
| 56 }); | |
| 57 | |
| 58 this.options_.addEventListener('activate', | |
| 59 this.onShowOptions_.bind(this)); | |
| 60 this.uninstall_.addEventListener('activate', | |
| 61 this.onUninstall_.bind(this)); | |
| 62 this.createShortcut_.addEventListener('activate', | |
| 63 this.onCreateShortcut_.bind(this)); | |
| 64 | |
| 65 menu.hidden = true; | |
| 66 document.body.appendChild(menu); | |
| 67 }, | |
| 68 | |
| 69 /** | |
| 70 * Appends a menu item to |this.menu_|. | |
| 71 * @param {?String} textId If non-null, the ID for the localized string | |
| 72 * that acts as the item's label. | |
| 73 */ | |
|
csilv
2011/06/22 21:21:30
add @private to comment
| |
| 74 appendMenuItem_: function(textId) { | |
| 75 var button = cr.doc.createElement('button'); | |
| 76 this.menu.appendChild(button); | |
| 77 cr.ui.decorate(button, cr.ui.MenuItem); | |
| 78 if (textId) | |
| 79 button.textContent = localStrings.getString(textId); | |
| 80 return button; | |
| 81 }, | |
| 82 | |
| 83 /** | |
| 84 * Iterates over all the launch type menu items. | |
| 85 * @param {function(cr.ui.MenuItem, number)} f The function to call for each | |
| 86 * menu item. The parameters to the function include the menu item and | |
| 87 * the associated launch ID. | |
| 88 */ | |
|
csilv
2011/06/22 21:21:30
add @private to doc comment
| |
| 89 forAllLaunchTypes_: function(f) { | |
| 90 // Order matters: index matches launchType id. | |
| 91 var launchTypes = [ this.launchPinnedTab_, | |
| 92 this.launchRegularTab_, | |
| 93 this.launchFullscreen_, | |
| 94 this.launchNewWindow_ ]; | |
| 95 | |
| 96 for (var i = 0; i < launchTypes.length; ++i) { | |
| 97 f(launchTypes[i], i); | |
| 98 } | |
| 99 }, | |
| 100 | |
| 101 /** | |
| 102 * Does all the necessary setup to show the menu for the give app. | |
| 103 * @param {App} app The App object that will be showing a context menu. | |
| 104 */ | |
| 105 setupForApp: function(app) { | |
| 106 this.app_ = app; | |
| 107 | |
| 108 this.launch_.textContent = app.appData.name; | |
| 109 | |
| 110 this.forAllLaunchTypes_(function(launchTypeButton, id) { | |
| 111 launchTypeButton.disabled = false; | |
| 112 launchTypeButton.checked = app.appData.launch_type == id; | |
| 113 }); | |
| 114 | |
| 115 this.options_.disabled = !app.appData.options_url; | |
| 116 }, | |
| 117 | |
| 118 /** | |
| 119 * Handlers for menu item activation. | |
| 120 * @param {Event} e The activation event. | |
| 121 * @private | |
| 122 */ | |
| 123 onLaunch_: function(e) { | |
| 124 chrome.send('launchApp', [this.app_.appId, APP_LAUNCH.NTP_APPS_MENU]); | |
| 125 }, | |
| 126 onLaunchTypeChanged_: function(e) { | |
| 127 var pressed = e.currentTarget; | |
| 128 var app = this.app_; | |
| 129 this.forAllLaunchTypes_(function(launchTypeButton, id) { | |
| 130 if (launchTypeButton == pressed) { | |
| 131 chrome.send('setLaunchType', [app.appId, id]); | |
| 132 // Manually update the launch type. We will only get | |
| 133 // appsPrefChangedCallback calls after changes to other NTP instances. | |
| 134 app.appData.launch_type = id; | |
| 135 } | |
| 136 }); | |
| 137 }, | |
| 138 onShowOptions_: function(e) { | |
| 139 window.location = this.app_.appData.options_url; | |
| 140 }, | |
| 141 onUninstall_: function(e) { | |
| 142 chrome.send('uninstallApp', [this.app_.appData.id]); | |
| 143 }, | |
| 144 onCreateShortcut_: function(e) { | |
| 145 chrome.send('createAppShortcut', [this.app_.appData.id]); | |
| 146 }, | |
| 147 }; | |
| 9 | 148 |
| 10 /** | 149 /** |
| 11 * Creates a new App object. | 150 * Creates a new App object. |
| 12 * @param {Object} appData The data object that describes the app. | 151 * @param {Object} appData The data object that describes the app. |
| 13 * @constructor | 152 * @constructor |
| 14 * @extends {HTMLDivElement} | 153 * @extends {HTMLDivElement} |
| 15 */ | 154 */ |
| 16 function App(appData) { | 155 function App(appData) { |
| 17 var el = cr.doc.createElement('div'); | 156 var el = cr.doc.createElement('div'); |
| 18 el.__proto__ = App.prototype; | 157 el.__proto__ = App.prototype; |
| 19 el.appData = appData; | 158 el.appData = appData; |
| 20 el.initialize(); | 159 el.initialize(); |
| 21 | 160 |
| 22 return el; | 161 return el; |
| 23 } | 162 } |
| 24 | 163 |
| 25 App.prototype = { | 164 App.prototype = { |
| 26 __proto__: HTMLDivElement.prototype, | 165 __proto__: HTMLDivElement.prototype, |
| 27 | 166 |
| 28 initialize: function() { | 167 initialize: function() { |
| 29 assert(this.appData.id, 'Got an app without an ID'); | 168 assert(this.appData_.id, 'Got an app without an ID'); |
| 30 | 169 |
| 31 this.className = 'app'; | 170 this.className = 'app'; |
| 32 | 171 |
| 33 var appImg = this.ownerDocument.createElement('img'); | 172 var appImg = this.ownerDocument.createElement('img'); |
| 34 appImg.src = this.appData.icon_big; | 173 appImg.src = this.appData_.icon_big; |
| 35 // We use a mask of the same image so CSS rules can highlight just the | 174 // We use a mask of the same image so CSS rules can highlight just the |
| 36 // image when it's touched. | 175 // image when it's touched. |
| 37 appImg.style.WebkitMaskImage = url(this.appData.icon_big); | 176 appImg.style.WebkitMaskImage = url(this.appData_.icon_big); |
| 38 // We put a click handler just on the app image - so clicking on the | 177 // We put a click handler just on the app image - so clicking on the |
| 39 // margins between apps doesn't do anything. | 178 // margins between apps doesn't do anything. |
| 40 appImg.addEventListener('click', this.onClick_.bind(this)); | 179 appImg.addEventListener('click', this.onClick_.bind(this)); |
| 41 this.appendChild(appImg); | 180 this.appendChild(appImg); |
| 42 this.appImg_ = appImg; | 181 this.appImg_ = appImg; |
| 43 | 182 |
| 44 var appSpan = this.ownerDocument.createElement('span'); | 183 var appSpan = this.ownerDocument.createElement('span'); |
| 45 appSpan.textContent = this.appData.name; | 184 appSpan.textContent = this.appData_.name; |
| 46 this.appendChild(appSpan); | 185 this.appendChild(appSpan); |
| 47 | 186 |
| 48 /* TODO(estade): grabber */ | 187 this.addEventListener('contextmenu', cr.ui.contextMenuHandler); |
| 188 this.addEventListener('keydown', cr.ui.contextMenuHandler); | |
| 189 this.addEventListener('keyup', cr.ui.contextMenuHandler); | |
| 49 }, | 190 }, |
| 50 | 191 |
| 51 /** | 192 /** |
| 52 * Set the size and position of the app tile. | 193 * Set the size and position of the app tile. |
| 53 * @param {number} size The total size of |this|. | 194 * @param {number} size The total size of |this|. |
| 54 * @param {number} x The x-position. | 195 * @param {number} x The x-position. |
| 55 * @param {number} y The y-position. | 196 * @param {number} y The y-position. |
| 56 * animate. | 197 * animate. |
| 57 */ | 198 */ |
| 58 setBounds: function(size, x, y) { | 199 setBounds: function(size, x, y) { |
| 59 this.appImg_.style.width = this.appImg_.style.height = | 200 this.appImg_.style.width = this.appImg_.style.height = |
| 60 (size * APP_IMG_SIZE_FRACTION) + 'px'; | 201 (size * APP_IMG_SIZE_FRACTION) + 'px'; |
| 61 this.style.width = this.style.height = size + 'px'; | 202 this.style.width = this.style.height = size + 'px'; |
| 62 this.style.left = x + 'px'; | 203 this.style.left = x + 'px'; |
| 63 this.style.top = y + 'px'; | 204 this.style.top = y + 'px'; |
| 64 }, | 205 }, |
| 65 | 206 |
| 66 /** | 207 /** |
| 67 * Invoked when an app is clicked | 208 * Invoked when an app is clicked |
| 68 * @param {Event} e The click event. | 209 * @param {Event} e The click event. |
| 69 * @private | 210 * @private |
| 70 */ | 211 */ |
| 71 onClick_: function(e) { | 212 onClick_: function(e) { |
| 72 // Tell chrome to launch the app. | 213 var args = [this.appId, APP_LAUNCH.NTP_APPS_MAXIMIZED]; |
| 73 var NTP_APPS_MAXIMIZED = 0; | 214 args.push(e.altKey, e.ctrlKey, e.metaKey, e.shiftKey, e.button); |
| 74 chrome.send('launchApp', [this.appData.id, NTP_APPS_MAXIMIZED]); | 215 chrome.send('launchApp', args); |
| 75 | 216 |
| 76 // Don't allow the click to trigger a link or anything | 217 // Don't allow the click to trigger a link or anything |
| 77 e.preventDefault(); | 218 e.preventDefault(); |
| 78 }, | 219 }, |
| 79 | 220 |
| 221 /** | |
| 222 * The data and preferences for this app. | |
| 223 * @type {Object} | |
| 224 */ | |
| 225 set appData(data) { | |
| 226 this.appData_ = data; | |
| 227 }, | |
| 228 get appData() { | |
| 229 return this.appData_; | |
| 230 }, | |
| 231 | |
| 80 get appId() { | 232 get appId() { |
| 81 return this.appData.id; | 233 return this.appData_.id; |
| 234 }, | |
| 235 | |
| 236 /** | |
| 237 * Returns a pointer to the context menu for this app. All apps share the | |
| 238 * singleton AppContextMenu. This function is called by the | |
| 239 * ContextMenuHandler in response to the 'contextmenu' event. | |
| 240 * @type {cr.ui.Menu} | |
| 241 */ | |
| 242 get contextMenu() { | |
| 243 var menu = AppContextMenu.getInstance(); | |
| 244 menu.setupForApp(this); | |
| 245 return menu.menu; | |
| 82 }, | 246 }, |
| 83 }; | 247 }; |
| 84 | 248 |
| 85 /** | 249 /** |
| 86 * Creates a new Link object. This is a stub implementation for now. | 250 * Creates a new Link object. This is a stub implementation for now. |
| 87 * @param {Object} data The url and title. | 251 * @param {Object} data The url and title. |
| 88 * @constructor | 252 * @constructor |
| 89 * @extends {HTMLAnchorElement} | 253 * @extends {HTMLAnchorElement} |
| 90 */ | 254 */ |
| 91 function Link(data) { | 255 function Link(data) { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 117 * @param {number} y The y-position. | 281 * @param {number} y The y-position. |
| 118 * animate. | 282 * animate. |
| 119 */ | 283 */ |
| 120 setBounds: function(size, x, y) { | 284 setBounds: function(size, x, y) { |
| 121 this.style.width = this.style.height = size + 'px'; | 285 this.style.width = this.style.height = size + 'px'; |
| 122 this.style.left = x + 'px'; | 286 this.style.left = x + 'px'; |
| 123 this.style.top = y + 'px'; | 287 this.style.top = y + 'px'; |
| 124 }, | 288 }, |
| 125 }; | 289 }; |
| 126 | 290 |
| 291 var TilePage = ntp4.TilePage; | |
| 292 | |
| 127 // The fraction of the app tile size that the icon uses. | 293 // The fraction of the app tile size that the icon uses. |
| 128 var APP_IMG_SIZE_FRACTION = 4 / 5; | 294 var APP_IMG_SIZE_FRACTION = 4 / 5; |
| 129 | 295 |
| 130 var appsPageGridValues = { | 296 var appsPageGridValues = { |
| 131 // The fewest tiles we will show in a row. | 297 // The fewest tiles we will show in a row. |
| 132 minColCount: 3, | 298 minColCount: 3, |
| 133 // The most tiles we will show in a row. | 299 // The most tiles we will show in a row. |
| 134 maxColCount: 6, | 300 maxColCount: 6, |
| 135 | 301 |
| 136 // The smallest a tile can be. | 302 // The smallest a tile can be. |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 217 } | 383 } |
| 218 | 384 |
| 219 chrome.send('reorderApps', [draggedTile.firstChild.appId, appIds]); | 385 chrome.send('reorderApps', [draggedTile.firstChild.appId, appIds]); |
| 220 }, | 386 }, |
| 221 }; | 387 }; |
| 222 | 388 |
| 223 return { | 389 return { |
| 224 AppsPage: AppsPage, | 390 AppsPage: AppsPage, |
| 225 }; | 391 }; |
| 226 }); | 392 }); |
| OLD | NEW |