Updated my patch
[webos-internals:modifications.git] / app-launcher / app-launcher-advanced-configuration-for-app-launcher.patch
1 --- .orig/usr/lib/luna/system/luna-applauncher/sources.json
2 +++ /usr/lib/luna/system/luna-applauncher/sources.json
3 @@ -7,6 +7,11 @@
4                 "source": "app\/controllers\/launcher-assistant.js",
5                 "scenes": "launcher"
6         },
7 +
8 +       {
9 +               "source": "app\/controllers\/prefs-assistant.js",
10 +               "scenes": "prefs"
11 +       },
12         
13         {
14                 "source": "app\/controllers\/global-search-assistant.js"
15 --- .orig/usr/lib/luna/system/luna-systemui/app/controllers/bar-assistant.js
16 +++ /usr/lib/luna/system/luna-systemui/app/controllers/bar-assistant.js
17 @@ -33,6 +33,21 @@
18                 
19                 this.getBuildName();
20                                                 
21 +               // Subscribe to the App Launcher and Quick Launch Bar prererences
22 +               this.appLauncherCfg = null;
23 +               this.quickLaunchCfg = null;
24 +
25 +               this.getPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice', {
26 +                       method: 'getPreferences', parameters: {"keys":["appLauncherCfg", "quickLaunchCfg"],"subscribe": true},
27 +                       onSuccess: function(payload) {
28 +                               if(payload != undefined) {
29 +                                       if(payload.appLauncherCfg != undefined)
30 +                                               this.appLauncherCfg = payload.appLauncherCfg;
31 +                                       if(payload.quickLaunchCfg != undefined)
32 +                                               this.quickLaunchCfg = payload.quickLaunchCfg;
33 +                               }
34 +                       }.bind(this) });
35 +               
36                 // Initialize the Battery Power Nofication and get the initial value
37                 this.initOnServerStart("com.palm.power", this.powerInitialize.bind(this), this.powerDeInit.bind(this));
38                 
39 @@ -294,6 +309,12 @@
40         this.phoneIsForeground = false;
41         this.updateIsForeground = false;
42         
43 +       if((this.appLauncherCfg) && (this.appLauncherCfg.names) && 
44 +               (this.appLauncherCfg.names[payload.id + "_default"] != undefined))
45 +       {
46 +               payload.appmenu = this.appLauncherCfg.names[payload.id + "_default"].replace("<br>", " ");
47 +       }
48 +       
49         if (payload.title) {
50                 $('carrier').hide();
51                 if (payload.id == "com.palm.app.phone" || payload.id == "com.palm.app.firstuse"){ 
52 @@ -316,6 +337,11 @@
53                 $('carrier').show();
54                 this.foregroundAppID=null;
55         }
56 +
57 +       if((this.quickLaunchCfg) && (this.quickLaunchCfg.mode == "hidden")) {
58 +               this.controller.serviceRequest('palm://com.palm.systemmanager', {
59 +                       method: 'systemUi', parameters: {"quicklaunch": false} });
60 +       }
61  },
62  
63  updatePhoneAppName: function(){
64 --- .orig/usr/lib/luna/system/luna-applauncher/app/controllers/global-search-assistant.js
65 +++ /usr/lib/luna/system/luna-applauncher/app/controllers/global-search-assistant.js
66 @@ -212,6 +212,13 @@
67                         this.launcherHiddenAtFirstKeydown = true;
68                 }
69                 
70 +               this.viewMenuState = this.launcherAssistant.viewMenuModel.visible;
71 +               
72 +               if(this.launcherAssistant.viewMenuModel.visible) {
73 +                       this.launcherAssistant.viewMenuModel.visible = false;
74 +                       this.controller.modelChanged(this.launcherAssistant.viewMenuModel, this);
75 +               }
76 +                       
77                 // save the launchers scroller states
78                 this.controller.hideWidgetContainer(this.controller.getSceneScroller());
79                 this.controller.get('launcher-main').hide();
80 @@ -237,6 +244,11 @@
81                         return;
82                 }
83                 
84 +               if(this.viewMenuState) {
85 +                       this.launcherAssistant.viewMenuModel.visible = this.viewMenuState;
86 +                       this.controller.modelChanged(this.launcherAssistant.viewMenuModel, this);
87 +               }
88 +                       
89                 // restore the launchers scroller states
90                 this.controller.get('global-search-main').addClassName('offscreen');
91                 this.controller.get('launcher-main').show();
92 @@ -249,9 +261,6 @@
93                         SystemManagerService.showLauncher(false);
94                         this.launcherHiddenAtFirstKeydown = false;
95                 }
96 -               else {
97 -                       SystemManagerService.showQuickLaunch(true);
98 -               }
99                 
100                 this.galInit();
101         },
102 @@ -265,15 +274,13 @@
103         },
104         
105         onKeyDown: function(event) {
106 -               
107 -               this.searchField.mojo.focus();
108  
109                 // block key events from global search
110 -               if (!this.searchEnabled) {
111 -                       event.stop();
112 +               if (!this.searchEnabled)
113                         return;
114 -               }
115                 
116 +               this.searchField.mojo.focus();
117 +
118                 // track whether we should hide the launcher when exiting global search
119                 if (this.searchTerm.length === 0 && !Mojo.Controller.stageController.isActiveAndHasScenes()) {                  
120                         this.launcherHiddenAtFirstKeydown = true;
121 @@ -283,10 +290,8 @@
122         onKeyUp: function(event) {
123                 
124                 // block key events from global search
125 -               if (!this.searchEnabled) {
126 -                       event.stop();
127 +               if (!this.searchEnabled)
128                         return;
129 -               }
130         
131                 // first key no longer being held
132                 this.searchPressHoldTerm = "";
133 @@ -299,6 +304,10 @@
134         
135         onKeyPress: function(event) {
136                 
137 +               // block key events from global search
138 +               if (!this.searchEnabled)
139 +                       return;
140 +                               
141                 if(this.searchPressHoldTerm && this.searchPressHoldTerm.length > 0 && event.keyCode != this.searchPressHoldTerm.charCodeAt(0)) {
142                 // first key no longer being held
143              this.searchPressHoldTerm = "";
144 @@ -310,8 +319,7 @@
145          } 
146  
147                 // block key events from global search and from repeating until the first key has been processed
148 -               if (!this.searchEnabled || 
149 -                       this.searchPressHoldTerm.length !== 0 ||
150 +               if (this.searchPressHoldTerm.length !== 0 ||
151                         (event.keyCode === Mojo.Char.spaceBar && !this.searchActive)) {
152                         
153                         event.stop();
154 @@ -341,6 +349,10 @@
155         
156         onSearchTermChanged: function(event) {
157                 
158 +               // block key events from global search
159 +               if (!this.searchEnabled)
160 +                       return;
161 +               
162                 if (event.originalEvent && event.originalEvent.keyCode === Mojo.Char.enter) {
163                         if (this.currentFilter.length > 0) {
164                                 // i'm feeling lucky
165 @@ -1734,6 +1746,12 @@
166                         // appitem.title need to highlight matched search string
167                         if ( this.currentFilter && this.currentFilter.length > 0) {
168                                 var apptitle = appitem.title;                                   
169 +
170 +                               if((this.launcherAssistant.appLauncherCfg) && (this.launcherAssistant.appLauncherCfg.names)) {
171 +                                       if(this.launcherAssistant.appLauncherCfg.names[appitem.launchPointId] != undefined)
172 +                                               apptitle = this.launcherAssistant.appLauncherCfg.names[appitem.launchPointId];
173 +                               }
174 +
175                                 apptitle = apptitle.replace(beginPattern, function(whole, match) {
176                                         return matchTemplate.replace('ZZZZ', match);
177                                 });
178 @@ -1783,8 +1801,8 @@
179                 this.searchAppsReq = new Mojo.Service.Request('palm://com.palm.applicationManager', {
180                         method: 'searchApps',
181                         parameters: {'keyword': t},
182 -                       onSuccess: this.handleSearchAppResults.bind(this),
183 -                       onFailure: this.handleSearchAppResults.bind(this)
184 +                       onSuccess: this.handleSearchAppResults.bind(this, t),
185 +                       onFailure: this.handleSearchAppResults.bind(this, t)
186                 });
187         
188                 if (kEasterStrings.indexOf(t) !== -1) {
189 @@ -1792,17 +1810,34 @@
190                 }
191         },
192         
193 -       handleSearchAppResults: function(response) {
194 +       handleSearchAppResults: function(keyword, response) {
195                 if(!response.apps)
196                         return;
197                         
198                 var matchingApps = response.apps;
199                 var appInfoObj;
200                 
201 +               var added = [];
202 +
203 +               if((this.launcherAssistant.appLauncherCfg) && (this.launcherAssistant.appLauncherCfg.names)) {
204 +                       for(var key in this.launcherAssistant.appLauncherCfg.names) {
205 +                               if(this.launcherAssistant.appLauncherCfg.names[key].substr(0, keyword.length).toLowerCase().replace("<br>", " ") == keyword) {
206 +                                       appInfoObj = this.launcherAssistant.pagesModel.getAppInfo(key);
207 +                                       if(appInfoObj != null) {
208 +                                               this.searchApps.push(appInfoObj);
209 +                                               
210 +                                               added.push(key);
211 +                                       }
212 +                               }
213 +                       }
214 +               }
215 +
216                 for(var i = 0; i< matchingApps.length; i++) {
217 -                       appInfoObj = this.launcherAssistant.pagesModel.getAppInfo(matchingApps[i].launchPoint);
218 -                       if(appInfoObj != null)
219 -                               this.searchApps.push(appInfoObj);
220 +                       if(added.indexOf(matchingApps[i].launchPoint) == -1) {
221 +                               appInfoObj = this.launcherAssistant.pagesModel.getAppInfo(matchingApps[i].launchPoint);
222 +                               if(appInfoObj != null)
223 +                                       this.searchApps.push(appInfoObj);
224 +                       }
225                 }
226                 
227                 this.updateLauncherIconsDiv(this.searchApps);
228 --- .orig/usr/lib/luna/system/luna-applauncher/app/controllers/reorder-controller.js
229 +++ /usr/lib/luna/system/luna-applauncher/app/controllers/reorder-controller.js
230 @@ -239,6 +239,13 @@
231                 for (var i = 0, len = this.appDivs.length; i < len; ++i) {
232                         
233                         var pos = this.launcherAssistant.calculateAppPosition(i);
234 +                       
235 +                       if((this.launcherAssistant.appLauncherCfg) && 
236 +                               (this.launcherAssistant.appLauncherCfg.header != "none"))
237 +                       {
238 +                               pos.top = pos.top + 50;
239 +                       }
240 +                       
241                         var item = new Element('div', {'class': 'droppable'});
242                         item.style.left = pos.left+'px';
243                         item.style.top = pos.top+'px';
244 @@ -314,7 +321,10 @@
245         
246         _startCyclePage: function(direction) {
247                 if (!this.pagingTimer && !this.pagingAnimating) {
248 -                       this.pagingTimer = this._cyclePage.bind(this, direction).delay(this.kHorizontalPageTimeout);
249 +                       if((this.launcherAssistant.appLauncherCfg) && (this.launcherAssistant.appLauncherCfg.wrap))
250 +                               this.pagingTimer = this._cyclePage.bind(this, direction).delay(this.kHorizontalPageTimeout * 2);
251 +                       else
252 +                               this.pagingTimer = this._cyclePage.bind(this, direction).delay(this.kHorizontalPageTimeout);
253                         
254                         Mojo.listen($('launcher_root'), Mojo.Event.scrollStarting, this.scrollerListenerHandler);
255                 }
256 @@ -427,15 +437,41 @@
257         _cyclePage: function(direction) {
258                 
259                 var canPage = false;
260 +               var snapIndex = 0;
261 +
262                 if (direction == -1 && this.activePage.previous() !== null) {
263                         this.previousPage = this.activePage;
264                         this.activePage = this.activePage.previous();
265                         canPage = true;
266 +                       snapIndex = this.launcherAssistant.activePageIndex + direction;
267 +               }
268 +               else if (direction == -1 && this.activePage.previous() == null) {
269 +                       if((this.launcherAssistant.appLauncherCfg) && 
270 +                               (this.launcherAssistant.appLauncherCfg.wrap))
271 +                       {
272 +                               this.previousPage = this.activePage;
273 +                               while(this.activePage.next() !== null)
274 +                                       this.activePage = this.activePage.next();
275 +                               canPage = true;
276 +                               snapIndex = this.launcherAssistant.pagesModel.getNumPages() - 1;
277 +                       }
278                 }
279                 else if (direction == 1 && this.activePage.next() !== null) {
280                         this.previousPage = this.activePage;
281                         this.activePage = this.activePage.next();
282                         canPage = true;
283 +                       snapIndex = this.launcherAssistant.activePageIndex + direction;
284 +               }
285 +               else if (direction == 1 && this.activePage.next() == null) {
286 +                       if((this.launcherAssistant.appLauncherCfg) &&
287 +                               (this.launcherAssistant.appLauncherCfg.wrap))
288 +                       {
289 +                               this.previousPage = this.activePage;
290 +                               while(this.activePage.previous() !== null)
291 +                                       this.activePage = this.activePage.previous();
292 +                               canPage = true;
293 +                               snapIndex = 0;
294 +                       }
295                 }
296             
297                 if (canPage) {
298 @@ -446,7 +482,18 @@
299                         this.activePage.show();
300                         
301                         this.pagingAnimating = true;
302 -                       $('launcher_root').mojo.setSnapIndex(this.launcherAssistant.activePageIndex + direction, true);
303 +                       
304 +                       this.launcherAssistant.changePage(snapIndex, true);
305 +                       
306 +                       if((this.launcherAssistant.appLauncherCfg) && 
307 +                               (this.launcherAssistant.appLauncherCfg.wrap))
308 +                       {
309 +                               this.launcherAssistant.onPageChange({value: snapIndex});
310 +                               
311 +                               this.pagingAnimating = false;
312 +                               var previousPageIndex = this.launcherAssistant.getPageIndex(this.previousPage);
313 +                               this._pagingComplete(previousPageIndex, this.launcherAssistant.activePageIndex);
314 +                       }
315                 }
316         },
317         
318 --- .orig/usr/lib/luna/system/luna-applauncher/app/controllers/launcher-assistant.js
319 +++ /usr/lib/luna/system/luna-applauncher/app/controllers/launcher-assistant.js
320 @@ -8,7 +8,7 @@
321          * hardcoding the quick launch height until we can find a better way. 
322          * This value = ql graphic height - the offset from the top (small fade area)
323          */
324 -       kQuickLaunchHeight: 67,
325 +       kQuickLaunchHeight: 0,
326         
327         kPageIndicatorSpacing: 6,       /* spacing between each page indicator */
328         kPageMargin: 10, /* 10 pixel margin on each side of a page */
329 @@ -23,11 +23,12 @@
330                 visible: true,
331                 label: $L('Launcher'),
332          items: [
333 -                       /*{ label: $L('New page'), command: 'newpage' },
334 -                       { label: $L('Delete page'), command: 'deletepage' },*/
335                         Mojo.Menu.editItem,
336 -                       { label: $L('List Apps...'), command: 'listapps' },
337 -                       { label: $L('Default Applications'), command: 'defaultapps'},
338 +                       { label: $L('Preferences'), command: 'preferences' },
339 +                       { label: $L('Enter Edit Mode'), command: 'startedit' },
340 +                       { label: $L('Set As Default Page'), command: 'setdefault' },
341 +                       { label: $L('List All Applications'), command: 'listapps' },
342 +                       { label: $L('Default Applications'), command: 'defaultapps' },
343                         Mojo.Menu.helpItem
344                 ]
345      },
346 @@ -59,13 +60,59 @@
347                 
348                 this.dragStartHandler = this.onDragStart.bindAsEventListener(this);
349                 this.launchApp = this.launchApp.bind(this);
350 +
351 +               this.pageText = "";
352 +               this.renaming = false;
353 +
354 +               this.activePageIndex = 0;
355 +               
356 +               this.pagingAnimating = false;
357 +               
358 +               this.appLauncherCfg = {header: "none", placement: "first", reset: false, wrap: false, 
359 +                       indicators: true, grid: "small", icons: "large", titles: true, page: "default", 
360 +                       pages: [], hidden: [], names: {}};
361 +               
362 +               this.quickLaunchCfg = {mode: "visible"};
363         },
364         
365         setup: function() {
366                 
367 +               this.getPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice/', {
368 +                       method: 'getPreferences', parameters: {subscribe: false, keys: ['appLauncherCfg', 'quickLaunchCfg']},
369 +                       onSuccess: this.handlePreferences.bind(this) });
370 +
371 +               this.viewMenuModel = {visible: false, items: []};
372 +
373 +               this.controller.setupWidget(Mojo.Menu.viewMenu, {spacerHeight: 0, menuClass: 'no-fade'},
374 +                       this.viewMenuModel);
375 +
376 +               this.commandMenuModel = {visible: false, items: [
377 +                       {items: [
378 +                               { icon: "new", command: "addnewpage"},
379 +                               { icon: 'delete', command: 'deletepage'}
380 +                       ]},
381 +                       {label: "Rename", command: "renamepage", width: 100},
382 +                       {items: [
383 +                               { icon: "back", command: "movepageleft"},
384 +                               { icon: 'forward', command: 'movepageright'}
385 +                       ]} ]};
386 +
387 +               this.controller.setupWidget(Mojo.Menu.commandMenu, {spacerHeight: 0, menuClass: 'no-fade'},
388 +                       this.commandMenuModel);
389 +
390 +               Mojo.listen(this.controller.document, Mojo.Event.activate, this.onActivate.bindAsEventListener(this));
391                 Mojo.listen(this.controller.document, Mojo.Event.deactivate, this.onDeactivate.bindAsEventListener(this));
392                 Mojo.listen(this.controller.window, 'resize', this.onResize.bindAsEventListener(this));
393                 
394 +               this.launcherTapHandler = this.handleLauncherTap.bindAsEventListener(this);
395 +               Mojo.listen($('launcher_root'), Mojo.Event.tap, this.launcherTapHandler);
396 +               
397 +               this.headerTapHandler = this.handleHeaderTap.bindAsEventListener(this);
398 +               Mojo.listen($('page_header'), Mojo.Event.tap, this.headerTapHandler);
399 +               
400 +               this.appRenameHandler = this.handleAppRename.bindAsEventListener(this);
401 +               this.pageRenameHandler = this.handlePageRename.bindAsEventListener(this);
402 +
403                 this.pagesModel = new LauncherPages({
404                                 onPagesLoaded: this.buildPages.bind(this),
405                                 onAppAdded: this.onAppAdded.bind(this),
406 @@ -84,10 +131,18 @@
407                 this.controller.setupWidget('launcher_root', undefined, this.launcherRootModel);
408                 
409                 this.reorderController = new ReorderController(this, this.onReorderFinished.bind(this));
410 -               Mojo.listen($('launcher_root'), Mojo.Event.propertyChange, this.onPageChange.bindAsEventListener(this));
411                 
412 -               this.controller.setupWidget(Mojo.Menu.appMenu, {omitDefaultItems:true}, this.appMenuModel);
413 +               this.pageChangeHandler = this.onPageChange.bindAsEventListener(this);
414 +               Mojo.listen($('launcher_root'), Mojo.Event.propertyChange, this.pageChangeHandler);
415 +               
416 +               this.scrollStartingHandler = this.scrollStarting.bindAsEventListener(this);
417  
418 +               this.controller.setupWidget(Mojo.Menu.appMenu, {omitDefaultItems:true}, this.appMenuModel);
419 +               
420 +               this.pageNameModel = { value: this.pageText };
421 +               
422 +               this.controller.setupWidget('page_text', {disabled: false, changeOnKeyPress: true}, this.pageNameModel);
423 +               
424                 // pre-calculate commonly used measurements
425                 this.kPageWidth = $('launcher_root').getWidth();
426                 this.kPageWidthNoMargin = (this.kPageWidth - this.kPageMargin * 2);
427 @@ -121,23 +176,60 @@
428                                 case 'defaultapps':
429                                         ApplicationService.launch(this.deviceInfo.id, this.deviceInfo.defaultAppParams);
430                                         break;
431 -                               /*
432 -                               case 'newpage':
433 -                                       if (this.pageDivs.length < 10) {
434 -                                               this.insertPage(this.activePageIndex, true);
435 +                               case 'preferences':
436 +                                       this.controller.stageController.pushScene("prefs", this.appLauncherCfg, 
437 +                                               this.quickLaunchCfg, this.reloadPreferences.bind(this));
438 +                                       break;
439 +                               case 'addnewpage':
440 +                                       if (this.pageDivs.length < 16) {
441 +                                               this.insertPage(this.pageDivs.length, true);
442                                         }
443                                         break;
444                                 case 'deletepage':
445                                         if (this.pageDivs.length > 1) {
446 -                                               this.deletePage(this.activePageIndex);
447 -                                               if (this.activePageIndex >= this.pageDivs.length) {
448 -                                                       this.activePageIndex = this.pageDivs.length - 1;
449 -                                               }
450 +                                               this.confirmDelete();
451                                         }
452                                         break;
453 -                               */
454 +                               case 'renamepage':
455 +                                       this.startPageRename();
456 +                                       break;
457 +                               case 'movepageleft':
458 +                                       this.movePage("left");
459 +                                       break;
460 +                               case 'movepageright':
461 +                                       this.movePage("right");
462 +                                       break;                                  
463 +                               case 'startedit':
464 +                                       this.startEditMode(event);
465 +                                       break;
466 +                               case 'setdefault':
467 +                                       this.setDefaultPage(event);
468 +                                       break;
469 +                               case 'showpagemenu':
470 +                                       this.tabPageSelect(event);
471 +                                       break;
472 +                               case 'selectpage1':
473 +                                       this.tabPageSelect(event, 0);
474 +                                       break;
475 +                               case 'selectpage2':
476 +                                       this.tabPageSelect(event, 1);
477 +                                       break;
478 +                               case 'selectpage3':
479 +                                       this.tabPageSelect(event, 2);
480 +                                       break;
481 +                               case 'selectpage4':
482 +                                       this.tabPageSelect(event, 3);
483 +                                       break;
484 +                               case 'selectpage5':
485 +                                       this.tabPageSelect(event, 4);
486 +                                       break;
487                         }
488                 }
489 +               else if(event.type == Mojo.Event.forward) {
490 +                       var chooseCallback = this.jumpToPage.bind(this);
491 +
492 +                       this.showPageMenus(false, $L("Jump to Page:"), chooseCallback);
493 +               }                       
494                 else if (event.type === Mojo.Event.commandEnable) {
495                         switch (event.command) {
496                                 case Mojo.Menu.copyCmd:
497 @@ -157,16 +249,773 @@
498                         }
499                 }
500         },
501 +       
502 +       handlePreferences: function(payload) {
503 +               if(payload != undefined) {
504 +                       if(payload.appLauncherCfg != undefined)
505 +                               this.appLauncherCfg = payload.appLauncherCfg;
506 +                       
507 +                       if(payload.quickLaunchCfg != undefined)
508 +                               this.quickLaunchCfg = payload.quickLaunchCfg;
509 +               }
510 +
511 +               // FIXME: remove at some point
512                 
513 +               if(this.appLauncherCfg) {
514 +                       if(this.appLauncherCfg.header == true) {
515 +                               if(this.appLauncherCfg.visual == "tabs")
516 +                                       this.appLauncherCfg.header = "tabs";
517 +                               else
518 +                                       this.appLauncherCfg.header = "name";
519 +                       }
520 +                       else if(this.appLauncherCfg.header == false)
521 +                               this.appLauncherCfg.header = "none";
522 +
523 +                       if(this.appLauncherCfg.placement == undefined)
524 +                               this.appLauncherCfg.placement = "first";
525 +
526 +                       if(this.appLauncherCfg.indicators == undefined)
527 +                               this.appLauncherCfg.indicators = true;
528 +
529 +                       if(this.appLauncherCfg.grid == undefined)
530 +                               this.appLauncherCfg.grid = "small";
531 +
532 +                       if(this.appLauncherCfg.icons == undefined)
533 +                               this.appLauncherCfg.icons = "large";
534 +
535 +                       if(this.appLauncherCfg.titles == undefined)
536 +                               this.appLauncherCfg.titles = true;;
537 +                       
538 +                       if(this.appLauncherCfg.titles == true)
539 +                               this.controller.get("launcher-main").removeClassName("notitles");
540 +                       else
541 +                               this.controller.get("launcher-main").addClassName("notitles");
542 +
543 +                       if(this.appLauncherCfg.indicators == true)
544 +                               this.controller.get("launcher-main").removeClassName("noindicators");
545 +                       else
546 +                               this.controller.get("launcher-main").addClassName("noindicators");
547 +               
548 +                       this.controller.get("launcher_root").className = "grid_" + this.appLauncherCfg.grid;
549 +               
550 +                       this.controller.get("pages_container").className = "icons_" + this.appLauncherCfg.icons;
551 +
552 +                       if(this.appLauncherCfg.page == "default")
553 +                               this.appMenuModel.items[3].label = "Set As Default Page";
554 +                       else
555 +                               this.appMenuModel.items[3].label = "Unset Default Page";
556 +               
557 +                       this.controller.modelChanged(this.appMenuModel, this);
558 +
559 +                       this.updateAppLauncher(true);
560 +                       this.updateQuickLaunch(true);
561 +
562 +                       this.setPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice/', {
563 +                               method: 'setPreferences', parameters: {'appLauncherCfg': this.appLauncherCfg}});
564 +
565 +                       this.getPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice/', {
566 +                               method: 'getPreferences', parameters: {subscribe: true, keys: ['appLauncherCfg']},
567 +                               onSuccess: this.handlePreferencesUpdate.bind(this) });
568 +               }
569 +       },
570 +
571 +       handlePreferencesUpdate: function(payload) {
572 +               if((this.appLauncherCfg) && (payload != undefined) && 
573 +                       (payload.appLauncherCfg != undefined))
574 +               {
575 +                       var oldHidden = [];
576 +               
577 +                       if(this.appLauncherCfg.hidden)
578 +                               oldHidden = this.appLauncherCfg.hidden;
579 +       
580 +                       this.appLauncherCfg = payload.appLauncherCfg;
581 +               
582 +                       for(var i = 0; i < oldHidden.length; i++) {
583 +                               if(this.appLauncherCfg.hidden.indexOf(oldHidden[i]) == -1) {
584 +                                       var location = {page: 0, position: 0};
585 +                       
586 +                                       for (var j=0, numPages=this.pagesModel.getNumPages(); j<numPages; j++) {
587 +                                               var page = this.pagesModel.getPage(j);
588 +               
589 +                                               location.page = j;
590 +                                       
591 +                                               for (var k=0; k<page.length; k++) {
592 +                                                       var appInfo = this.pagesModel.getAppInfo(page[k]);
593 +
594 +                                                       if(appInfo.launchPointId == oldHidden[i]) {
595 +                                                               location.position = k;
596 +                                                               this.insertApp(location, appInfo);
597 +                                                       }
598 +                                               }
599 +                                       }
600 +                               }
601 +                       }
602 +               
603 +                       for(var i = 0; i < this.appLauncherCfg.hidden.length; i++) {
604 +                               if(oldHidden.indexOf(this.appLauncherCfg.hidden[i]) == -1) {
605 +                                       this.deleteApp(this.appLauncherCfg.hidden[i], true);
606 +                               }
607 +                       }
608 +               }
609 +       },
610 +       
611 +       reloadPreferences: function(buildPages) {
612 +               this.updateAppLauncher(false);
613 +               this.updateQuickLaunch(false);
614 +       
615 +               if(this.appLauncherCfg.titles == true)
616 +                       this.controller.get("launcher-main").removeClassName("notitles");
617 +               else
618 +                       this.controller.get("launcher-main").addClassName("notitles");
619 +
620 +               if(this.appLauncherCfg.indicators == true)
621 +                       this.controller.get("launcher-main").removeClassName("noindicators");
622 +               else
623 +                       this.controller.get("launcher-main").addClassName("noindicators");
624 +                       
625 +               this.controller.get("launcher_root").className = "grid_" + this.appLauncherCfg.grid;
626 +
627 +               this.controller.get("pages_container").className = "icons_" + this.appLauncherCfg.icons;
628 +               
629 +               if(buildPages)
630 +                       this.buildPages();              
631 +       },
632 +
633 +       startEditMode: function(event) {
634 +               var chooseCallback = this.selectPage.bind(this);
635 +               
636 +               this.showPageMenus(true, $L("Edit Launcher Pages:"), chooseCallback);
637 +       },
638 +       
639 +       setDefaultPage: function(event) {
640 +               if(this.appLauncherCfg.page == "default") {
641 +                       this.appMenuModel.items[3].label = $L("Unset Default Page");
642 +                       this.appLauncherCfg.page = this.activePageIndex;
643 +               }
644 +               else {
645 +                       this.appMenuModel.items[3].label = $L("Set As Default Page");
646 +                       this.appLauncherCfg.page = "default";
647 +               }
648 +               
649 +               this.controller.modelChanged(this.appMenuModel, this);
650 +                       
651 +               if(this.setPreferencesRequest)
652 +                       this.setPreferencesRequest.cancel();
653 +       
654 +               this.setPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice/', {
655 +                       method: 'setPreferences', parameters: {'appLauncherCfg': this.appLauncherCfg} });
656 +       },
657 +       
658 +       updateAppLauncher: function(init) {
659 +               if(!this.appLauncherCfg)
660 +                       return;
661 +       
662 +               if(this.appLauncherCfg.header == "none") {
663 +                       this.controller.get('page_header').style.display = "none";
664 +                       this.controller.get('page_name').style.display = "none";
665 +                       
666 +                       this.viewMenuModel.visible = false;
667 +                       this.controller.modelChanged(this.viewMenuModel, this);
668 +               }
669 +               else if(this.appLauncherCfg.header == "name") {
670 +                       this.controller.get('page_header').style.display = "block";
671 +                       this.controller.get('page_name').style.display = "block";
672 +               
673 +                       this.viewMenuModel.visible = false;
674 +               }
675 +               else if(this.appLauncherCfg.header == "tabs") {
676 +                       this.controller.get('page_header').style.display = "none";
677 +                       this.controller.get('page_name').style.display = "none";
678 +
679 +                       this.viewMenuModel.visible = true;
680 +               }
681 +
682 +               this.controller.modelChanged(this.viewMenuModel, this);
683 +
684 +               this.updatePageTabs();
685 +               this.updatePageHeader();
686 +
687 +               if(this.appLauncherCfg.wrap)
688 +                       Mojo.listen($('launcher_root'), Mojo.Event.scrollStarting, this.scrollStartingHandler);
689 +               else
690 +                       Mojo.stopListening($('launcher_root'), Mojo.Event.scrollStarting, this.scrollStartingHandler);
691 +
692 +               for(var i = 0; i < this.pageDivs.length; i++)
693 +                       this.updatePageLayout(i, 0);
694 +       },
695 +
696 +       updateQuickLaunch: function(init) {
697 +               if(!this.quickLaunchCfg)
698 +                       return;
699 +                       
700 +               if(this.quickLaunchCfg.mode == "visible") {
701 +                       SystemManagerService.showQuickLaunch(true);
702 +                       this.kQuickLaunchHeight = 67;
703 +               }       
704 +               else if(this.quickLaunchCfg.mode == "hidden") {
705 +                       SystemManagerService.showQuickLaunch(false);
706 +                       this.kQuickLaunchHeight = 0;
707 +               }       
708 +               else if(this.quickLaunchCfg.mode == "mixed") {
709 +                       SystemManagerService.showQuickLaunch(init);
710 +                       this.kQuickLaunchHeight = 0;
711 +               }
712 +
713 +               this.adjustLayout();
714 +       },
715 +
716 +       updatePageHeader: function() {
717 +               if(this.appLauncherCfg.header == "name") {
718 +                       var pageName = this.getPageName(this.activePageIndex);
719 +                       
720 +                       this.controller.get('page_name').update(pageName);
721 +
722 +                       this.controller.get('page_header').style.display = "block";
723 +                       this.controller.get('page_text').style.display = "none";
724 +                       this.controller.get('page_name').style.display = "block";
725 +               }
726 +       },
727 +       
728 +       updatePageTabs: function() {
729 +               if(this.appLauncherCfg.header == "tabs") {
730 +                       this.viewMenuModel.visible = true;
731 +
732 +                       var tabs = [];
733 +                       var size = 325 / this.pageDivs.length;
734 +                       
735 +                       if(this.pageDivs.length > 5) {
736 +                               tabs.push({label: "#1", command: "selectpage1"});
737 +                               tabs.push({label: "#2", command: "selectpage2"});
738 +                               tabs.push({label: "Menu", command: "showpagemenu"});
739 +                               tabs.push({label: "#3", command: "selectpage3"});
740 +                               tabs.push({label: "#4", command: "selectpage4"});
741 +                       }
742 +                       else {
743 +                               for(var i = 0; i < this.pageDivs.length; i++) {
744 +                                       tabs.push({label: "#" + (i + 1), command: "selectpage" + (i + 1), width: size});
745 +                               }
746 +                       }
747 +               
748 +                       this.viewMenuModel.items.clear();
749 +                       this.viewMenuModel.items.push({items: []}, {items:¬†tabs}, {items: []});
750 +                       
751 +                       this.viewMenuModel.items[1].toggleCmd = 'selectpage' + (parseInt(this.activePageIndex) + 1);
752 +
753 +                       this.controller.modelChanged(this.viewMenuModel);
754 +               }
755 +       },
756 +       
757 +       tabPageSelect: function(event, index) {
758 +               if(index != undefined)
759 +                       this.viewMenuModel.items[1].toggleCmd = 'selectpage' + index;
760 +               else
761 +                       this.viewMenuModel.items[1].toggleCmd = 'selectpagemenu';
762 +       
763 +               if((event.originalEvent.up) && ( event.originalEvent.up.altKey || event.originalEvent.up.metaKey )) {
764 +                       if((this.pageDivs.length <= 5) || (index == undefined)) {               
765 +                               var chooseCallback = this.selectPage.bind(this);
766 +
767 +                               this.showPageMenus(true, $L("Edit Launcher Pages:"), chooseCallback);
768 +                       }
769 +                       else if(index + 4 < this.pageDivs.length) {
770 +                               this.changePage(index + 4, true);
771 +                       }       
772 +               }
773 +               else {
774 +                       if(index == undefined) {
775 +                               var chooseCallback = this.jumpToPage.bind(this);
776 +
777 +                               for(var i = 0; i < this.viewMenuModel.items[1].items.length; i++)
778 +                                       this.viewMenuModel.items[1].items[i].disabled = true;
779 +                                       
780 +                               this.controller.modelChanged(this.viewMenuModel, this);
781 +                       
782 +                               this.showPageMenus(false, null, chooseCallback);
783 +                       }
784 +                       else
785 +                               this.changePage(index, true);
786 +               }
787 +       },
788 +               
789 +       handleLauncherTap: function(event) {
790 +               if((event.up) && ( event.up.altKey || event.up.metaKey )) {
791 +                       var chooseCallback = this.selectPage.bind(this);
792 +
793 +                       this.showPageMenus(true, $L("Edit Launcher Pages:"), chooseCallback);
794 +               }
795 +               else {
796 +                       if(event.count == 2) {
797 +                               var chooseCallback = this.jumpToPage.bind(this);
798 +
799 +                               this.showPageMenus(false, $L("Jump to Page:"), chooseCallback);
800 +                       }
801 +               }
802 +       },
803 +       
804 +       handleHeaderTap: function(event) {
805 +               if((event.up) && ( event.up.altKey || event.up.metaKey )) {
806 +                       var chooseCallback = this.selectPage.bind(this);
807 +
808 +                       this.showPageMenus(true, $L("Edit Launcher Pages:"), chooseCallback);
809 +               }
810 +               else {
811 +                       var chooseCallback = this.jumpToPage.bind(this);
812 +
813 +                       this.showPageMenus(false, $L("Jump to Page:"), chooseCallback);
814 +               }
815 +       },
816 +       
817 +       startAppRename: function(appInfo) {
818 +               Mojo.stopListening($('page_header'), Mojo.Event.tap, this.headerTapHandler);
819 +
820 +               Mojo.listen($('page_text'), Mojo.Event.propertyChange, this.appRenameHandler);
821 +               
822 +               if(this.appLauncherCfg.header == "tabs") {
823 +                       this.viewMenuModel.visible = false;
824 +                       this.controller.modelChanged(this.viewMenuModel, this);
825 +               }
826 +
827 +               this.controller.get('page_header').style.display = "block";
828 +               this.controller.get('page_name').style.display = "none";
829 +               this.controller.get('page_text').style.display = "block";
830 +
831 +               if((this.appLauncherCfg.names) && (this.appLauncherCfg.names[appInfo.launchPointId] != undefined))
832 +                       this.pageNameModel.value = this.appLauncherCfg.names[appInfo.launchPointId];
833 +               else
834 +                       this.pageNameModel.value = appInfo.title;
835 +               
836 +               this.pageNameModel.id = appInfo.launchPointId;
837 +                       
838 +               this.controller.modelChanged(this.pageNameModel);                       
839 +                               
840 +               var curPos = this.pageNameModel.value.length;
841 +                       
842 +               this.controller.get('page_text').mojo.setCursorPosition(curPos, curPos);
843 +               this.controller.get('page_text').mojo.focus();
844 +       },
845 +
846 +       handleAppRename: function(event) {
847 +               if((!event) || (Mojo.Char.isEnterKey(event.originalEvent.keyCode))) {
848 +                       Mojo.listen($('page_header'), Mojo.Event.tap, this.headerTapHandler);
849 +
850 +                       Mojo.stopListening($('page_text'), Mojo.Event.propertyChange, this.appRenameHandler);
851 +
852 +                       this.controller.get('page_header').style.display = "none";
853 +                       this.controller.get('page_text').style.display = "none";
854 +               
855 +                       if(this.appLauncherCfg.header == "name") {
856 +                               this.controller.get('page_header').style.display = "block";
857 +                               this.controller.get('page_name').style.display = "block";
858 +                       }
859 +                       else if(this.appLauncherCfg.header == "tabs") {
860 +                               this.viewMenuModel.visible = true;
861 +                               this.controller.modelChanged(this.viewMenuModel, this);
862 +                       }
863 +
864 +                       var element = $(this.pageNameModel.id);
865 +
866 +                       if (element) {
867 +                               if(!this.appLauncherCfg.names) 
868 +                                       this.appLauncherCfg.names = {};
869 +                       
870 +                               this.appLauncherCfg.names[this.pageNameModel.id] = this.pageNameModel.value;
871 +
872 +                               var elm = element.down('.name');
873 +                               
874 +                               elm.innerHTML = this.pageNameModel.value;
875 +                       }
876 +
877 +                       this.globalSearchAssistant.enable(true);
878 +
879 +                       if(this.setPreferencesRequest)
880 +                               this.setPreferencesRequest.cancel();
881 +               
882 +                       this.setPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice/', {
883 +                               method: 'setPreferences', parameters: {'appLauncherCfg': this.appLauncherCfg} });
884 +               }       
885 +       },
886 +       
887 +       startPageRename: function(refresh) {
888 +               this.globalSearchAssistant.enable(false);
889 +       
890 +               if((!refresh) && (this.renaming)) {
891 +                       this.handlePageRename();
892 +               }
893 +               else {  
894 +                       this.renaming = true;
895 +
896 +                       Mojo.listen($('page_text'), Mojo.Event.propertyChange, this.pageRenameHandler);
897 +
898 +                       if(!refresh) {
899 +                               this.commandMenuModel.items[1].label = "Done";
900 +                               this.controller.modelChanged(this.commandMenuModel);
901 +
902 +                               this.pageNameModel.value = this.getPageName(this.activePageIndex);
903 +                               this.controller.modelChanged(this.pageNameModel);
904 +                       }
905 +
906 +                       this.controller.get('page_name').style.display = "none";
907 +                       this.controller.get('page_text').style.display = "block";
908 +                       
909 +                       var curPos = this.pageNameModel.value.length;
910 +                       
911 +                       this.controller.get('page_text').mojo.setCursorPosition(curPos, curPos);
912 +                       this.controller.get('page_text').mojo.focus();
913 +               }
914 +       },
915 +       
916 +       handlePageRename: function(event) {
917 +               if((!event) || (Mojo.Char.isEnterKey(event.originalEvent.keyCode))) {
918 +                       this.renaming = false;
919 +
920 +                       Mojo.stopListening($('page_text'), Mojo.Event.propertyChange, this.pageRenameHandler);
921 +
922 +                       this.setPageName(this.activePageIndex, this.pageNameModel.value);
923 +
924 +                       this.controller.get('page_name').style.display = "block";
925 +                       this.controller.get('page_text').style.display = "none";
926 +
927 +                       this.selectPage(this.activePageIndex);
928 +
929 +                       this.commandMenuModel.items[1].label = "Rename";
930 +                       this.controller.modelChanged(this.commandMenuModel);
931 +
932 +                       if(this.setPreferencesRequest)
933 +                               this.setPreferencesRequest.cancel();
934 +       
935 +                       this.setPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice/', {
936 +                               method: 'setPreferences', parameters: {'appLauncherCfg': this.appLauncherCfg} });
937 +               }
938 +       },
939 +
940 +       selectPage: function(index) {
941 +               if((index == undefined) && (!this.renaming))
942 +                       this.hidePageMenus();
943 +               else {
944 +                       if(index != undefined) {
945 +                               if(this.renaming)
946 +                                       this.handlePageRename();
947 +
948 +                               this.changePage(index, true);
949 +
950 +                               var chooseCallback = this.selectPage.bind(this);
951 +                       
952 +                               this.showPageMenus(true, $L("Edit Launcher Pages:"), chooseCallback);
953 +                       }
954 +                       else
955 +                               setTimeout(this.hideSymbolMenu.bind(this), 5);
956 +               }
957 +       },
958 +
959 +       hideSymbolMenu: function() {
960 +               var chooseCallback = this.selectPage.bind(this);
961 +               
962 +               this.showPageMenus(true, $L("Edit Launcher Pages:"), chooseCallback);
963 +
964 +               if(this.renaming)
965 +                       this.startPageRename(true);
966 +       },
967 +
968 +       jumpToPage: function(index) {
969 +               if(index == undefined) {
970 +                       this.hidePageMenus();
971 +               }
972 +               else {
973 +                       this.changePage(index, true);
974 +                       
975 +                       this.hidePageMenus();           
976 +               }
977 +       },
978 +       
979 +       movePage: function(direction) {
980 +               if(direction == "left") {
981 +                       var newIndex = parseInt(this.activePageIndex) - 1;
982 +                       
983 +                       if(newIndex < 0)
984 +                               return;
985 +               }
986 +               else if(direction == "right") {
987 +                       var newIndex = parseInt(this.activePageIndex) + 1;
988 +
989 +                       if(newIndex == this.pageDivs.length)
990 +                               return;
991 +               }
992 +       
993 +               if(this.appLauncherCfg.page != "default") {
994 +                       if(this.appLauncherCfg.page == this.activePageIndex)
995 +                               this.appLauncherCfg.page = newIndex;                    
996 +               }
997 +               
998 +               var oldIndex = parseInt(this.activePageIndex);
999 +
1000 +               var tmp = this.appLauncherCfg.pages.splice(oldIndex,1);
1001 +
1002 +               this.appLauncherCfg.pages.splice(newIndex,0,tmp[0]);
1003 +
1004 +               this.pagesModel.switchPages(oldIndex, newIndex);
1005 +
1006 +               this.pagesModel.save();
1007 +                                               
1008 +               var apps1 = this.getAppContainer(oldIndex).select('.app');
1009 +               var apps2 = this.getAppContainer(newIndex).select('.app');
1010 +
1011 +               var container1 = this.getAppContainer(oldIndex);
1012 +               var container2 = this.getAppContainer(newIndex);
1013 +
1014 +               apps1.each(function(app) {
1015 +                       container1.removeChild(app);
1016 +                       container2.appendChild(app);
1017 +               }.bind(this));
1018 +
1019 +               apps2.each(function(app) {
1020 +                       container2.removeChild(app);
1021 +                       container1.appendChild(app);
1022 +               }.bind(this));
1023 +
1024 +               if (apps1.length > 0)
1025 +                       this.updatePageLayout(oldIndex, apps1.length);
1026 +
1027 +               if (apps2.length > 0)
1028 +                       this.updatePageLayout(newIndex, apps2.length);
1029 +
1030 +               this.selectPage(newIndex);
1031 +               
1032 +               if(this.setPreferencesRequest)
1033 +                       this.setPreferencesRequest.cancel();
1034 +               
1035 +               this.setPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice/', {
1036 +                       method: 'setPreferences', parameters: {'appLauncherCfg': this.appLauncherCfg} });
1037 +       },
1038 +       
1039 +       movePageApp: function(appInfo, index) {
1040 +               if(index == undefined) {
1041 +                       this.hidePageMenus();
1042 +                       return;
1043 +               }
1044 +
1045 +               if(this.pageDivs[index] != undefined) {
1046 +                       var from = this.pagesModel.findApplication(appInfo.launchPointId);
1047 +                       var to = {page: parseInt(index), position: -1};
1048 +
1049 +                       this.moveApp(appInfo.launchPointId, to);
1050 +                       this.pagesModel.moveApplication(from, to);
1051 +
1052 +                       this.pagesModel.save();
1053 +               }
1054 +
1055 +               this.hidePageMenus();
1056 +       },
1057 +
1058 +       changePage: function(index, animate) {
1059 +               if(this.appLauncherCfg.reset) {
1060 +                       var scroller = this.getPageScroller(this.activePageIndex);
1061 +                       
1062 +                       if (scroller && scroller.mojo) { scroller.mojo.revealTop(); }
1063 +               }
1064 +               
1065 +               if(this.activePageIndex != index) {
1066 +                       this.activePageIndex = index;
1067 +
1068 +                       if(this.appLauncherCfg.wrap)
1069 +                               $('launcher_root').mojo.scrollTo((index) * -this.kPageWidth, undefined, false, true);
1070 +                       else {
1071 +                               $('launcher_root').mojo.setSnapIndex(parseInt(index), animate);
1072 +                       }
1073 +               }
1074 +       },
1075 +
1076 +       showPageMenus: function(viewMenu, menuTitle, chooseCallback) {
1077 +               Mojo.stopListening($('launcher_root'), Mojo.Event.propertyChange, this.pageChangeHandler);
1078 +
1079 +               if(menuTitle)
1080 +                       Mojo.stopListening($('page_header'), Mojo.Event.tap, this.headerTapHandler);
1081 +                                       
1082 +               this.globalSearchAssistant.enable(false);
1083 +
1084 +               var pageItems = [];
1085 +
1086 +               for(var i = 0; i < this.pageDivs.length; i++) {
1087 +                       var pageName = this.getPageName(i);
1088 +                       
1089 +                       pageItems.push({command: i, label: pageName, chosen: (i == this.activePageIndex)});
1090 +               }
1091 +
1092 +               if(viewMenu)
1093 +                       var menuClass = "pageMenu";
1094 +               else
1095 +                       var menuClass = "jumpMenu";
1096 +
1097 +               this.controller.popupSubmenu({
1098 +                       popupClass: menuClass,
1099 +                       scrimClass: "pageMenuScrim",
1100 +                       manualPlacement: true,
1101 +
1102 +                       items: pageItems,
1103 +
1104 +                       onChoose: chooseCallback
1105 +               });
1106 +
1107 +               if(menuTitle) {
1108 +                       if(this.appLauncherCfg.header == "tabs") {
1109 +                               this.viewMenuModel.visible = false;
1110 +                               this.controller.modelChanged(this.viewMenuModel, this);
1111 +                       }
1112 +               
1113 +                       this.controller.get('page_header').style.display = "block";
1114 +
1115 +                       this.controller.get('page_text').style.display = "none";
1116 +                       this.controller.get('page_name').style.display = "block";
1117 +
1118 +                       this.controller.get('page_name').update(menuTitle);
1119 +               }
1120 +               
1121 +               if(this.quickLaunchCfg.mode == "visible") {
1122 +                       SystemManagerService.showQuickLaunch(false);
1123 +                       this.kQuickLaunchHeight = 0;
1124 +                       this.adjustLayout();
1125 +               }
1126 +
1127 +               if(viewMenu) {
1128 +                       this.commandMenuModel.visible = true;
1129 +                       this.controller.modelChanged(this.commandMenuModel);
1130 +               }
1131 +       },
1132 +       
1133 +       hidePageMenus: function() {
1134 +               Mojo.listen($('page_header'), Mojo.Event.tap, this.headerTapHandler);
1135 +
1136 +               Mojo.listen($('launcher_root'), Mojo.Event.propertyChange, this.pageChangeHandler);
1137 +
1138 +               this.globalSearchAssistant.enable(true);
1139 +
1140 +               this.controller.get('page_header').style.display = "none";
1141 +               this.controller.get('page_name').style.display = "none";
1142 +
1143 +               this.updatePageHeader();
1144 +               this.updatePageTabs();
1145 +
1146 +               this.updatePageIndicators();
1147 +               
1148 +               this.commandMenuModel.visible = false;
1149 +               this.controller.modelChanged(this.commandMenuModel);
1150 +               
1151 +               if(this.quickLaunchCfg.mode == "visible") {
1152 +                       SystemManagerService.showQuickLaunch(true);
1153 +                       this.kQuickLaunchHeight = 67;
1154 +                       this.adjustLayout();
1155 +               }
1156 +       },
1157 +
1158 +       getPageName: function(index) {
1159 +               if(this.appLauncherCfg.pages[parseInt(index)] == undefined)
1160 +                       this.appLauncherCfg.pages[parseInt(index)] = "Launcher Page " + (parseInt(index) + 1);
1161 +
1162 +               return this.appLauncherCfg.pages[parseInt(index)];
1163 +       },
1164 +
1165 +       setPageName: function(index, pageName) {
1166 +               if((pageName.length > 0) &&¬†(pageName.split(' ').join('').length > 0))
1167 +                       this.appLauncherCfg.pages[parseInt(index)] = this.pageNameModel.value;
1168 +               else
1169 +                       this.appLauncherCfg.pages[parseInt(index)] = "Launcher Page " + (parseInt(index) + 1);
1170 +       },
1171 +
1172 +       confirmDelete: function() {
1173 +               var apps = this.getAppContainer(this.activePageIndex).select('.app');
1174 +       
1175 +               if(apps.length == 0)
1176 +                       this.deletePage(this.activePageIndex);
1177 +               else {
1178 +                       this.controller.showAlertDialog({
1179 +                               title: "Delete Launcher Page",
1180 +                               message: "Are you sure that you want to delete the current launcher page?",
1181 +                               choices:[
1182 +                                       {label:'Delete', value:"delete", type:'negative'},
1183 +                                       {label:'Cancel', value:"cancel", type:'default'}],
1184 +                               preventCancel: false,
1185 +                               allowHTMLMessage: false,
1186 +                               onChoose: function(value) {
1187 +                                       if(value == "delete")
1188 +                                       this.deletePage(this.activePageIndex);
1189 +
1190 +                                       var chooseCallback = this.selectPage.bind(this);
1191 +
1192 +                                       this.showPageMenus(true, $L("Edit Launcher Page:"), chooseCallback);
1193 +                               }.bind(this)});
1194 +
1195 +                       SystemManagerService.showQuickLaunch(false);
1196 +               }
1197 +       },
1198 +
1199 +       scrollStarting: function(event) {
1200 +               event.scroller.addListener(this);
1201 +       },
1202 +       
1203 +       moved: function(scrollEnded, position) {
1204 +               if(scrollEnded) {
1205 +                       this.pagingAnimating = false;
1206 +               }
1207 +               else {
1208 +                       this.pagingAnimating = true;
1209 +                       
1210 +                       if(this.appLauncherCfg.reset) {
1211 +                               var scroller = this.getPageScroller(this.activePageIndex);
1212 +
1213 +                               if(scroller && scroller.mojo) { scroller.mojo.revealTop(); }
1214 +                       }
1215 +
1216 +                       if(Math.abs(position.x) > ((this.pageDivs.length - 1) * this.kPageWidth))
1217 +                               $('launcher_root').mojo.scrollTo(0, undefined, false, true);
1218 +                       else if(position.x > 0 )
1219 +                               $('launcher_root').mojo.scrollTo((this.pageDivs.length - 1) * -this.kPageWidth , undefined, false, true);
1220 +                       else if( this.activePageIndex * -this.kPageWidth > position.x )
1221 +                               $('launcher_root').mojo.scrollTo( (this.activePageIndex + 1) * -this.kPageWidth, undefined, false, true);
1222 +                       else if( this.activePageIndex * -this.kPageWidth < position.x )
1223 +                               $('launcher_root').mojo.scrollTo( (this.activePageIndex - 1) * -this.kPageWidth, undefined, false, true);
1224 +               }
1225 +               
1226 +               this.activePageIndex = Math.abs($('launcher_root').mojo.getScrollPosition().left) / this.kPageWidth;
1227 +                       
1228 +               this.updatePageHeader();
1229 +               this.updatePageIndicators();
1230 +       },      
1231 +
1232         /* keep track of which page we are on */
1233         onPageChange: function(event) {
1234 -               this.activePageIndex = event.value;
1235 -               this.updatePageIndicators();
1236 +               if(this.appLauncherCfg.reset) {
1237 +                       var scroller = this.getPageScroller(this.activePageIndex);
1238 +
1239 +                       if (scroller && scroller.mojo) { scroller.mojo.revealTop(); }
1240 +               }
1241 +
1242 +               if((!this.appLauncherCfg.wrap) || (this.reorderController.reordering)) {
1243 +                       this.activePageIndex = event.value;
1244 +                                       
1245 +                       this.updatePageHeader();
1246 +                       this.updatePageIndicators();
1247 +               }
1248 +
1249 +               if((this.appLauncherCfg.header == "tabs")) {
1250 +                       this.viewMenuModel.items[1].toggleCmd = 'selectpage' + (event.value + 1);
1251 +       
1252 +                       this.controller.modelChanged(this.viewMenuModel);
1253 +               }
1254 +       },
1255 +
1256 +       /* hide quick launch */
1257 +       onActivate: function(event) {
1258 +               if(this.appLauncherCfg.page != "default") {
1259 +                       this.changePage(this.appLauncherCfg.page, false);
1260 +
1261 +                       this.updatePageHeader();
1262 +                       this.updatePageIndicators();
1263 +               }
1264 +
1265 +               this.updateQuickLaunch(false);
1266         },
1267         
1268         /* clean and hide global search */
1269         onDeactivate: function(event) {
1270 -               
1271                 this.globalSearchAssistant.deactivate();
1272                 
1273                 this.reorderController.cancel();
1274 @@ -174,8 +1023,19 @@
1275                 if (this.appDialog) {
1276                         this.appDialog.mojo.close();
1277                 }
1278 +
1279 +               if(this.appLauncherCfg.page != "default") {
1280 +                       this.changePage(this.appLauncherCfg.page, false);
1281 +
1282 +                       this.updatePageHeader();
1283 +                       this.updatePageIndicators();
1284 +               }
1285                 
1286 -               SystemManagerService.showQuickLaunch(true);
1287 +               if(this.quickLaunchCfg.mode != "hidden") {
1288 +                       SystemManagerService.showQuickLaunch(true);
1289 +                       this.kQuickLaunchHeight = 67;
1290 +                       this.adjustLayout();
1291 +               }
1292                 
1293                 this.launchRequest = undefined;
1294         },
1295 @@ -202,12 +1062,12 @@
1296         
1297         /* helper to consolidate all the places accessing these types of elements */
1298         getAppContainer: function(pageIndex) {
1299 -               Mojo.assert(this.pageDivs.length > pageIndex, "Attempting to access invalid page #{page}", {page: pageIndex});
1300 +               Mojo.assert(this.pageDivs.length >= pageIndex, "Attempting to access invalid page #{page}", {page: pageIndex});
1301                 return this.pageDivs[pageIndex].down('.page_scroller_container');
1302         },
1303         
1304         getPageScroller: function(pageIndex) {
1305 -               Mojo.assert(this.pageDivs.length > pageIndex, "Attempting to access invalid page #{page}", {page: pageIndex});
1306 +               Mojo.assert(this.pageDivs.length >= pageIndex, "Attempting to access invalid page #{page}", {page: pageIndex});
1307                 return this.pageDivs[pageIndex].down('.page_scroller');
1308         },
1309         
1310 @@ -255,15 +1115,59 @@
1311                 
1312                 // tell our scroller widget that it has a new page element to snap
1313                 this.updatePageSnappingPoints();
1314 +
1315 +               if(createPage) {
1316 +                       this.appLauncherCfg.pages.splice(newPageIndex, 0, "Launcher Page " + (parseInt(newPageIndex) + 1));
1317 +
1318 +                       this.changePage(newPageIndex, true);
1319 +                       
1320 +                       var chooseCallback = this.selectPage.bind(this);
1321 +
1322 +                       this.showPageMenus(true, $L("Edit Launcher Pages:"), chooseCallback);
1323 +                       
1324 +                       if(this.setPreferencesRequest)
1325 +                               this.setPreferencesRequest.cancel();
1326 +               
1327 +                       this.setPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice/', {
1328 +                               method: 'setPreferences', parameters: {'appLauncherCfg': this.appLauncherCfg} });
1329 +               }
1330         },
1331         
1332         deletePage: function(pageIndex) {
1333 +
1334                 // move all apps still on page[pageIndex] to the previous/next page  
1335                 var moveIndex = (pageIndex == 0 ? 1 : pageIndex-1);
1336                 if (!this.pagesModel.removePage(pageIndex, moveIndex)) {
1337                         return false;
1338                 }
1339                 
1340 +               // Weird problem in changePage / setsnapindex, no page change when index 0
1341 +
1342 +               if(this.pageDivs.length == 2) {
1343 +                       this.activePageIndex = 0;
1344 +                       $('launcher_root').mojo.scrollTo(0, undefined, true, false);
1345 +               }
1346 +               else {
1347 +                       // snap to a valid location
1348 +                       if(pageIndex >= this.pageDivs.length - 1)
1349 +                               this.changePage(this.pageDivs.length - 2, true);
1350 +                       else
1351 +                               this.changePage(pageIndex, true);
1352 +               }
1353 +               
1354 +               if(this.appLauncherCfg.page != "default") {
1355 +                       if(this.appLauncherCfg.page == pageIndex)
1356 +                               this.setupAppLauncher(null, "page");
1357 +               }
1358 +
1359 +               this.appLauncherCfg.pages.splice(pageIndex,1);
1360 +
1361 +               if(this.setPreferencesRequest)
1362 +                       this.setPreferencesRequest.cancel();
1363 +               
1364 +               this.setPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice/', {
1365 +                       method: 'setPreferences', parameters: {'appLauncherCfg': this.appLauncherCfg} });
1366 +
1367                 // move appDivs over to their new home
1368                 var apps = this.getAppContainer(pageIndex).select('.app');
1369                 var startIndex = apps.length;
1370 @@ -298,13 +1202,9 @@
1371                 // remove the pages indicator
1372                 this.deletePageIndicator();
1373                 
1374 -               // snap to a valid location
1375 -               if (pageIndex >= this.pageDivs.length) {
1376 -                       $('launcher_root').mojo.setSnapIndex(this.pageDivs.length-1, true);
1377 -               }
1378 -               else {
1379 -                       $('launcher_root').mojo.setSnapIndex(pageIndex, true);
1380 -               }
1381 +               var chooseCallback = this.selectPage.bind(this);
1382 +
1383 +               this.showPageMenus(true, $L("Edit Launcher Pages:"), chooseCallback);
1384                 
1385                 this.updatePageSnappingPoints();
1386         },
1387 @@ -326,6 +1226,10 @@
1388                         var appContainer = this.getAppContainer(location.page);
1389                         var content = Mojo.View.render({object:newAppInfo, template: "launcher/page-item"});
1390                         var children = appContainer.select('.app');
1391 +
1392 +                       if(location.position == null)
1393 +                               location.position = children.length;
1394 +
1395                         if (location.position >= children.length) {
1396                                 appContainer.insert({bottom:content});
1397                         } else {
1398 @@ -336,9 +1240,35 @@
1399                         newAppDiv = $(newAppInfo.launchPointId);
1400                         Mojo.assert(newAppDiv !== undefined, "Application (%d) was inserted into the DOM but unable to be retrieved!", newAppInfo.launchPointId);
1401                         if (isNaN(this.kAppWidth) || isNaN(this.kAppHeight)) {
1402 -                               this.kAppWidth = newAppDiv.getWidth();
1403 -                               this.kAppHeight = newAppDiv.getHeight();
1404 -                               this.kAppsPerRow = Math.round(this.kPageWidthNoMargin / this.kAppWidth);
1405 +                               if(this.appLauncherCfg.grid == "small") {
1406 +                                       this.kAppWidth = 104;
1407 +                                       this.kAppsPerRow = 3;
1408 +                               }
1409 +                               else if(this.appLauncherCfg.grid == "medium") {
1410 +                                       this.kAppWidth = 76;
1411 +                                       this.kAppsPerRow = 4;
1412 +                               }
1413 +                               else if(this.appLauncherCfg.grid == "large") {
1414 +                                       this.kAppWidth = 63;
1415 +                                       this.kAppsPerRow = 5;
1416 +                               }
1417 +
1418 +                               if(this.appLauncherCfg.titles == true) {
1419 +                                       if(this.appLauncherCfg.icons == "small")
1420 +                                               this.kAppHeight = 84;
1421 +                                       else if(this.appLauncherCfg.icons == "medium")
1422 +                                               this.kAppHeight = 94;
1423 +                                       else if(this.appLauncherCfg.icons == "large")
1424 +                                               this.kAppHeight = 104;
1425 +                               }
1426 +                               else {
1427 +                                       if(this.appLauncherCfg.icons == "small")
1428 +                                               this.kAppHeight = 72;
1429 +                                       else if(this.appLauncherCfg.icons == "medium")
1430 +                                               this.kAppHeight = 82;
1431 +                                       else if(this.appLauncherCfg.icons == "large")
1432 +                                               this.kAppHeight = 92;
1433 +                               }
1434                         }
1435                         
1436                         Mojo.listen(newAppDiv, Mojo.Event.tap, this.onAppTapped.bindAsEventListener(this));
1437 @@ -348,6 +1278,15 @@
1438                         // stash the application's data in the element
1439                         newAppDiv._info = newAppInfo;
1440  
1441 +                       // set the application name if renamed
1442 +                       elm = newAppDiv.down('.name');
1443 +
1444 +                       if((elm) && (this.appLauncherCfg.names) && 
1445 +                               (this.appLauncherCfg.names[newAppInfo.launchPointId] != undefined))
1446 +                       {
1447 +                               elm.innerHTML = this.appLauncherCfg.names[newAppInfo.launchPointId];
1448 +                       }                       
1449 +
1450                         this._updateBadge(newAppDiv, newAppInfo);
1451                 
1452                         /* adjust page position and height */
1453 @@ -435,14 +1374,20 @@
1454                 if (elm) {
1455                         var newTitle = "";
1456                         if (newAppInfo.update && newAppInfo.update.title) {
1457 -                               newTitle = newAppInfo.update.title.escapeHTML();
1458 +                               if((this.appLauncherCfg.names) && (this.appLauncherCfg.names[newAppInfo.update.launchPointId] != undefined))
1459 +                                       newTitle = this.appLauncherCfg.names[newAppInfo.update.launchPointId];
1460 +                               else
1461 +                                       newTitle = newAppInfo.update.title.escapeHTML();
1462                                 if (newTitle !== elm.innerHTML) {
1463                                         Mojo.Log.info("Updating title of app div, old: %d | new: %d", elm.innerHTML, newTitle);
1464                                         elm.innerHTML = newTitle;
1465                                 }
1466                         }
1467                         else if (newAppInfo.title) {
1468 -                               newTitle = newAppInfo.title.escapeHTML();
1469 +                               if((this.appLauncherCfg.names) && (this.appLauncherCfg.names[newAppInfo.launchPointId] != undefined))
1470 +                                       newTitle = this.appLauncherCfg.names[newAppInfo.launchPointId]; 
1471 +                               else            
1472 +                                       newTitle = newAppInfo.title.escapeHTML();
1473                                 if (elm.innerHTML !== newTitle) {
1474                                         Mojo.Log.info("Updating title of app div, old: %d | new: %d", elm.innerHTML, newTitle);
1475                                         elm.innerHTML = newTitle;
1476 @@ -514,6 +1459,10 @@
1477                 for (var i=offset, len = children.length; i<len; i++) {
1478                         var item = children[i];
1479                         var appPos = this.calculateAppPosition(i);
1480 +                       
1481 +                       if(this.appLauncherCfg.header != "none")
1482 +                               appPos.top = appPos.top + 50;
1483 +                       
1484                         if (animate) {
1485                                 LauncherAnimation.animateApp(item, appPos);
1486                         } else {
1487 @@ -535,8 +1484,15 @@
1488         
1489         /* determines the position of an app element at appIndex within a page */
1490         calculateAppPosition: function(appIndex) {
1491 +               if(this.appLauncherCfg.grid == "small")
1492 +                       var margin = 5;
1493 +               else if(this.appLauncherCfg.grid == "medium")
1494 +                       var margin = -5;
1495 +               else if(this.appLauncherCfg.grid == "large")
1496 +                       var margin = -16;
1497 +       
1498                 return {
1499 -                       left: (((appIndex % this.kAppsPerRow) * this.kAppWidth) + this.kPageMargin),
1500 +                       left: (((appIndex % this.kAppsPerRow) * this.kAppWidth) + margin),
1501                         top: (Math.floor(appIndex/this.kAppsPerRow) * this.kAppHeight)
1502                 };
1503         },
1504 @@ -577,17 +1533,51 @@
1505                                 return;
1506                         }
1507                 }
1508 +
1509 +               if(this.quickLaunchCfg.mode == "visible") {
1510 +                       SystemManagerService.showQuickLaunch(false);
1511 +                       this.kQuickLaunchHeight = 0;
1512 +                       this.adjustLayout();
1513 +               }
1514                 
1515 -               SystemManagerService.showQuickLaunch(false);
1516                 this.globalSearchAssistant.enable(false);
1517                 
1518                 var appInfoAssistant = new AppInfoAssistant(appInfo,
1519                                                                                                         this.controller,
1520 -                                                                                                       function() {
1521 +                                                                                                       function(appInfo, action) {
1522                                                                                                                 this.appDialog = undefined;
1523 -                                                                                                               SystemManagerService.showQuickLaunch(true);
1524 -                                                                                                               this.globalSearchAssistant.enable(true);
1525 -                                                                                                       }.bind(this));
1526 +                                                                                                               if(this.quickLaunchCfg.mode == "visible") {
1527 +                                                                                                                       SystemManagerService.showQuickLaunch(true);
1528 +                                                                                                                       this.kQuickLaunchHeight = 67;
1529 +                                                                                                                       this.adjustLayout();
1530 +                                                                                                               }
1531 +                                                                                                               if(action == "move") { 
1532 +                                                                                                                       var chooseCallback = this.movePageApp.bind(this, appInfo);
1533 +                                                                                                                       
1534 +                                                                                                                       this.showPageMenus(false, "Move Application:", chooseCallback);
1535 +                                                                                                               }
1536 +                                                                                                               else if(action == "hide") {
1537 +                                                                                                                       if(!this.appLauncherCfg.hidden)
1538 +                                                                                                                               this.appLauncherCfg.hidden = [];
1539 +                                                                                                                               
1540 +                                                                                                                       this.appLauncherCfg.hidden.push(appInfo.launchPointId);
1541 +                                                                                                                       
1542 +                                                                                                                       this.globalSearchAssistant.enable(true);
1543 +                                                                                                                       
1544 +                                                                                                                       this.deleteApp(appInfo.launchPointId, true);
1545 +                                                                                                                       
1546 +                                                                                                                       if(this.setPreferencesRequest)
1547 +                                                                                                                               this.setPreferencesRequest.cancel();
1548 +
1549 +                                                                                                                       this.setPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice/', {
1550 +                                                                                                                               method: 'setPreferences', parameters: {'appLauncherCfg': this.appLauncherCfg} });
1551 +                                                                                                               }
1552 +                                                                                                               else if(action == "rename") {
1553 +                                                                                                                       this.startAppRename(appInfo);
1554 +                                                                                                               }
1555 +                                                                                                               else
1556 +                                                                                                                       this.globalSearchAssistant.enable(true);
1557 +                                                                                                       }.bind(this, appInfo));
1558  
1559                 this.appDialog = this.controller.showDialog({
1560                                                         template: 'launcher/dialogs/app-info',
1561 @@ -602,22 +1592,53 @@
1562                 
1563                 this.deleteAllPages();
1564                 
1565 +               var allApps = [];
1566 +                                       
1567                 var location = {page: 0, position: 0};
1568                 for (var i=0, numPages=this.pagesModel.getNumPages(); i<numPages; i++) {
1569                         // create a new page
1570                         this.insertPage(i);
1571 +
1572 +                       var skip = 0;
1573                         
1574                         // insert all the applications for this page into the page container
1575                         var page = this.pagesModel.getPage(i);
1576                         location.page = i;
1577                         for (var j=0; j<page.length; j++) {
1578 -                               location.position = j;
1579 -                               this.insertApp(location, this.pagesModel.getAppInfo(page[j]));
1580 +                               var appInfo = this.pagesModel.getAppInfo(page[j]);
1581 +                       
1582 +                               allApps.push(appInfo.launchPointId);
1583 +                       
1584 +                               if(this.appLauncherCfg.hidden) {
1585 +                                       if(this.appLauncherCfg.hidden.indexOf(appInfo.launchPointId) != -1) {
1586 +                                               skip++;
1587 +                                               continue;
1588 +                                       }
1589 +                               }
1590 +                       
1591 +                               location.position = j - skip;
1592 +                               this.insertApp(location, appInfo);
1593 +                       }
1594 +               }
1595 +
1596 +               if(this.appLauncherCfg.names) {
1597 +                       for(var key in this.appLauncherCfg.names) {
1598 +                               if(allApps.indexOf(key) == -1)
1599 +                                       delete this.appLauncherCfg.names[key];
1600                         }
1601                 }
1602                 
1603 +               if(this.setPreferencesRequest)
1604 +                       this.setPreferencesRequest.cancel();
1605 +       
1606 +               this.setPreferencesRequest = new Mojo.Service.Request('palm://com.palm.systemservice/', {
1607 +                       method: 'setPreferences', parameters: {'appLauncherCfg': this.appLauncherCfg} });
1608 +               
1609                 this.globalSearchAssistant.enable(true);
1610  
1611 +               if(this.appLauncherCfg.header == "tabs")
1612 +                       this.updatePageTabs();
1613 +
1614                 PalmSystem.launcherReady();
1615         },
1616         
1617 @@ -633,10 +1654,12 @@
1618          * its starting position
1619          */
1620         createPageIndicator: function() {
1621 -               var indicator = new Element('div', {'class': 'page_indicator'});
1622 -               $('page_indicators').appendChild(indicator);
1623 -               this.indicators.push({element: indicator});
1624 -               this.recalculateIndicatorRanges();
1625 +               if(this.appLauncherCfg.indicators) {
1626 +                       var indicator = new Element('div', {'class': 'page_indicator'});
1627 +                       $('page_indicators').appendChild(indicator);
1628 +                       this.indicators.push({element: indicator});
1629 +                       this.recalculateIndicatorRanges();
1630 +               }
1631         },
1632         
1633         /*
1634 @@ -644,65 +1667,85 @@
1635          * the remaining page indicators
1636          */
1637         deletePageIndicator: function() {
1638 +               if(this.appLauncherCfg.indicators) {            
1639 +                       var indicator = this.indicators.pop();
1640 +                       if (indicator) {
1641 +                               indicator.element.remove();
1642 +                       }
1643                 
1644 -               var indicator = this.indicators.pop();
1645 -               if (indicator) {
1646 -                       indicator.element.remove();
1647 +                       this.recalculateIndicatorRanges();
1648                 }
1649 -               
1650 -               this.recalculateIndicatorRanges();
1651         },
1652         
1653         /* Updates the positions of all page indicators. */
1654         updatePageIndicators: function() {
1655 +               if(this.appLauncherCfg.indicators) {
1656 +                       if (this.indicators.length <= 0) {
1657 +                               return;
1658 +                       }
1659                 
1660 -               if (this.indicators.length <= 0) {
1661 -                       return;
1662 -               }
1663 -               
1664 -               for (var i = 0; i < this.indicators.length; i++) {
1665 -                       if (i < this.activePageIndex) {
1666 -                               this.moveIndicator(i, this.indicators[i].range.left);
1667 -                       } else {
1668 -                               this.moveIndicator(i, this.indicators[i].range.right);
1669 +                       for (var i = 0; i < this.indicators.length; i++) {
1670 +                               if (i < this.activePageIndex) {
1671 +                                       this.moveIndicator(i, this.indicators[i].range.left);
1672 +                               } else {
1673 +                                       this.moveIndicator(i, this.indicators[i].range.right);
1674 +                               }
1675                         }
1676                 }
1677         },
1678         
1679         /* recalculates the cached set of page indicator ranges and then redraws them */
1680         recalculateIndicatorRanges: function() {
1681 +               if(this.appLauncherCfg.indicators) {            
1682 +                       var indicator = this.indicators.first();
1683 +                       if (indicator === undefined) {
1684 +                               return;
1685 +                       }
1686                 
1687 -               var indicator = this.indicators.first();
1688 -               if (indicator === undefined) {
1689 -                       return;
1690 -               }
1691 -               
1692 -               var indicatorWidth = this.kPageIndicatorSpacing + indicator.element.getWidth();
1693 +                       var indicatorWidth = this.kPageIndicatorSpacing; // + indicator.element.getWidth();
1694                 
1695 -               for (var i=0; i<this.indicators.length; i++) {
1696 +                       for (var i=0; i<this.indicators.length; i++) {
1697                         
1698 -                       var left = (i+1) * indicatorWidth;
1699 -                       var right = this.kPageWidthNoMargin - ((this.indicators.length-i-1) * indicatorWidth);
1700 -                       this.indicators[i].range = {left: left, right: right};
1701 +                               var left = (i+1) * indicatorWidth;
1702 +                               var right = this.kPageWidthNoMargin - ((this.indicators.length-i-1) * indicatorWidth);
1703 +                               this.indicators[i].range = {left: left, right: right};
1704 +                       }
1705 +                       this.updatePageIndicators();
1706                 }
1707 -               this.updatePageIndicators();
1708         },
1709         
1710         /* Moves the indicator to newPosition */
1711         moveIndicator: function(indicatorIndex, newPosition) {
1712 -               
1713 -               var indicator = this.indicators[indicatorIndex];
1714 -               if (newPosition < indicator.range.left) {
1715 -                       newPosition = indicator.range.left;
1716 -               } else if (newPosition > indicator.range.right) {
1717 -                       newPosition = indicator.range.right;
1718 +               if(this.appLauncherCfg.indicators) {
1719 +                       var indicator = this.indicators[indicatorIndex];
1720 +                       if (newPosition < indicator.range.left) {
1721 +                               newPosition = indicator.range.left;
1722 +                       } else if (newPosition > indicator.range.right) {
1723 +                               newPosition = indicator.range.right;
1724 +                       }
1725 +                       indicator.element.style.left = newPosition + 'px';
1726                 }
1727 -               indicator.element.style.left = newPosition + 'px';
1728         },
1729  /********** Page Indicator end **********/
1730                 
1731         /* handler called by the pages model when a new application has been added */
1732         onAppAdded: function(newAppInfo, newLocation) {
1733 +               newLocation.position = null;
1734 +               if((this.appLauncherCfg) && (this.appLauncherCfg.placement)) {
1735 +                       if(this.appLauncherCfg.placement == "first")
1736 +                               newLocation.page = 0;
1737 +                       else if(this.appLauncherCfg.placement == "last")
1738 +                               newLocation.page = this.pageDivs.length - 1;
1739 +                       else if(this.appLauncherCfg.placement == "active")
1740 +                               newLocation.page = this.activePageIndex;
1741 +                       else if(this.appLauncherCfg.placement == "default") {
1742 +                               if((this.appLauncherCfg.page != undefined) &&
1743 +                                       (this.appLauncherCfg.page != "default"))
1744 +                               {
1745 +                                       newLocation.page = this.appLauncherCfg.page;
1746 +                               }                       
1747 +                       }       
1748 +               }
1749                 this.insertApp(newLocation, newAppInfo);
1750         },
1751         
1752 @@ -720,7 +1763,7 @@
1753         onAppTapped: function(event) {
1754                 var target = event.currentTarget;
1755                 var appInfo = target._info;
1756 -               if (event.up && event.up.altKey) {
1757 +               if (event.up && event.up.altKey || event.up && event.up.metaKey) {
1758                         // open app-info dialog
1759                         this.showAppInfoMenu(appInfo);
1760                 } else if (!this.launchRequest) { // are we already trying to launch something?
1761 --- .orig/usr/lib/luna/system/luna-applauncher/app/views/launcher/launcher-scene.html
1762 +++ /usr/lib/luna/system/luna-applauncher/app/views/launcher/launcher-scene.html
1763 @@ -17,9 +17,13 @@
1764                 <div class="palm-header-spacer strut"></div>\r
1765         </div>\r
1766         \r
1767 -       <div id="launcher-main">\r
1768 -               <div id="launcher_root" x-mojo-element="Scroller">\r
1769 -                       <div id="pages_container"></div>\r
1770 +       <div id="launcher-main" class="view">
1771 +               <div id="page_header" style="display: none;" class="palm-header center" x-mojo-touch-feedback="immediate">
1772 +                       <div id="page_name" style="display: block;">Launcher Page</div>
1773 +                       <div id="page_text" style="display: none;" x-mojo-element="TextField"></div>
1774 +               </div>
1775 +               <div id="launcher_root" class="grid_small" x-mojo-element="Scroller">\r
1776 +                       <div id="pages_container" class="icons_large"></div>\r
1777                 </div>\r
1778                 <div id="page_indicators"></div>\r
1779         </div>\r
1780 --- .orig/usr/lib/luna/system/luna-applauncher/app/controllers/app-info-assistant.js
1781 +++ /usr/lib/luna/system/luna-applauncher/app/controllers/app-info-assistant.js
1782 @@ -7,7 +7,12 @@
1783                 this.isDynamic = this.isDynamicLaunchPoint(this.appInfo);
1784                 this.closeCallback = closeCallback;
1785  
1786 -               this.onDone = this.onDone.bind(this);
1787 +               this.action = "";
1788 +
1789 +               this.onRename = this.onDone.bind(this, "rename");
1790 +               this.onHide = this.onDone.bind(this, "hide");
1791 +               this.onMove = this.onDone.bind(this, "move");
1792 +               this.onDone = this.onDone.bind(this, "done");
1793         },
1794         
1795         setup: function(widget) {
1796 @@ -86,7 +91,9 @@
1797         
1798         setupButtons: function() {
1799                 
1800 -               var doneModel = {buttonLabel: $L('Done')}
1801 +               var renameModel = {buttonLabel: $L('Rename')}
1802 +               var hideModel = {buttonLabel: $L('Hide')}
1803 +               var moveModel = {buttonLabel: $L('Move')}               
1804                 
1805                 if (this.appInfo.removable) {
1806                         
1807 @@ -97,19 +104,33 @@
1808                                 disabled: false
1809                         };
1810                         
1811 +                       if(this.isDynamic) 
1812 +                               this.sceneController.get('hide-btn').hide();
1813 +                       
1814                         this.sceneController.setupWidget('delete-btn', {type: Mojo.Widget.activityButton}, this.deleteModel);
1815                         this.sceneController.listen('delete-btn', Mojo.Event.tap, this.onDelete.bindAsEventListener(this));
1816                         this.sceneController.get('delete-btn').show();
1817 -                       
1818 -                       // done button
1819 -                       doneModel.buttonClass = 'dismiss';
1820 -                       
1821 +
1822 +                       // rename button
1823 +                       renameModel.buttonClass = 'dismiss';
1824 +
1825 +                       // hide button
1826 +                       hideModel.buttonClass = 'dismiss';
1827 +
1828 +                       // mode button
1829 +                       moveModel.buttonClass = 'dismiss';
1830                 } else {
1831                         this.sceneController.get('delete-btn').hide();
1832                 }
1833 +
1834 +               this.sceneController.setupWidget('rename-btn', undefined, renameModel);
1835 +               this.sceneController.listen('rename-btn', Mojo.Event.tap, this.onRename);
1836 +
1837 +               this.sceneController.setupWidget('hide-btn', undefined, hideModel);
1838 +               this.sceneController.listen('hide-btn', Mojo.Event.tap, this.onHide);
1839                 
1840 -               this.sceneController.setupWidget('done-btn', undefined, doneModel);
1841 -               this.sceneController.listen('done-btn', Mojo.Event.tap, this.onDone);
1842 +               this.sceneController.setupWidget('move-btn', undefined, moveModel);
1843 +               this.sceneController.listen('move-btn', Mojo.Event.tap, this.onMove);
1844         },
1845  
1846         isDynamicLaunchPoint: function(appInfo) {
1847 @@ -136,7 +157,9 @@
1848                 }
1849         },
1850  
1851 -       onDone: function() {
1852 +       onDone: function(action) {
1853 +               this.action = action;
1854 +               
1855                 var deleteBtn = this.sceneController.get('delete-btn');
1856                 if (deleteBtn && deleteBtn.mojo && deleteBtn.mojo.deactivate) {
1857                         deleteBtn.mojo.deactivate();
1858 @@ -163,6 +186,6 @@
1859                         this.appSizeRequest.cancel();
1860                         this.appSizeRequest = undefined;
1861                 }
1862 -               this.closeCallback();
1863 +               this.closeCallback(this.action);
1864         }
1865  });
1866 --- .orig/usr/lib/luna/system/luna-applauncher/app/views/launcher/dialogs/app-info.html
1867 +++ /usr/lib/luna/system/luna-applauncher/app/views/launcher/dialogs/app-info.html
1868 @@ -9,5 +9,7 @@
1869  <div class="palm-dialog-separator"></div>
1870  <div class="palm-dialog-buttons">
1871         <div id='delete-btn' x-mojo-element="Button"></div>     
1872 -       <div id='done-btn' x-mojo-element="Button"></div>
1873 +       <div id='rename-btn' x-mojo-element="Button"></div>
1874 +       <div id='hide-btn' x-mojo-element="Button"></div>
1875 +       <div id='move-btn' x-mojo-element="Button"></div>
1876  </div>
1877 --- .orig/usr/lib/luna/system/luna-applauncher/app/models/launcher-pages.js
1878 +++ /usr/lib/luna/system/luna-applauncher/app/models/launcher-pages.js
1879 @@ -4,7 +4,7 @@
1880  var LauncherPages = Class.create({
1881         kDepotOptions: {version: 1, name: 'paged_launcher_apps'},
1882         kDepotDataKey: "Pages",
1883 -       kMaxPages: 10,
1884 +       kMaxPages: 16,
1885         
1886         initialize: function(callbacks) {
1887                 
1888 @@ -240,6 +240,12 @@
1889                 return true;
1890         },
1891         
1892 +       switchPages: function(firstIndex, secondIndex) {
1893 +               var page = this._storedPages.splice(firstIndex, 1);
1894 +
1895 +               this._storedPages.splice(secondIndex, 0, page[0]);
1896 +       },
1897 +       
1898         getNumPages: function() {
1899                 return this._storedPages.length;
1900         },
1901 --- .orig/usr/lib/luna/system/luna-applauncher/stylesheets/launcher.css