Advertisement
Br3tt

JSSB debug 1

Sep 27th, 2015
407
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==PREPROCESSOR==
  2. // @name "JS Smooth Browser"
  3. // @version "20150927-1450-101"
  4. // @author "Br3tt aka Falstaff >> http://br3tt.deviantart.com"
  5. // @feature "v1.4"
  6. // @feature "watch-metadb"
  7. // @import "%fb2k_profile_path%wsh_br3tt\jssb\js\WSHcommon.js"
  8. // @import "%fb2k_profile_path%wsh_br3tt\jssb\js\WSHinputbox.js"
  9. // ==/PREPROCESSOR==
  10.  
  11. images = {
  12.     path: fb.ProfilePath+"\\wsh_br3tt\\jssb\\images\\",
  13.     glass_reflect: null,
  14.     loading_angle: 0,
  15.     loading_draw: null
  16. };
  17.  
  18. ppt = {
  19.     sourceMode: window.GetProperty("_PROPERTY: Source Mode", 0), // 0 = Library, 1 = Playlist
  20.     tagMode: window.GetProperty("_PROPERTY: Tag Mode", 1), // 1 = album, 2 = artist, 3 = genre
  21.     albumArtId: 0, // 0 = front
  22.     panelMode: window.GetProperty("_PROPERTY: Display Mode", 1), // 0 = text, 1 = stamps + text, 2 = lines + text, 3 = stamps no text
  23.     albumsTFsorting: window.GetProperty("Sort Order - ALBUM", "%album artist% | %album% | %date% | %discnumber% | %tracknumber% | %title%"),
  24.     artistsTFsorting: window.GetProperty("Sort Order - ARTIST", "%artist% | %album% | %date% | %discnumber% | %tracknumber% | %title%"),
  25.     genresTFsorting: window.GetProperty("Sort Order - GENRE", "%genre% | %album artist% | %album% | %date% | %discnumber% | %tracknumber% | %title%"),
  26.     showAllItem: window.GetProperty("_PROPERTY: Show ALL item", true),
  27.     lineHeightMin: window.GetProperty("SYSTEM Minimal Line Height", 90),
  28.     thumbnailWidthMin: window.GetProperty("SYSTEM thumbnails Minimal Width", 130),
  29.     scrollRowDivider: window.GetProperty("SYSTEM Scroll Row Divider", 1),
  30.     tf_groupkey_genre: fb.TitleFormat("%genre% ## %album artist% ^^ %album% ^^ %discnumber% ^^ %artist% ^^ %title% ^^ %date%"),
  31.     tf_groupkey_artist: fb.TitleFormat("%artist% ## %album artist% ^^ %album% ^^ %discnumber% ^^ %title% ^^ %genre% ^^ %date%"),
  32.     tf_groupkey_album: fb.TitleFormat("%album artist% ^^ %album% ## %discnumber% ^^ %artist% ^^ %title% ^^ %genre% ^^ %date%"),
  33.     tf_path: fb.TitleFormat("$directory_path(%path%)\\"),
  34.     tf_path_artist: fb.TitleFormat(window.GetProperty("_PROPERTY: Artist Images Folder", "X:\\XPS2720\\MP3\\artists\\%artist%.jpg")),
  35.     tf_path_genre: fb.TitleFormat(images.path+"genres\\%genre%.jpg"),
  36.     tf_crc: fb.TitleFormat("$crc32(%path%)"),
  37.     tf_crc_artist: fb.TitleFormat("$crc32('artists'%artist%)"),
  38.     tf_crc_genre: fb.TitleFormat("$crc32('genres'%genre%)"),
  39.     tf_time_remaining: fb.TitleFormat("$if(%length%,-%playback_time_remaining%,'0:00')"),
  40.     rowHeight: 22,
  41.     rowScrollStep: 1,
  42.     scrollSmoothness: 2.5,
  43.     refreshRate: 40,
  44.     refreshRateCover: 2,
  45.     showHeaderBar: window.GetProperty("_DISPLAY: Show Top Bar", true),
  46.     defaultHeaderBarHeight: 26,
  47.     headerBarHeight: 26,
  48.     enableCustomColors: window.GetProperty("_PROPERTY: Custom Colors", false),
  49.     showwallpaper: window.GetProperty("_DISPLAY: Show Wallpaper", false),
  50.     wallpaperalpha: 150,
  51.     wallpaperblurred: window.GetProperty("_DISPLAY: Wallpaper Blurred", true),
  52.     wallpaperblurvalue: 1.05,
  53.     wallpapermode: window.GetProperty("_SYSTEM: Wallpaper Mode", 0),
  54.     wallpaperpath: window.GetProperty("_PROPERTY: Default Wallpaper Path", ".\\wsh_br3tt\\jssb\\images\\default.png"),
  55.     extra_font_size: window.GetProperty("_SYSTEM: Extra font size value", 0),
  56.     enableTouchControl: window.GetProperty("_PROPERTY: Enable Scroll Touch Control", true)
  57. };
  58.  
  59. cTouch = {
  60.     down: false,
  61.     y_start: 0,
  62.     y_end: 0,
  63.     y_current: 0,
  64.     y_prev: 0,
  65.     y_move: 0,
  66.     scroll_delta: 0,
  67.     t1: null,
  68.     timer: false,
  69.     multiplier: 0,
  70.     delta: 0
  71. };
  72.  
  73. cSettings = {
  74.     visible: false
  75. };
  76.  
  77. cFilterBox = {
  78.     enabled: window.GetProperty("_PROPERTY: Enable Playlist Filter", true),
  79.     default_w: 120,
  80.     default_h: 20,
  81.     w: 120,
  82.     h: 20
  83. };
  84.  
  85. cScrollBar = {
  86.     enabled: window.GetProperty("_DISPLAY: Show Scrollbar", true),
  87.     visible: true,
  88.     themed: false,
  89.     defaultWidth: get_system_scrollbar_width(),
  90.     width: get_system_scrollbar_width(),
  91.     ButtonType: {cursor: 0, up: 1, down: 2},
  92.     defaultMinCursorHeight: 20,
  93.     minCursorHeight: 20,
  94.     timerID: false,
  95.     timerCounter: -1
  96. };
  97.  
  98. cover = {
  99.     draw_glass_reflect: false,
  100.     keepaspectratio: true,
  101.     max_w: 0
  102. };
  103.  
  104. timers = {
  105.     coverLoad: false,
  106.     coverDone: false,
  107.     mouseWheel: false,
  108.     saveCover: false,
  109.     mouseDown: false,
  110.     addItems: false,
  111.     showMenu: false
  112. };
  113.  
  114. /*
  115. ===================================================================================================
  116.     Images cache
  117. ===================================================================================================
  118. */
  119. function reset_cover_timers() {
  120.     if(timers.coverDone) {
  121.         timers.coverDone && window.ClearTimeout(timers.coverDone);
  122.         timers.coverDone = false;
  123.     };
  124. };
  125.  
  126. function on_load_image_done(tid, image){
  127.     var tot = brw.groups.length;
  128.     for(var k = 0; k < tot; k++) {
  129.         if(brw.groups[k].metadb) {
  130.             if(brw.groups[k].tid == tid && brw.groups[k].load_requested == 1) {
  131.                 brw.groups[k].load_requested = 2;
  132.                 brw.groups[k].cover_img = g_image_cache.getit(brw.groups[k].metadb, k, image);
  133.                 if(!isScrolling && !cScrollBar.timerID) {
  134.                     if(k < brw.groups.length && k >= g_start_ && k <= g_end_) {
  135.                         if(!timers.coverDone) {
  136.                             timers.coverDone = window.SetTimeout(function() {
  137.                                 g_1x1 = false;
  138.                                 brw.cover_repaint();
  139.                                 timers.coverDone && window.ClearTimeout(timers.coverDone);
  140.                                 timers.coverDone = false;
  141.                             }, 1);
  142.                         };
  143.                     }; else {
  144.                         if(!timers.coverDone) {
  145.                             timers.coverDone = window.SetTimeout(function() {
  146.                                 g_1x1 = true;
  147.                                 window.RepaintRect(0, 0, 1, 1);
  148.                                 g_1x1 = false;
  149.                                 timers.coverDone && window.ClearTimeout(timers.coverDone);
  150.                                 timers.coverDone = false;
  151.                             }, 1);
  152.                         };
  153.                     };
  154.                 };
  155.                 break;
  156.             };
  157.         };
  158.     };
  159. };
  160.  
  161. function on_get_album_art_done(metadb, art_id, image, image_path) {
  162.     var tot = brw.groups.length;
  163.     if(ppt.albumArtId != 0) {
  164.         for(var i = 0; i < tot; i++) {
  165.             if(brw.groups[i].metadb) {
  166.                 if(brw.groups[i].metadb.Compare(metadb)) {
  167.                     brw.groups[i].cover_img = g_image_cache.getit(metadb, i, image);
  168.                     if(!isScrolling && !cScrollBar.timerID) {
  169.                         if(i < brw.groups.length && i >= g_start_ && i <= g_end_) {
  170.                             if(!timers.coverDone) {
  171.                                 timers.coverDone = window.SetTimeout(function() {
  172.                                     g_1x1 = false;
  173.                                     brw.cover_repaint();
  174.                                     timers.coverDone && window.ClearTimeout(timers.coverDone);
  175.                                     timers.coverDone = false;
  176.                                 }, 5);
  177.                             };
  178.                         }; else {
  179.                             g_1x1 = true;
  180.                             window.RepaintRect(0, 0, 1, 1);
  181.                             g_1x1 = false;
  182.                         };
  183.                     };
  184.                     break;
  185.                 };
  186.             };
  187.         };
  188.     }; else {
  189.         var i = art_id - 5;
  190.         g_last = i;
  191.         if(i < tot) {
  192.             if(brw.groups[i].metadb) {
  193.                 brw.groups[i].cover_img = g_image_cache.getit(metadb, i, image);
  194.                 if(!isScrolling && !cScrollBar.timerID) {
  195.                     if(i < brw.groups.length && i >= g_start_ && i <= g_end_) {
  196.                         if(!timers.coverDone) {
  197.                             timers.coverDone = window.SetTimeout(function() {
  198.                                 g_1x1 = false;
  199.                                 brw.cover_repaint();
  200.                                 timers.coverDone && window.ClearTimeout(timers.coverDone);
  201.                                 timers.coverDone = false;
  202.                             }, 5);
  203.                         };
  204.                     }; else {
  205.                         g_1x1 = true;
  206.                         window.RepaintRect(0, 0, 1, 1);
  207.                         g_1x1 = false;
  208.                     };
  209.                 };
  210.             };
  211.         };
  212.     };
  213. };
  214.  
  215. //=================================================// Cover Tools
  216. image_cache = function () {
  217.     this._cachelist = {};
  218.     this.hit = function (metadb, albumIndex) {
  219.         var img = this._cachelist[brw.groups[albumIndex].cachekey];
  220.         if (typeof(img) == "undefined" || img == null) { // if image not in cache, we load it asynchronously
  221.             //if(!isScrolling  && !cScrollBar.timerID) { // and when no scrolling
  222.                 brw.groups[albumIndex].crc = check_cache(metadb, albumIndex);
  223.                 if(brw.groups[albumIndex].crc && brw.groups[albumIndex].load_requested == 0) {
  224.                     // load img from cache
  225.                     if(!timers.coverLoad) {
  226.                         if(!isScrolling  && !cScrollBar.timerID) {
  227.                             timers.coverLoad = window.SetTimeout(function() {
  228.                                 brw.groups[albumIndex].tid = load_image_from_cache(metadb, brw.groups[albumIndex].crc);
  229.                                 brw.groups[albumIndex].load_requested = 1;
  230.                                 timers.coverLoad && window.ClearTimeout(timers.coverLoad);
  231.                                 timers.coverLoad = false;
  232.                             }, 1);
  233.                         }; else {
  234.                             timers.coverLoad = window.SetTimeout(function() {
  235.                                 brw.groups[albumIndex].tid = load_image_from_cache(metadb, brw.groups[albumIndex].crc);
  236.                                 brw.groups[albumIndex].load_requested = 1;
  237.                                 timers.coverLoad && window.ClearTimeout(timers.coverLoad);
  238.                                 timers.coverLoad = false;
  239.                             }, 20);
  240.                         };
  241.                     };
  242.                 }; else if(brw.groups[albumIndex].load_requested == 0) {              
  243.                     // load img default method
  244.                     if(!timers.coverLoad) {
  245.                         timers.coverLoad = window.SetTimeout(function() {
  246.                             if(ppt.albumArtId==5) { // genre
  247.                                 var arr = brw.groups[albumIndex].groupkey.split(" ^^ ");
  248.                                 try {
  249.                                     var genre_img = gdi.Image(images.path + "genres\\" + arr[0] + ".jpg");
  250.                                 } catch(e) {
  251.                                     var genre_img = gdi.Image(images.path + "genres\\" + "default.jpg");
  252.                                 };
  253.                                 brw.groups[albumIndex].cover_img = g_image_cache.getit(metadb, albumIndex, genre_img);
  254.                                 brw.repaint();
  255.                             }; else {
  256.                                 this.albumArtId = ppt.albumArtId == 0 ? albumIndex + 5 : ppt.albumArtId;
  257.                                 utils.GetAlbumArtAsync(window.ID, metadb, this.albumArtId, true, false, false);
  258.                             };
  259.                             timers.coverLoad && window.ClearTimeout(timers.coverLoad);
  260.                             timers.coverLoad = false;
  261.                         }, (!isScrolling  && !cScrollBar.timerID ? 5 : 20));
  262.                     };
  263.                 };
  264.             //};
  265.         };
  266.         return img;
  267.     };
  268.     this.reset = function(key) {
  269.         this._cachelist[key] = null;
  270.     };
  271.     this.getit = function (metadb, albumId, image) {
  272.         var cw = cover.max_w;
  273.         var ch = cw;
  274.         var img;
  275.        
  276.         if(cover.keepaspectratio) {
  277.             if(!image) {
  278.                 var pw = cw;
  279.                 var ph = ch;
  280.             }; else {
  281.                 if(image.Height>=image.Width) {
  282.                     var ratio = image.Width / image.Height;
  283.                     var pw = cw * ratio;
  284.                     var ph = ch;
  285.                 }; else {
  286.                     var ratio = image.Height / image.Width;
  287.                     var pw = cw;
  288.                     var ph = ch * ratio;
  289.                 };
  290.             };
  291.         }; else {
  292.             var pw = cw;
  293.             var ph = ch;
  294.         };
  295.        
  296.         // cover.type : 0 = nocover, 1 = external cover, 2 = embedded cover, 3 = stream
  297.         if(brw.groups[albumId].tracktype != 3) {
  298.             if(metadb) {
  299.                 if(image) {
  300.                     img = FormatCover(image, pw, ph, cover.draw_glass_reflect, false);
  301.                     cover.type = 1;
  302.                 }; else {
  303.                     img = FormatNoCover(albumId, pw, ph, cover.draw_glass_reflect, false, ppt.albumArtId);
  304.                     cover.type = 0;
  305.                 };
  306.             };
  307.         }; else {
  308.             img = FormatNoCover(albumId, pw, ph, cover.draw_glass_reflect, false, ppt.albumArtId);
  309.             cover.type = 3;
  310.         };
  311.         this._cachelist[brw.groups[albumId].cachekey] = img;
  312.         // save img to cache
  313.         if(cover.type == 1 && !brw.groups[albumId].save_requested) {
  314.             if(!timers.saveCover) {
  315.                 brw.groups[albumId].save_requested = true;
  316.                 save_image_to_cache(metadb, albumId);
  317.                 timers.saveCover = window.SetTimeout(function() {
  318.                     window.ClearTimeout(timers.saveCover);
  319.                     timers.saveCover = false;
  320.                 }, 100);
  321.             };
  322.         };
  323.         return img;
  324.     };
  325. };
  326. var g_image_cache = new image_cache;
  327.  
  328. function FormatCover(image, w, h, reflect, rawBitmap) {
  329.     if(!image || w<=0 || h<=0) return image;
  330.     if(reflect) {
  331.         var new_img = image.Resize(w, h, 2);
  332.         var gb = new_img.GetGraphics();
  333.         if(h > w) {
  334.             gb.DrawImage(cover.glass_reflect, Math.floor((h-w)/2)*-1 + 1, 1, h - 2, h - 2, 0, 0, cover.glass_reflect.Width, cover.glass_reflect.Height, 0, 150);
  335.         }; else {
  336.             gb.DrawImage(cover.glass_reflect, 1, Math.floor((w-h)/2)*-1 + 1, w - 2, w - 2, 0, 0, cover.glass_reflect.Width, cover.glass_reflect.Height, 0, 150);
  337.         };
  338.         new_img.ReleaseGraphics(gb);
  339.         if(rawBitmap) {
  340.             return new_img.CreateRawBitmap();
  341.         }; else {
  342.             return new_img;
  343.         };
  344.     }; else {
  345.         if(rawBitmap) {
  346.             return image.Resize(w, h, 2).CreateRawBitmap();
  347.         }; else {
  348.             return image.Resize(w, h, 2);
  349.         };
  350.     };
  351. };
  352.  
  353. function FormatNoCover(albumId, w, h, reflect, rawBitmap, albumArtId) {
  354.     switch(ppt.tagMode) {
  355.         case 1:
  356.             var crc = ppt.tf_crc.EvalWithMetadb(brw.groups[albumId].metadb);
  357.             break;
  358.         case 2:
  359.             var crc = ppt.tf_crc_artist.EvalWithMetadb(brw.groups[albumId].metadb);
  360.             break;
  361.         case 3:
  362.             var crc = ppt.tf_crc_genre.EvalWithMetadb(brw.groups[albumId].metadb);
  363.             break;
  364.     }
  365.     var words = brw.groups[albumId].groupkey.split(" ");
  366.     if(words.length > 1) {
  367.         try {
  368.             var chr = words[0][0].toUpperCase()+words[1][0].toUpperCase();
  369.         }; catch(e) {
  370.             var chr = words[0][0]+words[1][0];
  371.         };
  372.     }; else {
  373.         if(brw.groups[albumId].groupkey.length > 1) {
  374.             try {
  375.                 var chr = words[0][0].toUpperCase()+words[0][1].toUpperCase();
  376.             }; catch(e) {
  377.                 var chr = words[0][0]+words[0][1];
  378.             };
  379.         }; else {
  380.             try {
  381.                 var chr = words[0][0].toUpperCase();
  382.             }; catch(e) {
  383.                 var chr = words[0][0];
  384.             };
  385.         };
  386.     };
  387.     var colors = Array(RGB(255,0,0), RGB(0,255,0), RGB(0,0,255), RGB(255,255,0), RGB(255,0,255), RGB(0,255,255));
  388.     var idx = crc % colors.length;
  389.    
  390.     var image = gdi.CreateImage(w, h);
  391.     var gb = image.GetGraphics();
  392.     // draw nocover image
  393.     gb.FillSolidRect(0, 0, w, h, RGB(255,255,255));
  394.     gb.FillGradRect(0, 0, w, h, 45, colors[idx] & 0x55ffffff, colors[idx] & 0x40ffffff, 0.5);
  395.     gb.SetTextRenderingHint(4);
  396.     switch(albumArtId) {
  397.         case 4: // artist
  398.             gb.SetSmoothingMode(2);
  399.             gb.FillEllipse(7, 2, w-14, h-14, RGBA(0,0,0,35));
  400.             gb.FillEllipse(-5, h-12, w+10, 45, RGBA(0,0,0,35));
  401.             gb.SetSmoothingMode(0);
  402.             gb.DrawString(chr, gdi.Font("Arial", Math.round(h/10*3.0), 1), RGBA(0,0,0,120), 3, 2, w-6, h-12, cc_stringformat);
  403.             break;
  404.         case 5: // genre
  405.             gb.SetSmoothingMode(2);
  406.             gb.FillEllipse(1, 1, w-2, h-2, RGBA(0,0,0,35));
  407.             gb.SetSmoothingMode(0);
  408.             gb.DrawString(brw.groups[albumId].groupkey.substr(0,5).toUpperCase(), gdi.Font("Arial", Math.round(h/10*2.0), 1), RGBA(0,0,0,120), 0, 0, w, h, cc_stringformat);
  409.             break;
  410.         default: // album + others
  411.             gb.SetSmoothingMode(2);
  412.             gb.FillEllipse(1, 1, w-2, h-2, RGBA(0,0,0,35));
  413.             gb.SetSmoothingMode(0);
  414.             gb.DrawString("NO COVER", gdi.Font("Arial", Math.round(h/10*2), 1), RGBA(0,0,0,120), 0, 0, w, h, cc_stringformat);
  415.     };
  416.     image.ReleaseGraphics(gb);
  417.  
  418.     if(reflect) {
  419.         var new_img = image.Resize(w, h, 2);
  420.         var gb = new_img.GetGraphics();
  421.         if(h > w) {
  422.             gb.DrawImage(cover.glass_reflect, Math.floor((h-w)/2)*-1 + 1, 1, h - 2, h - 2, 0, 0, cover.glass_reflect.Width, cover.glass_reflect.Height, 0, 150);
  423.         }; else {
  424.             gb.DrawImage(cover.glass_reflect, 1, Math.floor((w-h)/2)*-1 + 1, w - 2, w - 2, 0, 0, cover.glass_reflect.Width, cover.glass_reflect.Height, 0, 150);
  425.         };
  426.         new_img.ReleaseGraphics(gb);
  427.         if(rawBitmap) {
  428.             return new_img.CreateRawBitmap();
  429.         }; else {
  430.             return new_img;
  431.         };
  432.     }; else {
  433.         if(rawBitmap) {
  434.             return image.CreateRawBitmap();
  435.         }; else {
  436.             return image;
  437.         };
  438.     };
  439. };
  440.  
  441. /*
  442. ===================================================================================================
  443.     Objects
  444. ===================================================================================================
  445. */
  446. oFilterBox = function() {
  447.     this.images = {
  448.         filterIcon: gdi.Image(images.path+"mag.png"),
  449.         resetIcon_off: null,
  450.         resetIcon_ov: null
  451.     };
  452.    
  453.     this.getImages = function() {
  454.         var gb;
  455.         this.images.resetIcon_off = gdi.CreateImage(18, 18);
  456.         gb = this.images.resetIcon_off.GetGraphics();
  457.             gb.setSmoothingMode(2);
  458.             var xpts1 = Array(6,5, 13,12, 12,13, 5,6);
  459.             var xpts2 = Array(5,12, 12,5, 13,6, 6,13);
  460.             gb.FillPolygon(RGB(170,170,170), 0, xpts1);
  461.             gb.FillPolygon(RGB(170,170,170), 0, xpts2);
  462.             gb.DrawLine(6,6, 12, 12, 2.0, RGBA(255,255,255,180));
  463.             gb.DrawLine(6,12, 12, 6, 2.0, RGBA(255,255,255,180));
  464.             gb.setSmoothingMode(0);
  465.         this.images.resetIcon_off.ReleaseGraphics(gb);
  466.  
  467.         this.images.resetIcon_ov = gdi.CreateImage(18, 18);
  468.         gb = this.images.resetIcon_ov.GetGraphics();
  469.             gb.setSmoothingMode(2);
  470.             gb.DrawLine(4,4, 14, 14, 3.0, RGBA(255,255,255,240));
  471.             gb.DrawLine(4,14, 14, 4, 3.0, RGBA(255,255,255,240));
  472.             gb.setSmoothingMode(0);
  473.         this.images.resetIcon_ov.ReleaseGraphics(gb);
  474.  
  475.         this.images.resetIcon_dn = gdi.CreateImage(18, 18);
  476.         gb = this.images.resetIcon_dn.GetGraphics();
  477.             gb.setSmoothingMode(2);
  478.             gb.DrawLine(4, 4, 14, 14, 3.0, RGBA(255,50,50,255));
  479.             gb.DrawLine(4, 14, 14, 4, 3.0, RGBA(255,50,50,255));
  480.             gb.setSmoothingMode(0);
  481.         this.images.resetIcon_dn.ReleaseGraphics(gb);
  482.  
  483.         if(typeof(this.reset_bt) == "undefined") {
  484.             this.reset_bt = new button(this.images.resetIcon_off, this.images.resetIcon_ov, this.images.resetIcon_dn);
  485.         }; else {
  486.             this.reset_bt.img[0] = this.images.resetIcon_off;
  487.             this.reset_bt.img[1] = this.images.resetIcon_ov;
  488.             this.reset_bt.img[2] = this.images.resetIcon_dn;
  489.         };
  490.     };
  491.     this.getImages();
  492.    
  493.     this.on_init = function() {
  494.         this.inputbox = new oInputbox(cFilterBox.w, cFilterBox.h, "", "Library Filter", RGB(240,240,240), 0, 0, RGB(150, 170, 255), g_sendResponse, "brw");
  495.         this.inputbox.autovalidation = true;
  496.     };
  497.     this.on_init();
  498.    
  499.     this.draw = function(gr, x, y) {
  500.         var bx = x;
  501.         var by = y;
  502.         var bw = this.inputbox.w + 44;
  503.         //gr.FillSolidRect(bx-2, by, bw+2, 20, blendColors(g_color_normal_bg, RGB(255,255,255), 0.05));
  504.        
  505.         if(this.inputbox.edit) {
  506.             gr.SetSmoothingMode(2);
  507.             //gr.DrawRect(bx-3, by-1, bw+2, 21, 2.0, RGB(130,140,240));
  508.             gr.SetSmoothingMode(0);
  509.         }; else {
  510.             //gr.DrawRect(bx-3, by-1, bw+2, 21, 1.0, blendColors(g_color_normal_txt, g_color_normal_bg, 0.75));
  511.         };
  512.  
  513.         if(this.inputbox.text.length > 0) {
  514.             this.reset_bt.draw(gr, bx-1, by+1, 255);
  515.         }; else {
  516.             gr.DrawImage(this.images.filterIcon.Resize(cFilterBox.h-1,cFilterBox.h-1,2) , bx, by, cFilterBox.h-1, cFilterBox.h-1, 0, 0, cFilterBox.h-1, cFilterBox.h-1, 0, 255);
  517.         };
  518.         for(var i = 0; i < cFilterBox.h-2; i+=2) {
  519.             gr.FillSolidRect(bx+25+cFilterBox.w, by+2+i, 1, 1, RGB(100,100,100));
  520.         };
  521.         this.inputbox.draw(gr, bx+22, by, 0, 0);
  522.     };
  523.    
  524.     this.on_mouse = function(event, x, y, delta) {
  525.         switch(event) {
  526.             case "lbtn_down":
  527.                 this.inputbox.check("down", x, y);
  528.                 if(this.inputbox.text.length > 0) this.reset_bt.checkstate("down", x, y);
  529.                 break;
  530.             case "lbtn_up":
  531.                 this.inputbox.check("up", x, y);
  532.                 if(this.inputbox.text.length > 0) {
  533.                     if(this.reset_bt.checkstate("up", x, y) == ButtonStates.hover) {
  534.                         this.inputbox.text = "";
  535.                         this.inputbox.offset = 0;
  536.                         g_sendResponse();
  537.                     };
  538.                 };
  539.                 break;
  540.             case "lbtn_dblclk":
  541.                 this.inputbox.check("dblclk", x, y);
  542.                 break;
  543.             case "rbtn_down":
  544.                 this.inputbox.check("right", x, y);
  545.                 break;
  546.             case "move":
  547.                 this.inputbox.check("move", x, y);
  548.                 if(this.inputbox.text.length > 0) this.reset_bt.checkstate("move", x, y);
  549.                 break;
  550.         };
  551.     };
  552.    
  553.     this.on_key = function(event, vkey) {
  554.         switch(event) {
  555.             case "down":
  556.                 this.inputbox.on_key_down(vkey);
  557.                 break;
  558.         };
  559.     };
  560.    
  561.     this.on_char = function(code) {
  562.         this.inputbox.on_char(code);
  563.     };
  564.    
  565.     this.on_focus = function(is_focused) {
  566.         this.inputbox.on_focus(is_focused);
  567.     };
  568. };
  569.  
  570. oScrollbar = function(themed) {
  571.     this.themed = themed;
  572.     this.showButtons = true;
  573.     this.buttons = Array(null, null, null);
  574.     this.buttonType = {cursor: 0, up: 1, down: 2};
  575.     this.buttonClick = false;
  576.    
  577.     this.color_bg = g_color_normal_bg;
  578.     this.color_txt = g_color_normal_txt;
  579.    
  580.     if(this.themed) {
  581.         this.theme = window.CreateThemeManager("scrollbar");
  582.     }; else {
  583.         this.theme = false;
  584.     };
  585.    
  586.     this.setNewColors = function() {
  587.         this.color_bg = g_color_normal_bg;
  588.         this.color_txt = g_color_normal_txt;  
  589.         this.setButtons();
  590.         this.setCursorButton();
  591.     };
  592.  
  593.     this.setButtons = function() {
  594.         // normal scroll_up Image
  595.         // Draw Themed Scrollbar (lg/col)
  596.         if(this.themed) {
  597.             this.upImage_normal = gdi.CreateImage(this.w, this.w);
  598.             var gb = this.upImage_normal.GetGraphics();
  599.             try {
  600.                 this.theme.SetPartAndStateId(1, 1);
  601.                 this.theme.DrawThemeBackground(gb, 0, 0, this.w, this.w);
  602.             }; catch(e) {
  603.                 DrawPolyStar(gb, 4, 4, this.w-8, 1, 3, 0, RGB(0,0,0), blendColors(this.color_txt, this.color_bg, 0.5), 0, 255);
  604.             };
  605.         }; else {
  606.             this.upImage_normal = gdi.CreateImage(70, 70);
  607.             var gb = this.upImage_normal.GetGraphics();
  608.             DrawPolyStar(gb, 10, 16, 44, 1, 3, 0, RGB(0,0,0), blendColors(this.color_txt, this.color_bg, 0.5), 0, 255);
  609.         };
  610.         this.upImage_normal.ReleaseGraphics(gb);
  611.  
  612.         // hover scroll_up Image
  613.         // Draw Themed Scrollbar (lg/col)
  614.         if(this.themed) {
  615.             this.upImage_hover = gdi.CreateImage(this.w, this.w);
  616.             gb = this.upImage_hover.GetGraphics();
  617.             try {
  618.                 this.theme.SetPartAndStateId(1, 2);
  619.                 this.theme.DrawThemeBackground(gb, 0, 0, this.w, this.w);
  620.             }; catch(e) {
  621.                 DrawPolyStar(gb, 4, 4, this.w-8, 1, 3, 0, blendColors(this.color_txt, this.color_bg, 0.3), blendColors(this.color_txt, this.color_bg, 0.3), 0, 255);
  622.             };
  623.         }; else {
  624.             this.upImage_hover = gdi.CreateImage(70, 70);
  625.             var gb = this.upImage_hover.GetGraphics();
  626.             DrawPolyStar(gb, 10, 16, 44, 1, 3, 0, blendColors(this.color_txt, this.color_bg, 0.3), blendColors(this.color_txt, this.color_bg, 0.3), 0, 255);
  627.         };
  628.         this.upImage_hover.ReleaseGraphics(gb);
  629.  
  630.         // down scroll_up Image
  631.         // Draw Themed Scrollbar (lg/col)
  632.         if(this.themed) {
  633.             this.upImage_down = gdi.CreateImage(this.w, this.w);
  634.             gb = this.upImage_down.GetGraphics();
  635.             try {
  636.                 this.theme.SetPartAndStateId(1, 3);
  637.                 this.theme.DrawThemeBackground(gb, 0, 0, this.w, this.w);
  638.             }; catch(e) {
  639.                 DrawPolyStar(gb, 4, 4, this.w-8, 1, 3, 0, RGB(0,0,0), blendColors(this.color_txt, this.color_bg, 0.05), 0, 255);
  640.             };
  641.         }; else {
  642.             this.upImage_down = gdi.CreateImage(70, 70);
  643.             gb = this.upImage_down.GetGraphics();
  644.             DrawPolyStar(gb, 10, 13, 44, 1, 3, 0, RGB(0,0,0), blendColors(this.color_txt, this.color_bg, 0.05), 0, 255);
  645.         };
  646.         this.upImage_down.ReleaseGraphics(gb);
  647.  
  648.         // normal scroll_down Image
  649.         // Draw Themed Scrollbar (lg/col)
  650.         if(this.themed) {
  651.             this.downImage_normal = gdi.CreateImage(this.w, this.w);
  652.             gb = this.downImage_normal.GetGraphics();
  653.             try {
  654.                 this.theme.SetPartAndStateId(1, 5);
  655.                 this.theme.DrawThemeBackground(gb, 0, 0, this.w, this.w);
  656.             }; catch(e) {
  657.                 DrawPolyStar(gb, 4, 4, this.w-8, 1, 3, 0, RGB(0,0,0), blendColors(this.color_txt, this.color_bg, 0.5), 180, 255);
  658.             };
  659.         }; else {
  660.             this.downImage_normal = gdi.CreateImage(70, 70);
  661.             gb = this.downImage_normal.GetGraphics();
  662.             DrawPolyStar(gb, 10, 10, 44, 1, 3, 0, RGB(0,0,0), blendColors(this.color_txt, this.color_bg, 0.5), 180, 255);
  663.         };
  664.         this.downImage_normal.ReleaseGraphics(gb);
  665.  
  666.         // hover scroll_down Image
  667.         // Draw Themed Scrollbar (lg/col)
  668.         if(this.themed) {
  669.             this.downImage_hover = gdi.CreateImage(this.w, this.w);
  670.             gb = this.downImage_hover.GetGraphics();
  671.             try {
  672.                 this.theme.SetPartAndStateId(1, 6);
  673.                 this.theme.DrawThemeBackground(gb, 0, 0, this.w, this.w);
  674.             }; catch(e) {
  675.                 DrawPolyStar(gb, 4, 4, this.w-8, 1, 3, 1, blendColors(this.color_txt, this.color_bg, 0.3), blendColors(this.color_txt, this.color_bg, 0.3), 180, 255);
  676.             };
  677.         }; else {
  678.             this.downImage_hover = gdi.CreateImage(70, 70);
  679.             gb = this.downImage_hover.GetGraphics();
  680.             DrawPolyStar(gb, 10, 10, 44, 1, 3, 1, blendColors(this.color_txt, this.color_bg, 0.3), blendColors(this.color_txt, this.color_bg, 0.3), 180, 255);
  681.         };
  682.         this.downImage_hover.ReleaseGraphics(gb);
  683.  
  684.         // down scroll_down Image
  685.         // Draw Themed Scrollbar (lg/col)
  686.         if(this.themed) {
  687.             this.downImage_down = gdi.CreateImage(this.w, this.w);
  688.             gb = this.downImage_down.GetGraphics();
  689.             try {
  690.                 this.theme.SetPartAndStateId(1, 7);
  691.                 this.theme.DrawThemeBackground(gb, 0, 0, this.w, this.w);
  692.             }; catch(e) {
  693.                 DrawPolyStar(gb, 4, 4, this.w-8, 1, 3, 0, RGB(0,0,0), blendColors(this.color_txt, this.color_bg, 0.05), 180, 255);
  694.             };
  695.         }; else {
  696.             this.downImage_down = gdi.CreateImage(70, 70);
  697.             gb = this.downImage_down.GetGraphics();
  698.             DrawPolyStar(gb, 10, 13, 44, 1, 3, 0, RGB(0,0,0), blendColors(this.color_txt, this.color_bg, 0.05), 180, 255);
  699.         };
  700.         this.downImage_down.ReleaseGraphics(gb);
  701.        
  702.         for(i = 1; i < this.buttons.length; i++) {
  703.             switch(i) {
  704.             case this.buttonType.cursor:
  705.                 this.buttons[this.buttonType.cursor] = new button(this.cursorImage_normal, this.cursorImage_hover, this.cursorImage_down);
  706.                 break;
  707.             case this.buttonType.up:
  708.                 this.buttons[this.buttonType.up] = new button(this.upImage_normal.Resize(this.w,this.w,2), this.upImage_hover.Resize(this.w,this.w,2), this.upImage_down.Resize(this.w,this.w,2));
  709.                 break;
  710.             case this.buttonType.down:
  711.                 this.buttons[this.buttonType.down] = new button(this.downImage_normal.Resize(this.w,this.w,2), this.downImage_hover.Resize(this.w,this.w,2), this.downImage_down.Resize(this.w,this.w,2));
  712.                 break;
  713.             };
  714.         };
  715.     };
  716.  
  717.     this.setCursorButton = function() {
  718.         // normal cursor Image
  719.         this.cursorImage_normal = gdi.CreateImage(this.cursorw, this.cursorh);
  720.         var gb = this.cursorImage_normal.GetGraphics();
  721.         // Draw Themed Scrollbar (lg/col)
  722.         if(this.themed) {
  723.             try {
  724.                 this.theme.SetPartAndStateId(3, 1);
  725.                 this.theme.DrawThemeBackground(gb, 0, 0, this.cursorw, this.cursorh);
  726.                 if(this.cursorh >= 30) {
  727.                     this.theme.SetPartAndStateId(9, 1);
  728.                     this.theme.DrawThemeBackground(gb, 0, 0, this.cursorw, this.cursorh);
  729.                 };
  730.             }; catch(e) {
  731.                 gb.FillSolidRect(1, 0, this.cursorw-2, this.cursorh, blendColors(this.color_txt, this.color_bg, 0.5));
  732.             };
  733.         }; else {
  734.             gb.FillSolidRect(1, 0, this.cursorw-2, this.cursorh, blendColors(this.color_txt, this.color_bg, 0.5));
  735.         };
  736.         this.cursorImage_normal.ReleaseGraphics(gb);
  737.        
  738.         // hover cursor Image
  739.         this.cursorImage_hover = gdi.CreateImage(this.cursorw, this.cursorh);
  740.         gb = this.cursorImage_hover.GetGraphics();
  741.         // Draw Themed Scrollbar (lg/col)
  742.         if(this.themed) {
  743.             try {
  744.                 this.theme.SetPartAndStateId(3, 2);
  745.                 this.theme.DrawThemeBackground(gb, 0, 0, this.cursorw, this.cursorh);
  746.                 if(this.cursorh >= 30) {
  747.                     this.theme.SetPartAndStateId(9, 2);
  748.                     this.theme.DrawThemeBackground(gb, 0, 0, this.cursorw, this.cursorh);
  749.                 };
  750.             }; catch(e) {
  751.                 gb.FillSolidRect(1, 0, this.cursorw-2, this.cursorh, blendColors(this.color_txt, this.color_bg, 0.3));
  752.             };
  753.         }; else {
  754.             gb.FillSolidRect(1, 0, this.cursorw-2, this.cursorh, blendColors(this.color_txt, this.color_bg, 0.3));
  755.         };
  756.         this.cursorImage_hover.ReleaseGraphics(gb);
  757.        
  758.         // down cursor Image
  759.         this.cursorImage_down = gdi.CreateImage(this.cursorw, this.cursorh);
  760.         gb = this.cursorImage_down.GetGraphics();
  761.         // Draw Themed Scrollbar (lg/col)
  762.         if(this.themed) {
  763.             try {
  764.                 this.theme.SetPartAndStateId(3, 3);
  765.                 this.theme.DrawThemeBackground(gb, 0, 0, this.cursorw, this.cursorh);
  766.                 if(this.cursorh >= 30) {
  767.                     this.theme.SetPartAndStateId(9, 3);
  768.                     this.theme.DrawThemeBackground(gb, 0, 0, this.cursorw, this.cursorh);
  769.                 };
  770.             }; catch(e) {
  771.                 gb.FillSolidRect(1, 0, this.cursorw-2, this.cursorh, blendColors(this.color_txt, this.color_bg, 0.05));
  772.             };
  773.         }; else {
  774.             gb.FillSolidRect(1, 0, this.cursorw-2, this.cursorh, blendColors(this.color_txt, this.color_bg, 0.05));
  775.         };
  776.         this.cursorImage_down.ReleaseGraphics(gb);
  777.        
  778.         // create/refresh cursor Button in buttons array
  779.         this.buttons[this.buttonType.cursor] = new button(this.cursorImage_normal, this.cursorImage_hover, this.cursorImage_down);
  780.         this.buttons[this.buttonType.cursor].x = this.x;
  781.         this.buttons[this.buttonType.cursor].y = this.cursory;
  782.     };
  783.    
  784.     this.draw = function(gr) {
  785.         // scrollbar background
  786.         if(this.themed) {
  787.             try {
  788.                 this.theme.SetPartAndStateId(6, 1);
  789.                 this.theme.DrawThemeBackground(gr, this.x, this.y, this.w, this.h);
  790.             }; catch(e) {
  791.                 gr.FillSolidRect(this.x, this.y, this.w, this.h, this.color_bg & 0x25ffffff);
  792.                 gr.FillSolidRect(this.x, this.y, 1, this.h, this.color_txt & 0x05ffffff);
  793.             };
  794.         }; else {
  795.             gr.FillSolidRect(this.x, this.y, this.w, this.h, this.color_bg & 0x25ffffff);
  796.             gr.FillSolidRect(this.x, this.y, 1, this.h, this.color_txt & 0x05ffffff);
  797.         };
  798.         // scrollbar buttons
  799.         if(cScrollBar.visible) this.buttons[this.buttonType.cursor].draw(gr, this.x, this.cursory, 200);
  800.         if(this.showButtons) {
  801.             this.buttons[this.buttonType.up].draw(gr, this.x, this.y, 200);
  802.             this.buttons[this.buttonType.down].draw(gr, this.x, this.areay + this.areah, 200);
  803.         };
  804.     };
  805.        
  806.     this.updateScrollbar = function() {
  807.         var prev_cursorh = this.cursorh;
  808.         this.total = brw.rowsCount;
  809.         this.rowh = ppt.rowHeight;
  810.         this.totalh = this.total * this.rowh;
  811.         // set scrollbar visibility
  812.         cScrollBar.visible = (this.totalh > brw.h);
  813.         // set cursor width/height
  814.         this.cursorw = this.w;
  815.         if(this.total > 0) {
  816.             this.cursorh = Math.round((brw.h / this.totalh) * this.areah);
  817.             if(this.cursorh < cScrollBar.minCursorHeight) this.cursorh = cScrollBar.minCursorHeight;
  818.         }; else {
  819.             this.cursorh = cScrollBar.minCursorHeight;
  820.         };
  821.         // set cursor y pos
  822.         this.setCursorY();
  823.         if(this.cursorh != prev_cursorh) this.setCursorButton();
  824.     };
  825.    
  826.     this.setCursorY = function() {
  827.         // set cursor y pos
  828.         var ratio = scroll / (this.totalh - brw.h);
  829.         this.cursory = this.areay + Math.round((this.areah - this.cursorh) * ratio);
  830.     };
  831.    
  832.     this.setSize = function() {
  833.         this.buttonh = cScrollBar.width;
  834.         this.x = brw.x + brw.w;
  835.         this.y = brw.y - ppt.headerBarHeight*0;
  836.         this.w = cScrollBar.width;
  837.         this.h = brw.h + ppt.headerBarHeight*0;
  838.         if(this.showButtons) {
  839.             this.areay = this.y + this.buttonh;
  840.             this.areah = this.h - (this.buttonh * 2);
  841.         }; else {
  842.             this.areay = this.y;
  843.             this.areah = this.h;
  844.         };
  845.         this.setButtons();
  846.     };
  847.    
  848.     this.setScrollFromCursorPos = function() {
  849.         // calc ratio of the scroll cursor to calc the equivalent item for the full list (with gh)
  850.         var ratio = (this.cursory - this.areay) / (this.areah - this.cursorh);
  851.         // calc idx of the item (of the full list with gh) to display at top of the panel list (visible)
  852.         scroll = Math.round((this.totalh - brw.h) * ratio);
  853.     };
  854.  
  855.     this.cursorCheck = function(event, x, y) {
  856.         if(!this.buttons[this.buttonType.cursor]) return;
  857.         switch(event) {
  858.         case "down":
  859.             var tmp = this.buttons[this.buttonType.cursor].checkstate(event, x, y);
  860.             if(tmp == ButtonStates.down) {
  861.                 this.cursorClickX = x;
  862.                 this.cursorClickY = y;
  863.                 this.cursorDrag = true;
  864.                 this.cursorDragDelta = y - this.cursory;
  865.             };
  866.             break;
  867.         case "up":
  868.             this.buttons[this.buttonType.cursor].checkstate(event, x, y);
  869.             if(this.cursorDrag) {
  870.                 this.setScrollFromCursorPos();
  871.                 brw.repaint();
  872.             };
  873.             this.cursorClickX = 0;
  874.             this.cursorClickY = 0;
  875.             this.cursorDrag = false;
  876.             break;
  877.         case "move":
  878.             this.buttons[this.buttonType.cursor].checkstate(event, x, y);
  879.             if(this.cursorDrag) {
  880.                 this.cursory = y - this.cursorDragDelta;
  881.                 if(this.cursory + this.cursorh > this.areay + this.areah) {
  882.                     this.cursory = (this.areay + this.areah) - this.cursorh;
  883.                 };
  884.                 if(this.cursory < this.areay) {
  885.                     this.cursory = this.areay;
  886.                 };
  887.                 this.setScrollFromCursorPos();
  888.                 brw.repaint();
  889.             };
  890.             break;
  891.         case "leave":
  892.             this.buttons[this.buttonType.cursor].checkstate(event, 0, 0);
  893.             break;
  894.         };
  895.     };
  896.    
  897.     this._isHover = function(x, y) {
  898.         return (x >= this.x && x <= this.x + this.w && y >= this.y && y <= this.y + this.h);
  899.     };
  900.  
  901.     this._isHoverArea = function(x, y) {
  902.         return (x >= this.x && x <= this.x + this.w && y >= this.areay && y <= this.areay + this.areah);
  903.     };
  904.  
  905.     this._isHoverCursor = function(x, y) {
  906.         return (x >= this.x && x <= this.x + this.w && y >= this.cursory && y <= this.cursory + this.cursorh);
  907.     };
  908.  
  909.     this.on_mouse = function(event, x, y, delta) {
  910.         this.isHover = this._isHover(x, y);
  911.         this.isHoverArea = this._isHoverArea(x, y);
  912.         this.isHoverCursor = this._isHoverCursor(x, y);
  913.         this.isHoverButtons = this.isHover && !this.isHoverCursor && !this.isHoverArea;
  914.         this.isHoverEmptyArea = this.isHoverArea && !this.isHoverCursor;
  915.        
  916.         var scroll_step = ppt.rowHeight;
  917.         var scroll_step_page = brw.h;
  918.  
  919.         switch(event) {
  920.             case "down":
  921.             case "dblclk":
  922.                 if((this.isHoverCursor || this.cursorDrag) && !this.buttonClick && !this.isHoverEmptyArea) {
  923.                     this.cursorCheck(event, x, y);
  924.                 }; else {
  925.                     // buttons events
  926.                     var bt_state = ButtonStates.normal;
  927.                     for(var i = 1; i < 3; i++) {
  928.                         switch(i) {
  929.                             case 1: // up button
  930.                                 bt_state = this.buttons[i].checkstate(event, x, y);
  931.                                 if((event == "down" && bt_state == ButtonStates.down) || (event == "dblclk" && bt_state == ButtonStates.hover)) {
  932.                                     this.buttonClick = true;
  933.                                     scroll = scroll - scroll_step;
  934.                                     scroll = check_scroll(scroll);
  935.                                     if(!cScrollBar.timerID) {
  936.                                         cScrollBar.timerID = window.SetInterval(function() {
  937.                                             if(cScrollBar.timerCounter > 6) {
  938.                                                 scroll = scroll - scroll_step;
  939.                                                 scroll = check_scroll(scroll);
  940.                                             }; else {
  941.                                                 cScrollBar.timerCounter++;
  942.                                             };
  943.                                         }, 80);
  944.                                     };
  945.                                 };
  946.                                 break;
  947.                             case 2: // down button
  948.                                 bt_state = this.buttons[i].checkstate(event, x, y);
  949.                                 if((event == "down" && bt_state == ButtonStates.down) || (event == "dblclk" && bt_state == ButtonStates.hover)) {
  950.                                     this.buttonClick = true;
  951.                                     scroll = scroll + scroll_step;
  952.                                     scroll = check_scroll(scroll);
  953.                                     if(!cScrollBar.timerID) {
  954.                                         cScrollBar.timerID = window.SetInterval(function() {
  955.                                             if(cScrollBar.timerCounter > 6) {
  956.                                                 scroll = scroll + scroll_step;
  957.                                                 scroll = check_scroll(scroll);
  958.                                             }; else {
  959.                                                 cScrollBar.timerCounter++;
  960.                                             };
  961.                                         }, 80);
  962.                                     };
  963.                                 };
  964.                                 break;
  965.                         };
  966.                     };
  967.                     if(!this.buttonClick && this.isHoverEmptyArea) {
  968.                         // check click on empty area scrollbar
  969.                         if(y < this.cursory) {
  970.                             // up
  971.                             this.buttonClick = true;
  972.                             scroll = scroll - scroll_step_page;
  973.                             scroll = check_scroll(scroll);
  974.                             if(!cScrollBar.timerID) {
  975.                                 cScrollBar.timerID = window.SetInterval(function() {
  976.                                     if(cScrollBar.timerCounter > 6 && m_y < brw.scrollbar.cursory) {
  977.                                         scroll = scroll - scroll_step_page;
  978.                                         scroll = check_scroll(scroll);
  979.                                     }; else {
  980.                                         cScrollBar.timerCounter++;
  981.                                     };
  982.                                 }, 80);
  983.                             };
  984.                         }; else {
  985.                             // down
  986.                             this.buttonClick = true;
  987.                             scroll = scroll + scroll_step_page;
  988.                             scroll = check_scroll(scroll);
  989.                             if(!cScrollBar.timerID) {
  990.                                 cScrollBar.timerID = window.SetInterval(function() {
  991.                                     if(cScrollBar.timerCounter > 6 && m_y > brw.scrollbar.cursory + brw.scrollbar.cursorh) {
  992.                                         scroll = scroll + scroll_step_page;
  993.                                         scroll = check_scroll(scroll);
  994.                                     }; else {
  995.                                         cScrollBar.timerCounter++;
  996.                                     };
  997.                                 }, 80);
  998.                             };
  999.                         };
  1000.                     };
  1001.                 };
  1002.                 break;
  1003.             case "right":
  1004.             case "up":
  1005.                 if(cScrollBar.timerID) {
  1006.                     window.ClearInterval(cScrollBar.timerID);
  1007.                     cScrollBar.timerID = false;
  1008.                 };
  1009.                 cScrollBar.timerCounter = -1;
  1010.                
  1011.                 this.cursorCheck(event, x, y);
  1012.                 for(var i = 1; i < 3; i++) {
  1013.                     this.buttons[i].checkstate(event, x, y);
  1014.                 };
  1015.                 this.buttonClick = false;
  1016.                 break;
  1017.             case "move":
  1018.                 this.cursorCheck(event, x, y);
  1019.                 for(var i = 1; i < 3; i++) {
  1020.                     this.buttons[i].checkstate(event, x, y);
  1021.                 };
  1022.                 break;
  1023.             case "wheel":
  1024.                 if(!this.buttonClick) {
  1025.                     this.updateScrollbar();
  1026.                 };
  1027.                 break;
  1028.             case "leave":
  1029.                 this.cursorCheck(event, 0, 0);
  1030.                 for(var i = 1; i < 3; i++) {
  1031.                     this.buttons[i].checkstate(event, 0, 0);
  1032.                 };
  1033.                 break;
  1034.         };
  1035.     };
  1036. };
  1037.  
  1038. oGroup = function(index, start, handle, groupkey) {
  1039.     this.index = index;
  1040.     this.start = start;
  1041.     this.count = 1;
  1042.     this.metadb = handle;
  1043.     this.groupkey = groupkey;
  1044.     if(handle) {
  1045.         switch(ppt.tagMode) {
  1046.             case 1:
  1047.                 this.cachekey = process_cachekey(ppt.tf_crc.EvalWithMetadb(handle));
  1048.                 break;
  1049.             case 2:
  1050.                 this.cachekey = process_cachekey(ppt.tf_crc_artist.EvalWithMetadb(handle));
  1051.                 break;
  1052.             case 3:
  1053.                 this.cachekey = process_cachekey(ppt.tf_crc_genre.EvalWithMetadb(handle));
  1054.                 break;
  1055.         }
  1056.         this.tracktype = TrackType(handle.rawpath.substring(0, 4));
  1057.     }; else {
  1058.         this.cachekey = null;
  1059.         this.tracktype = 0;
  1060.     };
  1061.     //
  1062.     this.cover_img = null;
  1063.     this.load_requested = 0;
  1064.     this.save_requested = false;
  1065.  
  1066.     this.finalize = function(count, tracks, handles) {
  1067.         this.tra = tracks.slice(0);
  1068.         this.pl = handles.Clone();
  1069.         this.count = count;
  1070.     };
  1071.    
  1072.     //this.totalPreviousRows = 0
  1073. };
  1074.  
  1075. oBrowser = function(name) {
  1076.     this.name = name;
  1077.     this.groups = [];
  1078.     this.rows = [];
  1079.     this.SHIFT_start_id = null;
  1080.     this.SHIFT_count = 0;
  1081.     this.scrollbar = new oScrollbar(themed = cScrollBar.themed);
  1082.     this.keypressed = false;
  1083.    
  1084.     this.metadblist_selection = plman.GetPlaylistSelectedItems(g_active_playlist);
  1085.  
  1086.     var launch_timer = window.SetTimeout(function(){
  1087.         brw.populate(is_first_populate = true);
  1088.         launch_timer && window.ClearTimeout(launch_timer);
  1089.         launch_timer = false;
  1090.     }, 25);
  1091.    
  1092.     this.repaint = function() {
  1093.         repaint_main1 = repaint_main2;
  1094.     };
  1095.    
  1096.     this.cover_repaint = function() {
  1097.         repaint_cover1 = repaint_cover2;
  1098.     };
  1099.    
  1100.     this.update = function() {
  1101.         switch(ppt.panelMode) {
  1102.             case 1:
  1103.             case 3:
  1104.                 // *** STAMP MODES ***
  1105.                 this.stampDrawMode = (ppt.panelMode == 1 ? true : false);
  1106.                 this.thumb_w = ppt.thumbnailWidthMin;
  1107.                 this.marginLR = 0;
  1108.                 // set margins betweens album stamps
  1109.                 if(ppt.panelMode == 1) {
  1110.                     this.marginTop = 2;
  1111.                     this.marginBot = 2;
  1112.                     this.marginSide = 2;
  1113.                     this.marginCover = 12;
  1114.                 }; else {
  1115.                     this.marginTop = 0;
  1116.                     this.marginBot = 0;
  1117.                     this.marginSide = 0;
  1118.                     this.marginCover = 1;
  1119.                 };
  1120.                 // Adjust Column
  1121.                 this.totalColumns = Math.floor((this.w - this.marginLR * 2) / this.thumb_w);
  1122.                 // count total of rows for the whole library
  1123.                 this.rowsCount = Math.ceil(this.groups.length / this.totalColumns);
  1124.                 var gapeWidth = (this.w - this.marginLR * 2) - (this.totalColumns * this.thumb_w);
  1125.                 var deltaToAdd = Math.floor(gapeWidth / this.totalColumns);
  1126.                 this.thumbnailWidth = this.thumb_w + deltaToAdd;
  1127.                 // calc size of the cover art
  1128.                 cover.max_w = (this.thumbnailWidth - (this.marginSide * 2) - (this.marginCover * 2));
  1129.                 // Adjust Row & showList bloc Height
  1130.                 if(ppt.panelMode == 1) {
  1131.                     this.rowHeight = 10 + cover.max_w + 45;
  1132.                 }; else {
  1133.                     this.rowHeight = cover.max_w + 1;
  1134.                 };
  1135.                 break;
  1136.             case 0:
  1137.             case 2:
  1138.                 // *** LINE MODES ***
  1139.                 this.stampDrawMode = true;
  1140.                 this.thumb_w = this.w;
  1141.                 this.marginLR = 0;
  1142.                 // set margins betweens album stamps
  1143.                 this.marginTop = (ppt.panelMode > 0 ? 1 : 0);
  1144.                 this.marginBot = (ppt.panelMode > 0 ? 2 : 0);
  1145.                 this.marginSide = (ppt.panelMode > 0 ? 1 : 0);
  1146.                 this.marginCover = (ppt.panelMode > 0 ? 7 : 2);
  1147.                 // Adjust Column
  1148.                 this.totalColumns = 1;
  1149.                 // count total of rows for the whole library
  1150.                 this.rowsCount = Math.ceil(this.groups.length / this.totalColumns);
  1151.                 var gapeWidth = (this.w - this.marginLR * 2) - (this.totalColumns * this.thumb_w);
  1152.                 var deltaToAdd = Math.floor(gapeWidth / this.totalColumns);
  1153.                 this.thumbnailWidth = this.thumb_w + deltaToAdd;
  1154.                 // calc size of the cover art
  1155.                 cover.max_w = (ppt.lineHeightMin - (this.marginCover * 2));
  1156.                 // Adjust Row & showList bloc Height
  1157.                 this.rowHeight = ppt.lineHeightMin;
  1158.                 break;
  1159.         };
  1160.  
  1161.         this.totalRows = Math.ceil(this.h / this.rowHeight);
  1162.         this.totalRowsVis = Math.floor(this.h / this.rowHeight);
  1163.         ppt.rowHeight = this.rowHeight;
  1164.  
  1165.         //
  1166.         scroll = Math.round(scroll / this.rowHeight) * this.rowHeight;
  1167.         scroll = check_scroll(scroll);
  1168.         //scroll_ = scroll + (this.rowHeight / ppt.scrollRowDivider);
  1169.         scroll_ = scroll;
  1170.        
  1171.         // scrollbar update      
  1172.         this.scrollbar.updateScrollbar();
  1173.        
  1174.         // update images (scaled ones)
  1175.         get_images();
  1176.        
  1177.         this.repaint();
  1178.     };
  1179.    
  1180.     this.setSize = function(x, y, w, h) {
  1181.         this.x = x;
  1182.         this.y = y;
  1183.         this.w = w;
  1184.         this.h = h;
  1185.  
  1186.         this.scrollbar.setSize();
  1187.        
  1188.         scroll = Math.round(scroll / ppt.rowHeight) * ppt.rowHeight;
  1189.         scroll = check_scroll(scroll);
  1190.         scroll_ = scroll;
  1191.        
  1192.         // scrollbar update      
  1193.         this.scrollbar.updateScrollbar();
  1194.        
  1195.         this.update();
  1196.     };
  1197.          
  1198.     this.setList = function() {
  1199.         var end = this.groups.length;
  1200.         for(var i = 0; i < end; i++) {
  1201.             this.groups[i].load_requested = 0;
  1202.         };
  1203.         this.update();
  1204.     };  
  1205.    
  1206.     this.init_groups = function() {
  1207.         var handle = null;
  1208.         var current = "";
  1209.         var previous = "";
  1210.         var g = 0, t = 0;
  1211.         var arr = [];
  1212.         var tr = [];
  1213.         var pl = plman.GetPlaylistItems(-1);
  1214.         var total = this.list.Count;
  1215.         var t_all = 0;
  1216.         if(ppt.showAllItem) {
  1217.             var tr_all = [];
  1218.             var pl_all = plman.GetPlaylistItems(-1);
  1219.         };
  1220.  
  1221.         var d1 = new Date();
  1222.         var t1 = d1.getSeconds()*1000 + d1.getMilliseconds();
  1223.  
  1224.         this.groups.splice(0, this.groups.length);
  1225.        
  1226.         switch(ppt.tagMode) {
  1227.             case 1: // album
  1228.                 var tf = ppt.tf_groupkey_album;
  1229.                 break;
  1230.             case 2: // artist
  1231.                 var tf = ppt.tf_groupkey_artist;
  1232.                 break;
  1233.             case 3: // genre
  1234.                 var tf = ppt.tf_groupkey_genre;
  1235.                 break;
  1236.         };
  1237.         var str_filter = process_string(filter_text);
  1238.                
  1239.         for(var i = 0; i < total; i++) {
  1240.             handle = this.list.Item(i);
  1241.             arr = tf.EvalWithMetadb(handle).split(" ## ");
  1242.             current = arr[0].toLowerCase();
  1243.             if(str_filter.length > 0) {
  1244.                 var toAdd = match(arr[0]+" "+arr[1], str_filter);
  1245.             }; else {
  1246.                 var toAdd = true;  
  1247.             };
  1248.             if(toAdd) {
  1249.                 if(current != previous) {
  1250.                     if(g > 0) {
  1251.                         // update current group
  1252.                         this.groups[g-1].finalize(t, tr, pl);
  1253.                         tr.splice(0, t);
  1254.                         pl.RemoveAll();
  1255.                         t = 0;
  1256.                     };
  1257.                     if(i < total) {
  1258.                         // add new group
  1259.                         tr.push(arr[1]);
  1260.                         pl.Add(handle);
  1261.                         if(ppt.showAllItem) {
  1262.                             tr_all.push(arr[1]);
  1263.                             pl_all.Add(handle);
  1264.                         };
  1265.                         t_all++;
  1266.                         t++;
  1267.                         this.groups.push(new oGroup(g+1, i, handle, arr[0]));
  1268.                         g++;
  1269.                         previous = current;
  1270.                     };
  1271.                 }; else {
  1272.                     // add track to current group
  1273.                     tr.push(arr[1]);
  1274.                     pl.Add(handle);
  1275.                     if(ppt.showAllItem) {
  1276.                         tr_all.push(arr[1]);
  1277.                         pl_all.Add(handle);
  1278.                     };
  1279.                     t_all++;
  1280.                     t++;
  1281.                 };
  1282.             };
  1283.         };
  1284.        
  1285.         if(g > 0) {
  1286.             // update last group properties
  1287.             this.groups[g-1].finalize(t, tr, pl);
  1288.            
  1289.             // add 1st group ("ALL" item)
  1290.             if(ppt.showAllItem && g > 1) {
  1291.                 this.groups.unshift(new oGroup(0, 0, null, null));
  1292.                 this.groups[0].finalize(t_all, tr_all, pl_all);
  1293.             };
  1294.         };
  1295.  
  1296.         var d2 = new Date();
  1297.         var t2 = d2.getSeconds()*1000 + d2.getMilliseconds();
  1298.         fb.trace("JSB POPULATE: init groups delay = "+Math.round(t2 - t1)+" /handleList count="+total);
  1299.     };
  1300.      
  1301.     this.populate = function(is_first_populate) {
  1302.         fb.trace("--> populate");
  1303.         if(this.list) this.list.Dispose();
  1304.         if(ppt.sourceMode == 0) {
  1305.             // populate library
  1306.             this.list = fb.GetLibraryItems();
  1307.             // define sort order
  1308.             switch(ppt.tagMode) {
  1309.                 case 1: // album
  1310.                     var TFsorting = ppt.albumsTFsorting;
  1311.                     break;
  1312.                 case 2: // artist
  1313.                     var TFsorting = ppt.artistsTFsorting;
  1314.                     break;
  1315.                 case 3: // genre
  1316.                     var TFsorting = ppt.genresTFsorting;
  1317.                     break;
  1318.             };
  1319.             // sort the list
  1320.             if(TFsorting.length > 0) {
  1321.                 fb.trace(".. TFsorting="+TFsorting);
  1322.                 this.list.OrderByFormat(fb.TitleFormat(TFsorting), 1);
  1323.             };
  1324.         }; else {
  1325.             // populate current playlist
  1326.             this.list = plman.GetPlaylistItems(g_active_playlist);
  1327.         };
  1328.        
  1329.         this.init_groups();
  1330.         this.setList();
  1331.         this.scrollbar.updateScrollbar();
  1332.         this.repaint();
  1333.         g_first_populate_done = true;
  1334.     };
  1335.    
  1336.    
  1337.     this.activateItem = function(index) {
  1338.         if(this.groups.length == 0) return;
  1339.         this.selectedIndex = index;
  1340.     };
  1341.    
  1342.     this.sendItemToPlaylist = function(index) {
  1343.         if(this.groups.length == 0) return;
  1344.        
  1345.         // notify JSSmoothPlaylist panel to avoid "on_playlist_items_removed" until "on_playlist_items_added" was called (to avoid x2 call of populate function!)
  1346.         window.NotifyOthers("JSSmoothBRowser->JSSmoothPlaylist:avoid_on_playlist_items_removed_callbacks_on_sendItemToPlaylist", true);
  1347.        
  1348.         // parse stored tags
  1349.         if(ppt.showAllItem && index == 0 && this.groups.length > 1) {
  1350.             var arr = null;
  1351.         }; else {
  1352.             var arr = this.groups[index].groupkey.split(" ^^ ");
  1353.         };
  1354.         // ======================================
  1355.         // Send item tracks to JSBrowser playlist
  1356.         // ======================================
  1357.         // check if JSBrowser playlists are present
  1358.         var affectedItems = [];
  1359.         var pfound = false;
  1360.         var pfound_playing = false;
  1361.         var total = plman.PlaylistCount;
  1362.         var pidx = -1;
  1363.         var pidx_playing = -1;
  1364.         for(var i = 0; i < total; i++) {
  1365.             if(!pfound && plman.GetPlaylistName(i) == "Library selection") {
  1366.                 pidx = i;
  1367.                 pfound = true;
  1368.             };
  1369.             if(!pfound_playing && plman.GetPlaylistName(i) == "Library selection (playing)") {
  1370.                 pidx_playing = i;
  1371.                 pfound_playing = true;
  1372.             };
  1373.             if(pfound && pfound_playing) break;
  1374.         };
  1375.        
  1376.         if(utils.IsKeyPressed(VK_CONTROL)) {
  1377.             // initialize "Library selection" playlist
  1378.             if(pfound) {
  1379.                 var from = plman.PlaylistItemCount(pidx);
  1380.             }; else {
  1381.                 pidx = plman.PlaylistCount;
  1382.                 plman.CreatePlaylist(pidx, "Library selection");
  1383.                 var from = 0;
  1384.             };
  1385.             // *** insert tracks into pidx playlist
  1386.             plman.InsertPlaylistItems(pidx, from, brw.groups[index].pl, false);
  1387.         }; else {
  1388.             if(fb.IsPlaying) {
  1389.                 if(plman.PlayingPlaylist == pidx) { // playing playlist is "Library selection"
  1390.                     plman.RenamePlaylist(pidx, "Library selection (playing)");
  1391.                     if(pfound_playing) {
  1392.                         plman.RenamePlaylist(pidx_playing, "Library selection");
  1393.                         // 1. initialize old "Library selection (playing)" playlist
  1394.                         var tot = plman.PlaylistItemCount(pidx_playing);
  1395.                         affectedItems.splice(0, affectedItems.length);
  1396.                         for(var i = 0; i < tot; i++) {
  1397.                             affectedItems.push(i);
  1398.                         };
  1399.                         plman.SetPlaylistSelection(pidx_playing, affectedItems, true);
  1400.                         plman.RemovePlaylistSelection(pidx_playing, false);
  1401.                     }; else {
  1402.                         pidx_playing = plman.PlaylistCount;
  1403.                         plman.CreatePlaylist(pidx_playing, "Library selection");
  1404.                     };
  1405.                     // *** insert tracks into pidx_playing playlist
  1406.                     plman.InsertPlaylistItems(pidx_playing, 0, brw.groups[index].pl, false);
  1407.                     plman.MovePlaylist(pidx_playing, pidx);
  1408.                     plman.MovePlaylist(pidx + 1, pidx_playing);
  1409.                 }; else {
  1410.                     // initialize true "Library selection" playlist
  1411.                     if(pfound) {
  1412.                         // clear "Library selection" playlist content
  1413.                         var tot = plman.PlaylistItemCount(pidx);
  1414.                         for(var i = 0; i < tot; i++) {
  1415.                             affectedItems.push(i);
  1416.                         };
  1417.                         plman.SetPlaylistSelection(pidx, affectedItems, true);
  1418.                         plman.RemovePlaylistSelection(pidx, false);
  1419.                     }; else {
  1420.                         // create "Library selection" playlist
  1421.                         pidx = plman.PlaylistCount;
  1422.                         plman.CreatePlaylist(pidx, "Library selection");
  1423.                     };
  1424.                     // *** insert tracks into pidx playlist
  1425.                     plman.InsertPlaylistItems(pidx, 0, brw.groups[index].pl, false);
  1426.                 };
  1427.             }; else {
  1428.                 // initialize "Library selection" playlist
  1429.                 if(pfound) {
  1430.                     // clear "Library selection" playlist content
  1431.                     var tot = plman.PlaylistItemCount(pidx);
  1432.                     for(var i = 0; i < tot; i++) {
  1433.                         affectedItems.push(i);
  1434.                     };
  1435.                     plman.SetPlaylistSelection(pidx, affectedItems, true);
  1436.                     plman.RemovePlaylistSelection(pidx, false);
  1437.                 }; else {
  1438.                     // create "Library selection" playlist
  1439.                     pidx = plman.PlaylistCount;
  1440.                     plman.CreatePlaylist(pidx, "Library selection");
  1441.                 };
  1442.                 // *** insert tracks into pidx playlist
  1443.                 plman.InsertPlaylistItems(pidx, 0, brw.groups[index].pl, false);
  1444.             };
  1445.        
  1446.             plman.ActivePlaylist = pidx;
  1447.         };
  1448.     };
  1449.    
  1450.     this.getlimits = function() {
  1451.        
  1452.         // get visible stamps limits (start & end indexes)
  1453.         if(this.groups.length <= this.totalRowsVis * this.totalColumns) {
  1454.             var start_ = 0;
  1455.             var end_ = this.groups.length;
  1456.         }; else {
  1457.             var start_ = Math.round(scroll_/this.rowHeight) * this.totalColumns;
  1458.             var end_ = Math.round((scroll_ + wh + this.rowHeight) / this.rowHeight) * this.totalColumns;
  1459.             // check values / limits
  1460.             end_ = (this.groups.length < end_) ? this.groups.length : end_;
  1461.             start_ = start_ > 0 ? start_ - this.totalColumns : (start_ < 0 ? 0 : start_);
  1462.         };
  1463.  
  1464.         // save limits calculated into globals var
  1465.         g_start_ = start_;
  1466.         g_end_ = end_;
  1467.     };
  1468.        
  1469.     this.draw = function(gr) {
  1470.         var tmp, offset;
  1471.         var cx = 0;
  1472.         var ax, ay, by, rowStart, row, coverTop;
  1473.         var aw = this.thumbnailWidth - (this.marginSide * 2);
  1474.         var ah = this.rowHeight - this.marginTop - this.marginBot;
  1475.         if(ppt.panelMode > 0) {
  1476.             var coverWidth = cover.max_w;
  1477.         }; else {
  1478.             var coverWidth = 0;
  1479.         };
  1480.         var txt_color1, txt_color2, selbg_color;
  1481.         var total = this.groups.length;
  1482.         var all_x = -1, all_y = -1, all_w = 0, all_h = 0;
  1483.        
  1484.         this.getlimits();
  1485.        
  1486.         if(repaint_main || !repaintforced){
  1487.             repaint_main = false;
  1488.             repaintforced = false;
  1489.            
  1490.             // draw visible stamps (loop)
  1491.             for(var i = g_start_; i < g_end_; i++) {
  1492.                 row = Math.floor(i / this.totalColumns);
  1493.                 ax = this.x + (cx * this.thumbnailWidth) + this.marginSide + this.marginLR;
  1494.                 ay = Math.floor(this.y + (row * this.rowHeight) + this.marginTop - scroll_);
  1495.                 this.groups[i].x = ax;
  1496.                 this.groups[i].y = ay;
  1497.                
  1498.                 if(ay >= (0 - this.rowHeight) && ay < this.y + this.h) { // if stamp visible, we have to draw it
  1499.  
  1500.                     // parse stored tags
  1501.                     if(!(ppt.showAllItem && i == 0 && total > 1)) {
  1502.                         if(this.groups[i].groupkey.length > 0) {
  1503.                             var arr = this.groups[i].groupkey.split(" ^^ ");
  1504.                         };
  1505.                     };
  1506.                    
  1507.                     if(ppt.panelMode > 0) {
  1508.                         // get cover
  1509.                         if(ppt.showAllItem && i == 0 && total > 1) {
  1510.                             this.groups[i].cover_img = images.all;
  1511.                         }; else {
  1512.                             this.groups[i].cover_img = g_image_cache.hit(this.groups[i].metadb, i);
  1513.                         };
  1514.                     };
  1515.                                        
  1516.                     if(this.stampDrawMode) {
  1517.                         // BG under cover
  1518.                         if(ppt.panelMode == 0) {
  1519.                             if(Math.floor(i/2) != Math.ceil(i/2)) {
  1520.                                 gr.FillSolidRect(ax, ay, aw, ah, g_color_normal_txt & 0x05ffffff);
  1521.                             };
  1522.                         }; else {
  1523.                             gr.FillSolidRect(ax, ay, aw, ah, g_color_normal_txt & 0x10ffffff);
  1524.                             gr.DrawRect(ax, ay, aw-1, ah-1, 1.0, g_color_normal_txt & 0x10ffffff);
  1525.                         };
  1526.                         // background selection
  1527.                         if(i == this.selectedIndex) {
  1528.                             txt_color1 = g_color_normal_bg;
  1529.                             txt_color2 = blendColors(g_color_normal_bg, g_color_selected_bg, 0.25);
  1530.                             selbg_color = g_color_selected_bg & 0xb0ffffff;
  1531.                             gr.FillSolidRect(ax, ay, aw, ah, selbg_color);
  1532.                         }; else {
  1533.                             txt_color1 = g_color_normal_txt;
  1534.                             txt_color2 = blendColors(g_color_normal_txt, g_color_normal_bg, 0.25);
  1535.                         };
  1536.                     }; else { // panelMode = 3 (Grid)
  1537.                         // background selection
  1538.                         if(i == this.selectedIndex) {
  1539.                             txt_color1 = g_color_normal_bg;
  1540.                             txt_color2 = blendColors(g_color_normal_bg, g_color_selected_bg, 0.25);
  1541.                             selbg_color = g_color_selected_bg & 0xb0ffffff;
  1542.                         }; else {
  1543.                             txt_color1 = RGBA(240,240,240);
  1544.                             txt_color2 = RGBA(220,220,220);
  1545.                             selbg_color = RGBA(0,0,0,190);
  1546.                         };
  1547.                     };
  1548.                    
  1549.                     switch(ppt.panelMode) {
  1550.                         case 1:
  1551.                         case 3:
  1552.                             coverTop = ppt.panelMode == 1 ? ay + 10 : ay;
  1553.                             // draw cover
  1554.                             if(this.groups[i].cover_img) {
  1555.                                 if(cover.keepaspectratio) {
  1556.                                     var max = this.groups[i].cover_img.Width > this.groups[i].cover_img.Height ? this.groups[i].cover_img.Width: this.groups[i].cover_img.Height;
  1557.                                     var rw = this.groups[i].cover_img.Width / max;
  1558.                                     var rh = this.groups[i].cover_img.Height / max;
  1559.                                     var im_w = (rw * coverWidth)-2;
  1560.                                     var im_h = (rh * coverWidth)-2;
  1561.                                 }; else {
  1562.                                     var im_w = coverWidth;
  1563.                                     var im_h = coverWidth;
  1564.                                 };
  1565.                                 // save coords ALL cover image:
  1566.                                 if(ppt.showAllItem && i == 0 && total > 1) {
  1567.                                     all_x = ax + Math.round((aw - im_w) / 2);
  1568.                                     all_y = coverTop + coverWidth - im_h;
  1569.                                     all_w = im_w;
  1570.                                     all_h = im_h;
  1571.                                     gr.DrawImage(this.groups[i].cover_img, ax + Math.round((aw - im_w) / 2), coverTop + coverWidth - im_h, im_w, im_h, 1, 1, this.groups[i].cover_img.Width-2, this.groups[i].cover_img.Height-2, 0, 190);
  1572.                                 }; else {
  1573.                                     gr.DrawImage(this.groups[i].cover_img, ax + Math.round((aw - im_w) / 2), coverTop + coverWidth - im_h, im_w, im_h, 1, 1, this.groups[i].cover_img.Width-2, this.groups[i].cover_img.Height-2);
  1574.                                     gr.DrawRect(ax + Math.round((aw - im_w) / 2), coverTop + coverWidth - im_h, im_w - 1, im_h - 1, 1.0, RGB(40,40,40));
  1575.                                    
  1576.                                     // grid text background rect
  1577.                                     if(ppt.panelMode == 3) {
  1578.                                         if(i == this.selectedIndex) {
  1579.                                             gr.FillSolidRect(ax + 2, coverTop + coverWidth - 42, aw - 4, 42, RGBA(150,150,150,150));
  1580.                                         };
  1581.                                         gr.FillSolidRect(ax + 2, coverTop + coverWidth - 42, aw - 4, 42, selbg_color);
  1582.                                         gr.FillSolidRect(ax + 2, coverTop + coverWidth - 42, aw - 4, 1, selbg_color);
  1583.                                     };
  1584.                                 };
  1585.                             }; else {
  1586.                                 var im_w = coverWidth;
  1587.                                 var im_h = coverWidth;
  1588.                                 gr.DrawImage(images.loading_draw, ax + Math.round((aw - images.loading_draw.Width) / 2), ay + Math.round((aw - images.loading_draw.Height) / 2), images.loading_draw.Width, images.loading_draw.Height, 0, 0, images.loading_draw.Width, images.loading_draw.Height, images.loading_angle, 160);
  1589.                             };
  1590.                            
  1591.                             // in Grid mode (panelMode = 3), if cover is in portrait mode, adjust width to the stamp width
  1592.                             if(ppt.panelMode == 3 && im_h > im_w) {
  1593.                                 var frame_w = coverWidth;
  1594.                                 var frame_h = im_h;
  1595.                             }; else {
  1596.                                 var frame_w = im_w;
  1597.                                 var frame_h = im_h;
  1598.                             };
  1599.                            
  1600.                             if(g_rightClickedIndex > -1) {
  1601.                                 if(g_rightClickedIndex == i) {
  1602.                                     if(this.stampDrawMode) {
  1603.                                         gr.DrawRect(ax+1, ay+1, aw-2, ah-2, 2.0, g_color_normal_txt & 0x80ffffff);
  1604.                                     }; else {
  1605.                                         gr.setSmoothingMode(2);
  1606.                                         gr.DrawRect(ax + Math.round((aw - frame_w) / 2) + 2, coverTop + coverWidth - frame_h + 2, frame_w - 4, frame_h - 4, 3.0, RGBA(0,0,0,200));
  1607.                                         gr.setSmoothingMode(0);
  1608.                                         gr.DrawRect(ax + Math.round((aw - frame_w) / 2) + 1, coverTop + coverWidth - frame_h + 1, frame_w - 2, frame_h - 2, 3.0, g_color_normal_txt & 0xddffffff);
  1609.                                     };
  1610.                                 };
  1611.                             }; else {
  1612.                                 if(i == this.activeIndex) {
  1613.                                     if(this.stampDrawMode) {
  1614.                                         gr.DrawRect(ax+1, ay+1, aw-2, ah-2, 2.0, g_color_normal_txt & 0x80ffffff);
  1615.                                     }; else {
  1616.                                         gr.setSmoothingMode(2);
  1617.                                         gr.DrawRect(ax + Math.round((aw - frame_w) / 2) + 2, coverTop + coverWidth - frame_h + 2, frame_w - 4, frame_h - 4, 3.0, RGBA(0,0,0,200));
  1618.                                         gr.setSmoothingMode(0);
  1619.                                         gr.DrawRect(ax + Math.round((aw - frame_w) / 2) + 1, coverTop + coverWidth - frame_h + 1, frame_w - 2, frame_h - 2, 3.0, g_color_normal_txt & 0xddffffff);
  1620.                                     };
  1621.                                 };
  1622.                             };
  1623.  
  1624.                             if(ppt.panelMode == 1) {
  1625.                                 // draw text
  1626.                                 if(ppt.showAllItem && i == 0 && total > 1) { // aggregate item ( [ALL] )
  1627.                                     try{
  1628.                                         gr.gdiDrawText("[All items]", gdi.Font("arial", 13, 1), txt_color1, ax + Math.round((aw - coverWidth) / 2), (coverTop + 5 + coverWidth), coverWidth, 16, DT_LEFT | DT_TOP | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1629.                                         gr.gdiDrawText("("+(total-1)+" albums)", gdi.Font("arial", 12, 0), txt_color2, ax + Math.round((aw - coverWidth) / 2), (coverTop + 5 + coverWidth + 16), coverWidth, 16, DT_LEFT | DT_TOP | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1630.                                     } catch(e) {}
  1631.                                 }; else {
  1632.                                     if(arr[1] == "?") {
  1633.                                         if(this.groups[i].count > 1) {
  1634.                                             var album_name = "(Singles)"
  1635.                                         }; else {
  1636.                                             var arr_t = this.groups[i].tra[0].split(" ^^ ");
  1637.                                             var album_name = "(Single) " + arr_t[2];
  1638.                                         };
  1639.                                     }; else {
  1640.                                         var album_name = arr[1];
  1641.                                     };
  1642.                                     try{
  1643.                                         gr.gdiDrawText(album_name, gdi.Font("arial", 13, 1), txt_color1, ax + Math.round((aw - coverWidth) / 2), (coverTop + 5 + coverWidth), coverWidth, 16, DT_LEFT | DT_TOP | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1644.                                         gr.gdiDrawText(arr[0], gdi.Font("arial", 12, 0), txt_color2, ax + Math.round((aw - coverWidth) / 2), (coverTop + 5 + coverWidth + 16), coverWidth, 16, DT_LEFT | DT_TOP | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1645.                                     } catch(e) {}
  1646.                                 };
  1647.                             }; else if(this.groups[i].cover_img) { // panelMode = 3 (Grid)
  1648.                                 // draw text
  1649.                                 if(ppt.showAllItem && i == 0 && total > 1) { // aggregate item ( [ALL] )
  1650.                                     // nothing
  1651.                                 }; else {
  1652.                                     if(arr[1] == "?") {
  1653.                                         if(this.groups[i].count > 1) {
  1654.                                             var album_name = "(Singles)"
  1655.                                         }; else {
  1656.                                             var arr_t = this.groups[i].tra[0].split(" ^^ ");
  1657.                                             var album_name = "(Single) " + arr_t[2];
  1658.                                         };
  1659.                                     }; else {
  1660.                                         var album_name = arr[1];
  1661.                                     };
  1662.                                     try{
  1663.                                         gr.gdiDrawText(album_name, gdi.Font("arial", 13, 1), txt_color1, ax+10, (coverTop + 5 + coverWidth) - 42, aw-20, 16, DT_LEFT | DT_TOP | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1664.                                         gr.gdiDrawText(arr[0], gdi.Font("arial", 12, 0), txt_color2, ax+10, (coverTop + 5 + coverWidth + 16) - 42, aw-20, 16, DT_LEFT | DT_TOP | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1665.                                     } catch(e) {}
  1666.                                 };
  1667.                             };
  1668.                             break;
  1669.                         case 0:
  1670.                         case 2:
  1671.                             coverTop = ay;
  1672.                             if(ppt.panelMode > 0) {
  1673.                                 // draw cover
  1674.                                 this.coverMarginLeft = this.marginCover;
  1675.                                 if(this.groups[i].cover_img) {
  1676.                                     if(cover.keepaspectratio) {
  1677.                                         var max = this.groups[i].cover_img.Width > this.groups[i].cover_img.Height ? this.groups[i].cover_img.Width: this.groups[i].cover_img.Height;
  1678.                                         var rw = this.groups[i].cover_img.Width / max;
  1679.                                         var rh = this.groups[i].cover_img.Height / max;
  1680.                                         var im_w = (rw * coverWidth)-2;
  1681.                                         var im_h = (rh * coverWidth)-2;
  1682.                                     }; else {
  1683.                                         var im_w = coverWidth;
  1684.                                         var im_h = coverWidth;
  1685.                                     };
  1686.                                     var deltaY = Math.floor((ah - im_h)/2);
  1687.                                     var deltaX = Math.floor((coverWidth - im_w)/2);
  1688.                                     // save coords ALL cover image:
  1689.                                     if(ppt.showAllItem && i == 0 && total > 1) {
  1690.                                         all_x = ax + this.coverMarginLeft+deltaX;
  1691.                                         all_y = coverTop + deltaY;
  1692.                                         all_w = im_w;
  1693.                                         all_h = im_h;
  1694.                                         gr.DrawImage(this.groups[i].cover_img, ax+this.coverMarginLeft+deltaX, coverTop + deltaY, im_w, im_h, 1, 1, this.groups[i].cover_img.Width-2, this.groups[i].cover_img.Height-2, 0, 190);
  1695.                                     }; else {
  1696.                                         gr.DrawImage(this.groups[i].cover_img, ax+this.coverMarginLeft+deltaX, coverTop + deltaY, im_w, im_h, 1, 1, this.groups[i].cover_img.Width-2, this.groups[i].cover_img.Height-2);
  1697.                                         gr.DrawRect(ax+this.coverMarginLeft+deltaX, coverTop + deltaY, im_w - 1, im_h - 1, 1.0, RGB(40,40,40));                                  
  1698.                                     };
  1699.                                 }; else {
  1700.                                     var im_w = coverWidth;
  1701.                                     var im_h = coverWidth;
  1702.                                     var deltaY = Math.floor((ah - im_h)/2);
  1703.                                     var deltaX = Math.floor((coverWidth - im_w)/2);
  1704.                                     gr.DrawImage(images.loading_draw, ax+this.coverMarginLeft+deltaX, coverTop + deltaY, coverWidth, coverWidth, 0, 0, images.loading_draw.Width, images.loading_draw.Height, images.loading_angle, 160);
  1705.                                 };
  1706.                             };
  1707.  
  1708.                             if(g_rightClickedIndex > -1) {
  1709.                                 if(g_rightClickedIndex == i) {
  1710.                                     gr.DrawRect(ax+1, ay+1, aw-2, ah-2, 2.0, g_color_normal_txt & 0x80ffffff);
  1711.                                 };
  1712.                             }; else {
  1713.                                 if(i == this.activeIndex) {
  1714.                                     gr.DrawRect(ax+1, ay+1, aw-2, ah-2, 2.0, g_color_normal_txt & 0x80ffffff);
  1715.                                 };
  1716.                             };
  1717.  
  1718.                             if(ppt.panelMode < 3) {
  1719.                                 // draw text
  1720.                                 if(ppt.showAllItem && i==0 && total > 1) { // [ALL] item
  1721.                                     switch(ppt.tagMode) {
  1722.                                         case 1: // album
  1723.                                             try{
  1724.                                                 gr.gdiDrawText("[All items]", gdi.Font("arial", 13, 1), txt_color1, ax + coverWidth + this.marginCover*2, ay - 10, aw - coverWidth - this.marginCover*3, ah, DT_LEFT | DT_VCENTER | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1725.                                                 gr.gdiDrawText("("+(total-1)+" albums)", gdi.Font("arial", 12, 0), txt_color2, ax + coverWidth + this.marginCover*2, ay + 10, aw - coverWidth - this.marginCover*3, ah, DT_LEFT | DT_VCENTER | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1726.                                             } catch(e) {}
  1727.                                             break;
  1728.                                         case 2: // artist
  1729.                                             try{
  1730.                                                 gr.gdiDrawText("[All items] ("+(total-1)+" artists)", gdi.Font("arial", 13, (i == this.selectedIndex ? 1 : 0)), txt_color1, ax + coverWidth + this.marginCover*2, ay, aw - coverWidth - this.marginCover*3, ah, DT_LEFT | DT_VCENTER | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1731.                                             } catch(e) {}
  1732.                                             break;
  1733.                                         case 3: // genre
  1734.                                             try{
  1735.                                                 gr.gdiDrawText("[All items] ("+(total-1)+" genres)", gdi.Font("arial", 13, (i == this.selectedIndex ? 1 : 0)), txt_color1, ax + coverWidth + this.marginCover*2, ay, aw - coverWidth - this.marginCover*3, ah, DT_LEFT | DT_VCENTER | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1736.                                             } catch(e) {}
  1737.                                             break;
  1738.                                     };
  1739.                                 }; else {
  1740.                                     switch(ppt.tagMode) {
  1741.                                         case 1: // album
  1742.                                             if(arr[1] == "?") {
  1743.                                                 if(this.groups[i].count > 1) {
  1744.                                                     var album_name = "(Singles)"
  1745.                                                 }; else {
  1746.                                                     var arr_t = this.groups[i].tra[0].split(" ^^ ");
  1747.                                                     var album_name = "(Single) " + arr_t[2];
  1748.                                                 };
  1749.                                             }; else {
  1750.                                                 var album_name = arr[1];
  1751.                                             };
  1752.                                             try{
  1753.                                                 gr.gdiDrawText(album_name, gdi.Font("arial", 13, 1), txt_color1, ax + coverWidth + this.marginCover*2, ay - 10, aw - coverWidth - this.marginCover*3, ah, DT_LEFT | DT_VCENTER | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1754.                                                 gr.gdiDrawText(arr[0], gdi.Font("arial", 12, 0), txt_color2, ax + coverWidth + this.marginCover*2, ay + 10, aw - coverWidth - this.marginCover*3, ah, DT_LEFT | DT_VCENTER | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1755.                                             } catch(e) {}
  1756.                                             break;
  1757.                                         case 2: // artist
  1758.                                             try{
  1759.                                                 gr.gdiDrawText(arr[0], gdi.Font("arial", 13, (i == this.selectedIndex ? 1 : 0)), txt_color1, ax + coverWidth + this.marginCover*2, ay, aw - coverWidth - this.marginCover*3, ah, DT_LEFT | DT_VCENTER | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1760.                                             } catch(e) {}
  1761.                                             break;
  1762.                                         case 3: // genre
  1763.                                             try{
  1764.                                                 gr.gdiDrawText(arr[0], gdi.Font("arial", 13, (i == this.selectedIndex ? 1 : 0)), txt_color1, ax + coverWidth + this.marginCover*2, ay, aw - coverWidth - this.marginCover*3, ah, DT_LEFT | DT_VCENTER | DT_CALCRECT | DT_END_ELLIPSIS | DT_NOPREFIX);
  1765.                                             } catch(e) {}
  1766.                                             break;
  1767.                                     };
  1768.                                 };
  1769.                             };
  1770.                             break;
  1771.                     };
  1772.                    
  1773.                 };
  1774.  
  1775.                 // fill ALL cover image with the 1st four cover art found
  1776.                 if(ppt.panelMode > 0 && i == g_end_ - 1) {
  1777.                     // get cover
  1778.                     if(all_x > -1 && ppt.showAllItem && g_start_ == 0 && total > 1) {
  1779.                         var ii_w = Math.floor(all_w / 2);
  1780.                         var ii_h = Math.floor(all_h / 2);
  1781.                         var ii_x1 = all_x;
  1782.                         var ii_x2 = ii_x1 + ii_w;
  1783.                         var ii_y1 = all_y;
  1784.                         var ii_y2 = ii_y1 + ii_h;
  1785.                         var lim = this.groups.length;
  1786.                         if(lim > 5) lim = 5;
  1787.                         for(var ii=1; ii < lim; ii++) {
  1788.                             if(this.groups[ii].cover_img) {
  1789.                                 switch(ii) {
  1790.                                     case 1:
  1791.                                         gr.DrawImage(this.groups[ii].cover_img, ii_x1, ii_y1, ii_w, ii_h, 1, 1, this.groups[ii].cover_img.Width-2, this.groups[ii].cover_img.Height-2);
  1792.                                         break;
  1793.                                     case 2:
  1794.                                         gr.DrawImage(this.groups[ii].cover_img, ii_x2, ii_y1, ii_w, ii_h, 1, 1, this.groups[ii].cover_img.Width-2, this.groups[ii].cover_img.Height-2);
  1795.                                         break;
  1796.                                     case 3:
  1797.                                         gr.DrawImage(this.groups[ii].cover_img, ii_x1, ii_y2, ii_w, ii_h, 1, 1, this.groups[ii].cover_img.Width-2, this.groups[ii].cover_img.Height-2);
  1798.                                         break;
  1799.                                     case 4:
  1800.                                         gr.DrawImage(this.groups[ii].cover_img, ii_x2, ii_y2, ii_w, ii_h, 1, 1, this.groups[ii].cover_img.Width-2, this.groups[ii].cover_img.Height-2);
  1801.                                         break;
  1802.                                 };
  1803.                             };
  1804.                         };
  1805.                         gr.DrawRect(ii_x1, ii_y1, all_w-1, all_h-1, 1.0, RGB(40,40,40));
  1806.                         gr.DrawRect(ii_x1, ii_y1, all_w-1, Math.round(all_h/2)-1, 1.0, RGB(40,40,40));
  1807.                         gr.DrawRect(ii_x1, ii_y1, Math.round(all_w/2)-1, all_h-1, 1.0, RGB(40,40,40));
  1808.                     };
  1809.                 };
  1810.                
  1811.                 // set next column index
  1812.                 if(cx == this.totalColumns - 1) {
  1813.                     cx = 0;
  1814.                 }; else {
  1815.                     cx++;
  1816.                 };
  1817.             };
  1818.  
  1819.             // draw scrollbar
  1820.             if(cScrollBar.enabled) {
  1821.                 brw.scrollbar && brw.scrollbar.draw(gr);
  1822.             };
  1823.  
  1824.             // draw top header bar
  1825.             if(ppt.showHeaderBar) {
  1826.                 var nb_groups = (ppt.showAllItem && total > 1 ? total - 1 : total);
  1827.                 var boxText = "  "+nb_groups+" item"+(nb_groups > 1 ? "s  " : "  ");
  1828.                 gr.FillGradRect(this.x, 0, this.w + (cScrollBar.enabled ? cScrollBar.width : 0), ppt.headerBarHeight-1, 0, RGBA(20,20,20,255), RGBA(0,0,0,160), 1.0);
  1829.                 gr.FillSolidRect(this.x, ppt.headerBarHeight-2, this.w + (cScrollBar.enabled ? cScrollBar.width : 0), 1, RGBA(0,0,0,130));
  1830.                 gr.gdiDrawText(boxText, gdi.Font(g_fname, g_fsize-2, 1), RGB(255,255,255), this.x, 0, this.w + (cScrollBar.enabled ? cScrollBar.width : 0), ppt.headerBarHeight-1, DT_RIGHT | DT_VCENTER | DT_CALCRECT | DT_NOPREFIX | DT_END_ELLIPSIS);
  1831.             };
  1832.         };
  1833.     };
  1834.        
  1835.     this._isHover = function(x, y) {
  1836.         return (x >= this.x && x <= this.x + this.w && y >= this.y && y <= this.y + this.h);
  1837.     };
  1838.    
  1839.     this.on_mouse = function(event, x, y, delta) {      
  1840.         this.ishover = this._isHover(x, y);
  1841.        
  1842.         // get active item index at x,y coords...
  1843.         this.activeIndex = -1;
  1844.         if(this.ishover) {
  1845.             this.activeRow = Math.ceil((y + scroll_ - this.y) / this.rowHeight) - 1;
  1846.             if(y > this.y && x > this.x && x < this.x + this.w) {
  1847.                 this.activeColumn = Math.ceil((x - this.x - this.marginLR) / this.thumbnailWidth) - 1;
  1848.                 this.activeIndex = (this.activeRow * this.totalColumns) + this.activeColumn;
  1849.                 this.activeIndex = this.activeIndex > this.groups.length - 1 ? -1 : this.activeIndex;
  1850.             };
  1851.         };
  1852.         if(brw.activeIndex != brw.activeIndexSaved) {
  1853.             brw.activeIndexSaved = brw.activeIndex;
  1854.             this.repaint();
  1855.         };
  1856.        
  1857.         switch(event) {
  1858.             case "down":
  1859.                 if(this.ishover) {
  1860.                     if(this.activeIndex > -1) {
  1861.                         this.activateItem(this.activeIndex);
  1862.                         if(ppt.sourceMode == 0) {
  1863.                             this.sendItemToPlaylist(this.activeIndex);
  1864.                         }; else {
  1865.                             g_dnd_status = true;
  1866.                             //g_dnd_handles = this.groups[this.activeIndex].pl;
  1867.                         };
  1868.                     };
  1869.                     this.repaint(); // avirer
  1870.                 }; else {
  1871.                     if(cScrollBar.enabled && cScrollBar.visible) {
  1872.                         this.scrollbar && this.scrollbar.on_mouse(event, x, y);
  1873.                     };
  1874.                 };
  1875.                 break;
  1876.             case "up":
  1877.                 //if(g_dnd_status && g_dnd_handles != null) {
  1878.                 //    window.NotifyOthers("JSBrowser::dragndrop", g_dnd_handles);
  1879.                     g_dnd_status = false;
  1880.                 //};
  1881.                 if(cScrollBar.enabled && cScrollBar.visible) {
  1882.                     this.scrollbar && this.scrollbar.on_mouse(event, x, y);
  1883.                 };
  1884.                 break;
  1885.             case "dblclk":
  1886.                 if(this.ishover) {
  1887.                     if(brw.activeIndex > -1) {
  1888.                         if(ppt.sourceMode == 0) {
  1889.                             // play first track of the selection                    
  1890.                             plman.ExecutePlaylistDefaultAction(plman.ActivePlaylist, 0);
  1891.                         }; else {
  1892.                             plman.SetPlaylistFocusItemByHandle(plman.ActivePlaylist, brw.groups[brw.activeIndex].pl.Item(0));
  1893.                             fb.Play();
  1894.                         };
  1895.                     };
  1896.                 }; else {
  1897.                     if(cScrollBar.enabled && cScrollBar.visible) {
  1898.                         this.scrollbar && this.scrollbar.on_mouse(event, x, y);
  1899.                     };
  1900.                 };
  1901.                 break;
  1902.             case "right":
  1903.                 g_rightClickedIndex = this.activeIndex;
  1904.                 if(this.ishover && this.activeIndex > -1) {
  1905.                     this.activateItem(this.activeIndex);
  1906.                     if(ppt.sourceMode == 0) {
  1907.                         this.sendItemToPlaylist(this.activeIndex);
  1908.                     }; else {
  1909.                         g_dnd_status = true;
  1910.                         //g_dnd_handles = this.groups[this.activeIndex].pl;
  1911.                     };
  1912.                     this.item_context_menu(x, y, this.activeIndex);
  1913.                 }; else {
  1914.                     this.settings_context_menu(x, y);
  1915.                 };
  1916.                 g_rightClickedIndex = -1;
  1917.                 if(!this.ishover) {
  1918.                     if(cScrollBar.enabled && cScrollBar.visible) {
  1919.                         this.scrollbar && this.scrollbar.on_mouse(event, x, y);
  1920.                     };
  1921.                 };
  1922.                 break;
  1923.             case "move":
  1924.                 if(cScrollBar.enabled && cScrollBar.visible) {
  1925.                     this.scrollbar && this.scrollbar.on_mouse(event, x, y);
  1926.                 };
  1927.                 break;
  1928.             case "wheel":
  1929.                 if(cScrollBar.enabled && cScrollBar.visible) {
  1930.                     this.scrollbar.updateScrollbar();
  1931.                 };
  1932.                 break;
  1933.             case "leave":
  1934.                 if(cScrollBar.enabled && cScrollBar.visible) {
  1935.                     this.scrollbar && this.scrollbar.on_mouse(event, x, y);
  1936.                 };
  1937.                 break;
  1938.         };
  1939.     };
  1940.    
  1941.     if(this.g_timeCover) {
  1942.         window.ClearInterval(this.g_timeCover);
  1943.         this.g_timeCover = false;
  1944.     };
  1945.     this.g_timeCover = window.SetInterval(function() {
  1946.         if(!window.IsVisible) {
  1947.             window_visible = false;
  1948.             return;
  1949.         };
  1950.        
  1951.         var repaint_1 = false;
  1952.            
  1953.         if(repaint_cover1 == repaint_cover2){
  1954.             repaint_cover2 = !repaint_cover1;
  1955.             repaint_1 = true;
  1956.         };
  1957.        
  1958.         if(repaint_1){
  1959.             repaintforced = true;
  1960.             repaint_main = true;
  1961.             images.loading_angle = (images.loading_angle+30) % 360;
  1962.             window.Repaint();
  1963.         };
  1964.        
  1965.     }, ppt.refreshRateCover);
  1966.    
  1967.     if(this.g_time) {
  1968.         window.ClearInterval(this.g_time);
  1969.         this.g_time = false;
  1970.     };
  1971.     this.g_time = window.SetInterval(function() {
  1972.         if(!window.IsVisible) {
  1973.             window_visible = false;
  1974.             return;
  1975.         };
  1976.        
  1977.         var repaint_1 = false;
  1978.  
  1979.         if(!window_visible){
  1980.             window_visible = true;
  1981.             on_mouse_lbtn_down(3,3,0);
  1982.             on_mouse_lbtn_up(3,3,0);
  1983.             scroll_ += 1;
  1984.         };
  1985.            
  1986.         if(repaint_main1 == repaint_main2){
  1987.             repaint_main2 = !repaint_main1;
  1988.             repaint_1 = true;
  1989.         };
  1990.        
  1991.         scroll = check_scroll(scroll);
  1992.         if(scroll - scroll_ < -5.5 || scroll - scroll_ > 5.5){
  1993.             scroll_ += (scroll - scroll_) / ppt.scrollSmoothness;
  1994.             isScrolling = true;
  1995.             repaint_1 = true;
  1996.             if(scroll_prev != scroll) brw.scrollbar.updateScrollbar();
  1997.         }; else {
  1998.             if(scroll_ != scroll) {
  1999.                 scroll_ = scroll; // force to scroll_ value to fixe the 5.5 stop value for expanding album action
  2000.                 repaint_1 = true;
  2001.             };
  2002.             if(isScrolling) {
  2003.                 isScrolling = false;
  2004.                 repaint_1 = true;
  2005.             };
  2006.         };
  2007.        
  2008.         if(repaint_1){
  2009.             repaintforced = true;
  2010.             repaint_main = true;
  2011.             images.loading_angle = (images.loading_angle+30) % 360;
  2012.             window.Repaint();
  2013.         };
  2014.        
  2015.         scroll_prev = scroll;
  2016.        
  2017.     }, ppt.refreshRate);
  2018.  
  2019.     this.item_context_menu = function(x, y, albumIndex) {
  2020.         var _menu = window.CreatePopupMenu();
  2021.         var Context = fb.CreateContextMenuManager();
  2022.         var _child01 = window.CreatePopupMenu();
  2023.         var _child02 = window.CreatePopupMenu();
  2024.        
  2025.         var crc = this.groups[albumIndex].cachekey;
  2026.        
  2027.         this.metadblist_selection = this.groups[albumIndex].pl.Clone();
  2028.         Context.InitContext(this.metadblist_selection);
  2029.                
  2030.         _menu.AppendMenuItem(MF_STRING, 1, "Settings...");
  2031.         _menu.AppendMenuSeparator();
  2032.         Context.BuildMenu(_menu, 2, -1);
  2033.        
  2034.         _child01.AppendTo(_menu, MF_STRING, "Selection...");
  2035.  
  2036.         _child01.AppendMenuItem(MF_STRING, 1010, "Reset Image Cache");
  2037.         _child02.AppendTo(_child01, MF_STRING, "Send to...");
  2038.         _child02.AppendMenuItem(MF_STRING, 2000, "a New playlist...");
  2039.        
  2040.         var pl_count = plman.PlaylistCount;
  2041.         if(pl_count > 1) {
  2042.             _child02.AppendMenuItem(MF_SEPARATOR, 0, "");
  2043.         };
  2044.         for(var i=0; i < pl_count; i++) {
  2045.             if(i != this.playlist && !fb.IsAutoPlaylist(i)) {
  2046.                 _child02.AppendMenuItem(MF_STRING, 2001 + i, plman.GetPlaylistName(i));
  2047.             };
  2048.         };
  2049.  
  2050.         var ret = _menu.TrackPopupMenu(x, y);
  2051.         if(ret > 1 && ret < 800) {
  2052.             Context.ExecuteByID(ret - 2);
  2053.         }; else if(ret<2) {
  2054.             switch (ret) {
  2055.             case 1:
  2056.                 //window.ShowProperties();
  2057.                 this.settings_context_menu(x, y);
  2058.                 break;
  2059.             };
  2060.         }; else {
  2061.             switch (ret) {
  2062.             case 1010:
  2063.                 if(fso.FileExists(fb.ProfilePath + "wsh_br3tt\\cache\\imgcache\\" + crc)) {
  2064.                     try {
  2065.                         fso.DeleteFile(fb.ProfilePath + "wsh_br3tt\\cache\\imgcache\\" + crc);
  2066.                     }; catch(e) {
  2067.                         fb.trace("WSH Panel Error: Image cache ["+crc+"] can't be deleted on disk, file in use, try later or reload panel.");
  2068.                     };
  2069.                 };
  2070.                 this.groups[albumIndex].tid = -1;
  2071.                 this.groups[albumIndex].load_requested = 0;
  2072.                 this.groups[albumIndex].save_requested = false;
  2073.                 g_image_cache.reset(crc);
  2074.                 this.groups[albumIndex].cover_img = null;
  2075.                 this.repaint();
  2076.                 break;
  2077.             case 2000:
  2078.                 fb.RunMainMenuCommand("File/New playlist");
  2079.                 plman.InsertPlaylistItems(plman.PlaylistCount-1, 0, this.metadblist_selection, false);
  2080.                 break;
  2081.             default:
  2082.                 var insert_index = plman.PlaylistItemCount(ret-2001);
  2083.                 plman.InsertPlaylistItems((ret-2001), insert_index, this.metadblist_selection, false);
  2084.             };
  2085.         };
  2086.         _child01.Dispose();
  2087.         _child02.Dispose();
  2088.         _menu.Dispose();
  2089.         g_rbtn_click = false;
  2090.         return true;
  2091.     };
  2092.    
  2093.     this.settings_context_menu = function(x, y) {
  2094.             var _menu = window.CreatePopupMenu();
  2095.             var _menu0 = window.CreatePopupMenu();
  2096.             var _menu1 = window.CreatePopupMenu();
  2097.             var _menu2 = window.CreatePopupMenu();
  2098.             var _menu3 = window.CreatePopupMenu();
  2099.             var idx;
  2100.            
  2101.             _menu0.AppendMenuItem(MF_STRING, 50, "Library");
  2102.             _menu0.AppendMenuItem(MF_STRING, 51, "Playlist");
  2103.             _menu0.CheckMenuRadioItem(50, 51, 50 + ppt.sourceMode);
  2104.             _menu0.AppendTo(_menu,MF_STRING, "Source");
  2105.             _menu.AppendMenuSeparator();
  2106.  
  2107.             _menu1.AppendMenuItem(MF_STRING, 111, "Album");
  2108.             _menu1.AppendMenuItem(MF_STRING, 112, "Artist");
  2109.             _menu1.AppendMenuItem(MF_STRING, 113, "Genre");
  2110.             _menu1.CheckMenuRadioItem(111, 113, 110 + ppt.tagMode);
  2111.             _menu1.AppendTo(_menu,MF_STRING, "Columns");
  2112.  
  2113.             _menu2.AppendMenuItem(MF_STRING, 900, "Column");
  2114.             _menu2.AppendMenuItem(MF_STRING, 901, "Album Art (bottom labels)");
  2115.             _menu2.AppendMenuItem(MF_STRING, 902, "Album Art (right labels)");
  2116.             _menu2.AppendMenuItem(MF_STRING, 903, "Album Art Grid");
  2117.             _menu2.CheckMenuRadioItem(900, 903, 900 + ppt.panelMode);
  2118.             _menu2.AppendMenuSeparator();
  2119.             _menu2.AppendMenuItem(MF_STRING, 910, "Header Bar");
  2120.             _menu2.CheckMenuItem(910, ppt.showHeaderBar);
  2121.             _menu2.AppendMenuItem(MF_STRING, 911, "Aggregate Item");
  2122.             _menu2.CheckMenuItem(911, ppt.showAllItem);
  2123.  
  2124.             _menu2.AppendTo(_menu,MF_STRING, "Display");
  2125.            
  2126.             _menu3.AppendMenuItem(MF_STRING, 200, "Show");
  2127.             _menu3.CheckMenuItem(200, ppt.showwallpaper);
  2128.             _menu3.AppendMenuItem(MF_STRING, 220, "Blur");
  2129.             _menu3.CheckMenuItem(220, ppt.wallpaperblurred);
  2130.             _menu3.AppendMenuSeparator();
  2131.             _menu3.AppendMenuItem(MF_STRING, 210, "Default");
  2132.             _menu3.AppendMenuItem(MF_STRING, 211, "Playing Album Cover");
  2133.             _menu3.CheckMenuRadioItem(210, 211, ppt.wallpapermode == 0 ? 211 : 210);
  2134.            
  2135.             _menu3.AppendTo(_menu,MF_STRING, "Background Wallpaper");
  2136.            
  2137.             //_menu.AppendMenuSeparator();
  2138.             //_menu.AppendMenuItem(MF_STRING, 990, "Reload Library");
  2139.             _menu.AppendMenuSeparator();
  2140.             _menu.AppendMenuItem(MF_STRING, 991, "Panel Properties");
  2141.             _menu.AppendMenuItem(MF_STRING, 992, "Configure...");
  2142.            
  2143.             idx = _menu.TrackPopupMenu(x,y);
  2144.            
  2145.             switch(true) {
  2146.                 case (idx >= 50 && idx <= 51):
  2147.                     ppt.sourceMode = idx - 50;
  2148.                     window.SetProperty("_PROPERTY: Source Mode", ppt.sourceMode);
  2149.                     window.Reload();
  2150.                     break;
  2151.                 case (idx >= 111 && idx <= 113):
  2152.                     ppt.tagMode = idx - 110;
  2153.                     window.SetProperty("_PROPERTY: Tag Mode", ppt.tagMode);
  2154.                     switch(ppt.tagMode) {
  2155.                         case 1:
  2156.                             ppt.albumArtId = 0;
  2157.                             if(idx = 111 && ppt.lineHeightMin < 44) {
  2158.                                 ppt.lineHeightMin = 44;
  2159.                                 window.SetProperty("SYSTEM Minimal Line Height", ppt.lineHeightMin);
  2160.                             };
  2161.                             break;
  2162.                         case 2:
  2163.                             ppt.albumArtId = 4;
  2164.                             break;
  2165.                         case 3:
  2166.                             ppt.albumArtId = 5;
  2167.                             break;
  2168.                     };
  2169.                     g_image_cache = new image_cache;
  2170.                     CollectGarbage();
  2171.                     brw.populate(true);
  2172.                     brw.setList();
  2173.                     break;
  2174.                 case (idx == 200):
  2175.                     ppt.showwallpaper = !ppt.showwallpaper;
  2176.                     window.SetProperty("_DISPLAY: Show Wallpaper", ppt.showwallpaper);
  2177.                     brw.repaint();
  2178.                     break;
  2179.                 case (idx == 210):
  2180.                     ppt.wallpapermode = 99;
  2181.                     window.SetProperty("_SYSTEM: Wallpaper Mode", ppt.wallpapermode);
  2182.                     if(fb.IsPlaying) g_wallpaperImg = setWallpaperImg(ppt.wallpaperpath, fb.GetNowPlaying());
  2183.                     brw.repaint();
  2184.                     break;
  2185.                 case (idx == 211):
  2186.                     ppt.wallpapermode = 0;
  2187.                     window.SetProperty("_SYSTEM: Wallpaper Mode", ppt.wallpapermode);
  2188.                     if(fb.IsPlaying) g_wallpaperImg = setWallpaperImg(ppt.wallpaperpath, fb.GetNowPlaying());
  2189.                     brw.repaint();
  2190.                     break;
  2191.                 case (idx == 220):
  2192.                     ppt.wallpaperblurred = !ppt.wallpaperblurred;
  2193.                     window.SetProperty("_DISPLAY: Wallpaper Blurred", ppt.wallpaperblurred);
  2194.                     if(fb.IsPlaying) g_wallpaperImg = setWallpaperImg(ppt.wallpaperpath, fb.GetNowPlaying());
  2195.                     brw.repaint();
  2196.                     break;
  2197.                 case (idx >= 900 && idx <= 903):
  2198.                     ppt.panelMode = idx - 900;
  2199.                     window.SetProperty("_PROPERTY: Display Mode", ppt.panelMode);
  2200.                     g_image_cache = new image_cache;
  2201.                     CollectGarbage();
  2202.                     brw.setList();
  2203.                     break;
  2204.                 case (idx == 910):
  2205.                     ppt.showHeaderBar = !ppt.showHeaderBar;
  2206.                     window.SetProperty("_DISPLAY: Show Top Bar", ppt.showHeaderBar);
  2207.                     get_metrics();
  2208.                     break;
  2209.                 case (idx == 911):
  2210.                     ppt.showAllItem = !ppt.showAllItem;
  2211.                     window.SetProperty("_PROPERTY: Show ALL item", ppt.showAllItem);
  2212.                     brw.populate(false);
  2213.                     break;
  2214.                 case (idx == 990):
  2215.                     brw.populate(true);
  2216.                     break;
  2217.                 case (idx == 991):
  2218.                     window.ShowProperties();
  2219.                     break;
  2220.                 case (idx == 992):
  2221.                     window.ShowConfigure();
  2222.                     break;
  2223.             };
  2224.             _menu3.Dispose();
  2225.             _menu2.Dispose();
  2226.             _menu1.Dispose();
  2227.             _menu0.Dispose();
  2228.             _menu.Dispose();
  2229.             return true;
  2230.     };
  2231. };
  2232.  
  2233. /*
  2234. ===================================================================================================
  2235.     Main
  2236. ===================================================================================================
  2237. */
  2238. var g_seconds = 0;
  2239. var g_time_remaining = null;
  2240.  
  2241. var gtt = fb.CreateProfiler();
  2242. var g_dnd_handles = null;
  2243. var g_dnd_status = false;
  2244.  
  2245. var fso = new ActiveXObject("Scripting.FileSystemObject");
  2246. var Img = new ActiveXObject("WIA.ImageFile.1");
  2247. var IP = new ActiveXObject("WIA.ImageProcess.1");
  2248. IP.Filters.Add(IP.FilterInfos("Scale").FilterID);   //ID = 1
  2249. IP.Filters.Add(IP.FilterInfos("Crop").FilterID);    //ID = 2
  2250. IP.Filters.Add(IP.FilterInfos("Convert").FilterID); //ID = 3
  2251. var WshShell = new ActiveXObject("WScript.Shell");
  2252. var htmlfile = new ActiveXObject('htmlfile');
  2253.  
  2254. var cover_path = new RegExp("(artwork)|(cover)|(scan)|(image)");
  2255. var cover_img = "*front*.*-*cover*.*-*.*".split("-");  
  2256. var stub_image, cell_null;
  2257.  
  2258. var brw = null;
  2259. var g_1x1 = false;
  2260. var g_last = 0;
  2261. var isScrolling = false;
  2262. var g_zoom_percent = 100;
  2263.  
  2264. var g_filterbox = null;
  2265. var filter_text = "";
  2266.  
  2267. var g_instancetype = window.InstanceType;
  2268. var g_counter_repaint = 0;
  2269.  
  2270. // fonts
  2271. var g_font = null;
  2272. var g_font_headers = null;
  2273. var g_font_group1 = null;
  2274. var g_font_group2 = null;
  2275. var g_font_rating = null;
  2276. var g_font_mood = null;
  2277. var g_font_guifx_found = utils.CheckFont("guifx v2 transports");
  2278. var g_font_wingdings2_found = utils.CheckFont("wingdings 2");
  2279.  
  2280. //
  2281. var ww = 0, wh = 0;
  2282. var g_metadb = null;
  2283. var g_focus = false;
  2284. var foo_playcount = utils.CheckComponent("foo_playcount", true);
  2285. clipboard = {
  2286.     selection: null
  2287. };
  2288. // wallpaper infos
  2289. var wpp_img_info = {orient: 0, cut: 0, cut_offset: 0, ratio: 0, x: 0, y: 0, w: 0, h: 0};
  2290.  
  2291. var m_x = 0, m_y = 0;
  2292. var g_active_playlist = null;
  2293. var g_populate_opt = 1;
  2294. // color vars
  2295. var g_color_normal_bg = 0;
  2296. var g_color_selected_bg = 0;
  2297. var g_color_normal_txt = 0;
  2298. var g_color_selected_txt = 0;
  2299. var g_color_highlight = 0;
  2300. var g_syscolor_window_bg = 0;
  2301. var g_syscolor_highlight = 0;
  2302. var g_syscolor_button_bg = 0;
  2303. var g_syscolor_button_txt = 0;
  2304. // boolean to avoid callbacks
  2305. var g_avoid_on_playlists_changed = false;
  2306. var g_avoid_on_item_focus_change = false;
  2307. var g_avoid_on_playlist_items_added = false;
  2308. var g_avoid_on_playlist_items_removed = false;
  2309. var g_avoid_on_playlist_items_removed_callbacks_on_sendItemToPlaylist = false;
  2310. var g_avoid_on_playlist_items_reordered = false;
  2311. // mouse actions
  2312. var g_lbtn_click = false;
  2313. var g_rbtn_click = false;
  2314. //
  2315. var g_total_duration_text = "";
  2316. var g_first_populate_done = false;
  2317. var repaintforced = false;
  2318. var launch_time = fb.CreateProfiler("launch_time");
  2319. var form_text = "";
  2320. var repaint_main = true, repaint_main1 = true, repaint_main2 = true;
  2321. var repaint_cover = true, repaint_cover1 = true, repaint_cover2 = true;
  2322. var window_visible = false;
  2323. var scroll_ = 0, scroll = 0, scroll_prev = 0;
  2324. var time222;
  2325. var g_start_ = 0, g_end_ = 0;
  2326. var g_last = 0;
  2327. var g_wallpaperImg = null;
  2328.  
  2329. var g_rightClickedIndex = -1;
  2330.  
  2331. function on_init() {
  2332.     window.DlgCode = DLGC_WANTALLKEYS;
  2333.    
  2334.     get_font();
  2335.     get_colors();
  2336.     get_metrics();
  2337.  
  2338.     g_active_playlist = plman.ActivePlaylist;
  2339.    
  2340.     switch(ppt.tagMode) {
  2341.         case 1:
  2342.             ppt.albumArtId = 0;
  2343.             break;
  2344.         case 2:
  2345.             ppt.albumArtId = 4;
  2346.             break;
  2347.         case 3:
  2348.             ppt.albumArtId = 5;
  2349.             break;
  2350.     };
  2351.  
  2352.     brw = new oBrowser("brw");
  2353.     g_filterbox = new oFilterBox();
  2354.     g_filterbox.inputbox.visible = true;
  2355. };
  2356. on_init();
  2357.  
  2358. // START
  2359. function on_size() {
  2360.     window.DlgCode = DLGC_WANTALLKEYS;
  2361.    
  2362.     ww = window.Width;
  2363.     wh = window.Height;
  2364.    
  2365.     window.MinWidth = 200;
  2366.     window.MinHeight = 200;
  2367.    
  2368.     // set wallpaper
  2369.     if(fb.IsPlaying) {
  2370.         g_wallpaperImg = setWallpaperImg(ppt.wallpaperpath, fb.GetNowPlaying());
  2371.     }; else {
  2372.         //g_wallpaperImg = null;
  2373.         g_wallpaperImg = setWallpaperImg(ppt.wallpaperpath, fb.GetNowPlaying());
  2374.     };
  2375.  
  2376.     get_images();
  2377.  
  2378.     // set Size of browser
  2379.     if(cScrollBar.enabled) {
  2380.         brw.setSize(0, (ppt.showHeaderBar ? ppt.headerBarHeight : 0), ww - cScrollBar.width, wh - (ppt.showHeaderBar ? ppt.headerBarHeight : 0));
  2381.     }; else {
  2382.         brw.setSize(0, (ppt.showHeaderBar ? ppt.headerBarHeight : 0), ww, wh - (ppt.showHeaderBar ? ppt.headerBarHeight : 0));
  2383.     };
  2384. };
  2385.  
  2386. function on_paint(gr) {
  2387.    
  2388.     if(!ww) return;
  2389.    
  2390.     if(!g_1x1) {
  2391.         //gr.FillSolidRect(0, 0, ww, wh, RGBA(210,210,215,255));
  2392.         // draw background under playlist
  2393.         if(fb.IsPlaying && g_wallpaperImg && ppt.showwallpaper) {
  2394.             gr.GdiDrawBitmap(g_wallpaperImg, 0, 0, ww, wh, 0, 0, g_wallpaperImg.Width, g_wallpaperImg.Height);
  2395.             gr.FillSolidRect(0, 0, ww, wh, g_color_normal_bg & RGBA(255,255,255,ppt.wallpaperalpha));
  2396.         }; else {
  2397.             //gr.FillSolidRect(0, 0, ww, wh, g_color_normal_bg);
  2398.             if(g_wallpaperImg && ppt.showwallpaper) {
  2399.                 gr.GdiDrawBitmap(g_wallpaperImg, 0, 0, ww, wh, 0, 0, g_wallpaperImg.Width, g_wallpaperImg.Height);
  2400.                 gr.FillSolidRect(0, 0, ww, wh, g_color_normal_bg & RGBA(255,255,255,ppt.wallpaperalpha));
  2401.             }; else {
  2402.                 gr.FillSolidRect(0, 0, ww, wh, g_color_normal_bg);
  2403.             };
  2404.  
  2405.         };
  2406.        
  2407.         brw && brw.draw(gr);
  2408.        
  2409.         if(ppt.showHeaderBar) {
  2410.             // inputBox
  2411.             if(cFilterBox.enabled && g_filterbox) {
  2412.                 if(g_filterbox.inputbox.visible) {
  2413.                     g_filterbox.draw(gr, 5, 2);
  2414.                 };
  2415.             };
  2416.         };
  2417.     };
  2418.    
  2419.     // tweak to fix bug in timer/memory/repaint handle in WSH Panel Mod with timers
  2420.     g_counter_repaint++;
  2421.     if(g_counter_repaint > 500) {
  2422.         g_counter_repaint = 0;
  2423.         CollectGarbage();
  2424.     };
  2425. };
  2426.  
  2427. function on_mouse_lbtn_down(x, y) {
  2428.     g_lbtn_click = true;
  2429.     g_rbtn_click = false;
  2430.    
  2431.     // stop inertia
  2432.     if(cTouch.timer) {
  2433.         window.ClearInterval(cTouch.timer);
  2434.         cTouch.timer = false;
  2435.         // stop scrolling but not abrupt, add a little offset for the stop
  2436.         if(Math.abs(scroll - scroll_) > ppt.rowHeight) {
  2437.             scroll = (scroll > scroll_ ? scroll_ + ppt.rowHeight : scroll_ - ppt.rowHeight);
  2438.             scroll = check_scroll(scroll);
  2439.         };
  2440.     };
  2441.    
  2442.     var is_scroll_enabled = brw.rowsCount > brw.totalRowsVis;
  2443.     if(ppt.enableTouchControl && is_scroll_enabled) {
  2444.         if(brw._isHover(x, y) && !brw.scrollbar._isHover(x, y)) {
  2445.             if(!timers.mouseDown) {
  2446.                 cTouch.y_prev = y;
  2447.                 cTouch.y_start = y;
  2448.                 if(cTouch.t1) {
  2449.                     cTouch.t1.Reset();
  2450.                 }; else {
  2451.                     cTouch.t1 = fb.CreateProfiler("t1");
  2452.                 };
  2453.                 timers.mouseDown = window.SetTimeout(function() {
  2454.                     window.ClearTimeout(timers.mouseDown);
  2455.                     timers.mouseDown = false;
  2456.                     if(Math.abs(cTouch.y_start - m_y) > 015) {
  2457.                         cTouch.down = true;
  2458.                     }; else {
  2459.                         brw.on_mouse("down", x, y);
  2460.                     };
  2461.                 },50);
  2462.             };
  2463.         }; else {
  2464.             brw.on_mouse("down", x, y);
  2465.         };
  2466.     }; else {
  2467.         brw.on_mouse("down", x, y);
  2468.     };
  2469.    
  2470.     // inputBox
  2471.     if(ppt.showHeaderBar && cFilterBox.enabled && g_filterbox.inputbox.visible) {
  2472.         g_filterbox.on_mouse("lbtn_down", x, y);
  2473.     };
  2474. };
  2475.  
  2476. function on_mouse_lbtn_up(x, y) {
  2477.  
  2478.     // inputBox
  2479.     if(ppt.showHeaderBar && cFilterBox.enabled && g_filterbox.inputbox.visible) {
  2480.         g_filterbox.on_mouse("lbtn_up", x, y);
  2481.     };
  2482.     brw.on_mouse("up", x, y);
  2483.    
  2484.     if(timers.mouseDown) {
  2485.         window.ClearTimeout(timers.mouseDown);
  2486.         timers.mouseDown = false;
  2487.         if(Math.abs(cTouch.y_start - m_y) <= 030) {
  2488.             brw.on_mouse("down", x, y);
  2489.         };
  2490.     };
  2491.  
  2492.     // create scroll inertia on mouse lbtn up
  2493.     if(cTouch.down) {
  2494.         cTouch.down = false;
  2495.         cTouch.y_end = y;
  2496.         cTouch.scroll_delta = scroll - scroll_;
  2497.         if(Math.abs(cTouch.scroll_delta) > 015 ) {
  2498.             cTouch.multiplier = ((1000 - cTouch.t1.Time) / 20);
  2499.             cTouch.delta = Math.round((cTouch.scroll_delta) / 015);
  2500.             if(cTouch.multiplier < 1) cTouch.multiplier = 1;
  2501.             if(cTouch.timer) window.ClearInterval(cTouch.timer);
  2502.             cTouch.timer = window.SetInterval(function() {
  2503.                 scroll += cTouch.delta * cTouch.multiplier;
  2504.                 scroll = check_scroll(scroll);
  2505.                 cTouch.multiplier = cTouch.multiplier - 1;
  2506.                 cTouch.delta = cTouch.delta - (cTouch.delta / 10);
  2507.                 if(cTouch.multiplier < 1) {
  2508.                     window.ClearInterval(cTouch.timer);
  2509.                     cTouch.timer = false;
  2510.                 };
  2511.             }, 75);
  2512.         };
  2513.     };
  2514.    
  2515.     g_lbtn_click = false;
  2516. };
  2517.  
  2518. function on_mouse_lbtn_dblclk(x, y, mask) {
  2519.     if(y >= brw.y) {    
  2520.         brw.on_mouse("dblclk", x, y);
  2521.     }; else if(x > brw.x && x < brw.x + brw.w) {
  2522.         //brw.showNowPlaying();
  2523.     }; else {
  2524.         brw.on_mouse("dblclk", x, y);
  2525.     };
  2526. };
  2527.  
  2528. function on_mouse_rbtn_down(x, y, mask) {
  2529.     g_rbtn_click = true;
  2530.    
  2531.     if(!utils.IsKeyPressed(VK_SHIFT)) {
  2532.         // inputBox
  2533.         if(ppt.showHeaderBar && cFilterBox.enabled && g_filterbox.inputbox.visible) {
  2534.             g_filterbox.on_mouse("rbtn_down", x, y);
  2535.         };
  2536.        
  2537.         brw.on_mouse("right", x, y);
  2538.     };
  2539. };
  2540.  
  2541. function on_mouse_rbtn_up(x, y){
  2542.     g_rbtn_click = false;
  2543.    
  2544.     if(!utils.IsKeyPressed(VK_SHIFT)) {
  2545.         return true;
  2546.     };
  2547. };
  2548.  
  2549. function on_mouse_move(x, y) {
  2550.    
  2551.     if(m_x == x && m_y == y) return;
  2552.    
  2553.     // inputBox
  2554.     if(ppt.showHeaderBar && cFilterBox.enabled && g_filterbox.inputbox.visible) {
  2555.         g_filterbox.on_mouse("move", x, y);
  2556.     };
  2557.    
  2558.     if(cTouch.down) {
  2559.         cTouch.y_current = y;
  2560.         cTouch.y_move = (cTouch.y_current - cTouch.y_prev);
  2561.         if(x < brw.w) {
  2562.                 scroll -= cTouch.y_move;
  2563.                 cTouch.scroll_delta = scroll - scroll_;
  2564.                 if(Math.abs(cTouch.scroll_delta) < 030) cTouch.y_start = cTouch.y_current;
  2565.                 cTouch.y_prev = cTouch.y_current;
  2566.         };
  2567.     }; else {
  2568.         brw.on_mouse("move", x, y);
  2569.     };
  2570.  
  2571.     m_x = x;
  2572.     m_y = y;
  2573. };
  2574.  
  2575. function on_mouse_wheel(step){
  2576.    
  2577.     if(utils.IsKeyPressed(VK_CONTROL)) {
  2578.         if(ppt.panelMode == 1 || ppt.panelMode == 3) { // Stamps mode != Lines mode
  2579.             var previous = ppt.thumbnailWidthMin;
  2580.             //g_scroll_rows = Math.round(scroll / brw.rowHeight);
  2581.             ppt.thumbnailWidthMin += step * Math.floor(ppt.thumbnailWidthMin / 4);
  2582.             if(ppt.thumbnailWidthMin < 130) ppt.thumbnailWidthMin = 125;
  2583.             if(ppt.thumbnailWidthMin > 230) ppt.thumbnailWidthMin = 225;
  2584.             if(previous != ppt.thumbnailWidthMin) {
  2585.                 g_image_cache = new image_cache;
  2586.                 CollectGarbage();
  2587.                 window.SetProperty("SYSTEM thumbnails Minimal Width", ppt.thumbnailWidthMin);
  2588.                 brw.setList();
  2589.             };
  2590.             return;
  2591.         }; else if(ppt.panelMode == 0) {
  2592.             var previous = ppt.lineHeightMin;
  2593.             ppt.lineHeightMin += step * Math.floor(ppt.lineHeightMin / 4);
  2594.             if(ppt.tagMode == 1) {
  2595.                 if(ppt.lineHeightMin < 44) ppt.lineHeightMin = 44;
  2596.             }; else {
  2597.                 if(ppt.lineHeightMin < 22) ppt.lineHeightMin = 22;
  2598.             };
  2599.             if(ppt.lineHeightMin > 100) ppt.lineHeightMin = 100;
  2600.             if(previous != ppt.lineHeightMin) {
  2601.                 g_image_cache = new image_cache;
  2602.                 CollectGarbage();
  2603.                 window.SetProperty("SYSTEM Minimal Line Height", ppt.lineHeightMin);
  2604.                 brw.setList();
  2605.             };
  2606.             return;
  2607.         }; else if(ppt.panelMode == 2) {
  2608.             var previous = ppt.lineHeightMin;
  2609.             ppt.lineHeightMin += step * Math.floor(ppt.lineHeightMin / 4);
  2610.             if(ppt.lineHeightMin < 60) ppt.lineHeightMin = 60;
  2611.             if(ppt.lineHeightMin > 180) ppt.lineHeightMin = 180;
  2612.             if(previous != ppt.lineHeightMin) {
  2613.                 g_image_cache = new image_cache;
  2614.                 CollectGarbage();
  2615.                 window.SetProperty("SYSTEM Minimal Line Height", ppt.lineHeightMin);
  2616.                 brw.setList();
  2617.             };
  2618.             return;
  2619.         };
  2620.     };
  2621.  
  2622.     scroll -= step * (brw.rowHeight / ppt.scrollRowDivider * ppt.rowScrollStep);
  2623.     scroll = check_scroll(scroll)
  2624.    
  2625.     brw.on_mouse("wheel", m_x, m_y, step);
  2626.    
  2627. };
  2628.  
  2629. function on_mouse_leave() {
  2630.     // inputBox
  2631.     if(ppt.showHeaderBar && cFilterBox.enabled && g_filterbox.inputbox.visible) {
  2632.         g_filterbox.on_mouse("leave", 0, 0);
  2633.     };
  2634.     brw.on_mouse("leave", 0, 0);
  2635. };
  2636.  
  2637. //=================================================// Metrics & Fonts & Colors & Images
  2638. function get_metrics() {
  2639.     if(ppt.showHeaderBar) {
  2640.         ppt.headerBarHeight = Math.round(ppt.defaultHeaderBarHeight * g_zoom_percent / 100);
  2641.         ppt.headerBarHeight = Math.floor(ppt.headerBarHeight / 2) != ppt.headerBarHeight / 2 ? ppt.headerBarHeight : ppt.headerBarHeight - 1;
  2642.     }; else {
  2643.         ppt.headerBarHeight = 0;
  2644.     };
  2645.     cScrollBar.width = Math.floor(cScrollBar.defaultWidth * g_zoom_percent / 100);
  2646.     cScrollBar.minCursorHeight = Math.round(cScrollBar.defaultMinCursorHeight * g_zoom_percent / 100);
  2647.    
  2648.     if(brw) {
  2649.         brw.setSize(0, ppt.headerBarHeight, ww - cScrollBar.width, wh - ppt.headerBarHeight);
  2650.         brw.setList();
  2651.     };
  2652. };
  2653.  
  2654. function get_images() {
  2655.    
  2656.     // PLAY icon  
  2657.     images.play_on = gdi.CreateImage(70, 70);
  2658.     var gb = images.play_on.GetGraphics();
  2659.     DrawPolyStar(gb, 12-2, 12, 46, 1, 3, 2, g_color_normal_bg, g_color_normal_txt, 90, 255);
  2660.     images.play_on.ReleaseGraphics(gb);
  2661.  
  2662.     images.play_off = gdi.CreateImage(70, 70);
  2663.     var gb = images.play_off.GetGraphics();
  2664.     DrawPolyStar(gb, 16-2, 16, 38, 1, 3, 2, g_color_normal_bg, g_color_normal_txt, 90, 255);
  2665.     images.play_off.ReleaseGraphics(gb);
  2666.    
  2667.     images.all = gdi.CreateImage(150, 150);
  2668.     var gb = images.all.GetGraphics();
  2669.     gb.FillSolidRect(0, 0, 150, 150, RGB(0,0,0));
  2670.     images.all.ReleaseGraphics(gb);
  2671.    
  2672.     var img_loading = gdi.Image(images.path+"load.png");
  2673.     var iw = Math.round(ppt.rowHeight / 2);
  2674.     images.loading_draw = img_loading.Resize(iw, iw, 7);
  2675. };
  2676.  
  2677. function get_font() {
  2678.     var font_error = false;
  2679.     var default_font = null;
  2680.    
  2681.     if (g_instancetype == 0) {
  2682.         default_font = window.GetFontCUI(FontTypeCUI.items);
  2683.         g_font_headers = window.GetFontCUI(FontTypeCUI.labels);
  2684.     }; else if (g_instancetype == 1) {
  2685.         default_font = window.GetFontDUI(FontTypeDUI.playlists);
  2686.         g_font_headers = window.GetFontDUI(FontTypeDUI.tabs);
  2687.     };
  2688.    
  2689.     // tweaks to fix a problem with WSH Panel Mod on Font object Name property
  2690.     try {
  2691.         g_fname = default_font.Name;
  2692.         g_fsize = default_font.Size;
  2693.         g_fstyle = default_font.Style;
  2694.     }; catch(e) {
  2695.         fb.trace("WSH Panel Error: Unable to use the default font. Using Arial font instead.");
  2696.         g_fname = "arial";
  2697.         g_fsize = 12;
  2698.         g_fstyle = 0;
  2699.         font_error = true;
  2700.     };
  2701.    
  2702.     // adjust font size if extra zoom activated
  2703.     g_fsize += ppt.extra_font_size;
  2704.     g_font = gdi.Font(g_fname, g_fsize, g_fstyle);
  2705.    
  2706.     g_zoom_percent = Math.floor(g_fsize / 12 * 100);
  2707.  
  2708.     g_font_group1 = gdi.Font(g_fname, (g_fsize * 160 / 100), 1);
  2709.     g_font_group2 = gdi.Font(g_fname, (g_fsize * 140 / 100), 0);
  2710.    
  2711.     if(g_font_guifx_found) {
  2712.         g_font_rating = gdi.Font("guifx v2 transports", (g_fsize * 140 / 100), 0);
  2713.         g_font_mood = gdi.Font("guifx v2 transports", (g_fsize * 130 / 100), 0);
  2714.     }; else if(g_font_wingdings2_found) {
  2715.         g_font_rating = gdi.Font("wingdings 2", (g_fsize * 140 / 100), 0);
  2716.         g_font_mood = gdi.Font("wingdings 2", (g_fsize * 200 / 100), 0);
  2717.     }; else {
  2718.         g_font_rating = gdi.Font("arial", (g_fsize * 140 / 100), 0);
  2719.         g_font_mood = gdi.Font("arial", (g_fsize * 140 / 100), 0);
  2720.     };
  2721. };
  2722.  
  2723. function get_colors() {
  2724.     var arr;
  2725.     // get some system colors
  2726.     g_syscolor_window_bg = utils.GetSysColor(COLOR_WINDOW);
  2727.     g_syscolor_highlight = utils.GetSysColor(COLOR_HIGHLIGHT);
  2728.     g_syscolor_button_bg = utils.GetSysColor(COLOR_BTNFACE);
  2729.     g_syscolor_button_txt = utils.GetSysColor(COLOR_BTNTEXT);
  2730.  
  2731.     arr = window.GetProperty("CUSTOM COLOR TEXT NORMAL", "180-180-180").split("-");
  2732.     g_color_normal_txt = RGB(arr[0], arr[1], arr[2]);
  2733.     arr = window.GetProperty("CUSTOM COLOR TEXT SELECTED", "200-210-255").split("-");
  2734.     g_color_selected_txt = RGB(arr[0], arr[1], arr[2]);
  2735.     arr = window.GetProperty("CUSTOM COLOR BACKGROUND NORMAL", "25-25-35").split("-");
  2736.     g_color_normal_bg = RGB(arr[0], arr[1], arr[2]);
  2737.     arr = window.GetProperty("CUSTOM COLOR BACKGROUND SELECTED", "130-150-255").split("-");
  2738.     g_color_selected_bg = RGB(arr[0], arr[1], arr[2]);
  2739.     arr = window.GetProperty("CUSTOM COLOR HIGHLIGHT", "255-175-50").split("-");
  2740.     g_color_highlight = RGB(arr[0], arr[1], arr[2]);
  2741.  
  2742.     // get custom colors from window ppt first  
  2743.     if(!ppt.enableCustomColors) {
  2744.         // get UI colors set in UI Preferences if no custom color set
  2745.         if (g_instancetype == 0) {
  2746.             g_color_normal_txt = window.GetColorCUI(ColorTypeCUI.text);
  2747.             g_color_selected_txt = window.GetColorCUI(ColorTypeCUI.selection_text);
  2748.             g_color_normal_bg = window.GetColorCUI(ColorTypeCUI.background);
  2749.             g_color_selected_bg = window.GetColorCUI(ColorTypeCUI.selection_background);
  2750.             g_color_highlight = window.GetColorCUI(ColorTypeCUI.active_item_frame);
  2751.         }; else if (g_instancetype == 1) {
  2752.             g_color_normal_txt = window.GetColorDUI(ColorTypeDUI.text);
  2753.             g_color_selected_txt = window.GetColorDUI(ColorTypeDUI.selection);
  2754.             g_color_normal_bg = window.GetColorDUI(ColorTypeDUI.background);
  2755.             g_color_selected_bg = g_color_selected_txt;
  2756.             g_color_highlight = window.GetColorDUI(ColorTypeDUI.highlight);
  2757.         };
  2758.     };
  2759. };
  2760.  
  2761. function on_font_changed() {
  2762.     get_font();
  2763.     get_metrics();
  2764.     brw.repaint();
  2765. };
  2766.  
  2767. function on_colors_changed() {
  2768.     get_colors();
  2769.     get_images();
  2770.     if(brw) brw.scrollbar.setNewColors();
  2771.     g_filterbox.getImages();
  2772.     brw.repaint();
  2773. };
  2774.  
  2775. function on_script_unload() {
  2776.     brw.g_time && window.ClearInterval(brw.g_time);
  2777.     brw.g_time = false;
  2778.     brw.g_timeCover && window.ClearInterval(brw.g_timeCover);
  2779.     brw.g_timeCover = false;
  2780. };
  2781.  
  2782. //=================================================// Keyboard Callbacks
  2783. function on_key_up(vkey) {
  2784.     if(cSettings.visible) {
  2785.  
  2786.     }; else {
  2787.         // inputBox
  2788.         if(cFilterBox.enabled && g_filterbox.inputbox.visible) {
  2789.             g_filterbox.on_key("up", vkey);
  2790.         };
  2791.        
  2792.         // scroll keys up and down RESET (step and timers)
  2793.         brw.keypressed = false;
  2794.         cScrollBar.timerCounter = -1;
  2795.         cScrollBar.timerID && window.ClearTimeout(cScrollBar.timerID);
  2796.         cScrollBar.timerID = false;
  2797.         if(vkey == VK_SHIFT) {
  2798.             brw.SHIFT_start_id = null;
  2799.             brw.SHIFT_count = 0;
  2800.         };
  2801.     };
  2802.     brw.repaint();
  2803. };
  2804.  
  2805.  
  2806. function on_key_down(vkey) {
  2807.     var mask = GetKeyboardMask();
  2808.    
  2809.     if(cSettings.visible) {
  2810.  
  2811.     }; else {
  2812.         //if(dragndrop.drag_in) return true;
  2813.  
  2814.         // inputBox
  2815.         if(cFilterBox.enabled && g_filterbox.inputbox.visible) {
  2816.             g_filterbox.on_key("down", vkey);
  2817.         };
  2818.  
  2819.         var act_pls = g_active_playlist;
  2820.        
  2821.         if (mask == KMask.none) {
  2822.             switch (vkey) {
  2823.             case VK_F2:
  2824.  
  2825.                 break;
  2826.             case VK_F5:
  2827.                 // refresh covers
  2828.                 g_image_cache = new image_cache;
  2829.                 CollectGarbage();
  2830.                 brw.repaint();
  2831.                 break;
  2832.             case VK_F6:
  2833.  
  2834.                 break;
  2835.             case VK_TAB:
  2836.                 break;
  2837.             case VK_BACK:
  2838.  
  2839.                 break;
  2840.             case VK_ESCAPE:
  2841.             case 222:
  2842.  
  2843.                 break;
  2844.             case VK_UP:              
  2845.                 if(brw.rowsCount > 0 && !brw.keypressed && !cScrollBar.timerID) {
  2846.                     brw.keypressed = true;
  2847.                     reset_cover_timers();
  2848.                 };
  2849.                 break;
  2850.             case VK_DOWN:
  2851.                 if(brw.rowsCount > 0 && !brw.keypressed && !cScrollBar.timerID) {
  2852.                     brw.keypressed = true;
  2853.                     reset_cover_timers();
  2854.                 };
  2855.                 break;
  2856.             case VK_PGUP:
  2857.                 if(brw.rowsCount > 0 && !brw.keypressed && !cScrollBar.timerID) {
  2858.                     brw.keypressed = true;
  2859.                     reset_cover_timers();
  2860.                 };
  2861.                 break;
  2862.             case VK_PGDN:
  2863.                 if(brw.rowsCount > 0 && !brw.keypressed && !cScrollBar.timerID) {
  2864.                     brw.keypressed = true;
  2865.                     reset_cover_timers();
  2866.                 };
  2867.                 break;
  2868.             case VK_RETURN:
  2869.                 // play/enqueue focused item
  2870.                 break;
  2871.             case VK_END:
  2872.                 if(brw.rowsCount > 0) {
  2873.  
  2874.                 };
  2875.                 break;
  2876.             case VK_HOME:
  2877.                 if(brw.rowsCount > 0) {
  2878.  
  2879.                 };
  2880.                 break;
  2881.             case VK_DELETE:
  2882.                 if(!fb.IsAutoPlaylist(act_pls)) {
  2883.  
  2884.                 };
  2885.                 break;
  2886.             };
  2887.         }; else {
  2888.             switch(mask) {
  2889.                 case KMask.shift:
  2890.                     switch(vkey) {
  2891.                         case VK_SHIFT: // SHIFT key alone
  2892.  
  2893.                             break;
  2894.                         case VK_UP: // SHIFT + KEY UP
  2895.  
  2896.                             break;
  2897.                         case VK_DOWN: // SHIFT + KEY DOWN
  2898.  
  2899.                             break;
  2900.                     };
  2901.                     break;
  2902.                 case KMask.ctrl:
  2903.                     if(vkey==65) { // CTRL+A
  2904.  
  2905.                     };
  2906.                     if(vkey==88) { // CTRL+X
  2907.                         if(!fb.IsAutoPlaylist(act_pls)) {
  2908.  
  2909.                         };
  2910.                     };
  2911.                     if(vkey==67) { // CTRL+C
  2912.  
  2913.                     };
  2914.                     if(vkey==86) { // CTRL+V
  2915.  
  2916.                     };
  2917.                     if(vkey==70) { // CTRL+F
  2918.                         fb.RunMainMenuCommand("Edit/Search");
  2919.                     };
  2920.                     if(vkey==73) { // CTRL+I
  2921.  
  2922.                     };
  2923.                     if(vkey==78) { // CTRL+N
  2924.                         fb.RunMainMenuCommand("File/New playlist");
  2925.                     };
  2926.                     if(vkey==79) { // CTRL+O
  2927.                         fb.RunMainMenuCommand("File/Open...");
  2928.                     };
  2929.                     if(vkey==80) { // CTRL+P
  2930.                         fb.RunMainMenuCommand("File/Preferences");
  2931.                     };
  2932.                     if(vkey==83) { // CTRL+S
  2933.                         fb.RunMainMenuCommand("File/Save playlist...");
  2934.                     };
  2935.                     if(vkey==84) { // CTRL+T
  2936.  
  2937.                     };
  2938.                     if(vkey == 48) { // CTRL + 0
  2939.  
  2940.                     };
  2941.                     break;
  2942.                 case KMask.alt:
  2943.                     switch(vkey) {
  2944.                     case 65: // ALT+A
  2945.                         fb.RunMainMenuCommand("View/Always on Top");
  2946.                         break;
  2947.                     case VK_ALT: // ALT key alone
  2948.                         break;
  2949.                     };
  2950.                     break;
  2951.             };
  2952.         };
  2953.  
  2954.     };
  2955. };
  2956.  
  2957. function on_char(code) {
  2958.     // inputBox
  2959.     if(cFilterBox.enabled && g_filterbox.inputbox.visible) {
  2960.         g_filterbox.on_char(code);
  2961.     };
  2962. };
  2963.  
  2964. //=================================================// Playback Callbacks
  2965. function on_playback_stop(reason) {
  2966.     g_seconds = 0;
  2967.     g_time_remaining = null;
  2968.     g_metadb = null;
  2969.    
  2970.     switch(reason) {
  2971.     case 0: // user stop
  2972.     case 1: // eof (e.g. end of playlist)
  2973.         // update wallpaper
  2974.         if(ppt.showwallpaper) {
  2975.             g_wallpaperImg = setWallpaperImg(ppt.wallpaperpath, null);
  2976.         };
  2977.         brw.repaint();
  2978.         break;
  2979.     case 2: // starting_another (only called on user action, i.e. click on next button)
  2980.         break;
  2981.     };
  2982. };
  2983.  
  2984. function on_playback_new_track(metadb) {
  2985.     g_metadb = metadb;
  2986.     if(ppt.showwallpaper) {
  2987.         g_wallpaperImg = setWallpaperImg(ppt.wallpaperpath, metadb);
  2988.     };
  2989.     brw.repaint();
  2990. };
  2991.  
  2992. function on_playback_starting(cmd, is_paused) {
  2993. };
  2994.  
  2995. function on_playback_time(time) {
  2996.     g_seconds = time;
  2997.     g_time_remaining = ppt.tf_time_remaining.Eval(true);
  2998. };
  2999.  
  3000. //=================================================// Library Callbacks
  3001. function on_library_items_added() {
  3002.     //fb.trace("..on_library_items_added "+gtt.Time);
  3003.     brw.populate(is_first_populate = false);
  3004. };
  3005.  
  3006. function on_library_items_removed() {
  3007.     //fb.trace("..on_library_items_removed "+gtt.Time);
  3008.     brw.populate(is_first_populate = false);
  3009. };
  3010.  
  3011. function on_library_items_changed() {
  3012.     //fb.trace("..on_library_items_changed "+gtt.Time);
  3013.     brw.populate(is_first_populate = false);
  3014.    
  3015.     //ask_for_reloading_library();
  3016.     //on_tags_updated();
  3017. };
  3018.  
  3019. //=================================================// Playlist Callbacks
  3020. function on_playlists_changed() {
  3021.     if(plman.ActivePlaylist < 0 || plman.ActivePlaylist > plman.PlaylistCount - 1) {
  3022.         plman.ActivePlaylist = 0;
  3023.     };
  3024.     if(g_active_playlist != plman.ActivePlaylist) {
  3025.         g_active_playlist = plman.ActivePlaylist;
  3026.     };
  3027. };
  3028.  
  3029. function on_playlist_switch() {
  3030.     //fb.trace("pl switch");
  3031.     g_active_playlist = plman.ActivePlaylist;
  3032.     if(ppt.sourceMode == 1) {
  3033.         brw.populate(is_first_populate = true);
  3034.     };
  3035. };
  3036.  
  3037. function on_playlist_items_added(playlist_idx) {
  3038.     g_avoid_on_playlist_items_removed_callbacks_on_sendItemToPlaylist = false;
  3039.    
  3040.     if(ppt.sourceMode == 1) {
  3041.         if(playlist_idx == g_active_playlist) {
  3042.             brw.populate(is_first_populate = false);
  3043.         };
  3044.     };
  3045. };
  3046.  
  3047. function on_playlist_items_removed(playlist_idx, new_count) {
  3048.     if(g_avoid_on_playlist_items_removed_callbacks_on_sendItemToPlaylist) return;
  3049.    
  3050.     //fb.trace("items removed");
  3051.     if(ppt.sourceMode == 1) {
  3052.         if(playlist_idx == g_active_playlist) {
  3053.             brw.populate(is_first_populate = true);
  3054.         };
  3055.     };
  3056. };
  3057.  
  3058. function on_playlist_items_reordered(playlist_idx) {
  3059.     if(ppt.sourceMode == 1) {
  3060.         if(playlist_idx == g_active_playlist) {
  3061.             brw.populate(is_first_populate = true);
  3062.         };
  3063.     };
  3064. };
  3065.  
  3066.  
  3067. function on_item_focus_change(playlist, from, to) {
  3068.  
  3069. };
  3070.  
  3071. function on_metadb_changed(metadb_or_metadbs, fromhook) {
  3072.     // rebuild list
  3073.     if(ppt.sourceMode == 1) {
  3074.         if(filter_text.length > 0) {
  3075.             brw.populate(is_first_populate = true);
  3076.         }; else {
  3077.             brw.populate(is_first_populate = false);
  3078.         };
  3079.     };
  3080. };
  3081.  
  3082. function on_item_selection_change() {
  3083.     brw.repaint();
  3084. };
  3085.  
  3086. function on_playlist_items_selection_change() {
  3087.     brw.repaint();
  3088. };
  3089.  
  3090. function on_focus(is_focused) {
  3091.     //fb.trace("on focus");
  3092.    
  3093.     g_focus = is_focused;
  3094.  
  3095.     if(!is_focused) {
  3096.         brw.repaint();
  3097.     };
  3098. };
  3099.  
  3100. //=================================================// Custom functions
  3101. function match(input, str){
  3102.     var temp = "";
  3103.     input = input.toLowerCase();
  3104.     for(var j in str){
  3105.         if(input.indexOf(str[j]) < 0)
  3106.             return false;
  3107.     };
  3108.     return true;
  3109. };
  3110.  
  3111. function check_playlist(name){
  3112.     var pl_name = "", pl_idx = -1;
  3113.     for(var i=0; i < plman.PlaylistCount; i++) {
  3114.         pl_name = plman.GetPlaylistName(i);
  3115.         if(pl_name == name) {
  3116.             pl_idx = i;
  3117.             break;
  3118.         };
  3119.     };
  3120.     return pl_idx;
  3121. };
  3122.  
  3123. function process_string(str){
  3124.     str_ = [];
  3125.     str = str.toLowerCase();
  3126.     while(str !=(temp = str.replace("  "," ")))
  3127.         str  = temp;
  3128.     var str = str.split(" ").sort();
  3129.     for(var i in str){
  3130.         if(str[i] != "")
  3131.             str_[str_.length] = str[i];
  3132.     };
  3133.     return str_;
  3134. };
  3135.  
  3136. function check_scroll(scroll___){
  3137.     if(scroll___ < 0)
  3138.         scroll___ = 0;
  3139.     var g1 = brw.h - (brw.totalRowsVis * ppt.rowHeight);
  3140.     //var scroll_step = Math.ceil(ppt.rowHeight / ppt.scrollRowDivider);
  3141.     //var g2 = Math.floor(g1 / scroll_step) * scroll_step;
  3142.  
  3143.     var end_limit = (brw.rowsCount * ppt.rowHeight) - (brw.totalRowsVis * ppt.rowHeight) - g1;
  3144.     if(scroll___ != 0 && scroll___ > end_limit) {
  3145.         scroll___ = end_limit;
  3146.     };
  3147.     return scroll___;
  3148. };
  3149.  
  3150. // ===================================================== // Wallpaper
  3151. function setWallpaperImg(path, metadb) {
  3152.     var fmt_path = fb.TitleFormat(path).Eval(true);
  3153.     var fmt_path_arr = utils.Glob(fmt_path).toArray();
  3154.     if(fmt_path_arr.length > 0) {
  3155.         var final_path = fmt_path_arr[0];
  3156.     }; else {
  3157.         var final_path = null;
  3158.     };
  3159.    
  3160.     if(metadb && ppt.wallpapermode == 0) {
  3161.         var tmp_img = utils.GetAlbumArtV2(metadb, ppt.wallpapermode);
  3162.     }; else {
  3163.         if(final_path) {
  3164.             tmp_img = gdi.Image(final_path);
  3165.         }; else {
  3166.             tmp_img = null;
  3167.         };
  3168.     };
  3169.     if(!tmp_img) {
  3170.         if(final_path) {
  3171.             tmp_img = gdi.Image(final_path);
  3172.         }; else {
  3173.             tmp_img = null;
  3174.         };
  3175.     };
  3176.  
  3177.     g_wallpaperImg = null;
  3178.     var img = FormatWallpaper(tmp_img, ww, wh, 2, 0, 0, "", true);
  3179.     return img;
  3180. };
  3181.  
  3182. function draw_blurred_image(image,ix,iy,iw,ih,bx,by,bw,bh,blur_value,overlay_color) {
  3183.     var blurValue = blur_value;
  3184.     var imgA = image.Resize(iw*blurValue/100,ih*blurValue/100,2);
  3185.     var imgB = imgA.resize(iw, ih, 2);
  3186.    
  3187.     var bbox = gdi.CreateImage(bw, bh);
  3188.     // Get graphics interface like "gr" in on_paint
  3189.     var gb = bbox.GetGraphics();
  3190.     var offset = 90-blurValue;
  3191.     gb.DrawImage(imgB, 0-offset, 0-(ih-bh)-offset, iw+offset*2, ih+offset*2, 0, 0, imgB.Width, imgB.Height, 0, 255);
  3192.     bbox.ReleaseGraphics(gb);
  3193.  
  3194.     var newImg = gdi.CreateImage(iw, ih);
  3195.     var gb = newImg.GetGraphics();
  3196.  
  3197.     if(ix!=bx || iy!=by || iw!=bw || ih!=bh) {
  3198.         gb.DrawImage(image, ix, iy, iw, ih, 0, 0, image.Width, image.Height, 0, 255);
  3199.         gb.FillSolidRect(bx,by,bw,bh,0xffffffff);
  3200.     };
  3201.     gb.DrawImage(bbox, bx, by, bw, bh, 0, 0, bbox.Width, bbox.Height, 0, 255);
  3202.    
  3203.     // overlay
  3204.     if(overlay_color!=null) {
  3205.         gb.FillSolidRect(bx,by,bw,bh,overlay_color);
  3206.     };
  3207.    
  3208.     // top border of blur area
  3209.     if(ix!=bx || iy!=by || iw!=bw || ih!=bh) {
  3210.         gb.FillSolidRect(bx,by,bw,1,0x22ffffff);
  3211.         gb.FillSolidRect(bx,by-1,bw,1,0x22000000);
  3212.     };
  3213.     newImg.ReleaseGraphics(gb);
  3214.    
  3215.     return newImg;
  3216. };
  3217.  
  3218. function FormatWallpaper(image, iw, ih, interpolation_mode, display_mode, angle, txt, rawBitmap) {
  3219.     if(!image||!iw||!ih) return image;
  3220.     var i, j;
  3221.  
  3222.     var panel_ratio = iw / ih;
  3223.     wpp_img_info.ratio = image.Width / image.Height;
  3224.     wpp_img_info.orient = 0;
  3225.  
  3226.     if(wpp_img_info.ratio > panel_ratio) {
  3227.         wpp_img_info.orient = 1;
  3228.         // 1/3 : default image is in landscape mode    
  3229.         switch(display_mode) {
  3230.             case 0:     // Filling
  3231.                 //wpp_img_info.w = iw * wpp_img_info.ratio / panel_ratio;
  3232.                 wpp_img_info.w = ih * wpp_img_info.ratio;
  3233.                 wpp_img_info.h = ih;
  3234.                 wpp_img_info.cut = wpp_img_info.w - iw;
  3235.                 wpp_img_info.x = 0 - (wpp_img_info.cut / 2);
  3236.                 wpp_img_info.y = 0;
  3237.                 break;
  3238.             case 1:     // Adjust
  3239.                 wpp_img_info.w = iw;
  3240.                 wpp_img_info.h = ih / wpp_img_info.ratio * panel_ratio;
  3241.                 wpp_img_info.cut = ih - wpp_img_info.h;
  3242.                 wpp_img_info.x = 0;
  3243.                 wpp_img_info.y = wpp_img_info.cut / 2;
  3244.                 break;
  3245.             case 2:     // Stretch
  3246.                 wpp_img_info.w = iw;
  3247.                 wpp_img_info.h = ih;
  3248.                 wpp_img_info.cut = 0;
  3249.                 wpp_img_info.x = 0;
  3250.                 wpp_img_info.y = 0;
  3251.                 break;
  3252.         };
  3253.     }; else if(wpp_img_info.ratio < panel_ratio) {
  3254.         wpp_img_info.orient = 2;
  3255.         // 2/3 : default image is in portrait mode
  3256.         switch(display_mode) {
  3257.             case 0:     // Filling
  3258.                 wpp_img_info.w = iw;
  3259.                 //wpp_img_info.h = ih / wpp_img_info.ratio * panel_ratio;
  3260.                 wpp_img_info.h = iw / wpp_img_info.ratio;
  3261.                 wpp_img_info.cut = wpp_img_info.h - ih;
  3262.                 wpp_img_info.x = 0;
  3263.                 wpp_img_info.y = 0 - (wpp_img_info.cut / 4);
  3264.                 break;
  3265.             case 1:     // Adjust
  3266.                 wpp_img_info.h = ih;
  3267.                 wpp_img_info.w = iw * wpp_img_info.ratio / panel_ratio;
  3268.                 wpp_img_info.cut = iw - wpp_img_info.w;
  3269.                 wpp_img_info.y = 0;
  3270.                 wpp_img_info.x = wpp_img_info.cut / 2;
  3271.                 break;
  3272.             case 2:     // Stretch
  3273.                 wpp_img_info.w = iw;
  3274.                 wpp_img_info.h = ih;
  3275.                 wpp_img_info.cut = 0;
  3276.                 wpp_img_info.x = 0;
  3277.                 wpp_img_info.y = 0;
  3278.                 break;
  3279.         };
  3280.     }; else {
  3281.         // 3/3 : default image is a square picture, ratio = 1
  3282.         wpp_img_info.w = iw;
  3283.         wpp_img_info.h = ih;
  3284.         wpp_img_info.cut = 0;
  3285.         wpp_img_info.x = 0;
  3286.         wpp_img_info.y = 0;
  3287.     };
  3288.  
  3289.     var tmp_img = gdi.CreateImage(iw, ih);
  3290.     var gp = tmp_img.GetGraphics();
  3291.     gp.SetInterpolationMode(interpolation_mode);
  3292.     gp.DrawImage(image, wpp_img_info.x, wpp_img_info.y, wpp_img_info.w, wpp_img_info.h, 0, 0, image.Width, image.Height, angle, 255);
  3293.     tmp_img.ReleaseGraphics(gp);
  3294.    
  3295.     // blur it!
  3296.     if(ppt.wallpaperblurred) {
  3297.         var blur_factor = ppt.wallpaperblurvalue; // [1-90]
  3298.         tmp_img = draw_blurred_image(tmp_img,0,0,tmp_img.Width,tmp_img.Height,0,0,tmp_img.Width,tmp_img.Height,blur_factor,0x00ffffff);
  3299.     };
  3300.    
  3301.     CollectGarbage();
  3302.     if(rawBitmap) {
  3303.         return tmp_img.CreateRawBitmap();
  3304.     }; else {
  3305.         return tmp_img;
  3306.     };
  3307. };
  3308.  
  3309. function g_sendResponse() {
  3310.     if(g_filterbox.inputbox.text.length == 0) {
  3311.         filter_text = "";
  3312.     }; else {
  3313.         filter_text = g_filterbox.inputbox.text;
  3314.     };
  3315.        
  3316.     // filter in current panel
  3317.     brw.populate(true);
  3318. };
  3319.  
  3320. function on_notify_data(name, info) {
  3321.     switch(name) {
  3322.         case "JSSmoothBRowser->JSSmoothPlaylist:avoid_on_playlist_items_removed_callbacks_on_sendItemToPlaylist":
  3323.             g_avoid_on_playlist_items_removed_callbacks_on_sendItemToPlaylist = true;
  3324.             break;
  3325.     };
  3326. };
  3327.  
  3328. // ======================================================================================================================= //
  3329. function getpath(path){
  3330.     var img_path = "";
  3331.     var path_, temp, subFlds, tmp;
  3332.     for(var iii = 0; iii < 2; iii++){
  3333.         if(tmp = getpath_(iii == 0 ? path :(path + "..\\")))
  3334.             return tmp;
  3335.         try {
  3336.         subFlds = new Enumerator(fso.GetFolder((iii == 0 ? path : (path + "..\\"))).SubFolders);
  3337.         }; catch(err) { return null };
  3338.         for (; !subFlds.atEnd(); subFlds.moveNext()) {
  3339.             temp = subFlds.item() + "\\";
  3340.             if(temp.toLowerCase().match(cover_path)){
  3341.                 if(tmp = getpath_(temp))
  3342.                     return tmp;
  3343.             };
  3344.         };
  3345.     };
  3346.     return null;
  3347. };
  3348.  
  3349. function getpath_(temp){
  3350.     var img_path = "", path_;
  3351.     for(var iii in cover_img){
  3352.         path_ = utils.Glob(temp + cover_img[iii], exc_mask = FILE_ATTRIBUTE_DIRECTORY, inc_mask = 0xffffffff).toArray();
  3353.         for(var j in path_){
  3354.             if(path_[j].toLowerCase().indexOf(".jpg") > -1 || path_[j].toLowerCase().indexOf(".png") > -1 || path_[j].toLowerCase().indexOf(".gif") > -1 ){
  3355.                 return path_[j];
  3356.             };
  3357.         };
  3358.     };
  3359.     return null;
  3360. };
  3361.  
  3362. function check_cache(metadb, albumIndex){
  3363.     //var crc = ppt.tf_crc.EvalWithMetadb(metadb);
  3364.     var crc = brw.groups[albumIndex].cachekey;
  3365.     if(fso.FileExists(fb.ProfilePath + "wsh_br3tt\\cache\\imgcache\\" + crc)) {
  3366.         return crc;
  3367.     };
  3368.     return null;
  3369. };
  3370.  
  3371. function load_image_from_cache(metadb, crc){
  3372.     if(fso.FileExists(fb.ProfilePath + "wsh_br3tt\\cache\\imgcache\\" + crc)){ // image in folder cache
  3373.         var tdi = gdi.LoadImageAsync(window.ID, fb.ProfilePath + "wsh_br3tt\\cache\\imgcache\\" + crc);
  3374.         return tdi;
  3375.     }; else {
  3376.         return -1;
  3377.     };
  3378. };
  3379.  
  3380. function save_image_to_cache(metadb, albumIndex) {
  3381.     var tran = false;
  3382.     switch(ppt.tagMode) {
  3383.         case 1:
  3384.             var path = ppt.tf_path.EvalWithMetadb(metadb);
  3385.             var path_ = getpath_(path);
  3386.             break;
  3387.         case 2:
  3388.             var path_ = ppt.tf_path_artist.EvalWithMetadb(metadb);
  3389.             break;
  3390.         case 3:
  3391.             var path_ = ppt.tf_path_genre.EvalWithMetadb(metadb);
  3392.             break;
  3393.     };
  3394.  
  3395.     if(path_) {
  3396.         var crc = brw.groups[albumIndex].cachekey;
  3397.     }; else {
  3398.         return false;
  3399.     };
  3400.    
  3401.     var comm = "wscript //E:jscript \"" + fb.ProfilePath + "wsh_br3tt\\cache\\LoadIMG.js\" \""
  3402.         + fb.ProfilePath + "\" \""+ path_ + "\" \"" + crc + "\" \"" + tran + "\"";
  3403.     WshShell.Run(comm, false, false);
  3404. };
  3405.  
  3406. function process_cachekey(str){
  3407.     var str_return = "";
  3408.     str = str.toLowerCase();
  3409.     var len = str.length;
  3410.     for(var i  = 0;i < len; i++){
  3411.         var charcode = str.charCodeAt(i);
  3412.         if(charcode > 96 && charcode < 123)
  3413.             str_return += str.charAt(i);
  3414.         if(charcode > 47 && charcode < 58)
  3415.             str_return += str.charAt(i);
  3416.     };
  3417.     return str_return;
  3418. };
  3419.  
  3420. on_load();
  3421. function on_load(){
  3422.     if(!fso.FileExists(fb.ProfilePath + "wsh_br3tt\\cache\\LoadIMG.js")){
  3423.         var data = "var fso = new ActiveXObject(\"Scripting.FileSystemObject\");\r\n"
  3424.          + "var Img = new ActiveXObject(\"WIA.ImageFile.1\");\r\n"
  3425.          + "var IP = new ActiveXObject(\"WIA.ImageProcess.1\");\r\n"
  3426.          + "IP.Filters.Add(IP.FilterInfos(\"Scale\").FilterID);//ID = 1\r\n"
  3427.          + "IP.Filters.Add(IP.FilterInfos(\"Crop\").FilterID);//ID = 2\r\n"
  3428.          + "IP.Filters.Add(IP.FilterInfos(\"Convert\").FilterID);//ID = 3\r\n"
  3429.          + "function resize_image(path,crc,tranparent)\r\n"
  3430.          + "{\r\n"
  3431.          + "    var ratio = 1;\r\n"
  3432.          + "    var cachesize = 150;\r\n"
  3433.          + "    var img_w = cachesize, img_h = cachesize, cr_x = 0, cr_y = 0;\r\n"
  3434.          + "    try{\r\n"
  3435.          + "    Img.LoadFile(path);\r\n"
  3436.          + "    }catch(err){\r\n"
  3437.          + "        return false;\r\n"
  3438.          + "    }\r\n"
  3439.          + "if(Img.Height >= Img.Width) {\r\n"
  3440.          + "    ratio = Img.Width / Img.Height;\r\n"
  3441.          + "    img_w = img_w * ratio;\r\n"
  3442.          + "    cr_x = (img_h - img_w)/2;\r\n"
  3443.          + "} else {\r\n"
  3444.          + "    ratio = Img.Height / Img.Width;\r\n"
  3445.          + "    img_h = img_h * ratio;\r\n"
  3446.          + "    cr_y = (img_w - img_h)/2;\r\n"
  3447.          + "}\r\n"
  3448.          + "    IP.Filters(1).Properties(\"MaximumWidth\") = img_w;\r\n"
  3449.          + "    IP.Filters(1).Properties(\"MaximumHeight\") = img_h;\r\n"
  3450.          + "    if(tranparent == \"true\"){\r\n"
  3451.          + "        IP.Filters(3).Properties(\"FormatID\").Value = '{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}';\r\n"
  3452.          + "    }else{\r\n"
  3453.          + "        IP.Filters(3).Properties(\"FormatID\").Value = '{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}';\r\n"
  3454.          + "        IP.Filters(3).Properties(\"Quality\").Value = 75; \r\n"
  3455.          + "    }\r\n"
  3456.          + "    //IP.Filters(2).Properties(\"Left\") = cr_x;\r\n"
  3457.          + "    //IP.Filters(2).Properties(\"Top\") = cr_y;\r\n"
  3458.          + "    //IP.Filters(2).Properties(\"Right\") = cr_x;\r\n"
  3459.          + "    //IP.Filters(2).Properties(\"Bottom\") = cr_y;\r\n"
  3460.          + "    Img = IP.Apply(Img);\r\n"
  3461.          + "    try{\r\n"
  3462.          + "        if(fso.FileExists(WScript.arguments(0) + \"\\\\wsh_br3tt\\\\cache\\\\imgcache\\\\\" + crc))\r\n"
  3463.          + "            fso.DeleteFile(WScript.arguments(0)+ \"\\\\wsh_br3tt\\\\cache\\\\imgcache\\\\\" + crc);\r\n"
  3464.          + "        Img.SaveFile(WScript.arguments(0) + \"\\\\wsh_br3tt\\\\cache\\\\imgcache\\\\\" + crc);\r\n"
  3465.          + "    }catch(err){\r\n"
  3466.          + "        return false;\r\n"
  3467.          + "    }\r\n"
  3468.          + "    return true;\r\n"
  3469.          + "}\r\n"
  3470.          + "resize_image(WScript.arguments(1),WScript.arguments(2),WScript.arguments(3));";
  3471.         if(!fso.FolderExists(fb.ProfilePath + "wsh_br3tt"))
  3472.             fso.CreateFolder(fb.ProfilePath + "wsh_br3tt");
  3473.         if(!fso.FolderExists(fb.ProfilePath + "wsh_br3tt\\cache"))
  3474.             fso.CreateFolder(fb.ProfilePath + "wsh_br3tt\\cache");
  3475.         if(!fso.FolderExists(fb.ProfilePath + "wsh_br3tt\\cache\\imgcache"))
  3476.             fso.CreateFolder(fb.ProfilePath + "wsh_br3tt\\cache\\imgcache");
  3477.         var file = fso.CreateTextFile(fb.ProfilePath + "wsh_br3tt\\cache\\LoadIMG.js", true, 65001);
  3478.         file.WriteLine(data);
  3479.         file.Close();
  3480.     };
  3481. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement