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