Br3tt

WSH CoverFlow v1.4.3

May 8th, 2012
4,562
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==PREPROCESSOR==
  2. // @name "CoverFlow View"
  3. // @version "1.4.3"
  4. // @author "Br3tt aka Falstaff >> http://br3tt.deviantart.com"
  5. // @feature "v1.4"
  6. // @feature "watch-metadb"
  7. // @feature "dragdrop"
  8. // ==/PREPROCESSOR==
  9.  
  10. // [Requirements]
  11. // * foobar2000 v1.1 or better  >> http://foobar2000.org
  12. // * WSH panel Mod v1.5.2 or better  >> http://code.google.com/p/foo-wsh-panel-mod/downloads/list
  13. // * Optional: Font uni 05_53  >> http://www.dafont.com/uni-05-x.font
  14. //    this font is required to display total tracks info
  15. // [/Requirements]
  16.  
  17. // [Installation]
  18. // * import/paste this jscript into a WSH Panel Mod instance of your foobar2000 layout (DUI or CUI)
  19. // [/Installation]
  20.  
  21. // [Informations]
  22. // * change colors and fonts in foobar2000 Preferences > DefaultUI or ColumsUI
  23. // * Some Settings (*USER_xxx ones only) can be changed in window Properties
  24. // * middle click on cover > Send album tracks to specific playlist "CoverFlow View"
  25. // * keyboard keys : left/right arrows, Home/End, page up/down, spacebar to set focus on the centered album, Return key to play ...
  26. // * Type as you Search feature : type artist name with keyboard to automatically set the focus on its first album
  27. // * Think about it >> Adjust size/effects of the panel according to your cpu capacities to avoid bad perf
  28. // [/Informations]
  29.  
  30. //=================================================// General declarations
  31. SM_CXVSCROLL = 2;
  32. SM_CYHSCROLL = 3;
  33. DLGC_WANTARROWS = 0x0001;
  34. DLGC_WANTALLKEYS = 0x0004;
  35. // }}
  36. // Use with MenuManager()
  37. // {{
  38. MF_STRING = 0x00000000;
  39. MF_SEPARATOR = 0x00000800;
  40. MF_GRAYED = 0x00000001;
  41. MF_DISABLED = 0x00000002;
  42. MF_POPUP = 0x00000010;
  43. // }}
  44. // Used in window.SetCursor()
  45. // {{
  46. IDC_ARROW = 32512;
  47. IDC_IBEAM = 32513;
  48. IDC_WAIT = 32514;
  49. IDC_CROSS = 32515;
  50. IDC_UPARROW = 32516;
  51. IDC_SIZE = 32640;
  52. IDC_ICON = 32641;
  53. IDC_SIZENWSE = 32642;
  54. IDC_SIZENESW = 32643;
  55. IDC_SIZEWE = 32644;
  56. IDC_SIZENS = 32645;
  57. IDC_SIZEALL = 32646;
  58. IDC_NO = 32648;
  59. IDC_APPSTARTING = 32650;
  60. IDC_HAND = 32649;
  61. IDC_HELP = 32651;
  62. // }}
  63. // Use with GdiDrawText()
  64. // {{
  65. var DT_LEFT = 0x00000000;
  66. var DT_RIGHT = 0x00000002;
  67. var DT_TOP = 0x00000000;
  68. var DT_CENTER = 0x00000001;
  69. var DT_VCENTER = 0x00000004;
  70. var DT_WORDBREAK = 0x00000010;
  71. var DT_SINGLELINE = 0x00000020;
  72. var DT_CALCRECT = 0x00000400;
  73. var DT_NOPREFIX = 0x00000800;
  74. var DT_EDITCONTROL = 0x00002000;
  75. var DT_END_ELLIPSIS = 0x00008000;
  76. // }}
  77. // Keyboard Flags & Tools
  78. // {{
  79. var VK_BACK = 0x08;
  80. var VK_RETURN = 0x0D;
  81. var VK_SHIFT = 0x10;
  82. var VK_CONTROL = 0x11;
  83. var VK_ALT = 0x12;
  84. var VK_ESCAPE = 0x1B;
  85. var VK_PGUP = 0x21;
  86. var VK_PGDN = 0x22;
  87. var VK_END = 0x23;
  88. var VK_HOME = 0x24;
  89. var VK_LEFT = 0x25;
  90. var VK_UP = 0x26;
  91. var VK_RIGHT = 0x27;
  92. var VK_DOWN = 0x28;
  93. var VK_INSERT = 0x2D;
  94. var VK_DELETE = 0x2E;
  95. var VK_SPACEBAR = 0x20;
  96. var KMask = {
  97.     none: 0,
  98.     ctrl: 1,
  99.     shift: 2,
  100.     ctrlshift: 3,
  101.     ctrlalt: 4,
  102.     ctrlaltshift: 5,
  103.     alt: 6
  104. };
  105. function GetKeyboardMask() {
  106.     var c = utils.IsKeyPressed(VK_CONTROL) ? true : false;
  107.     var a = utils.IsKeyPressed(VK_ALT) ? true : false;
  108.     var s = utils.IsKeyPressed(VK_SHIFT) ? true : false;
  109.     var ret = KMask.none;
  110.     if (c && !a && !s) ret = KMask.ctrl;
  111.     if (!c && !a && s) ret = KMask.shift;
  112.     if (c && !a && s) ret = KMask.ctrlshift;
  113.     if (c && a && !s) ret = KMask.ctrlalt;
  114.     if (c && a && s) ret = KMask.ctrlaltshift;
  115.     if (!c && a && !s) ret = KMask.alt;
  116.     return ret;
  117. };
  118. // }}
  119. // {{
  120. // Used in window.GetColorCUI()
  121. ColorTypeCUI = {
  122.     text: 0,
  123.     selection_text: 1,
  124.     inactive_selection_text: 2,
  125.     background: 3,
  126.     selection_background: 4,
  127.     inactive_selection_background: 5,
  128.     active_item_frame: 6
  129. };
  130. // Used in window.GetFontCUI()
  131. FontTypeCUI = {
  132.     items: 0,
  133.     labels: 1
  134. };
  135. // Used in window.GetColorDUI()
  136. ColorTypeDUI = {
  137.     text: 0,
  138.     background: 1,
  139.     highlight: 2,
  140.     selection: 3
  141. };
  142. // Used in window.GetFontDUI()
  143. FontTypeDUI = {
  144.     defaults: 0,
  145.     tabs: 1,
  146.     lists: 2,
  147.     playlists: 3,
  148.     statusbar: 4,
  149.     console: 5
  150. };
  151. //}}
  152. // {{
  153. // Used in gr.DrawString()
  154. function StringFormat() {
  155.     var h_align = 0,
  156.     v_align = 0,
  157.     trimming = 0,
  158.     flags = 0;
  159.     switch (arguments.length) {
  160.         case 3:
  161.         trimming = arguments[2];
  162.         case 2:
  163.         v_align = arguments[1];
  164.         case 1:
  165.         h_align = arguments[0];
  166.         break;
  167.         default:
  168.         return 0;
  169.     };
  170.     return ((h_align << 28) | (v_align << 24) | (trimming << 20) | flags);
  171. };
  172. StringAlignment = {
  173.     Near: 0,
  174.     Centre: 1,
  175.     Far: 2
  176. };
  177. var lt_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Near);
  178. var ct_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Near);
  179. var rt_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Near);
  180. var lc_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Centre);
  181. var cc_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Centre);
  182. var rc_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Centre);
  183. var lb_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Far);
  184. var cb_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Far);
  185. var rb_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Far);
  186. //}}
  187. // {{
  188. // Used in utils.GetAlbumArt()
  189. AlbumArtId = {
  190.     front: 0,
  191.     back: 1,
  192.     disc: 2,
  193.     icon: 3,
  194.     artist: 4
  195. };
  196. //}}
  197. // {{
  198. // Used everywhere!
  199. function RGB(r, g, b) {
  200.     return (0xff000000 | (r << 16) | (g << 8) | (b));
  201. };
  202. function RGBA(r, g, b, a) {
  203.     return ((a << 24) | (r << 16) | (g << 8) | (b));
  204. };
  205. function getAlpha(color) {
  206.     return ((color >> 24) & 0xff);
  207. }
  208.  
  209. function getRed(color) {
  210.     return ((color >> 16) & 0xff);
  211. }
  212.  
  213. function getGreen(color) {
  214.     return ((color >> 8) & 0xff);
  215. }
  216.  
  217. function getBlue(color) {
  218.     return (color & 0xff);
  219. }
  220. function num(strg, nb) {
  221.     var i;
  222.     var str = strg.toString();
  223.     var k = nb - str.length;
  224.     if (k > 0) {
  225.         for (i=0;i<k;i++) {
  226.             str = "0" + str;
  227.         };
  228.     };
  229.     return str.toString();
  230. };
  231. //Time formatting secondes -> 0:00
  232. function TimeFromSeconds(t){
  233.     var zpad = function(n){
  234.     var str = n.toString();
  235.         return (str.length<2) ? "0"+str : str;
  236.     };
  237.     var h = Math.floor(t/3600); t-=h*3600;
  238.     var m = Math.floor(t/60); t-=m*60;
  239.     var s = Math.floor(t);
  240.     if(h>0) return h.toString()+":"+zpad(m)+":"+zpad(s);
  241.     return m.toString()+":"+zpad(s);
  242. };
  243. function TrackType(trkpath) {
  244.     var taggable;
  245.     var type;
  246.     switch (trkpath) {
  247.         case "file":
  248.         taggable = 1;
  249.         type = 0;
  250.         break;
  251.         case "cdda":
  252.         taggable = 1;
  253.         type = 1;
  254.         break;
  255.         case "FOO_":
  256.         taggable = 0;
  257.         type = 2;
  258.         break;
  259.         case "http":
  260.         taggable = 0;
  261.         type = 3;
  262.         break;
  263.         case "mms:":
  264.         taggable = 0;
  265.         type = 3;
  266.         break;
  267.         case "unpa":
  268.         taggable = 0;
  269.         type = 4;
  270.         break;
  271.         default:
  272.         taggable = 0;
  273.         type = 5;
  274.     };
  275.     return type;
  276. };
  277. function replaceAll(str, search, repl) {
  278.     while (str.indexOf(search) != -1) {
  279.         str = str.replace(search, repl);
  280.     };
  281.     return str;
  282. };
  283. function removeAccents(str) {
  284.     /*
  285.     var norm = new Array('À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë',
  286.     'Ì','Í','Î','Ï', 'Ð','Ñ','Ò','Ó','Ô','Õ','Ö','Ø','Ù','Ú','Û','Ü','Ý',
  287.     'Þ','ß');
  288.     var spec = new Array('A','A','A','A','A','A','AE','C','E','E','E','E',
  289.     'I','I','I','I', 'D','N','O','O','O','O','O','O','U','U','U','U','Y',
  290.     'b','SS');
  291.     for (var i = 0; i < spec.length; i++) {
  292.         str = replaceAll(str, norm[i], spec[i]);
  293.     };
  294.     */
  295.     return str;
  296. };
  297. //}}
  298.  
  299. //=================================================// Button object
  300. ButtonStates = {normal: 0, hover: 1, down: 2};
  301. button = function (normal, hover, down) {
  302.     this.img = Array(normal, hover, down);
  303.     this.w = this.img[0].Width;
  304.     this.h = this.img[0].Height;
  305.     this.state = ButtonStates.normal;
  306.     this.update = function (normal, hover, down) {
  307.         this.img = Array(normal, hover, down);
  308.     };
  309.     this.draw = function (gr, x, y, alpha) {
  310.         this.x = x;
  311.         this.y = y;
  312.         this.img[this.state] && gr.DrawImage(this.img[this.state], this.x, this.y, this.w, this.h, 0, 0, this.w, this.h, 0, alpha);
  313.     };
  314.     this.display_context_menu = function (x, y, id) {};
  315.     this.repaint = function () {
  316.         window.RepaintRect(this.x, this.y, this.w, this.h);
  317.     };
  318.     this.checkstate = function (event, x, y) {
  319.         this.ishover = (x > this.x && x < this.x + this.w - 1 && y > this.y && y < this.y + this.h - 1);
  320.         this.old = this.state;
  321.         switch (event) {
  322.          case "down":
  323.             switch(this.state) {
  324.              case ButtonStates.normal:
  325.              case ButtonStates.hover:
  326.                 this.state = this.ishover ? ButtonStates.down : ButtonStates.normal;
  327.                 break;
  328.             };
  329.             break;
  330.          case "up":
  331.             this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
  332.             break;
  333.          case "right":
  334.              if(this.ishover) this.display_context_menu(x, y, id);
  335.              break;
  336.          case "move":
  337.             switch(this.state) {
  338.              case ButtonStates.normal:
  339.              case ButtonStates.hover:
  340.                 this.state = this.ishover ? ButtonStates.hover : ButtonStates.normal;
  341.                 break;
  342.             };
  343.             break;
  344.          case "leave":
  345.             this.state = this.isdown ? ButtonStates.down : ButtonStates.normal;
  346.             break;
  347.         };
  348.         if(this.state!=this.old) this.repaint();
  349.         return this.state;
  350.     };
  351. };
  352.  
  353. //=================================================// Tools (general)
  354. function get_system_scrollbar_width() {
  355.     var tmp = utils.GetSystemMetrics(SM_CXVSCROLL);
  356.     return tmp;
  357. };
  358.  
  359. function get_system_scrollbar_height() {
  360.     var tmp = utils.GetSystemMetrics(SM_CYHSCROLL);
  361.     return tmp;
  362. };
  363.  
  364. String.prototype.repeat = function(num) {
  365.     if(num>=0 && num<=5) {
  366.         var g = Math.round(num);
  367.     } else {
  368.         return "";
  369.     };
  370.     return new Array(g+1).join(this);
  371. };
  372.  
  373. function getTimestamp() {
  374.     var d, s1, s2, s3, hh, min, sec, timestamp;
  375.     d = new Date();
  376.     s1 = d.getFullYear();
  377.     s2 = (d.getMonth() + 1);
  378.     s3 = d.getDate();
  379.     hh = d.getHours();
  380.     min = d.getMinutes();
  381.     sec = d.getSeconds();
  382.     if(s3.length == 1) s3 = "0" + s3;
  383.     timestamp = s1 + ((s2 < 10) ? "-0" : "-") + s2 + ((s3 < 10) ? "-0" : "-" ) + s3 + ((hh < 10) ? " 0" : " ") + hh + ((min < 10) ? ":0" : ":") + min + ((sec < 10) ? ":0" : ":") + sec;
  384.     return timestamp;
  385. };
  386.  
  387. //=================================================// Image declarations
  388. var nocover;
  389. var nocover_img;
  390. var streamcover;
  391. var streamcover_img;
  392. var loading;
  393. var loading_img;
  394. var star_img_off;
  395. var star_img_on;
  396. var star_img_hov;
  397. var star_img_kill;
  398. var toggle_scrollbar;
  399. var menu_button;
  400. var glass_reflect_img;
  401.  
  402. //=================================================// Cover Tools
  403. image_cache = function () {
  404.     this._cachelist = {};
  405.     this.hit = function (item) {
  406.         var img = this._cachelist[item.metadb.Path];
  407.         if (list.drag_stop && typeof img == "undefined") {
  408.             if(!cover.load_timer) {
  409.                 cover.load_timer = window.SetTimeout(function() {
  410.                     utils.GetAlbumArtAsync(window.ID, item.metadb, 0, true, false, false);
  411.                     cover.load_timer && window.ClearTimeout(cover.load_timer);
  412.                     cover.load_timer = false;
  413.                 }, 35);
  414.             };
  415.         };
  416.         return img;
  417.     };
  418.     this.getit = function (item, image) {
  419.         var img;
  420.         var quotient = (panel.flat_mode) ? 2 : 12;
  421.         if(cover.keepaspectratio) {
  422.             if(!image) {
  423.                 var pw = (cover.w+cover.margin*quotient);
  424.                 var ph = (cover.h+cover.margin*quotient);
  425.             } else {
  426.                 if(image.Height>=image.Width) {
  427.                     var ratio = image.Width / image.Height;
  428.                     var pw = (cover.w+cover.margin*quotient)*ratio;
  429.                     var ph = (cover.h+cover.margin*quotient);
  430.                 } else {
  431.                     var ratio = image.Height / image.Width;
  432.                     var pw = (cover.w+cover.margin*quotient);
  433.                     var ph = (cover.h+cover.margin*quotient)*ratio;
  434.                 };
  435.             };
  436.         } else {
  437.             var pw = (cover.w+cover.margin*quotient);
  438.             var ph = (cover.h+cover.margin*quotient);
  439.         };
  440.         // item.cover_type : 0 = nocover, 1 = external cover, 2 = embedded cover, 3 = stream
  441.         if(item.track_type!=3) {
  442.             if(item.metadb) {
  443.                 img = FormatCover(image, pw, ph);
  444.                 if(!img) {
  445.                     img = nocover_img;
  446.                     item.cover_type = 0;
  447.                 } else {
  448.                     item.cover_type = 1;
  449.                 };
  450.             };
  451.         } else {
  452.             img = streamcover_img;
  453.             item.cover_type = 3;
  454.         };    
  455.         this._cachelist[item.metadb.Path] = img;
  456.         return img;
  457.     };
  458. };
  459. var g_image_cache = new image_cache;
  460.  
  461. function FormatCover(image, w, h) {
  462.     if(!image || w<=0 || h<=0) return image;
  463.     if(cover.draw_glass_effect) {
  464.         var new_img = image.Resize(w, h, 2);
  465.         var gb = new_img.GetGraphics();
  466.         if(h>w) {
  467.             gb.DrawImage(glass_reflect_img, Math.floor((h-w)/2)*-1, 0, h, h, 0, 0, glass_reflect_img.Width, glass_reflect_img.Height, 0, 150);
  468.         } else {
  469.             gb.DrawImage(glass_reflect_img, 0, Math.floor((w-h)/2)*-1, w, w, 0, 0, glass_reflect_img.Width, glass_reflect_img.Height, 0, 150);
  470.         };
  471.         new_img.ReleaseGraphics(gb);
  472.         return new_img;
  473.     } else {
  474.         return image.Resize(w, h, 2);
  475.     };
  476. };
  477.  
  478. function draw_glass_reflect(w, h) {
  479.     // Mask for glass effect
  480.     var Mask_img = gdi.CreateImage(w, h);
  481.     var gb = Mask_img.GetGraphics();
  482.     gb.FillSolidRect(0,0,w,h,0xffffffff);
  483.     gb.FillGradRect(0,0,w-20,h,0,0x99000000,0,1.0);
  484.     gb.SetSmoothingMode(2);
  485.     gb.FillEllipse(-20, 25, w*2+40, h*2, 0xffffffff);
  486.     Mask_img.ReleaseGraphics(gb);
  487.     // drawing the white rect
  488.     var glass_img = gdi.CreateImage(w, h);
  489.     gb = glass_img.GetGraphics();
  490.     gb.FillSolidRect(0, 0, w, h, 0xffffffff);
  491.     glass_img.ReleaseGraphics(gb);
  492.     // resizing and applying the mask
  493.     var Mask = Mask_img.Resize(w, h);
  494.     glass_img.ApplyMask(Mask);
  495.     Mask.Dispose();
  496.     return glass_img;
  497. };
  498.  
  499. function reset_cover_timers() {
  500.     cover.load_timer && window.ClearTimeout(cover.load_timer);
  501.     cover.load_timer = false;
  502. };
  503.  
  504. function on_get_album_art_done(metadb, art_id, image, image_path) {
  505.     var len = list.item.length;
  506.     for(var i=0;i<len;i++) {
  507.         if(list.item[i].metadb) {
  508.             if(list.item[i].metadb.Compare(metadb)) {
  509.                 list.item[i].cover_img = g_image_cache.getit(list.item[i], image);
  510.                 if(list.item[i].show) {
  511.                     if(panel.vertical_mode) {
  512.                         if(!list.item[i].y) list.item[i].y = 5; else if(list.item[i].y<5) list.item[i].y = 5;
  513.                         try{
  514.                             window.RepaintRect(cover.pad_left_mid-10, list.item[i].y-10, ww-cover.pad_left_mid+20, list.item[i].h+20);
  515.                         } catch(e) {};
  516.                     } else {
  517.                         if(!list.item[i].x) list.item[i].x = 5; else if(list.item[i].x<5) list.item[i].x = 5;
  518.                         try{
  519.                             window.RepaintRect(list.item[i].x-10, cover.pad_top_mid-10, list.item[i].w+20, wh-cover.pad_top_mid+20);
  520.                         } catch(e) {};
  521.                     };
  522.                 } else {
  523.                     list.item[i].show = true;
  524.                 };
  525.                 break;
  526.             };
  527.         };
  528.     };
  529. };
  530.  
  531. //=================================================// Item Object
  532. ItemStates = {normal: 0, hover: 1, selected: 2};
  533. item = function (id, idx, gh_id) {
  534.     var i;
  535.     if (typeof this.id == "undefined") {
  536.         if(id<0) {
  537.             this.id = id;
  538.             this.idx = idx;
  539.             this.gh_id = gh_id;
  540.             this.metadb = false;
  541.             this.albumartist = "";
  542.             this.album = "";
  543.             this.track_type = null;
  544.             this.group_info = "";
  545.         } else {
  546.             this.id = id;
  547.             this.idx = idx;
  548.             this.gh_id = gh_id;
  549.             this.metadb = list.handlelist.Item(this.id);
  550.             if(this.metadb) {
  551.                 this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
  552.                 this.album = tf_album.EvalWithMetadb(this.metadb);
  553.                 this.track_type = TrackType(this.metadb.rawpath.substring(0,4));
  554.                 this.group_info = tf_group_info.EvalWithMetadb(this.metadb);
  555.                 this.group_key = tf_group_key.EvalWithMetadb(this.metadb);
  556.             };
  557.         };
  558.         this.left = 0;
  559.         this.top = 0;
  560.     };
  561.  
  562.     this.update_infos = function() {
  563.         if(this.metadb) {
  564.             this.albumartist = tf_albumartist.EvalWithMetadb(this.metadb);
  565.             this.track_type = TrackType(this.metadb.rawpath.substring(0,4));
  566.             this.group_info = tf_group_info.EvalWithMetadb(this.metadb);
  567.             this.group_key = tf_group_key.EvalWithMetadb(this.metadb);
  568.         } else {
  569.             this.albumartist = "";
  570.             this.track_type = null;
  571.             this.group_info = "";
  572.         };
  573.     };
  574.  
  575.     this.draw = function(gr, id, idx, level, show) {
  576.         if(panel.vertical_mode) {
  577.             // --------------
  578.             // VERTICAL MODE
  579.             // --------------
  580.             this.show = show;
  581.             if(panel.flat_mode) {
  582.                 this.h = cover.h;
  583.                 this.w = cover.h;
  584.                 this.x = cover.pad_left_mid;
  585.                 this.x += Math.floor(((ww-cover.pad_left_mid-cover.pad_right_mid)-cover.w)/2);
  586.                 this.y = Math.floor((wh/2) - (this.h/2) + (cover.margin/2)*0) - (level*this.h);
  587.             } else {
  588.                 if(list.mid==idx) {
  589.                     this.h = cover.h;
  590.                     this.w = cover.h;
  591.                     this.x = cover.pad_left_mid;
  592.                     this.x += Math.floor(((ww-cover.pad_left_mid-cover.pad_right_mid)-cover.w)/2);
  593.                     this.y = Math.floor((wh/2) - (cover.h/2));
  594.                 } else {
  595.                     this.h = Math.abs(level)==1 ? cover.h - cover.normal_delta*1 : cover.h - cover.normal_delta*2;
  596.                     this.w = this.h;
  597.                     this.y = Math.abs(level)==1 ? Math.floor((wh/2) - (this.h/2)) - (level*(this.h-0010)): Math.floor((wh/2) - (this.h/2)) - (level*this.h);
  598.                     this.x = Math.abs(level)==1 ? cover.pad_left_mid + Math.ceil(cover.normal_delta/2) : cover.pad_left_mid + cover.normal_delta;
  599.                     this.x += Math.floor(((ww-cover.pad_left_mid-cover.pad_right_mid)-cover.w)/2);
  600.                 };
  601.             };
  602.             if(panel.scroll_effect) this.y += scroll.delta;
  603.             // cover
  604.             if(this.id>=0) {
  605.                 this.cover_img = g_image_cache.hit(this);
  606.                 if(typeof(this.cover_img) != "undefined") {
  607.                     // *** check aspect ratio *** //
  608.                     if(this.cover_img.Height>=this.cover_img.Width) {
  609.                         var ratio = this.cover_img.Width / this.cover_img.Height;
  610.                         var pw = this.w*ratio;
  611.                         var ph = this.h;
  612.                         this.left = Math.floor((ph-pw) / 2);
  613.                         this.top = 0;
  614.                         this.x += this.left;
  615.                         this.y += this.top;
  616.                         this.w = this.w - this.left*2 - cover.margin - 1;
  617.                         this.h = this.h - this.top*2 - cover.margin - 1;
  618.                     } else {
  619.                         var ratio = this.cover_img.Height / this.cover_img.Width;
  620.                         var pw = this.w;
  621.                         var ph = this.h*ratio;
  622.                         this.top = Math.floor((pw-ph) / 2);
  623.                         this.left = 0;
  624.                         this.x += this.left;
  625.                         this.y += this.top;
  626.                         this.w = this.w - this.left*2 - cover.margin - 1;
  627.                         this.h = this.h - this.top*2 - cover.margin - 1;
  628.                     };
  629.                     // Draw true Cover
  630.                     gr.DrawImage(this.cover_img, this.x, Math.floor(cover.margin/2)+this.y, this.w, this.h, 0, 0, this.cover_img.Width, this.cover_img.Height, 0, 255);
  631.                     gr.DrawRect(this.x, Math.floor(cover.margin/2)+this.y, this.w-1, this.h-1, 1.0, RGB(90,90,90));
  632.                     gr.DrawRect(this.x, Math.floor(cover.margin/2)+this.y, this.w-1, this.h-1, 1.0, g_textcolor&0x40ffffff);
  633.                 } else {
  634.                     // adjust cover size with margin
  635.                     this.w = this.w - cover.margin - 1;
  636.                     this.h = this.h - cover.margin - 1;
  637.                     // Draw loading Cover
  638.                     gr.DrawImage(loading_img, this.x, Math.floor(cover.margin/2)+this.y, this.w, this.h, 0, 0, loading_img.Width, loading_img.Height, 0, 255);
  639.                     gr.DrawRect(this.x, Math.floor(cover.margin/2)+this.y, this.w-1, this.h-1, 1.0, g_backcolor);
  640.                     gr.DrawRect(this.x, Math.floor(cover.margin/2)+this.y, this.w-1, this.h-1, 1.0, g_textcolor&0x40ffffff);
  641.                 };
  642.                 // Draw text item info if flat mode activated
  643.                 if(panel.flat_mode && panel.show_text) {
  644.                     var text_y = this.y+this.h+this.top+Math.floor(cover.margin/2);
  645.                     var text_x = cover.pad_left_mid;
  646.                     var text_h = cover.margin;
  647.                     var text_w = ww - cover.pad_left_mid*2 - (scrollbar.show?vscrollbar.w:0);
  648.                     if(list.item[list.mid].id>=0) {
  649.                         try {
  650.                             gr.GdiDrawText(this.album, g_font, g_backcolor, text_x, text_y+1, text_w, text_h, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  651.                             gr.GdiDrawText(this.album, g_font, g_textcolor, text_x, text_y, text_w, text_h, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  652.                         } catch(e) {
  653.                             gr.GdiDrawText(this.album, gdi.Font("tahoma", 11), g_backcolor, text_x, text_y+1, text_w, text_h, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  654.                             gr.GdiDrawText(this.album, gdi.Font("tahoma", 11), g_textcolor, text_x, text_y, text_w, text_h, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  655.                         };
  656.                     };
  657.                 };
  658.                 // focus item border (selection marker)
  659.                 if(typeof(this.cover_img) != "undefined" && this.gh_id == list.selected_gh_id) {
  660.                     list.focus_id_item_idx = this.idx;
  661.                     if(cover.draw_focus_border) {
  662.                         gr.SetSmoothingMode(2);
  663.                         gr.DrawRoundRect(this.x-1, Math.floor(cover.margin/2)+this.y-1, this.w-cover.margin*0+1, this.h-cover.margin*0+2, 2, 2, 3.0, g_backcolor_sel);
  664.                         gr.DrawRoundRect(this.x-2, Math.floor(cover.margin/2)+this.y-2, this.w-cover.margin*0+3, this.h-cover.margin*0+4, 3, 3, 1.0, RGBA(255,255,255,60));
  665.                         gr.SetSmoothingMode(0);
  666.                         gr.DrawRect(this.x+1, Math.floor(cover.margin/2)+this.y+1, this.w-cover.margin*0-3, this.h-cover.margin*0-2, 1.0, g_backcolor_sel);
  667.                         gr.DrawRect(this.x+1, Math.floor(cover.margin/2)+this.y+1, this.w-cover.margin*0-3, this.h-cover.margin*0-2, 1.0, RGBA(0,0,0,40));
  668.                     };
  669.                 };
  670.                 // total tracks counter
  671.                 if(panel.flat_mode) {
  672.                     if(panel.tracks_counter_show) {
  673.                         if(typeof(this.cover_img) != "undefined") {
  674.                             gr.SetSmoothingMode(2);
  675.                             gr.FillRoundRect(this.x-7, Math.floor(cover.margin/2)+this.y-6, 28, 16, 3, 3, RGBA(0,0,0,210));
  676.                             gr.DrawRoundRect(this.x-6, Math.floor(cover.margin/2)+this.y-5, 26, 14, 1, 1, 1.0, RGBA(255,255,255,60));
  677.                             gr.DrawRoundRect(this.x-7, Math.floor(cover.margin/2)+this.y-6, 28, 16, 1, 1, 1.0, RGBA(0,0,0,200));
  678.                             gr.GdiDrawText(list.groups[this.gh_id], mini_font, RGB(250,250,250), this.x-6, Math.floor(cover.margin/2)+this.y-6, 29, 16, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  679.                             gr.SetSmoothingMode(0);
  680.                         };
  681.                     };
  682.                 };
  683.             };
  684.             this.y = this.y + Math.floor(cover.margin/2);
  685.         } else {
  686.             // ----------------
  687.             // HORIZONTAL MODE
  688.             // ----------------
  689.             this.show = show;
  690.             if(panel.flat_mode) {
  691.                 this.w = cover.w;
  692.                 this.h = cover.w;
  693.                 this.y = cover.pad_top_mid;
  694.                 this.y += Math.floor(((wh-cover.pad_top_mid-cover.pad_bot_mid)-cover.h)/2);
  695.                 this.x = Math.floor((ww/2) - (this.w/2) + (cover.margin/2)*0) - (level*this.w);                
  696.             } else {
  697.                 if(list.mid==idx) {
  698.                     this.w = cover.w;
  699.                     this.h = cover.w;
  700.                     this.y = cover.pad_top_mid;
  701.                     this.y += Math.floor(((wh-cover.pad_top_mid-cover.pad_bot_mid)-cover.h)/2);
  702.                     this.x = Math.floor((ww/2) - (cover.w/2));
  703.                 } else {
  704.                     this.w = Math.abs(level)==1 ? cover.w - cover.normal_delta*1 : cover.w - cover.normal_delta*2;
  705.                     this.h = this.w;
  706.                     this.x = Math.abs(level)==1 ? Math.floor((ww/2) - (this.w/2)) - (level*(this.w-0010)): Math.floor((ww/2) - (this.w/2)) - (level*this.w);
  707.                     this.y = Math.abs(level)==1 ? cover.pad_top_mid + Math.ceil(cover.normal_delta/2) : cover.pad_top_mid + cover.normal_delta;
  708.                     this.y += Math.floor(((wh-cover.pad_top_mid-cover.pad_bot_mid)-cover.h)/2);
  709.                 };
  710.             };
  711.             if(panel.scroll_effect) this.x += scroll.delta;
  712.             // cover
  713.             if(this.id>=0) {
  714.                 this.cover_img = g_image_cache.hit(this);
  715.                 if(typeof(this.cover_img)!="undefined") {
  716.                     // *** check aspect ratio *** //
  717.                     if(this.cover_img.Height>=this.cover_img.Width) {
  718.                         var ratio = this.cover_img.Width / this.cover_img.Height;
  719.                         var pw = this.w*ratio;
  720.                         var ph = this.h;
  721.                         this.left = Math.floor((ph-pw) / 2);
  722.                         this.top = 0;
  723.                         this.x += this.left;
  724.                         this.y += this.top*2;
  725.                         this.w = this.w - this.left*2 - cover.margin - 1;
  726.                         this.h = this.h - this.top*2 - cover.margin - 1;
  727.                     } else {
  728.                         var ratio = this.cover_img.Height / this.cover_img.Width;
  729.                         var pw = this.w;
  730.                         var ph = this.h*ratio;
  731.                         this.top = Math.floor((pw-ph) / 2);
  732.                         this.left = 0;
  733.                         this.x += this.left;
  734.                         this.y += this.top*2;
  735.                         this.w = this.w - this.left*2 - cover.margin - 1;
  736.                         this.h = this.h - this.top*2 - cover.margin - 1;
  737.                     };
  738.                     // Draw Reflect (true COVER)
  739.                     var reflect_strength = 255-Math.floor(cover.reflect_strength_percent*2.55);
  740.                     if(cover.draw_reflection && reflect_strength>0 && cover.reflect_strength_percent>0) {
  741.                         gr.DrawImage(this.cover_img, Math.floor(cover.margin/2)+this.x+this.w, this.y + this.h, -1*this.w, this.h, 0, 0, this.cover_img.Width, this.cover_img.Height, 180, 255);
  742.                         gr.DrawRect(Math.floor(cover.margin/2)+this.x, this.y + this.h+1, this.w-1, this.h-1, 1.0, g_backcolor);
  743.                         gr.DrawRect(Math.floor(cover.margin/2)+this.x, this.y + this.h+1, this.w-1, this.h-1, 1.0, g_textcolor&0x40ffffff);
  744.                         // Overlay
  745.                         if(panel.flat_mode) {
  746.                             gr.FillGradRect(Math.floor(cover.margin/2)+this.x-1, this.y + this.h - 10, this.w+2, this.h + 11, 90, RGBA(g_backcolor_R, g_backcolor_G, g_backcolor_B, reflect_strength), g_backcolor, 1.0);
  747.                         } else {
  748.                             gr.FillGradRect(Math.floor(cover.margin/2)+this.x, this.y + this.h - 10, this.w, this.h + 11, 90, RGBA(g_backcolor_R, g_backcolor_G, g_backcolor_B, reflect_strength), g_backcolor, 1.0);
  749.                         };
  750.                     };
  751.                     // Draw true Cover
  752.                     gr.DrawImage(this.cover_img, Math.floor(cover.margin/2)+this.x, this.y, this.w, this.h, 0, 0, this.cover_img.Width, this.cover_img.Height, 0, 255);
  753.                     gr.DrawRect(Math.floor(cover.margin/2)+this.x, this.y, this.w-1, this.h-1, 1.0, g_backcolor);
  754.                     gr.DrawRect(Math.floor(cover.margin/2)+this.x, this.y, this.w-1, this.h-1, 1.0, g_textcolor&0x40ffffff);
  755.                 } else {
  756.                     // adjust cover size with margin
  757.                     this.w = this.w - cover.margin - 1;
  758.                     this.h = this.h - cover.margin - 1;
  759.                     // Draw Reflect (loading COVER)
  760.                     var reflect_strength = 255-Math.floor(cover.reflect_strength_percent*2.55);
  761.                     if(cover.draw_reflection && reflect_strength>0 && cover.reflect_strength_percent>0) {
  762.                         gr.DrawImage(loading_img, Math.floor(cover.margin/2)+this.x+this.w, this.y + this.h, -1*this.w, this.h, 0, 0, loading_img.Width, loading_img.Height, 180, 255);
  763.                         gr.DrawRect(Math.floor(cover.margin/2)+this.x, this.y + this.h+1, this.w-1, this.h-1, 1.0, g_backcolor);
  764.                         gr.DrawRect(Math.floor(cover.margin/2)+this.x, this.y + this.h+1, this.w-1, this.h-1, 1.0, g_textcolor&0x40ffffff);
  765.                         // Overlay
  766.                         gr.FillGradRect(Math.floor(cover.margin/2)+this.x, this.y + this.h - 10, this.w, this.h + 11, 90, RGBA(g_backcolor_R, g_backcolor_G, g_backcolor_B, reflect_strength), g_backcolor, 1.0);
  767.                     };
  768.                     // Draw loading Cover
  769.                     gr.DrawImage(loading_img, Math.floor(cover.margin/2)+this.x, this.y, this.w, this.h, 0, 0, loading_img.Width, loading_img.Height, 0, 255);
  770.                     gr.DrawRect(Math.floor(cover.margin/2)+this.x, this.y, this.w-1, this.h-1, 1.0, g_backcolor);
  771.                     gr.DrawRect(Math.floor(cover.margin/2)+this.x, this.y, this.w-1, this.h-1, 1.0, g_textcolor&0x40ffffff);
  772.                 };
  773.                 // item info if flat mode activated (tangle effect off)
  774.                 if(panel.flat_mode && panel.show_text) {
  775.                     var text_x = this.x + Math.floor(this.w/2) - Math.floor(cover.w/2) + cover.margin;
  776.                     var text_y = wh - cover.pad_bot_mid - cover.margin;
  777.                     var text_w = cover.w - cover.margin;
  778.                     var text_h = (cover.pad_bot_mid + cover.margin) - (scrollbar.show?hscrollbar.h:0);
  779.                     if(list.item[list.mid].id>=0) {
  780.                         try {
  781.                             gr.GdiDrawText(this.album, g_font, g_backcolor, text_x, text_y+1, text_w, text_h, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  782.                             gr.GdiDrawText(this.album, g_font, g_textcolor, text_x, text_y, text_w, text_h, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  783.                         } catch(e) {
  784.                             gr.GdiDrawText(this.album, gdi.Font("tahoma", 11), g_backcolor, text_x, text_y+1, text_w, text_h, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  785.                             gr.GdiDrawText(this.album, gdi.Font("tahoma", 11), g_textcolor, text_x, text_y, text_w, text_h, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  786.                         };
  787.                     };
  788.                 };
  789.                 // focus item border (selection marker)
  790.                 if(typeof(this.cover_img) != "undefined" && this.gh_id == list.selected_gh_id) {
  791.                     list.focus_id_item_idx = this.idx;
  792.                     if(cover.draw_focus_border) {
  793.                         gr.SetSmoothingMode(2);
  794.                         gr.DrawRoundRect(Math.floor(cover.margin/2)+this.x-1, this.y-1, this.w-cover.margin*0+1, this.h-cover.margin*0+2, 2, 2, 3.0, g_backcolor_sel);
  795.                         gr.DrawRoundRect(Math.floor(cover.margin/2)+this.x-2, this.y-2, this.w-cover.margin*0+3, this.h-cover.margin*0+4, 3, 3, 1.0, RGBA(255,255,255,60));
  796.                         gr.SetSmoothingMode(0);
  797.                         gr.DrawRect(Math.floor(cover.margin/2)+this.x+1, this.y+1, this.w-cover.margin*0-3, this.h-cover.margin*0-2, 1.0, g_backcolor_sel);
  798.                         gr.DrawRect(Math.floor(cover.margin/2)+this.x+1, this.y+1, this.w-cover.margin*0-3, this.h-cover.margin*0-2, 1.0, RGBA(0,0,0,40));
  799.                     };
  800.                 };
  801.                 // total tracks counter
  802.                 if(panel.flat_mode) {
  803.                     if(panel.tracks_counter_show) {
  804.                         if(typeof(this.cover_img) != "undefined") {
  805.                             gr.SetSmoothingMode(2);
  806.                             gr.FillRoundRect(this.x-1, this.y-6, 28, 16, 3, 3, RGBA(0,0,0,210));
  807.                             gr.DrawRoundRect(this.x-0, this.y-5, 26, 14, 1, 1, 1.0, RGBA(255,255,255,60));
  808.                             gr.DrawRoundRect(this.x-1, this.y-6, 28, 16, 1, 1, 1.0, RGBA(0,0,0,200));
  809.                             gr.GdiDrawText(list.groups[this.gh_id], mini_font, RGB(250,250,250), this.x, this.y-6, 29, 16, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  810.                             gr.SetSmoothingMode(0);
  811.                         };
  812.                     };
  813.                 };
  814.             };
  815.             this.x = this.x + Math.floor(cover.margin/2);
  816.         };
  817.     };
  818.    
  819.     this.checkstate = function (event, x, y, id) {
  820.         if(y<toolbar.delta) return true;
  821.         if(this.id>=0) {
  822.             this.ishover = (x > this.x && x < this.x + this.w && y >= this.y && y < this.y + this.h);
  823.         } else {
  824.             this.ishover = false;
  825.         };
  826.         switch (event) {
  827.         case "down":
  828.             if(this.id>=0) {
  829.                 if(plman.IsPlaylistItemSelected(panel.active_playlist, this.id)) {
  830.                     if(this.ishover) {
  831.                         if(panel.lock_playlist) {
  832.                             this.checkstate("mid", x, y, id);
  833.                         } else {
  834.                             SelectGroupItems(this.id, this.gh_id, true);
  835.                         };
  836.                         if(panel.scroll_effect) {
  837.                           if(this.idx<list.mid) {
  838.                               var tmp = list.mid - this.idx;
  839.                               scrollcoverflow(0, tmp, scroll.factor);
  840.                           } else if(this.idx>list.mid) {
  841.                               var tmp = this.idx - list.mid;
  842.                               scrollcoverflow(tmp, 0, scroll.factor);
  843.                           }
  844.                         }
  845.                         g_saved = this;
  846.                         refresh_spv(panel.active_playlist, bool_on_size);
  847.                     };
  848.                 } else {
  849.                     if(this.ishover) {
  850.                         if(utils.IsKeyPressed(VK_SHIFT)) {
  851.                             if(list.focus_id != this.id) {
  852.                                 if(list.SHIFT_start_id!=null) {
  853.                                     //SelectAtoB(list.SHIFT_start_id, this.id);
  854.                                 } else {
  855.                                     //SelectAtoB(list.focus_id, this.id);
  856.                                 };
  857.                             };
  858.                         } else if(utils.IsKeyPressed(VK_CONTROL)) {
  859.                             if(panel.lock_playlist) {
  860.                                 this.checkstate("mid", x, y, id);
  861.                             } else {
  862.                                 SelectGroupItems(this.id, this.gh_id, true);
  863.                                 if(panel.scroll_effect) {
  864.                                   if(this.idx<list.mid) {
  865.                                       var tmp = list.mid - this.idx;
  866.                                       scrollcoverflow(0, tmp, scroll.factor);
  867.                                   } else if(this.idx>list.mid) {
  868.                                       var tmp = this.idx - list.mid;
  869.                                       scrollcoverflow(tmp, 0, scroll.factor);
  870.                                   }
  871.                                 }
  872.                             };
  873.                         } else {
  874.                             SelectGroupItems(this.id, this.gh_id, true);
  875.                             if(panel.scroll_effect) {
  876.                               if(this.idx<list.mid) {
  877.                                   var tmp = list.mid - this.idx;
  878.                                   scrollcoverflow(0, tmp, scroll.factor);
  879.                               } else if(this.idx>list.mid) {
  880.                                   var tmp = this.idx - list.mid;
  881.                                   scrollcoverflow(tmp, 0, scroll.factor);
  882.                               }
  883.                             }
  884.                             g_saved = this;
  885.                             if(panel.lock_playlist) {
  886.                                 g_saved.checkstate("mid", x, y, id);
  887.                             };
  888.                         };
  889.                     };
  890.                 };
  891.             } else {
  892.                 g_saved = null;
  893.             };
  894.             break;
  895.  
  896.         case "dblclk":
  897.             if(this.id>=0 && g_saved!=null) {
  898.                 if(plman.IsPlaylistItemSelected(panel.active_playlist, this.id)) {
  899.                     if(panel.lock_playlist) {
  900.                         if(this.id==g_saved.id) {
  901.                             plman.ExecutePlaylistDefaultAction(panel.active_playlist, list.hlist[g_saved.gh_id]);
  902.                             g_saved = null;
  903.                         };
  904.                     } else {
  905.                         if(this.id==g_saved.id) {
  906.                             plman.ExecutePlaylistDefaultAction(panel.active_playlist, list.hlist[g_saved.gh_id]);
  907.                             g_saved = null;
  908.                             window.Repaint();
  909.                         };
  910.                     };
  911.                 };
  912.             };
  913.             break;
  914.            
  915.         case "mid":
  916.             if(this.ishover) {
  917.                 if(plman.GetPlaylistName(panel.active_playlist)!="CoverFlow View") {
  918.                     SelectGroupItems(this.id, this.gh_id, true);
  919.                     var found = false;
  920.                     var playlist_CF_id = 0;
  921.                     var source_pl = panel.active_playlist;
  922.                     var pl_count = plman.PlaylistCount;
  923.                     for(var i=0; i<pl_count; i++) {
  924.                         if(plman.GetPlaylistName(i)=="CoverFlow View") {
  925.                             found = true;
  926.                             playlist_CF_id = i;
  927.                             break;
  928.                         };
  929.                     };
  930.                     if(!found) {
  931.                         bypass.on_playlists_changed = true;
  932.                         playlist_CF_id = plman.PlaylistCount;
  933.                         plman.CreatePlaylist(plman.PlaylistCount, "CoverFlow View");
  934.                     };
  935.                     plman.ActivePlaylist = playlist_CF_id;
  936.                     fb.ClearPlaylist();
  937.                     var insert_index = fb.PlaylistItemCount(playlist_CF_id);
  938.                     plman.InsertPlaylistItems(playlist_CF_id, insert_index, plman.GetPlaylistSelectedItems(source_pl), false);
  939.                     plman.SetPlaylistFocusItem(playlist_CF_id, 0);
  940.                 };
  941.             };
  942.             break;
  943.                        
  944.         case "right":
  945.             if(this.ishover) {
  946.                 if(panel.lock_playlist) {
  947.                     list.selected_gh_id = this.gh_id;
  948.                     list.focus_id = this.id;
  949.                     bypass.on_item_focus_change = true;
  950.                     this.checkstate("mid", x, y, id);
  951.                 } else {
  952.                     list.selected_gh_id = this.gh_id;
  953.                     list.focus_id = this.id;
  954.                     bypass.on_item_focus_change = true;
  955.                     SelectGroupItems(this.id, this.gh_id, true);
  956.                 };
  957.             };
  958.             break;
  959.            
  960.         case "up":
  961.  
  962.             break;
  963.            
  964.         case "move":
  965.  
  966.             break;
  967.            
  968.         case "leave":
  969.  
  970.             break;
  971.         };
  972.         return this.ishover;
  973.     };
  974. };
  975.  
  976. //=================================================// Titleformat field
  977. var tf_path = fb.TitleFormat("$left(%_path_raw%,4)");
  978. var tf_albumartist = fb.TitleFormat("$if(%length%,%album artist%,'Stream')");
  979. var tf_album = fb.TitleFormat("$if2(%album%,$if(%length%,'Single(s)','web radios'))");
  980. var tf_group_key = fb.TitleFormat(window.GetProperty("*USER.group Key", "%album artist%%album%"));
  981. var tf_group_info = fb.TitleFormat(window.GetProperty("*USER.group TF text info", "%album artist%[ | %album%][ | %date%]"));
  982.  
  983. //=================================================// Globals
  984. var g_instancetype = window.InstanceType;
  985. var g_font = null;
  986. var g_font_headers = null;
  987. var mini_font = gdi.Font("uni 05_53", 8, 0);
  988. var ww = 0, wh = 0;
  989. var mouse_x = 0, mouse_y = 0;
  990. var g_textcolor = 0, g_textcolor_sel = 0, g_textcolor_hl = 0, g_backcolor = 0, g_backcolor_sel = 0;
  991. var g_syscolor = 0;
  992. var g_syscolor_text = 0;
  993. var COLOR_TEXT = 8;
  994. var COLOR_BTNFACE = 15;
  995. var g_metadb;
  996. var bool_on_size = false;
  997. var g_search_string = "";
  998. var incsearch_font = gdi.Font("lucida console", 9, 0);
  999. var incsearch_font_big = gdi.Font("lucida console", 20, 1);
  1000. var clear_incsearch_timer = false;
  1001. var incsearch_timer = false;
  1002. var incsearch_timer_lock = false;
  1003. var g_saved = null;
  1004. var hand = false;
  1005. var g_menu_displayed = false;
  1006. var g_drag = false;
  1007.  
  1008. bypass = {
  1009.     on_item_focus_change: false,
  1010.     on_playlists_changed: false
  1011. };
  1012. panel = {
  1013.     max_width: 300,
  1014.     max_height: 300,
  1015.     arr_buttons: Array(),
  1016.     show_text: window.GetProperty("SYSTEM.panel.album.info", true),
  1017.     lock_playlist: window.GetProperty("SYSTEM.panel.lock.playlist", false),
  1018.     active_playlist: window.GetProperty("SYSTEM.panel.active.playlist", 0),
  1019.     vertical_mode: false,
  1020.     scroll_effect: window.GetProperty("SYSTEM.panel.scroll.effect", true),
  1021.     flat_mode: window.GetProperty("SYSTEM.panel.flat.mode", false),
  1022.     custom_textcolor: window.GetProperty("*USER.custom.text.color.normal", "RGB(240,240,240)"),
  1023.     custom_textcolor_selection: window.GetProperty("*USER.custom.text.color.selection", "RGB(64,128,250)"),
  1024.     custom_backcolor: window.GetProperty("*USER.custom.background.color", "RGB(0,0,0)"),
  1025.     custom_colors: window.GetProperty("SYSTEM.panel.custom.colors", false),
  1026.     tracks_counter_show: window.GetProperty("*USER.total.tracks.visible", true),
  1027.     side_shadows_show: window.GetProperty("SYSTEM.side.shadows.visible", false),
  1028.     properties_separator: window.GetProperty("----------------------------", "----------------------------")
  1029. };
  1030. list = {
  1031.     first_launch: true,
  1032.     total: 0,
  1033.     total_gh: 0,
  1034.     start_id: 0,
  1035.     nbvis: 0,
  1036.     mid: 0,
  1037.     item: Array(),
  1038.     hlist: Array(),
  1039.     groups: Array(),
  1040.     handlelist: null,
  1041.     metadblist_selection: plman.GetPlaylistSelectedItems(panel.active_playlist),
  1042.     focus_id: 0,
  1043.     focus_id_item_idx: 0,
  1044.     selected_gh_id: 0,
  1045.     marker_id: 0,
  1046.     gh_id: 0,
  1047.     mousewheel_timer_value: 20,
  1048.     key_timer_value: 60,
  1049.     nowplaying: 0,
  1050.     SHIFT_start_id: null,
  1051.     SHIFT_count: 0,
  1052.     inc_search_noresult: false,
  1053.     nb_cover_to_draw: 0,
  1054.     buttonclicked: false,
  1055.     drag_stop: true,
  1056.     drag_timer: false
  1057. };
  1058. images = {
  1059.     nocover: window.GetProperty("*USER.image.nocover", ".\\images\\nocover.png"),
  1060.     stream: window.GetProperty("*USER.image.stream", ".\\images\\stream.png"),
  1061.     loading: window.GetProperty("*USER.image.loading", ".\\images\\loading.png")
  1062. };
  1063. scroll = {
  1064.     delta: 0,
  1065.     step: 0,
  1066.     timerID: false,
  1067.     nbcovers: 0,
  1068.     direction: 0,
  1069.     factor: 2
  1070. };
  1071. toolbar = {
  1072.     h: 0,
  1073.     lock: window.GetProperty("SYSTEM.toolbar.lock", false),
  1074.     button_total: 3,
  1075.     buttons: Array(),
  1076.     timerID_on: false,
  1077.     timerID_off: false,
  1078.     timerID1: false,
  1079.     timerID2: false,
  1080.     collapsed_y: -24,
  1081.     delta: 0,
  1082.     step: 3,
  1083.     state: false
  1084. };
  1085. scrollbar = {
  1086.     theme: false,
  1087.     themed: window.GetProperty("SYSTEM.scrollbar.themed", false),
  1088.     show: window.GetProperty("SYSTEM.scrollbar.visible", true),
  1089.     visible: true,
  1090.     step: 3,
  1091.     letter: null,
  1092.     button_total: 2,
  1093.     arr_buttons: Array(),
  1094.     timerID: false
  1095. }
  1096. hscrollbar = {
  1097.     hover: false,
  1098.     x: 0,
  1099.     y: 0,
  1100.     default_h: get_system_scrollbar_height(),
  1101.     h: get_system_scrollbar_height(),
  1102.     w: 0
  1103. };
  1104. vscrollbar = {
  1105.     hover: false,
  1106.     x: 0,
  1107.     y: 0,
  1108.     default_w: get_system_scrollbar_width(),
  1109.     w: get_system_scrollbar_width(),
  1110.     h: 0
  1111. };
  1112. scrollbarbt = {
  1113.     timerID1: false,
  1114.     timerID2: false,
  1115.     timer1_value: 400,
  1116.     timer2_value: 60
  1117. };
  1118. button_up = {
  1119.     img_normal: null,
  1120.     img_hover: null,
  1121.     img_down: null,
  1122.     x: 0,
  1123.     y: 0,
  1124.     w: hscrollbar.default_h,
  1125.     h: hscrollbar.default_h
  1126. };
  1127. button_down = {
  1128.     img_normal: null,
  1129.     img_hover: null,
  1130.     img_down: null,
  1131.     x: 0,
  1132.     y: 0,
  1133.     w: hscrollbar.default_h,
  1134.     h: hscrollbar.default_h
  1135. };
  1136. cursor = {
  1137.     bt: null,
  1138.     img_normal: null,
  1139.     img_hover: null,
  1140.     img_down: null,
  1141.     popup: null,
  1142.     x: 0,
  1143.     y: 0,
  1144.     w: hscrollbar.default_h,
  1145.     h: hscrollbar.default_h,
  1146.     default_w: hscrollbar.default_h+3,
  1147.     hover: false,
  1148.     drag: false,
  1149.     grap_x: 0,
  1150.     timerID: false,
  1151.     last_x: 0
  1152. };
  1153. cover = {
  1154.     margin_default: 2,
  1155.     margin: 2,
  1156.     max_size: window.GetProperty("*USER.cover.maximum.size", 300),
  1157.     keepaspectratio: window.GetProperty("*USER.cover.keep.ratio.aspect", true),
  1158.     w: 0,
  1159.     h: 0,
  1160.     top_offset: 0,
  1161.     default_pad_top_mid: 32,
  1162.     default_pad_bot_mid: 36,
  1163.     pad_top_mid: 32,
  1164.     pad_bot_mid: 36,
  1165.     default_pad_left_mid: 15,
  1166.     default_pad_right_mid: 12,
  1167.     pad_left_mid: 15,
  1168.     pad_right_mid: 12,
  1169.     normal_delta: 20,
  1170.     draw_reflection: window.GetProperty("SYSTEM.cover.draw.reflection", true),
  1171.     reflect_strength_percent: window.GetProperty("*USER.floor.reflection.percent", 25),
  1172.     draw_focus_border: window.GetProperty("SYSTEM.cover.draw.focus.border", true),
  1173.     draw_glass_effect: window.GetProperty("*USER.cover.glass.effect", true),
  1174.     load_timer: false
  1175. };
  1176.  
  1177. function scrollcoverflow(from, to, step_factor) {
  1178.     var diff = to - from;
  1179.     var tmp1, tmp2;
  1180.     scroll.nbcovers = Math.abs(diff);
  1181.     var tval = Math.round(60/scroll.nbcovers);
  1182.     if(tval<40) tval = 40;
  1183.     if(panel.flat_mode) {
  1184.         scroll.step = Math.floor(cover.w/(scroll.nbcovers==1?step_factor+1:scroll.nbcovers>(panel.flat_mode?2:3)?1:step_factor));
  1185.     } else {
  1186.         scroll.step = Math.floor((cover.w - cover.normal_delta*2)/(scroll.nbcovers==1?step_factor+1:scroll.nbcovers>(panel.flat_mode?2:3)?1:step_factor));
  1187.     };
  1188.     if(diff<0) {
  1189.         if(list.item[list.mid].gh_id<list.total_gh-1) {
  1190.             if(panel.flat_mode) {
  1191.                 scroll.delta = (cover.w*scroll.nbcovers); // delta > 0
  1192.             } else {
  1193.                 scroll.delta = ((cover.w - cover.normal_delta*2)*scroll.nbcovers); // delta > 0
  1194.             };
  1195.             tmp1 = scroll.delta;
  1196.             for(var j = 0; j < scroll.nbcovers; j++) {
  1197.                 scrolldown_spv(panel.active_playlist);
  1198.             };
  1199.             scroll.timerID && window.ClearInterval(scroll.timerID);
  1200.             scroll.timerID = window.SetInterval(function() {
  1201.                 tmp2 = scroll.delta;
  1202.                 scroll.delta = scroll.delta - scroll.step;
  1203.                 if(scroll.delta <= 0) {
  1204.                    scroll.delta = 0;
  1205.                    window.ClearInterval(scroll.timerID);
  1206.                    scroll.timerID = false;
  1207.                    window.Repaint();
  1208.                 } else {
  1209.                     // pas de repaint au 1er cran de scrolling
  1210.                     if(tmp2!=tmp1) window.Repaint();
  1211.                 };
  1212.             }, tval);
  1213.         };
  1214.     } else {
  1215.         if(list.item[list.mid].gh_id>0 ) {
  1216.             if(panel.flat_mode) {
  1217.                 scroll.delta = (cover.w*scroll.nbcovers) * -1; // delta < 0
  1218.             } else {
  1219.                 scroll.delta = ((cover.w - cover.normal_delta*2)*scroll.nbcovers) * -1; // delta < 0
  1220.             };
  1221.             tmp1 = scroll.delta;
  1222.             for(var j = 0; j < scroll.nbcovers; j++) {
  1223.                 scrollup_spv(panel.active_playlist);
  1224.             };
  1225.             scroll.timerID && window.ClearInterval(scroll.timerID);
  1226.             scroll.timerID = window.SetInterval(function() {
  1227.                 tmp2 = scroll.delta;
  1228.                 scroll.delta = scroll.delta + scroll.step;
  1229.                 if(scroll.delta >= 0) {
  1230.                    scroll.delta = 0;
  1231.                    window.ClearInterval(scroll.timerID);
  1232.                    scroll.timerID = false;
  1233.                    window.Repaint();
  1234.                 } else {
  1235.                     // pas de repaint au 1er cran de scrolling
  1236.                     if(tmp2!=tmp1) window.Repaint();
  1237.                 };
  1238.             }, tval);
  1239.         };
  1240.     };
  1241. };
  1242.  
  1243. function refresh_spv_cursor(pls) {
  1244.     if(panel.vertical_mode) {
  1245.         var ratio = (cursor.y-vscrollbar.y) / (vscrollbar.h-cursor.h);
  1246.     } else {
  1247.         var ratio = (cursor.x-hscrollbar.x) / (hscrollbar.w-cursor.w);
  1248.     };
  1249.     if(ratio>1) ratio = 1;
  1250.     if(ratio<0) ratio = 0;
  1251.     var r = Math.round(ratio * list.total_gh);
  1252.     set_gh_id(pls, list.hlist[r-1]);
  1253.     window.Repaint();
  1254. }
  1255.  
  1256. function set_gh_id(pls, id) {
  1257.     reset_cover_timers();
  1258.     // RAZ actual list
  1259.     list.item.splice(0, list.item.length);
  1260.     if(list.total_gh<=0) return true;
  1261.     // rech gh idx of the searched item
  1262.     list.gh_id = get_gh_id(id);
  1263.     if(list.gh_id==null) {
  1264.         list.gh_id = 0;
  1265.     };
  1266.     var r = list.gh_id - list.mid;
  1267.     if(r<0) {
  1268.         list.start_id = Math.abs(r);
  1269.         r = 0;
  1270.     } else {
  1271.         list.start_id = 0;
  1272.     };
  1273.     for(var k = 0; k < list.nbvis; k++) {
  1274.         if(k>=list.start_id && r<list.total_gh) {
  1275.             list.item.push(new item(list.hlist[r] , k, r));
  1276.             r++;
  1277.         } else {
  1278.             list.item.push(new item(-1 , k, -1));
  1279.         };
  1280.     };
  1281. };
  1282.  
  1283. function scrollup_spv(pls) {
  1284.     var r = list.item[list.mid].gh_id;
  1285.     if(r>0) {
  1286.         var s = list.item[0].gh_id;
  1287.         if(s>0) {
  1288.             list.item.unshift(new item(list.hlist[s-1] , 0, s-1));
  1289.         } else {
  1290.             list.item.unshift(new item(-1 , 0, -1));
  1291.         };
  1292.         list.item.pop();
  1293.     };
  1294.     var len = list.item.length;
  1295.     for(var i=0; i<len; i++) {
  1296.         list.item[i].idx = i;
  1297.     };
  1298.     setcursorx();
  1299. };
  1300.  
  1301. function scrolldown_spv(pls) {
  1302.     var r = list.item[list.mid].gh_id;
  1303.     if(r<list.total_gh-1) {
  1304.         var s = list.item[list.item.length-1].gh_id;
  1305.         if(s>0 && s<list.total_gh-1) {
  1306.             list.item.push(new item(list.hlist[s+1] , 0, s+1));
  1307.         } else {
  1308.             list.item.push(new item(-1 , 0, -1));
  1309.         };
  1310.         list.item.shift();
  1311.     };
  1312.     var len = list.item.length;
  1313.     for(var i=0; i<len; i++) {
  1314.         list.item[i].idx = i;
  1315.     };
  1316.     setcursorx();
  1317. };
  1318.  
  1319. function refresh_spv(pls, force) {
  1320.     reset_cover_timers();
  1321.     // RAZ actual list
  1322.     list.item.splice(0, list.item.length);
  1323.     if(list.total_gh<=0) return true;
  1324.     // rech gh idx of the focus item
  1325.     list.gh_id = get_gh_id(list.focus_id);
  1326.     if(list.gh_id==null) {
  1327.         init_active_pls();
  1328.         return true;
  1329.     };
  1330.     list.selected_gh_id = list.gh_id;
  1331.     var r = list.gh_id - list.mid;
  1332.     if(r<0) {
  1333.         list.start_id = Math.abs(r);
  1334.         r = 0;
  1335.     } else {
  1336.         list.start_id = 0;
  1337.     };
  1338.     for(var k = 0; k < list.nbvis; k++) {
  1339.         if(k>=list.start_id && r<list.total_gh) {
  1340.             list.item.push(new item(list.hlist[r] , k, r));
  1341.             r++;
  1342.         } else {
  1343.             list.item.push(new item(-1 , k, -1));
  1344.         };
  1345.     };
  1346.     if(scrollbar.show) {
  1347.         if(list.total_gh<2) scrollbar.visible = false; else scrollbar.visible=true;
  1348.     } else {
  1349.         scrollbar.visible = false;
  1350.     };
  1351.     if(panel.vertical_mode) {
  1352.         cursor.h = Math.round(vscrollbar.h / list.total_gh);
  1353.         // boundaries for cursor height
  1354.         if(cursor.h>vscrollbar.h) cursor.h = vscrollbar.h;
  1355.         if(cursor.h<cursor.default_w) cursor.h = cursor.default_w;
  1356.     } else {
  1357.         cursor.w = Math.round(hscrollbar.w / list.total_gh);
  1358.         // boundaries for cursor height
  1359.         if(cursor.w>hscrollbar.w) cursor.w = hscrollbar.w;
  1360.         if(cursor.w<cursor.default_w) cursor.w = cursor.default_w;
  1361.     };
  1362.     // redraw cursor image
  1363.     set_scroller();
  1364.     // set cursor position
  1365.     setcursorx();
  1366. };
  1367.  
  1368. function get_gh_id(focus_id) {
  1369.     var mid_id = Math.floor(list.total_gh / 2);
  1370.     if(focus_id < list.hlist[mid_id]) {
  1371.         var start_id = 0;
  1372.     } else {
  1373.         var start_id = mid_id;
  1374.     };
  1375.     for(var i = start_id; i < list.total_gh; i++) {
  1376.         if(i<list.total_gh-1) {
  1377.             if(focus_id >= list.hlist[i] && focus_id < list.hlist[i+1]) {
  1378.                 return i;
  1379.             };
  1380.         } else { // we are on the last item of the array
  1381.             if(focus_id >= list.hlist[i]) {
  1382.                 return i;
  1383.             } else {
  1384.                 //fb.trace("error: gh_id not found");
  1385.                 return null;
  1386.             };
  1387.         };
  1388.     };
  1389. };
  1390.  
  1391. function setcursorx() {
  1392.     if(list.item.length>0) {
  1393.         var centered_id = Math.floor(list.item.length/2);
  1394.         var centered_gh_id = list.item[centered_id].gh_id;
  1395.         var ratio = centered_gh_id / (list.total_gh-1);
  1396.         if(panel.vertical_mode) {
  1397.             cursor.y = vscrollbar.y + Math.round(ratio * (vscrollbar.h-cursor.h));
  1398.         } else {
  1399.             cursor.x = hscrollbar.x + Math.round(ratio * (hscrollbar.w-cursor.w));
  1400.         };
  1401.     } else {
  1402.         if(panel.vertical_mode) {
  1403.             cursor.y = vscrollbar.y;
  1404.         } else {
  1405.             cursor.x = hscrollbar.x;
  1406.         };
  1407.     };
  1408. };
  1409.  
  1410. function init_active_pls() {
  1411.     var temp_key1;
  1412.     var temp_key2;
  1413.     var metadb = null;
  1414.     var count = 0;
  1415.    
  1416.     //var d1 = new Date();
  1417.     //var t1 = d1.getSeconds()*1000 + d1.getMilliseconds();
  1418.     //fb.trace("avant="+t1);
  1419.      
  1420.     list.hlist.splice(0, list.hlist.length);
  1421.     list.groups.splice(0, list.groups.length);
  1422.     if(list.handlelist) list.handlelist.Dispose();
  1423.     list.handlelist = plman.GetPlaylistItems(panel.active_playlist);
  1424.     list.total = list.handlelist.Count;
  1425.     for (var i = 0; i < list.total; i++) {
  1426.         metadb = list.handlelist.Item(i);
  1427.         temp_key2 = tf_group_key.EvalWithMetadb(metadb);
  1428.         if(temp_key1 != temp_key2){
  1429.             if(i>0) {
  1430.                 list.groups.push(count);
  1431.             };
  1432.             count = 0;
  1433.             list.hlist.push(i);
  1434.             temp_key1 = temp_key2;
  1435.         };
  1436.         count++;
  1437.         // on last item
  1438.         if(i == list.total - 1) {
  1439.             list.groups.push(count);
  1440.         };
  1441.     };
  1442.     list.total_gh = list.hlist.length;
  1443.  
  1444.     //var d2 = new Date();
  1445.     //var t2 = d2.getSeconds()*1000 + d2.getMilliseconds();
  1446.     //fb.trace("old apres="+t2+" ==> delta = "+Math.round(t2-t1)+" // total_gh="+list.total_gh);
  1447. };
  1448.  
  1449. //=================================================// Colour & Font Callbacks
  1450. function on_font_changed() {
  1451.     get_font();
  1452.     on_playlist_switch();
  1453. };
  1454.  
  1455. function on_colors_changed() {
  1456.     get_colors();  
  1457.     init_icons();
  1458.     redraw_stub_images();
  1459.     init_hscrollbar_buttons();
  1460.     set_scroller();
  1461.     g_image_cache = new image_cache;
  1462.     CollectGarbage();
  1463.     on_playlist_switch();
  1464. };
  1465.  
  1466. //=================================================// Init
  1467. function on_init() {
  1468. };
  1469.  
  1470. //=================================================// OnSize
  1471. function on_size() {
  1472.     if (!window.Width || !window.Height) return;
  1473.    
  1474.     window.DlgCode = DLGC_WANTALLKEYS;
  1475.    
  1476.     bool_on_size = true;
  1477.    
  1478.     if(g_instancetype == 0) { // CUI
  1479.         window.MinWidth = 160;
  1480.         window.MinHeight = 160;
  1481.     } else if(g_instancetype == 1) { // DUI
  1482.         window.MinWidth = 160;
  1483.         window.MinHeight = 160;
  1484.     };
  1485.     ww = window.Width;
  1486.     wh = window.Height;
  1487.        
  1488.     if(ww>wh) {
  1489.         panel.vertical_mode = false;
  1490.         if(wh<160) wh = 158;
  1491.     } else {
  1492.         panel.vertical_mode = true;
  1493.         if(ww<160) ww = 158;
  1494.     };
  1495.    
  1496.     // test TF group text, if empty, reset to default
  1497.     var temp = window.GetProperty("*USER.group TF text info", "%album artist%[ | %album%][ | %date%]");
  1498.     if(temp=="") window.SetProperty("*USER.group TF text info", "%album artist%[ | %album%][ | %date%]");
  1499.     tf_group_info = fb.TitleFormat(window.GetProperty("*USER.group TF text info", "%album artist%[ | %album%][ | %date%]"));
  1500.  
  1501.     get_font();
  1502.     get_colors();
  1503.     init_icons();
  1504.  
  1505.     recalc_datas();
  1506.     redraw_stub_images();
  1507.          
  1508.     // only on first launch
  1509.     if(list.first_launch) {
  1510.         list.first_launch = false;
  1511.         on_playlist_switch();
  1512.     } else {
  1513.         // if just a window resize, refresh list.item and repaint :)
  1514.         g_image_cache = new image_cache;
  1515.         CollectGarbage();
  1516.         refresh_spv(panel.active_playlist, true);
  1517.     };
  1518.    
  1519.  
  1520. };
  1521.  
  1522. //=================================================// OnPaint
  1523. function on_paint(gr) {
  1524.  
  1525.     // default background
  1526.     gr.FillSolidRect(0, 0, ww, wh, g_backcolor);
  1527.     /*
  1528.     if(panel.vertical_mode) {
  1529.         gr.FillGradRect(0, 0, Math.floor(ww/4), wh, 0, g_textcolor&0x10ffffff, 0, 1.0);
  1530.         gr.FillGradRect(ww-Math.floor(ww/4), 0, Math.floor(ww/4), wh, 0, 0, g_textcolor&0x10ffffff, 1.0);
  1531.         gr.DrawLine(ww-Math.floor(ww/4), 0, ww-Math.floor(ww/4), wh, 1.0, g_backcolor);
  1532.     } else {
  1533.         gr.FillGradRect(0, 0, ww, Math.floor(wh/4), 90, g_textcolor&0x10ffffff, 0, 1.0);
  1534.     };
  1535.     */
  1536.  
  1537.     if(list.item.length>0) {
  1538.         var cover_show, mid2;
  1539.         list.item[list.mid].draw(gr, list.item[list.mid].id, list.mid, 0, true);
  1540.         for(var idx = 1; idx < list.mid + 1; idx++) {
  1541.             if(idx>1 && idx <= list.mid) {
  1542.                 cover_show = true;
  1543.             } else {
  1544.                 cover_show = false;
  1545.             };
  1546.             mid2 = list.mid - idx;
  1547.             if(mid2>=0 && mid2<=list.item.length-1) {
  1548.                 list.item[mid2].draw(gr, list.item[mid2].id, mid2, idx, cover_show);
  1549.             };
  1550.             mid2 = list.mid + idx;
  1551.             if(mid2>=0 && mid2<=list.item.length-1) {
  1552.                 list.item[mid2].draw(gr, list.item[mid2].id, mid2, idx*-1, cover_show);
  1553.             };
  1554.         };
  1555.        
  1556.         // draw final cover in the right order (stack effect)
  1557.         mid2 = list.mid - 1;
  1558.         if(mid2>=0 && mid2<=list.item.length-1) {
  1559.             list.item[mid2].draw(gr, list.item[mid2].id, mid2, 1, true);
  1560.         };
  1561.         mid2 = list.mid + 1;
  1562.         if(mid2>=0 && mid2<=list.item.length-1) {
  1563.             list.item[mid2].draw(gr, list.item[mid2].id, mid2, -1, true);
  1564.         };
  1565.         if(!panel.flat_mode) {
  1566.             list.item[list.mid].draw(gr, list.item[list.mid].id, list.mid, 0, true);
  1567.         };
  1568.  
  1569.         // draw text info on the centered album
  1570.         if(!panel.vertical_mode) {
  1571.             if(!panel.flat_mode && panel.show_text) {
  1572.                 var text_x = 10;
  1573.                 var text_w = ww-20;
  1574.                 if(list.item[list.mid].id>=0) {
  1575.                     try {
  1576.                         gr.GdiDrawText(list.item[list.mid].group_info, g_font, g_backcolor, text_x, 2, text_w, cover.pad_top_mid, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  1577.                         gr.GdiDrawText(list.item[list.mid].group_info, g_font, g_textcolor, text_x, 1, text_w, cover.pad_top_mid, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  1578.                     } catch(e) {
  1579.                         gr.GdiDrawText(list.item[list.mid].group_info, gdi.Font("tahoma", 11), g_backcolor, text_x, 2, text_w, cover.pad_top_mid, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  1580.                         gr.GdiDrawText(list.item[list.mid].group_info, gdi.Font("tahoma", 11), g_textcolor, text_x, 1, text_w, cover.pad_top_mid, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  1581.                     };
  1582.                 };
  1583.             };
  1584.         };
  1585.     } else {
  1586.         if(fb.PlaylistCount>0) {
  1587.             var text_top = fb.GetPlaylistName(fb.ActivePlaylist);
  1588.             var text_bot = "This playlist is empty";
  1589.         } else {
  1590.             var text_top = "Br3tt's WSH CoverFlow";
  1591.             var text_bot = "Create a playlist to start!";
  1592.         };
  1593.         // if empty playlist, display text info
  1594.         gr.SetTextRenderingHint(5);
  1595.         gr.DrawString(text_top, gdi.Font("Tahoma", 17, 0), g_textcolor&0x40ffffff, 0, -20, ww, wh, cc_stringformat);
  1596.         gr.DrawString(text_bot, gdi.Font("Tahoma", 13, 0), g_textcolor&0x40ffffff, 0, 20, ww, wh, cc_stringformat);
  1597.         gr.FillGradRect(40, Math.floor(wh/2), ww-80, 1, 0, 0, g_textcolor&0x40ffffff, 0.5);
  1598.    
  1599.     };
  1600.    
  1601.     // draw left/right shadows
  1602.     if(panel.side_shadows_show) {
  1603.         if(!panel.vertical_mode) {
  1604.             gr.FillGradRect(-3, 0, 15, wh, 0, g_backcolor, 0, 1.0);
  1605.             gr.FillGradRect(ww-12, 0, 16, wh, 0, 0, g_backcolor, 1.0);
  1606.         };
  1607.     };
  1608.  
  1609.     // draw scrollbar
  1610.     if(list.total_gh>0 && scrollbar.visible && scrollbar.show) {
  1611.         if(panel.vertical_mode) {
  1612.             // draw scrollbar background
  1613.             try {
  1614.                 scrollbar.theme.SetPartAndStateId(6, 1);
  1615.                 scrollbar.theme.DrawThemeBackground(gr, ww-vscrollbar.w, 0, vscrollbar.w, wh);
  1616.             } catch(e) {
  1617.                 gr.FillSolidRect(ww-vscrollbar.w, 0, vscrollbar.w, wh, g_backcolor&0x77ffffff);
  1618.                 gr.FillSolidRect(ww-vscrollbar.w, 0, 1, wh, RGBA(0,0,0,20));
  1619.             };
  1620.            
  1621.             // draw cursor
  1622.             cursor.bt.draw(gr, ww-vscrollbar.w, cursor.y, 255);
  1623.            
  1624.             try {
  1625.                 scrollbar.theme.SetPartAndStateId(9, 1);
  1626.                 scrollbar.theme.DrawThemeBackground(gr, ww-vscrollbar.w, cursor.y, cursor.w, cursor.h);
  1627.             } catch(e) {};
  1628.            
  1629.             // draw scrollbar buttons (up/down)
  1630.             for(i=0;i<scrollbar.arr_buttons.length;i++) {
  1631.                 switch (i) {
  1632.                  case 0:
  1633.                     scrollbar.arr_buttons[i].draw(gr, ww-vscrollbar.w, button_up.y, 255);
  1634.                     break;
  1635.                  case 1:
  1636.                     scrollbar.arr_buttons[i].draw(gr, ww-vscrollbar.w, button_down.y, 255);
  1637.                     break;
  1638.                 };
  1639.             };
  1640.            
  1641.             if(cursor.drag) {
  1642.                 scrollbar.letter = list.item[Math.floor(list.nbvis/2)].group_key.substring(0,1).toUpperCase();
  1643.                 cursor.popup && gr.DrawImage(cursor.popup, ww-vscrollbar.w-cursor.popup.Width-00, cursor.y+Math.floor(cursor.h/2)-Math.floor(cursor.popup.Height/2), cursor.popup.Width, cursor.popup.Height, 0, 0, cursor.popup.Width, cursor.popup.Height, 0, 155);
  1644.                 cursor.popup && gr.GdiDrawText(scrollbar.letter, gdi.Font("segoe ui", 14, 0), g_backcolor, ww-vscrollbar.w-cursor.popup.Width-00, cursor.y+Math.floor(cursor.h/2)-Math.floor(cursor.popup.Height/2), cursor.popup.Width-5, cursor.popup.Height, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  1645.             };
  1646.         } else {
  1647.            
  1648.             // draw scrollbar background
  1649.             try {
  1650.                 scrollbar.theme.SetPartAndStateId(4, 1);
  1651.                 scrollbar.theme.DrawThemeBackground(gr, 0, wh-hscrollbar.h, ww, hscrollbar.h);
  1652.                 gr.FillSolidRect(0, wh-hscrollbar.h-1, ww, 1, RGBA(0,0,0,10));
  1653.             } catch(e) {
  1654.                 gr.FillSolidRect(0, wh-hscrollbar.h, ww, hscrollbar.h, g_backcolor&0x77ffffff);
  1655.                 gr.FillSolidRect(0, wh-hscrollbar.h, ww, 1, RGBA(0,0,0,20));
  1656.             };
  1657.            
  1658.             // draw cursor
  1659.             try {
  1660.                 cursor.bt.draw(gr, cursor.x, cursor.y, 255);
  1661.             } catch(e) {};
  1662.            
  1663.             try {
  1664.                 scrollbar.theme.SetPartAndStateId(8, 1);
  1665.                 scrollbar.theme.DrawThemeBackground(gr, cursor.x, wh-hscrollbar.h+0, cursor.w, cursor.h);
  1666.             } catch(e) {};
  1667.            
  1668.             // draw scrollbar buttons (up/down)
  1669.             for(i=0;i<scrollbar.arr_buttons.length;i++) {
  1670.                 switch (i) {
  1671.                  case 0:
  1672.                     scrollbar.arr_buttons[i].draw(gr, button_up.x, button_up.y, 255);
  1673.                     break;
  1674.                  case 1:
  1675.                     scrollbar.arr_buttons[i].draw(gr, button_down.x, button_down.y, 255);
  1676.                     break;
  1677.                 };
  1678.             };
  1679.            
  1680.             if(cursor.drag) {
  1681.                 scrollbar.letter = list.item[Math.floor(list.nbvis/2)].group_key.substring(0,1).toUpperCase();
  1682.                 cursor.popup && gr.DrawImage(cursor.popup, cursor.x+Math.floor(cursor.w/2)-Math.floor(cursor.popup.Width/2), wh-hscrollbar.h-cursor.popup.Height, cursor.popup.Width, cursor.popup.Height, 0, 0, cursor.popup.Width, cursor.popup.Height, 0, 155);
  1683.                 cursor.popup && gr.GdiDrawText(scrollbar.letter, gdi.Font("segoe ui", 14, 0), g_backcolor, cursor.x+Math.floor(cursor.w/2)-Math.floor(cursor.popup.Width/2), wh-hscrollbar.h-cursor.popup.Height, cursor.popup.Width, cursor.popup.Height-5, DT_CENTER | DT_CALCRECT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
  1684.             };
  1685.         };
  1686.     };
  1687.        
  1688.     // Thin top line (border)
  1689.     if(!panel.vertical_mode) {
  1690.         //gr.FillGradRect(0, 0, ww, 1, 0, 0, g_textcolor&0x25ffffff, 0.5);
  1691.     };
  1692.  
  1693.     // Incremental Search Tooltip (bot/left corner)
  1694.     if(g_search_string.length>0) {
  1695.         gr.SetSmoothingMode(2);
  1696.         var tt_x = Math.floor((ww / 2) - ((g_search_string.length*13)+(10*2)) / 2);
  1697.         var tt_y = Math.floor(wh/2) - 30;
  1698.         var tt_w = ((g_search_string.length*13)+(10*2));
  1699.         var tt_h = 60;
  1700.         gr.FillRoundRect(tt_x, tt_y, tt_w, tt_h, 5, 5, RGBA(0,0,0,150));
  1701.         gr.DrawRoundRect(tt_x, tt_y, tt_w, tt_h, 5, 5, 2.0, RGBA(255,255,255,200));
  1702.         gr.DrawRoundRect(tt_x+2, tt_y+2, tt_w-4, tt_h-4, 3, 3, 1.0, RGBA(0,0,0,150));
  1703.         gr.GdiDrawText(g_search_string, incsearch_font_big, RGB(0,0,0), tt_x+1, tt_y+1 , tt_w , tt_h, DT_CENTER | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER);
  1704.         gr.GdiDrawText(g_search_string, incsearch_font_big, list.inc_search_noresult?RGB(255,75,75):RGB(250,250,250), tt_x, tt_y , tt_w , tt_h, DT_CENTER | DT_NOPREFIX | DT_CALCRECT | DT_VCENTER);
  1705.     };
  1706.    
  1707.     // draw toolbar
  1708.     var vscrollbar_w = panel.vertical_mode ? (scrollbar.visible?vscrollbar.w:0) : 0;
  1709.     if(!toolbar.state && !toolbar.timerID1) {
  1710.         // draw marker to indicate toolbar expandable
  1711.         gr.DrawLine(Math.floor((ww-vscrollbar_w)/2)-3, 2, Math.floor((ww-vscrollbar_w)/2)+3, 2, 1.0, g_textcolor&0x44ffffff);
  1712.         gr.DrawLine(Math.floor((ww-vscrollbar_w)/2)-2, 3, Math.floor((ww-vscrollbar_w)/2)+0, 5, 1.0, g_textcolor&0x44ffffff);
  1713.         gr.DrawLine(Math.floor((ww-vscrollbar_w)/2)+2, 3, Math.floor((ww-vscrollbar_w)/2)+1, 4, 1.0, g_textcolor&0x44ffffff);
  1714.     }
  1715.     if(toolbar.state || toolbar.timerID1) {
  1716.         gr.SetSmoothingMode(2);
  1717.         gr.FillRoundRect(09, (toolbar.collapsed_y + toolbar.delta) - 10, ww-vscrollbar_w-20 + 2, Math.abs(toolbar.collapsed_y) + 10 + 1, 6, 6, RGBA(0,0,0,60));
  1718.         gr.FillRoundRect(10, (toolbar.collapsed_y + toolbar.delta) - 10, ww-vscrollbar_w-20, Math.abs(toolbar.collapsed_y) + 10, 5, 5, RGBA(0,0,0,190));
  1719.         gr.DrawRoundRect(11, (toolbar.collapsed_y + toolbar.delta) - 10, ww-vscrollbar_w-20-2, Math.abs(toolbar.collapsed_y) + 10-1, 4, 4, 1.0, RGBA(250,250,250,40));
  1720.         gr.SetSmoothingMode(0);
  1721.         // draw toolbar buttons
  1722.         for(i=0;i<toolbar.buttons.length;i++) {
  1723.             switch (i) {
  1724.              case 0:
  1725.                 if(!panel.lock_playlist) {
  1726.                     toolbar.buttons[i].draw(gr, ww-vscrollbar_w-33, (toolbar.collapsed_y + toolbar.delta) + 4, (fb.IsPlaying || list.total_gh>0)?255:80);
  1727.                 };
  1728.                 break;
  1729.              case 1:
  1730.                 toolbar.buttons[i].draw(gr, 16, (toolbar.collapsed_y + toolbar.delta) + 3, 255);
  1731.                 break;
  1732.              case 2:
  1733.                 if(panel.lock_playlist) {
  1734.                     toolbar.buttons[i].draw(gr, ww-vscrollbar_w-33, (toolbar.collapsed_y + toolbar.delta) + 4, 255);
  1735.                 };
  1736.                 break;
  1737.             };
  1738.         };
  1739.     };
  1740.  
  1741. };
  1742.  
  1743. //=================================================// Mouse Callbacks
  1744. function on_mouse_lbtn_down(x, y) {
  1745.    
  1746.     g_drag = true;
  1747.    
  1748.     bool_on_size = false;
  1749.  
  1750.     var len = list.item.length;
  1751.     var mid2 = 0;
  1752.     if(list.total_gh>0) {
  1753.         if(!list.item[list.mid].checkstate("down", x, y, list.mid)) {
  1754.             for(var i = 1; i < list.mid + 1; i++) {
  1755.                 mid2 = list.mid - i;
  1756.                 if(mid2>=0 && mid2<=len-1) {
  1757.                     if(list.item[mid2].checkstate("down", x, y, mid2)) {
  1758.                         break;
  1759.                     };
  1760.                 };
  1761.                 mid2 = list.mid + i;
  1762.                 if(mid2>=0 && mid2<=len-1) {
  1763.                     if(list.item[mid2].checkstate("down", x, y, mid2)) {
  1764.                         break;
  1765.                     };
  1766.                 };
  1767.             };
  1768.         };
  1769.     };
  1770.  
  1771.     if(list.total_gh>0 && scrollbar.visible && scrollbar.show) {
  1772.         if(panel.vertical_mode) {
  1773.             if(cursor.bt.checkstate("down", x, y)==ButtonStates.down) {
  1774.                 cursor.drag = true;
  1775.                 cursor.grap_y = y - cursor.y;
  1776.                 cursor.last_y = cursor.y;
  1777.             };
  1778.             if(vscrollbar.hover && !cursor.drag) {
  1779.                 scrollbar.step = Math.floor(list.nb_cover_to_draw/2);
  1780.                 if(scrollbar.step<1) scrollbar.step = 1;
  1781.                 if(y<cursor.y) {
  1782.                     if(!list.buttonclicked) {
  1783.                         list.buttonclicked = true;
  1784.                         on_scrolling(scrollbar.step, 1);
  1785.                         scrollbarbt.timerID1 = window.SetTimeout(function () {
  1786.                             on_mouse_wheel(scrollbar.step);
  1787.                             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  1788.                             scrollbarbt.timerID1 = false;
  1789.                             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
  1790.                             scrollbarbt.timerID2 = window.SetInterval(function () {
  1791.                                 if(hscrollbar.hover) {
  1792.                                     if(mouse_x>ww-vscrollbar.w && cursor.y > mouse_y) {
  1793.                                         on_mouse_wheel(scrollbar.step);
  1794.                                     };
  1795.                                 };
  1796.                             }, scrollbarbt.timer2_value);
  1797.                         }, scrollbarbt.timer1_value);
  1798.                     };
  1799.                 } else {
  1800.                     if(!list.buttonclicked) {
  1801.                         list.buttonclicked = true;
  1802.                         on_scrolling(-1*scrollbar.step, 1);
  1803.                         scrollbarbt.timerID1 = window.SetTimeout(function () {
  1804.                             on_mouse_wheel(-1*scrollbar.step);
  1805.                             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  1806.                             scrollbarbt.timerID1 = false;
  1807.                             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
  1808.                             scrollbarbt.timerID2 = window.SetInterval(function () {
  1809.                                 if(hscrollbar.hover) {
  1810.                                     if(mouse_x>ww-vscrollbar.w && cursor.y+cursor.h < mouse_y) {
  1811.                                         on_mouse_wheel(-1*scrollbar.step);
  1812.                                     };
  1813.                                 };
  1814.                             }, scrollbarbt.timer2_value);
  1815.                         }, scrollbarbt.timer1_value);
  1816.                     };
  1817.                 };
  1818.             };
  1819.         } else {
  1820.             if(cursor.bt.checkstate("down", x, y)==ButtonStates.down) {
  1821.                 cursor.drag = true;
  1822.                 cursor.grap_x = x - cursor.x;
  1823.                 cursor.last_x = cursor.x;
  1824.             };
  1825.             if(hscrollbar.hover && !cursor.drag) {
  1826.                 scrollbar.step = Math.floor(list.nb_cover_to_draw/2);
  1827.                 if(scrollbar.step<1) scrollbar.step = 1;
  1828.                 if(x<cursor.x) {
  1829.                     if(!list.buttonclicked) {
  1830.                         list.buttonclicked = true;
  1831.                         on_scrolling(scrollbar.step, 1);
  1832.                         scrollbarbt.timerID1 = window.SetTimeout(function () {
  1833.                             on_mouse_wheel(scrollbar.step);
  1834.                             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  1835.                             scrollbarbt.timerID1 = false;
  1836.                             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
  1837.                             scrollbarbt.timerID2 = window.SetInterval(function () {
  1838.                                 if(hscrollbar.hover) {
  1839.                                     if(mouse_y>wh-hscrollbar.h && cursor.x > mouse_x) {
  1840.                                         on_mouse_wheel(scrollbar.step);
  1841.                                     };
  1842.                                 };
  1843.                             }, scrollbarbt.timer2_value);
  1844.                         }, scrollbarbt.timer1_value);
  1845.                     };
  1846.                 } else {
  1847.                     if(!list.buttonclicked) {
  1848.                         list.buttonclicked = true;
  1849.                         on_scrolling(-1*scrollbar.step, 1);
  1850.                         scrollbarbt.timerID1 = window.SetTimeout(function () {
  1851.                             on_mouse_wheel(-1*scrollbar.step);
  1852.                             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  1853.                             scrollbarbt.timerID1 = false;
  1854.                             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
  1855.                             scrollbarbt.timerID2 = window.SetInterval(function () {
  1856.                                 if(hscrollbar.hover) {
  1857.                                     if(mouse_y>wh-hscrollbar.h && cursor.x+cursor.w < mouse_x) {
  1858.                                         on_mouse_wheel(-1*scrollbar.step);
  1859.                                     };
  1860.                                 };
  1861.                             }, scrollbarbt.timer2_value);
  1862.                         }, scrollbarbt.timer1_value);
  1863.                     };
  1864.                 };
  1865.             };
  1866.         };
  1867.        
  1868.         // check scrollbar buttons (UP & DOWN buttons)
  1869.         for(i=0;i<scrollbar.arr_buttons.length;i++) {
  1870.             switch(i) {
  1871.              case 0:
  1872.                 if(scrollbar.arr_buttons[i].checkstate("down", x, y)==ButtonStates.down) {
  1873.                     if(!list.buttonclicked) {
  1874.                         list.buttonclicked = true;
  1875.                         on_mouse_wheel(1);
  1876.                         scrollbarbt.timerID1 = window.SetTimeout(function () {
  1877.                             reset_cover_timers();
  1878.                             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  1879.                             scrollbarbt.timerID1 = false;
  1880.                             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
  1881.                             scrollbarbt.timerID2 = window.SetInterval(function () {
  1882.                                 on_mouse_wheel(1);
  1883.                             }, scrollbarbt.timer2_value+10);
  1884.                         }, scrollbarbt.timer1_value);
  1885.                     };
  1886.                 };
  1887.                 break;
  1888.              case 1:
  1889.                 if(scrollbar.arr_buttons[i].checkstate("down", x, y)==ButtonStates.down) {
  1890.                     if(!list.buttonclicked) {
  1891.                         list.buttonclicked = true;
  1892.                         on_mouse_wheel(-1);
  1893.                         scrollbarbt.timerID1 = window.SetTimeout(function () {
  1894.                             reset_cover_timers();
  1895.                             scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  1896.                             scrollbarbt.timerID1 = false;
  1897.                             scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
  1898.                             scrollbarbt.timerID2 = window.SetInterval(function () {
  1899.                                 on_mouse_wheel(-1);
  1900.                             }, scrollbarbt.timer2_value+10);
  1901.                         }, scrollbarbt.timer1_value);
  1902.                     };
  1903.                 };
  1904.                 break;
  1905.             };
  1906.         };
  1907.     };
  1908.  
  1909.     // check panel buttons
  1910.     for(var i=0;i<toolbar.buttons.length;i++) {
  1911.         switch(i) {
  1912.             case 0:
  1913.                 if(!panel.lock_playlist) {
  1914.                     if(fb.IsPlaying || list.total_gh>0) {
  1915.                         toolbar.buttons[i].checkstate("down", x, y);
  1916.                     };
  1917.                 };
  1918.                 break;
  1919.             default:
  1920.                 toolbar.buttons[i].checkstate("down", x, y);
  1921.         };
  1922.     };
  1923.  
  1924. };
  1925.  
  1926. function on_mouse_lbtn_dblclk(x, y, mask) {
  1927.     if(list.total_gh>0) {
  1928.         if(panel.vertical_mode) {
  1929.             if(x<cover.pad_left_mid) {
  1930.                 //ShowNowPlaying();
  1931.             } else if(x<ww-cover.pad_right_mid) {
  1932.                 var len = list.item.length;
  1933.                 for(var i=0;i<len;i++) {
  1934.                     list.item[i].checkstate("dblclk", x, y, i);
  1935.                 };
  1936.             } else {
  1937.                 on_mouse_lbtn_down(x, y);
  1938.             };  
  1939.         } else {
  1940.             if(y<cover.pad_top_mid) {
  1941.                 //ShowNowPlaying();
  1942.             } else if(y<wh-cover.pad_bot_mid) {
  1943.                 var len = list.item.length;
  1944.                 for(var i=0;i<len;i++) {
  1945.                     if(list.item[i].id>=0) {
  1946.                         list.item[i].checkstate("dblclk", x, y, i);
  1947.                     };
  1948.                 };
  1949.             } else {
  1950.                 on_mouse_lbtn_down(x, y);
  1951.             };
  1952.         };
  1953.     };
  1954. };
  1955.  
  1956. function on_mouse_lbtn_up(x, y) {
  1957.    
  1958.     // scrollbar button up and down RESET
  1959.     list.buttonclicked = false;
  1960.     scrollbar.timerID && window.ClearTimeout(scrollbar.timerID);
  1961.     scrollbar.timerID = false;
  1962.     scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  1963.     scrollbarbt.timerID1 = false;
  1964.     scrollbarbt.timerID2 && window.ClearTimeout(scrollbarbt.timerID2);
  1965.     scrollbarbt.timerID2 = false;
  1966.    
  1967.     if(list.drag_timer) {
  1968.         window.ClearTimeout(list.drag_timer);
  1969.         list.drag_timer = false;
  1970.         list.drag_stop = true;
  1971.     }
  1972.        
  1973.     // check panel buttons
  1974.     for(i=0;i<toolbar.buttons.length;i++) {
  1975.         switch(i) {
  1976.             case 0:
  1977.                 if(!panel.lock_playlist) {
  1978.                     if(fb.IsPlaying || list.total_gh>0) {
  1979.                         if(toolbar.buttons[i].checkstate("up", x, y)==ButtonStates.hover) {
  1980.                             ShowNowPlaying();
  1981.                         };
  1982.                     };
  1983.                 };
  1984.                 break;
  1985.             case 1:
  1986.                 if(toolbar.buttons[i].checkstate("up", x, y)==ButtonStates.hover) {
  1987.                     g_menu_displayed = true;
  1988.                     settings_menu(x, y);
  1989.                 };
  1990.                 break;
  1991.             case 2:
  1992.                 if(panel.lock_playlist) {
  1993.                     if(toolbar.buttons[i].checkstate("up", x, y)==ButtonStates.hover) {
  1994.                         panel.lock_playlist = false;
  1995.                         window.SetProperty("SYSTEM.panel.lock.playlist", panel.lock_playlist);
  1996.                         plman.ActivePlaylist = panel.active_playlist;
  1997.                     };
  1998.                 };
  1999.                 break;
  2000.         };
  2001.     };
  2002.    
  2003.     // toolbar collapse if mouse out after a lbtn up
  2004.     if(!toolbar.lock) {
  2005.         if(y>30 || x<10 || x>ww-vscrollbar.w-10) {
  2006.             if(toolbar.delta==0) {
  2007.                 toolbar.timerID_on && window.ClearTimeout(toolbar.timerID_on);
  2008.                 toolbar.timerID_on = false;
  2009.             };
  2010.             if(toolbar.state) {
  2011.                 if(!toolbar.timerID_off) {
  2012.                     if(toolbar.delta == toolbar.collapsed_y*-1) {
  2013.                         toolbar.timerID_off = window.SetTimeout(function() {
  2014.                             if(!toolbar.timerID2) {
  2015.                                 toolbar.timerID2 = window.SetInterval(function() {
  2016.                                     toolbar.delta -= toolbar.step;
  2017.                                     if(toolbar.delta <= 0) {
  2018.                                         toolbar.delta = 0;
  2019.                                         toolbar.state = false;
  2020.                                         window.ClearInterval(toolbar.timerID2);
  2021.                                         toolbar.timerID2 = false;
  2022.                                     };
  2023.                                     window.RepaintRect(0, 0, ww, 30);
  2024.                                 }, 30);
  2025.                             } ;
  2026.                             toolbar.timerID_off && window.ClearTimeout(toolbar.timerID_off);
  2027.                             toolbar.timerID_off = false;
  2028.                         }, 400);
  2029.                     };
  2030.                 };  
  2031.             };
  2032.         };
  2033.     };
  2034.    
  2035.     if(list.total_gh>0) {
  2036.        
  2037.         // check scrollbar buttons
  2038.         cursor.bt.checkstate("up", x, y);
  2039.         for(var i=0;i<scrollbar.arr_buttons.length;i++) {
  2040.             scrollbar.arr_buttons[i].checkstate("up", x, y);
  2041.         };
  2042.                
  2043.         if(cursor.drag) {
  2044.             window.RepaintRect(0, wh-hscrollbar.h, ww, hscrollbar.h);
  2045.             cursor.drag = false;
  2046.         } else {
  2047.             // check items
  2048.             var len = list.item.length;
  2049.             for(i=0;i<len;i++) {
  2050.                 list.item[i].checkstate("up", x, y, i);
  2051.             };
  2052.         };
  2053.        
  2054.         setcursorx();
  2055.        
  2056.         window.Repaint();
  2057.     };
  2058.    
  2059.     g_drag = false;
  2060. };
  2061.  
  2062. function on_mouse_mbtn_down(x, y, mask) {
  2063.     bool_on_size = false;
  2064.     var len = list.item.length;
  2065.     if(list.total_gh>0) {
  2066.         for(var i=0;i<len;i++) {
  2067.             list.item[i].checkstate("mid", x, y, i);
  2068.         };
  2069.     };
  2070. };
  2071.  
  2072. function on_mouse_rbtn_down(x, y) {
  2073.     bool_on_size = false;
  2074.     var len = list.item.length;
  2075.     var item_found = false;
  2076.     var mid2 = list.mid;
  2077.  
  2078.     if(list.total_gh>0) {
  2079.         if(list.item[list.mid].checkstate("right", x, y, list.mid)) {
  2080.             item_found = true;
  2081.         } else {
  2082.             for(var i = 1; i < list.mid + 1; i++) {
  2083.                 mid2 = list.mid - i;
  2084.                 if(mid2>=0 && mid2<=len-1) {
  2085.                     if(list.item[mid2].checkstate("right", x, y, mid2)==true) {
  2086.                         item_found = true;
  2087.                         break;
  2088.                     };
  2089.                 };
  2090.                 mid2 = list.mid + i;
  2091.                 if(mid2>=0 && mid2<=len-1) {
  2092.                     if(list.item[mid2].checkstate("right", x, y, mid2)==true) {
  2093.                         item_found = true;
  2094.                         break;
  2095.                     };
  2096.                 };
  2097.             };
  2098.         };
  2099.         if(item_found) {
  2100.             if(y>toolbar.delta) {
  2101.                 new_context_menu(x, y, list.item[mid2].id, list.item[mid2].idx);
  2102.             };
  2103.         };
  2104.     };
  2105. };
  2106.  
  2107. function on_mouse_rbtn_up(x, y) {
  2108.     if(!utils.IsKeyPressed(VK_SHIFT)) {
  2109.         return true;
  2110.     };
  2111. };
  2112.  
  2113. function on_mouse_move(x, y) {
  2114.        
  2115.     if(x==mouse_x && y==mouse_y) return true;
  2116.    
  2117.     hand = false;
  2118.    
  2119.     if(cursor.drag) {
  2120.         list.drag_stop = false;
  2121.         if(list.drag_timer) {
  2122.             window.ClearTimeout(list.drag_timer);
  2123.             list.drag_timer = false;
  2124.         }
  2125.         list.drag_timer = window.SetTimeout(function() {
  2126.             list.drag_stop = true;
  2127.             window.ClearTimeout(list.drag_timer);
  2128.             list.drag_timer = false;
  2129.             window.Repaint();
  2130.         }, 25);
  2131.     } else {
  2132.         list.drag_stop = true;
  2133.     };
  2134.    
  2135.     if(list.total_gh>0 && scrollbar.visible && scrollbar.show) {
  2136.         if(panel.vertical_mode) {
  2137.             vscrollbar.hover = (x>=ww-vscrollbar.w && x<=ww && y>=vscrollbar.y && y<=vscrollbar.y+vscrollbar.h);
  2138.             cursor.hover = (x>=cursor.x && x<=cursor.x+cursor.w && y>=cursor.y && y<=cursor.y+cursor.h);
  2139.             // check buttons
  2140.             cursor.bt.checkstate("move", x, y);
  2141.                    
  2142.             for(var i=0;i<scrollbar.arr_buttons.length;i++) {
  2143.                 scrollbar.arr_buttons[i].checkstate("move", x, y);
  2144.             };
  2145.             if(cursor.drag && mouse_y!=y) {
  2146.                 reset_cover_timers();
  2147.                 cursor.y = y - cursor.grap_y;
  2148.                 // check boundaries
  2149.                 if(cursor.y<vscrollbar.y) cursor.y = vscrollbar.y;
  2150.                 if(cursor.y>vscrollbar.y+vscrollbar.h-cursor.h) cursor.y = vscrollbar.y+vscrollbar.h-cursor.h;
  2151.                 if(!cursor.timerID) {
  2152.                     cursor.timerID = window.SetTimeout(function() {
  2153.                         refresh_spv_cursor(fb.ActivePlaylist);
  2154.                         window.Repaint();
  2155.                         cursor.timerID = false;
  2156.                     }, 30);
  2157.                 };
  2158.             };
  2159.         } else {
  2160.             hscrollbar.hover = (y>=wh-hscrollbar.h && y<=wh && x>=hscrollbar.x && x<=hscrollbar.x+hscrollbar.w);
  2161.             cursor.hover = (x>=cursor.x && x<=cursor.x+cursor.w && y>=cursor.y && y<=cursor.y+cursor.h);
  2162.             // check buttons
  2163.             cursor.bt.checkstate("move", x, y);
  2164.                    
  2165.             for(var i=0;i<scrollbar.arr_buttons.length;i++) {
  2166.                 scrollbar.arr_buttons[i].checkstate("move", x, y);
  2167.             };
  2168.             if(cursor.drag && mouse_x!=x) {
  2169.                 reset_cover_timers();
  2170.                 cursor.x = x - cursor.grap_x;
  2171.                 // check boundaries
  2172.                 if(cursor.x<hscrollbar.x) cursor.x = hscrollbar.x;
  2173.                 if(cursor.x>hscrollbar.x+hscrollbar.w-cursor.w) cursor.x = hscrollbar.x+hscrollbar.w-cursor.w;
  2174.                 if(!cursor.timerID) {
  2175.                     cursor.timerID = window.SetTimeout(function() {
  2176.                         refresh_spv_cursor(panel.active_playlist);
  2177.                         window.Repaint();
  2178.                         cursor.timerID && window.ClearTimeout(cursor.timerID);
  2179.                         cursor.timerID = false;
  2180.                     }, 30);
  2181.                 };
  2182.             };
  2183.         };
  2184.     };
  2185.    
  2186.     // check panel buttons  
  2187.     for(var j=0;j<toolbar.buttons.length;j++) {
  2188.         switch (j) {
  2189.             case 0:
  2190.                 if(!panel.lock_playlist) {
  2191.                     if(fb.IsPlaying || list.total_gh>0) {
  2192.                         if(toolbar.buttons[j].checkstate("move", x, y)==ButtonStates.hover) {
  2193.                             hand = true;
  2194.                         };
  2195.                     };
  2196.                 };
  2197.                 break;
  2198.             case 2:
  2199.                 if(panel.lock_playlist) {
  2200.                     if(toolbar.buttons[j].checkstate("move", x, y)==ButtonStates.hover) {
  2201.                         hand = true;
  2202.                     };
  2203.                 };
  2204.                 break;
  2205.             default:
  2206.                 if(toolbar.buttons[j].checkstate("move", x, y)==ButtonStates.hover) {
  2207.                     hand = true;
  2208.                 };
  2209.         };
  2210.     };
  2211.    
  2212.     // hide/show toolbar
  2213.     var vscrollbar_w = panel.vertical_mode ? (scrollbar.visible?vscrollbar.w:0) : 0;
  2214.     if(!toolbar.lock && !g_drag) {
  2215.         if(y>=0 && y<=15 && x>10 && x<ww-vscrollbar_w-10) {
  2216.             if(toolbar.delta==toolbar.collapsed_y*-1) {
  2217.                 toolbar.timerID_off && window.ClearTimeout(toolbar.timerID_off);
  2218.                 toolbar.timerID_off = false;
  2219.             };
  2220.             if(!toolbar.timerID_on) {
  2221.                 if(toolbar.delta==0) {
  2222.                     toolbar.timerID_on = window.SetTimeout(function() {
  2223.                         toolbar.timerID2 && window.ClearInterval(toolbar.timerID2);
  2224.                         toolbar.timerID2 = false;
  2225.                         if(!toolbar.timerID1) {
  2226.                             toolbar.timerID1 = window.SetInterval(function() {
  2227.                                 toolbar.delta += toolbar.step;
  2228.                                 if(toolbar.collapsed_y + toolbar.delta >= 0) {
  2229.                                     toolbar.delta = toolbar.collapsed_y*-1;
  2230.                                     toolbar.state = true;
  2231.                                     window.ClearInterval(toolbar.timerID1);
  2232.                                     toolbar.timerID1 = false;
  2233.                                 };
  2234.                                 window.RepaintRect(0, 0, ww, 30);
  2235.                             }, 30);
  2236.                         };
  2237.                         toolbar.timerID_on && window.ClearTimeout(toolbar.timerID_on);
  2238.                         toolbar.timerID_on = false;
  2239.                     }, 400);
  2240.                 } else if(toolbar.timerID2) {
  2241.                     toolbar.timerID2 && window.ClearInterval(toolbar.timerID2);
  2242.                     toolbar.timerID2 = false;
  2243.                     if(!toolbar.timerID1) {
  2244.                         toolbar.timerID1 = window.SetInterval(function() {
  2245.                             toolbar.delta += toolbar.step;
  2246.                             if(toolbar.collapsed_y + toolbar.delta >= 0) {
  2247.                                 toolbar.delta = toolbar.collapsed_y*-1;
  2248.                                 toolbar.state = true;
  2249.                                 window.ClearInterval(toolbar.timerID1);
  2250.                                 toolbar.timerID1 = false;
  2251.                             };
  2252.                             window.RepaintRect(0, 0, ww, 30);
  2253.                         }, 30);
  2254.                     };
  2255.                 };
  2256.             };
  2257.         } else if(y>30 || x<10 || x>ww-vscrollbar_w-10) {
  2258.             if(toolbar.delta==0) {
  2259.                 toolbar.timerID_on && window.ClearTimeout(toolbar.timerID_on);
  2260.                 toolbar.timerID_on = false;
  2261.             };
  2262.             if(toolbar.state) {
  2263.                 if(!toolbar.timerID_off) {
  2264.                     if(toolbar.delta == toolbar.collapsed_y*-1) {
  2265.                         toolbar.timerID_off = window.SetTimeout(function() {
  2266.                             if(!toolbar.timerID2) {
  2267.                                 toolbar.timerID2 = window.SetInterval(function() {
  2268.                                     toolbar.delta -= toolbar.step;
  2269.                                     if(toolbar.delta <= 0) {
  2270.                                         toolbar.delta = 0;
  2271.                                         toolbar.state = false;
  2272.                                         window.ClearInterval(toolbar.timerID2);
  2273.                                         toolbar.timerID2 = false;
  2274.                                     };
  2275.                                     window.RepaintRect(0, 0, ww, 30);
  2276.                                 }, 30);
  2277.                             } ;
  2278.                             toolbar.timerID_off && window.ClearTimeout(toolbar.timerID_off);
  2279.                             toolbar.timerID_off = false;
  2280.                         }, 400);
  2281.                     };
  2282.                 };  
  2283.             };
  2284.         };
  2285.     };
  2286.    
  2287.     // Mouse Cursor
  2288.     window.SetCursor(hand? IDC_HAND : IDC_ARROW);
  2289.  
  2290.     mouse_x = x;
  2291.     mouse_y = y;
  2292. };
  2293.  
  2294. function on_mouse_wheel(delta) {
  2295.        
  2296.     var abs_delta = Math.abs(delta);
  2297.     reset_cover_timers();
  2298.    
  2299.     if(list.total_gh>0) {
  2300.         if(!scrollbar.timerID) {
  2301.             if(abs_delta>=1) {
  2302.                 if(delta>0) {
  2303.                     if(panel.scroll_effect) {
  2304.                         for(var i=0; i<abs_delta-1; i++) {
  2305.                             scrollup_spv(panel.active_playlist);
  2306.                         };
  2307.                         scrollcoverflow(0, 1, scroll.factor);
  2308.                     } else {
  2309.                         for(var i=0; i<abs_delta; i++) {
  2310.                             scrollup_spv(panel.active_playlist);
  2311.                         };
  2312.                     };
  2313.                     scrollbar.timerID = window.SetTimeout(function () {
  2314.                         window.Repaint();
  2315.                         scrollbar.timerID && window.ClearTimeout(scrollbar.timerID);
  2316.                         scrollbar.timerID = false;
  2317.                     }, list.mousewheel_timer_value);
  2318.                 } else {
  2319.                     if(panel.scroll_effect) {
  2320.                         for(var i=0; i<abs_delta-1; i++) {
  2321.                             scrolldown_spv(panel.active_playlist);
  2322.                         };
  2323.                         scrollcoverflow(1, 0, scroll.factor);
  2324.                     } else {
  2325.                         for(var i=0; i<abs_delta; i++) {
  2326.                             scrolldown_spv(panel.active_playlist);
  2327.                         };
  2328.                     };
  2329.                     scrollbar.timerID = window.SetTimeout(function () {
  2330.                         window.Repaint();
  2331.                         scrollbar.timerID && window.ClearTimeout(scrollbar.timerID);
  2332.                         scrollbar.timerID = false;
  2333.                     }, list.mousewheel_timer_value);                        
  2334.                 };
  2335.             };
  2336.         };
  2337.     };
  2338. };
  2339.  
  2340. function on_scrolling(delta, factor) {
  2341.    
  2342.     var abs_delta = Math.abs(delta);
  2343.     reset_cover_timers();
  2344.    
  2345.     if(list.total_gh>0) {
  2346.         if(!scrollbar.timerID) {
  2347.             if(abs_delta>=1) {
  2348.                 if(delta>0) {
  2349.                     if(panel.scroll_effect) {
  2350.                         scrollcoverflow(0, abs_delta, factor);
  2351.                     } else {
  2352.                         for(var i=0; i<abs_delta; i++) {
  2353.                             scrollup_spv(panel.active_playlist);
  2354.                         };
  2355.                         scrollbar.timerID = window.SetTimeout(function () {
  2356.                             window.Repaint();
  2357.                             scrollbar.timerID && window.ClearTimeout(scrollbar.timerID);
  2358.                             scrollbar.timerID = false;
  2359.                         }, list.mousewheel_timer_value);
  2360.                     };
  2361.                 } else {
  2362.                     if(panel.scroll_effect) {
  2363.                         scrollcoverflow(abs_delta, 0, factor);
  2364.                     } else {
  2365.                         for(var i=0; i<abs_delta; i++) {
  2366.                             scrolldown_spv(panel.active_playlist);
  2367.                         }
  2368.                         scrollbar.timerID = window.SetTimeout(function () {
  2369.                             window.Repaint();
  2370.                             scrollbar.timerID && window.ClearTimeout(scrollbar.timerID);
  2371.                             scrollbar.timerID = false;
  2372.                         }, list.mousewheel_timer_value);                        
  2373.                     };
  2374.                 };
  2375.             };
  2376.         };
  2377.     };
  2378. };
  2379.  
  2380. function on_mouse_leave() {
  2381.     var len = list.item.length;
  2382.     if(list.total_gh>0) {
  2383.         for(var i=0;i<len;i++) {
  2384.             list.item[i].checkstate("leave", 0, 0, i);
  2385.         };
  2386.     };
  2387.     for(i=0;i<toolbar.buttons.length;i++) {
  2388.         toolbar.buttons[i].checkstate("leave", 0, 0);
  2389.     };
  2390.  
  2391.     // toolbar is to hide if visible or amorced
  2392.     if(toolbar.delta==0) {
  2393.         toolbar.timerID_on && window.ClearTimeout(toolbar.timerID_on);
  2394.         toolbar.timerID_on = false;
  2395.     };
  2396.     if(!toolbar.lock && !g_drag) {
  2397.         if(!g_menu_displayed) {
  2398.             if(!toolbar.timerID_off) {
  2399.                 toolbar.timerID_off = window.SetTimeout(function() {
  2400.                     if(!toolbar.timerID2) {
  2401.                         toolbar.timerID2 = window.SetInterval(function() {
  2402.                             toolbar.delta -= toolbar.step;
  2403.                             if(toolbar.delta <= 0) {
  2404.                                 toolbar.delta = 0;
  2405.                                 toolbar.state = false;
  2406.                                 window.ClearInterval(toolbar.timerID2);
  2407.                                 toolbar.timerID2 = false;
  2408.                             };
  2409.                             window.RepaintRect(0, 0, ww, 30);
  2410.                         }, 30);
  2411.                     } ;
  2412.                     toolbar.timerID_off && window.ClearTimeout(toolbar.timerID_off);
  2413.                     toolbar.timerID_off = false;
  2414.                 }, 400);
  2415.             };  
  2416.         };
  2417.     };
  2418.     window.Repaint();
  2419. };
  2420.  
  2421. //=================================================// Callbacks
  2422.  
  2423. function on_playlist_switch() {
  2424.     // set/check the active playlist for the panel
  2425.     if(!panel.lock_playlist) {
  2426.         panel.active_playlist = plman.ActivePlaylist;
  2427.     };
  2428.  
  2429.     // test if there is an active playlist focused (may happen whenyou delete a playlist from pl manager)
  2430.     if(plman.ActivePlaylist < 0 || plman.ActivePlaylist > fb.PlaylistCount) {
  2431.         if(fb.PlaylistCount>0) {
  2432.             plman.ActivePlaylist = 0;
  2433.         };
  2434.     };
  2435.     init_active_pls();
  2436.     list.focus_id = plman.GetPlaylistFocusItemIndex(panel.active_playlist);
  2437.     if(list.focus_id<0) {
  2438.         list.focus_id = 0;
  2439.     }
  2440.     refresh_spv(panel.active_playlist, true);
  2441.     window.Repaint();
  2442. };
  2443.  
  2444. function on_playlist_items_added(playlist_idx) {
  2445.     if(playlist_idx==panel.active_playlist) {
  2446.         on_playlist_switch();
  2447.     };
  2448.     plman.SetActivePlaylistContext();
  2449. };
  2450.  
  2451. function on_playlist_items_removed(playlist_idx, new_count) {
  2452.     if(playlist_idx==panel.active_playlist) {
  2453.         on_playlist_switch();
  2454.     };
  2455.     plman.SetActivePlaylistContext();
  2456. };
  2457.  
  2458. function on_playlist_items_reordered(playlist_idx) {
  2459.     if(playlist_idx==panel.active_playlist) {
  2460.         on_playlist_switch();
  2461.     };
  2462. };
  2463.  
  2464. function on_selection_changed(metadb) {
  2465. };
  2466.  
  2467. function on_playlist_items_selection_change() {
  2468. };
  2469.  
  2470. function on_playlists_changed() {
  2471.     if(bypass.on_playlists_changed) {
  2472.         //bypass.on_playlists_changed = false;
  2473.         return true;
  2474.     } else {
  2475.         if(panel.lock_playlist) {
  2476.             // unlock on playlist changed because locked playlist may have be moved or deleted
  2477.             panel.lock_playlist = !panel.lock_playlist;
  2478.             window.SetProperty("SYSTEM.panel.lock.playlist", panel.lock_playlist);
  2479.             plman.ActivePlaylist = panel.active_playlist;
  2480.             window.Repaint();
  2481.         };
  2482.     };
  2483. };
  2484.  
  2485. function on_item_focus_change(playlist, from, to) {
  2486.     if(bypass.on_item_focus_change || to<0) {
  2487.         bypass.on_item_focus_change = false;
  2488.         return true;
  2489.     };
  2490.     if(playlist==panel.active_playlist) {
  2491.         list.focus_id = to;
  2492.         plman.SetActivePlaylistContext();
  2493.         refresh_spv(panel.active_playlist, bool_on_size);
  2494.         bool_on_size = false;
  2495.         window.Repaint();
  2496.     };
  2497. };
  2498.  
  2499. function on_metadb_changed(metadb_or_metadbs, fromhook) {
  2500.     var len = list.item.length;
  2501.     for(var i=0;i<len;i++) {
  2502.         list.item[i].update_infos();
  2503.     };
  2504.     window.Repaint();
  2505. };
  2506.  
  2507. function on_focus(is_focused) {
  2508.     if(is_focused) {
  2509.         plman.SetActivePlaylistContext();
  2510.     };
  2511. };
  2512.  
  2513. //=================================================// Keyboard Callbacks
  2514. function on_key_up(vkey) {
  2515.     // scrollbar button up and down RESET
  2516.     list.buttonclicked = false;
  2517.     scrollbar.timerID && window.ClearTimeout(scrollbar.timerID);
  2518.     scrollbar.timerID = false;
  2519.     scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  2520.     scrollbarbt.timerID1 = false;
  2521.     scrollbarbt.timerID2 && window.ClearTimeout(scrollbarbt.timerID2);
  2522.     scrollbarbt.timerID2 = false;
  2523. };
  2524.  
  2525. function on_key_down(vkey) {
  2526.     var mask = GetKeyboardMask();
  2527.  
  2528.     if (mask == KMask.none) {
  2529.         switch (vkey) {
  2530.         case VK_SHIFT:
  2531.             list.SHIFT_count = 0;
  2532.             break;
  2533.         case VK_BACK:
  2534.             if(g_search_string.length>0) {
  2535.                 var tt_x = Math.floor((ww / 2) - ((g_search_string.length*13)+(10*2)) / 2);
  2536.                 var tt_y = Math.floor(wh/2) - 30;
  2537.                 var tt_w = ((g_search_string.length*13)+(10*2));
  2538.                 var tt_h = 60;
  2539.                 g_search_string = g_search_string.substring(0, g_search_string.length-1);
  2540.                 window.RepaintRect(0, tt_y-2, ww, tt_h+4);
  2541.                 clear_incsearch_timer && window.ClearInterval(clear_incsearch_timer);
  2542.                 incsearch_timer && window.ClearTimeout(incsearch_timer);
  2543.                 incsearch_timer = window.SetTimeout(function () {
  2544.                     IncrementalSearch();
  2545.                     window.ClearTimeout(incsearch_timer);
  2546.                     incsearch_timer = false;
  2547.                 }, 400);
  2548.             };
  2549.             break;
  2550.         case VK_ESCAPE:
  2551.         case 222:
  2552.             var tt_x = Math.floor((ww / 2) - ((g_search_string.length*13)+(10*2)) / 2);
  2553.             var tt_y = Math.floor(wh/2) - 30;
  2554.             var tt_w = ((g_search_string.length*13)+(10*2));
  2555.             var tt_h = 60;
  2556.             g_search_string = "";
  2557.             window.RepaintRect(0, tt_y-2, ww, tt_h+4);
  2558.             break;
  2559.         case VK_UP:
  2560.         case VK_LEFT:
  2561.             if(list.total_gh>0) {
  2562.                 if(!list.buttonclicked) {
  2563.                     list.buttonclicked = true;
  2564.                     on_mouse_wheel(1);
  2565.                     window.Repaint();
  2566.                     scrollbarbt.timerID1 = window.SetTimeout(function () {
  2567.                         reset_cover_timers();
  2568.                         scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  2569.                         scrollbarbt.timerID1 = false;
  2570.                         scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
  2571.                         scrollbarbt.timerID2 = window.SetInterval(function () {
  2572.                             on_mouse_wheel(1);
  2573.                         }, scrollbarbt.timer2_value);
  2574.                     }, scrollbarbt.timer1_value);
  2575.                 };
  2576.             };
  2577.             break;
  2578.         case VK_DOWN:
  2579.         case VK_RIGHT:
  2580.             if(list.total_gh>0) {
  2581.                 if(!list.buttonclicked) {
  2582.                     list.buttonclicked = true;
  2583.                     on_mouse_wheel(-1);
  2584.                     window.Repaint();
  2585.                     scrollbarbt.timerID1 = window.SetTimeout(function () {
  2586.                         reset_cover_timers();
  2587.                         scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  2588.                         scrollbarbt.timerID1 = false;
  2589.                         scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
  2590.                         scrollbarbt.timerID2 = window.SetInterval(function () {
  2591.                             on_mouse_wheel(-1);
  2592.                         }, scrollbarbt.timer2_value);
  2593.                     }, scrollbarbt.timer1_value);
  2594.                 };
  2595.             };
  2596.             break;
  2597.         case VK_PGUP:
  2598.             if(list.total_gh>0) {
  2599.                 scrollbar.step = Math.floor(list.nb_cover_to_draw/2);
  2600.                 if(scrollbar.step<1) scrollbar.step = 1;
  2601.                 if(!list.buttonclicked) {
  2602.                     list.buttonclicked = true;
  2603.                     on_mouse_wheel(scrollbar.step);
  2604.                     window.Repaint();
  2605.                     scrollbarbt.timerID1 = window.SetTimeout(function () {
  2606.                         reset_cover_timers();
  2607.                         scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  2608.                         scrollbarbt.timerID1 = false;
  2609.                         scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
  2610.                         scrollbarbt.timerID2 = window.SetInterval(function () {
  2611.                             on_mouse_wheel(scrollbar.step);
  2612.                         }, scrollbarbt.timer2_value);
  2613.                     }, scrollbarbt.timer1_value);
  2614.                 };
  2615.             };
  2616.             break;
  2617.         case VK_PGDN:
  2618.             if(list.total_gh>0) {
  2619.                 scrollbar.step = Math.floor(list.nb_cover_to_draw/2);
  2620.                 if(scrollbar.step<1) scrollbar.step = 1;
  2621.                 if(!list.buttonclicked) {
  2622.                     list.buttonclicked = true;
  2623.                     on_mouse_wheel(scrollbar.step*-1);
  2624.                     window.Repaint();
  2625.                     scrollbarbt.timerID1 = window.SetTimeout(function () {
  2626.                         reset_cover_timers();
  2627.                         scrollbarbt.timerID1 && window.ClearTimeout(scrollbarbt.timerID1);
  2628.                         scrollbarbt.timerID1 = false;
  2629.                         scrollbarbt.timerID2 && window.ClearInterval(scrollbarbt.timerID2);
  2630.                         scrollbarbt.timerID2 = window.SetInterval(function () {
  2631.                             on_mouse_wheel(scrollbar.step*-1);
  2632.                         }, scrollbarbt.timer2_value);
  2633.                     }, scrollbarbt.timer1_value);
  2634.                 };
  2635.             };
  2636.             break;
  2637.         case VK_RETURN:
  2638.             // play focus item
  2639.             if(list.total_gh>0) {
  2640.                 plman.ExecutePlaylistDefaultAction(panel.active_playlist, list.focus_id);
  2641.             };
  2642.             break;
  2643.         case VK_END:
  2644.             if(list.total_gh>0) {
  2645.                 plman.SetPlaylistFocusItem(panel.active_playlist, list.total-1);
  2646.                 plman.ClearPlaylistSelection(panel.active_playlist);
  2647.                 plman.SetPlaylistSelectionSingle(panel.active_playlist, list.total-1, true);
  2648.             };
  2649.             break;
  2650.         case VK_HOME:
  2651.             if(list.total_gh>0) {
  2652.                 plman.SetPlaylistFocusItem(panel.active_playlist, 0);
  2653.                 plman.ClearPlaylistSelection(panel.active_playlist);
  2654.                 plman.SetPlaylistSelectionSingle(panel.active_playlist, 0, true);
  2655.             };
  2656.             break;
  2657.         case VK_DELETE:
  2658.             if(list.total_gh>0) {
  2659.                 if(!fb.IsAutoPlaylist(panel.active_playlist)) {
  2660.                     plman.RemovePlaylistSelection(panel.active_playlist, false);
  2661.                     plman.SetPlaylistSelectionSingle(panel.active_playlist, plman.GetPlaylistFocusItemIndex(panel.active_playlist), true);
  2662.                 };
  2663.             };
  2664.             break;
  2665.         case VK_SPACEBAR:
  2666.             if(g_search_string.length==0) {
  2667.                 if(list.total_gh>0) {
  2668.                     if(panel.lock_playlist) {
  2669.                         plman.SetPlaylistFocusItem(panel.active_playlist, new_focus_id);
  2670.                         plman.ClearPlaylistSelection(panel.active_playlist);
  2671.                         plman.SetPlaylistSelectionSingle(panel.active_playlist, new_focus_id, true);
  2672.                         var mid_idx = Math.floor(list.nbvis/2);
  2673.                         list.item[mid_idx].checkstate("mid", list.item[mid_idx].x+5, list.item[mid_idx].y+5, mid_idx);
  2674.                     } else {
  2675.                         var new_focus_id = list.item[Math.floor(list.nbvis/2)].id;
  2676.                         SelectGroupItems(new_focus_id, get_gh_id(new_focus_id), true);
  2677.                     };
  2678.                 };
  2679.                 break;
  2680.             };
  2681.         };
  2682.     } else {
  2683.         switch(mask) {
  2684.             case KMask.shift:
  2685.                 break;
  2686.             case KMask.ctrl:
  2687.                 if(vkey==65) { // CTRL+A
  2688.                     fb.RunMainMenuCommand("Edit/Select all");
  2689.                     window.Repaint();
  2690.                 };
  2691.                 if(vkey==70) { // CTRL+F
  2692.                     fb.RunMainMenuCommand("Edit/Search");
  2693.                 };
  2694.                 if(vkey==78) { // CTRL+N
  2695.                     fb.RunMainMenuCommand("File/New playlist");
  2696.                 };
  2697.                 if(vkey==79) { // CTRL+O
  2698.                     fb.RunMainMenuCommand("File/Open...");
  2699.                 };
  2700.                 if(vkey==80) { // CTRL+P
  2701.                     fb.RunMainMenuCommand("File/Preferences");
  2702.                 };
  2703.                 if(vkey==83) { // CTRL+S
  2704.                     fb.RunMainMenuCommand("File/Save playlist...");
  2705.                 };
  2706.                 break;
  2707.             case KMask.alt:
  2708.                 if(vkey==65) { // ALT+A
  2709.                     fb.RunMainMenuCommand("View/Always on Top");
  2710.                 };
  2711.                 break;
  2712.         };
  2713.     };
  2714. };
  2715.  
  2716. function on_char(code) {
  2717.     if(list.total_gh>0) {
  2718.         var tt_x = Math.floor((ww / 2) - ((g_search_string.length*13)+(10*2)) / 2);
  2719.         var tt_y = Math.floor(wh/2) - 30;
  2720.         var tt_w = ((g_search_string.length*13)+(10*2));
  2721.         var tt_h = 60;
  2722.         if(code==32 && g_search_string.length==0) return true; // SPACE Char not allowed on 1st char
  2723.         if(g_search_string.length<=20 && tt_w<=ww-50) {
  2724.             if (code > 31) {
  2725.                 g_search_string = g_search_string + String.fromCharCode(code).toUpperCase();
  2726.                 window.RepaintRect(0, tt_y-2, ww, tt_h+4);
  2727.                 clear_incsearch_timer && window.ClearInterval(clear_incsearch_timer);
  2728.                 clear_incsearch_timer = false;
  2729.                 incsearch_timer && window.ClearTimeout(incsearch_timer);
  2730.                 incsearch_timer = window.SetTimeout(function () {
  2731.                     IncrementalSearch();
  2732.                     window.ClearTimeout(incsearch_timer);
  2733.                     incsearch_timer = false;
  2734.                 }, 400);
  2735.             };
  2736.         };
  2737.     };
  2738. };
  2739.  
  2740. //=================================================// Playback Callbacks
  2741. function on_playback_new_track(info) {
  2742.     g_metadb = fb.GetNowPlaying();
  2743.     window.Repaint();
  2744. };
  2745.  
  2746. function on_playback_stop(reason) {
  2747.     if(reason==0) { // on user Stop
  2748.         g_metadb = fb.GetFocusItem();
  2749.         on_metadb_changed();
  2750.     };
  2751. };
  2752.  
  2753. function on_playback_pause(state){
  2754. };
  2755.  
  2756. function on_playback_time(time) {
  2757. };
  2758.  
  2759. //=================================================// Font & Colors
  2760. function get_font() {
  2761.     if (g_instancetype == 0) { // CUI
  2762.         g_font = window.GetFontCUI(FontTypeCUI.items);
  2763.         g_font_headers = window.GetFontCUI(FontTypeCUI.labels);
  2764.     } else if (g_instancetype == 1) { // DUI
  2765.         g_font = window.GetFontDUI(FontTypeDUI.playlists);
  2766.         g_font_headers = window.GetFontDUI(FontTypeDUI.tabs);
  2767.     };
  2768. };
  2769.  
  2770. function get_colors() {
  2771.     if(g_instancetype == 0) { // CUI
  2772.         g_textcolor = window.GetColorCUI(ColorTypeCUI.text);
  2773.         g_textcolor_sel = window.GetColorCUI(ColorTypeCUI.selection_text);
  2774.         g_textcolor_hl = window.GetColorCUI(ColorTypeCUI.active_item_frame);
  2775.         g_backcolor = window.GetColorCUI(ColorTypeCUI.background);
  2776.         g_backcolor_sel = window.GetColorCUI(ColorTypeCUI.selection_background);
  2777.     } else if(g_instancetype == 1) { // DUI
  2778.         g_textcolor = window.GetColorDUI(ColorTypeDUI.text);
  2779.         g_textcolor_sel = window.GetColorDUI(ColorTypeDUI.selection);
  2780.         g_textcolor_hl = window.GetColorDUI(ColorTypeDUI.highlight);
  2781.         g_backcolor = window.GetColorDUI(ColorTypeDUI.background);
  2782.         g_backcolor_sel = g_textcolor_sel;
  2783.     };
  2784.     g_syscolor = utils.GetSysColor(COLOR_BTNFACE);
  2785.     g_syscolor_text = utils.GetSysColor(COLOR_TEXT);
  2786.    
  2787.     // Custom colors set in Properties of the panel
  2788.     if(panel.custom_colors) {
  2789.         try{
  2790.             if(panel.custom_textcolor.length>0) g_textcolor = eval(panel.custom_textcolor);
  2791.             if(panel.custom_textcolor_selection.length>0) {
  2792.                 g_textcolor_sel = eval(panel.custom_textcolor_selection);
  2793.                 g_backcolor_sel = g_textcolor_sel;
  2794.             };
  2795.             if(panel.custom_backcolor.length>0) g_backcolor = eval(panel.custom_backcolor);
  2796.         } catch(e) {};
  2797.     };
  2798.    
  2799.     //g_backcolor = g_syscolor;
  2800.     //g_textcolor = g_syscolor_text;
  2801.    
  2802.     g_backcolor_R = getRed(g_backcolor);
  2803.     g_backcolor_G = getGreen(g_backcolor);
  2804.     g_backcolor_B = getBlue(g_backcolor);
  2805. };
  2806.  
  2807. //=================================================// Images (general)
  2808. function set_scroller() {
  2809.     var gb;
  2810.        
  2811.     if(panel.vertical_mode) {
  2812.         try {
  2813.             cursor.img_normal = gdi.CreateImage(cursor.w, cursor.h);
  2814.         } catch(e) {
  2815.             cursor.h = cursor.default_h;
  2816.             cursor.img_normal = gdi.CreateImage(cursor.w, cursor.h);
  2817.         };
  2818.        
  2819.         gb = cursor.img_normal.GetGraphics();
  2820.         // Draw Themed Scrollbar (lg/col)
  2821.         try {
  2822.             scrollbar.theme.SetPartAndStateId(3, 1);
  2823.             scrollbar.theme.DrawThemeBackground(gb, 0, 0, cursor.w, cursor.h);
  2824.         } catch(e) {
  2825.             gb.SetSmoothingMode(2);
  2826.             gb.FillRoundRect(3, 0, cursor.w-6, cursor.h-1, 1, 1, g_textcolor&0x44ffffff);
  2827.             gb.DrawRoundRect(3, 0, cursor.w-6, cursor.h-1, 1, 1, 1.0, g_textcolor&0x44ffffff);
  2828.             gb.SetSmoothingMode(0);
  2829.         };
  2830.         cursor.img_normal.ReleaseGraphics(gb);
  2831.  
  2832.         cursor.img_hover = gdi.CreateImage(cursor.w, cursor.h);
  2833.         gb = cursor.img_hover.GetGraphics();
  2834.         // Draw Themed Scrollbar (lg/col)
  2835.         try {
  2836.             scrollbar.theme.SetPartAndStateId(3, 2);
  2837.             scrollbar.theme.DrawThemeBackground(gb, 0, 0, cursor.w, cursor.h);
  2838.         } catch(e) {
  2839.             gb.SetSmoothingMode(2);
  2840.             gb.FillRoundRect(3, 0, cursor.w-6, cursor.h-1, 1, 1, g_textcolor&0x88ffffff);
  2841.             gb.DrawRoundRect(3, 0, cursor.w-6, cursor.h-1, 1, 1, 1.0, g_textcolor&0x88ffffff);
  2842.             gb.SetSmoothingMode(0);
  2843.         };
  2844.         cursor.img_hover.ReleaseGraphics(gb);
  2845.         cursor.bt = new button(cursor.img_normal, cursor.img_hover, cursor.img_hover);
  2846.     } else {
  2847.         try {
  2848.             cursor.img_normal = gdi.CreateImage(cursor.w, cursor.h);
  2849.         } catch(e) {
  2850.             cursor.h = cursor.default_h;
  2851.             cursor.img_normal = gdi.CreateImage(cursor.w, cursor.h);
  2852.         };
  2853.  
  2854.         gb = cursor.img_normal.GetGraphics();
  2855.         // Draw Themed Scrollbar (lg/col)
  2856.         try {
  2857.             scrollbar.theme.SetPartAndStateId(2, 1);
  2858.             scrollbar.theme.DrawThemeBackground(gb, 0, 0, cursor.w, cursor.h);
  2859.         } catch(e) {
  2860.             gb.SetSmoothingMode(2);
  2861.             gb.FillRoundRect(0, 3, cursor.w-1, cursor.h-6, 1, 1, g_textcolor&0x44ffffff);
  2862.             gb.DrawRoundRect(0, 3, cursor.w-1, cursor.h-6, 1, 1, 1.0, g_textcolor&0x44ffffff);
  2863.             gb.SetSmoothingMode(0);
  2864.         };
  2865.         cursor.img_normal.ReleaseGraphics(gb);
  2866.  
  2867.         cursor.img_hover = gdi.CreateImage(cursor.w, cursor.h);
  2868.         gb = cursor.img_hover.GetGraphics();
  2869.         // Draw Themed Scrollbar (lg/col)
  2870.         try {
  2871.             scrollbar.theme.SetPartAndStateId(2, 2);
  2872.             scrollbar.theme.DrawThemeBackground(gb, 0, 0, cursor.w, cursor.h);
  2873.         } catch(e) {
  2874.             gb.SetSmoothingMode(2);
  2875.             gb.FillRoundRect(0, 3, cursor.w-1, cursor.h-6, 1, 1, g_textcolor&0x88ffffff);
  2876.             gb.DrawRoundRect(0, 3, cursor.w-1, cursor.h-6, 1, 1, 1.0, g_textcolor&0x88ffffff);
  2877.             gb.SetSmoothingMode(0);
  2878.         };
  2879.         cursor.img_hover.ReleaseGraphics(gb);
  2880.         cursor.bt = new button(cursor.img_normal, cursor.img_hover, cursor.img_hover);
  2881.     };
  2882. };
  2883.  
  2884. function init_hscrollbar_buttons() {
  2885.     var i, gb;
  2886.  
  2887.     cursor.popup = gdi.CreateImage(22, 27);
  2888.     gb = cursor.popup.GetGraphics();
  2889.     gb.SetSmoothingMode(2);
  2890.     gb.FillRoundRect(0,0,22-1,22-1,3,3,g_textcolor);
  2891.     gb.DrawRoundRect(0,0,22-1,22-1,3,3,1.0,RGBA(0,0,0,150));
  2892.     var points = Array(7,22-2, 11,22-2+6, 22-7,22-2);
  2893.     gb.FillPolygon(g_textcolor, 0, points);
  2894.     gb.DrawPolygon(RGBA(0,0,0,150), 1.0, points);
  2895.     gb.SetSmoothingMode(0);
  2896.     gb.FillSolidRect(6,22-4,22-10,3,g_textcolor);
  2897.     cursor.popup.ReleaseGraphics(gb);
  2898.    
  2899.     button_up.img_normal = gdi.CreateImage(button_up.w, button_up.h);
  2900.     gb = button_up.img_normal.GetGraphics();
  2901.     // Draw Themed Scrollbar (lg/col)
  2902.     try {
  2903.         scrollbar.theme.SetPartAndStateId(1, 9);
  2904.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h);
  2905.     } catch(e) {
  2906.         gb.SetSmoothingMode(2);
  2907.         var mid_y = Math.round(button_up.h/2);
  2908.         gb.DrawLine(10, mid_y-4, 6, mid_y+0, 2.0, g_textcolor&0x44ffffff);
  2909.         gb.DrawLine(7, mid_y+0, 10, mid_y+3, 2.0, g_textcolor&0x44ffffff);
  2910.     };
  2911.     button_up.img_normal.ReleaseGraphics(gb);
  2912.  
  2913.     button_up.img_hover = gdi.CreateImage(button_up.w, button_up.h);
  2914.     gb = button_up.img_hover.GetGraphics();
  2915.     // Draw Themed Scrollbar (lg/col)
  2916.     try {
  2917.         scrollbar.theme.SetPartAndStateId(1, 10);
  2918.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h);
  2919.     } catch(e) {
  2920.         gb.SetSmoothingMode(2);
  2921.         var mid_y = Math.round(button_up.h/2);
  2922.         gb.DrawLine(10, mid_y-4, 6, mid_y+0, 2.0, g_textcolor&0x88ffffff);
  2923.         gb.DrawLine(7, mid_y+0, 10, mid_y+3, 2.0, g_textcolor&0x88ffffff);
  2924.     };
  2925.     button_up.img_hover.ReleaseGraphics(gb);
  2926.  
  2927.     button_up.img_down = gdi.CreateImage(button_up.w, button_up.h);
  2928.     gb = button_up.img_down.GetGraphics();
  2929.     // Draw Themed Scrollbar (lg/col)
  2930.     try {
  2931.         scrollbar.theme.SetPartAndStateId(1, 11);
  2932.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h);
  2933.     } catch(e) {
  2934.         gb.SetSmoothingMode(2);
  2935.         var mid_y = Math.round(button_up.h/2);
  2936.         gb.DrawLine(10, mid_y-4, 6, mid_y+0, 2.0, g_textcolor);
  2937.         gb.DrawLine(7, mid_y+0, 10, mid_y+3, 2.0, g_textcolor);
  2938.     };
  2939.     button_up.img_down.ReleaseGraphics(gb);
  2940.  
  2941.     button_down.img_normal = gdi.CreateImage(button_down.w, button_down.h);
  2942.     gb = button_down.img_normal.GetGraphics();
  2943.     // Draw Themed Scrollbar (lg/col)
  2944.     try {
  2945.         scrollbar.theme.SetPartAndStateId(1, 13);
  2946.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h);
  2947.     } catch(e) {
  2948.         gb.SetSmoothingMode(2);
  2949.         var mid_y = Math.round(button_up.h/2);
  2950.         gb.DrawLine(button_down.w-11, mid_y-4, button_down.w-7, mid_y+0, 2.0, g_textcolor&0x44ffffff);
  2951.         gb.DrawLine(button_down.w-8, mid_y+0, button_down.w-11, mid_y+3, 2.0, g_textcolor&0x44ffffff);
  2952.     };
  2953.     button_down.img_normal.ReleaseGraphics(gb);
  2954.  
  2955.     button_down.img_hover = gdi.CreateImage(button_down.w, button_down.h);
  2956.     gb = button_down.img_hover.GetGraphics();
  2957.     // Draw Themed Scrollbar (lg/col)
  2958.     try {
  2959.         scrollbar.theme.SetPartAndStateId(1, 14);
  2960.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h);
  2961.     } catch(e) {
  2962.         gb.SetSmoothingMode(2);
  2963.         var mid_y = Math.round(button_up.h/2);
  2964.         gb.DrawLine(button_down.w-11, mid_y-4, button_down.w-7, mid_y+0, 2.0, g_textcolor&0x88ffffff);
  2965.         gb.DrawLine(button_down.w-8, mid_y+0, button_down.w-11, mid_y+3, 2.0, g_textcolor&0x88ffffff);
  2966.     };
  2967.     button_down.img_hover.ReleaseGraphics(gb);
  2968.  
  2969.     button_down.img_down = gdi.CreateImage(button_down.w, button_down.h);
  2970.     gb = button_down.img_down.GetGraphics();
  2971.     // Draw Themed Scrollbar (lg/col)
  2972.     try {
  2973.         scrollbar.theme.SetPartAndStateId(1, 15);
  2974.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h);
  2975.     } catch(e) {
  2976.         gb.SetSmoothingMode(2);
  2977.         var mid_y = Math.round(button_up.h/2);
  2978.         gb.DrawLine(button_down.w-11, mid_y-4, button_down.w-7, mid_y+0, 2.0, g_textcolor);
  2979.         gb.DrawLine(button_down.w-8, mid_y+0, button_down.w-11, mid_y+3, 2.0, g_textcolor);
  2980.     };
  2981.     button_down.img_down.ReleaseGraphics(gb);
  2982.  
  2983.     scrollbar.arr_buttons.splice(0, scrollbar.arr_buttons.length);
  2984.     for(i=0;i<scrollbar.button_total;i++) {
  2985.         switch(i) {
  2986.          case 0:
  2987.             scrollbar.arr_buttons.push(new button(button_up.img_normal, button_up.img_hover, button_up.img_down));
  2988.             break;
  2989.          case 1:
  2990.             scrollbar.arr_buttons.push(new button(button_down.img_normal, button_down.img_hover, button_down.img_down));
  2991.             break;            
  2992.         };
  2993.     };
  2994. };
  2995.  
  2996. function init_vscrollbar_buttons() {
  2997.     var i, gb;
  2998.  
  2999.     cursor.popup = gdi.CreateImage(27, 22);
  3000.     gb = cursor.popup.GetGraphics();
  3001.     gb.SetSmoothingMode(2);
  3002.     gb.FillRoundRect(0,0,22-1,22-1,3,3,g_textcolor);
  3003.     gb.DrawRoundRect(0,0,22-1,22-1,3,3,1.0,RGBA(0,0,0,150));
  3004.     var points = Array(22-2,7, 22-2+6,11, 22-2,22-7);
  3005.     gb.FillPolygon(g_textcolor, 0, points);
  3006.     gb.DrawPolygon(RGBA(0,0,0,150), 1.0, points);
  3007.     gb.SetSmoothingMode(0);
  3008.     gb.FillSolidRect(22-4,6,3,22-10,g_textcolor);
  3009.     cursor.popup.ReleaseGraphics(gb);
  3010.    
  3011.     button_up.img_normal = gdi.CreateImage(button_up.w, button_up.h);
  3012.     gb = button_up.img_normal.GetGraphics();
  3013.     // Draw Themed Scrollbar (lg/col)
  3014.     try {
  3015.         scrollbar.theme.SetPartAndStateId(1, 1);
  3016.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h);
  3017.     } catch(e) {
  3018.         gb.SetSmoothingMode(2);
  3019.         var mid_x = Math.round(button_up.w/2);
  3020.         gb.DrawLine(mid_x-4, 10, mid_x+0, 5, 2.0, g_textcolor&0x44ffffff);
  3021.         gb.DrawLine(mid_x+0, 6, mid_x+3, 10, 2.0, g_textcolor&0x44ffffff);
  3022.     };
  3023.     button_up.img_normal.ReleaseGraphics(gb);
  3024.  
  3025.     button_up.img_hover = gdi.CreateImage(button_up.w, button_up.h);
  3026.     gb = button_up.img_hover.GetGraphics();
  3027.     // Draw Themed Scrollbar (lg/col)
  3028.     try {
  3029.         scrollbar.theme.SetPartAndStateId(1, 2);
  3030.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h);
  3031.     } catch(e) {
  3032.         gb.SetSmoothingMode(2);
  3033.         var mid_x = Math.round(button_up.w/2);
  3034.         gb.DrawLine(mid_x-4, 10, mid_x+0, 5, 2.0, g_textcolor&0x88ffffff);
  3035.         gb.DrawLine(mid_x+0, 6, mid_x+3, 10, 2.0, g_textcolor&0x88ffffff);
  3036.     };
  3037.     button_up.img_hover.ReleaseGraphics(gb);
  3038.  
  3039.     button_up.img_down = gdi.CreateImage(button_up.w, button_up.h);
  3040.     gb = button_up.img_down.GetGraphics();
  3041.     // Draw Themed Scrollbar (lg/col)
  3042.     try {
  3043.         scrollbar.theme.SetPartAndStateId(1, 3);
  3044.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_up.w, button_up.h);
  3045.     } catch(e) {
  3046.         gb.SetSmoothingMode(2);
  3047.         var mid_x = Math.round(button_up.w/2);
  3048.         gb.DrawLine(mid_x-4, 10, mid_x+0, 5, 2.0, g_textcolor);
  3049.         gb.DrawLine(mid_x+0, 6, mid_x+3, 10, 2.0, g_textcolor);
  3050.     };
  3051.     button_up.img_down.ReleaseGraphics(gb);
  3052.  
  3053.     button_down.img_normal = gdi.CreateImage(button_down.w, button_down.h);
  3054.     gb = button_down.img_normal.GetGraphics();
  3055.     // Draw Themed Scrollbar (lg/col)
  3056.     try {
  3057.         scrollbar.theme.SetPartAndStateId(1, 5);
  3058.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h);
  3059.     } catch(e) {
  3060.         gb.SetSmoothingMode(2);
  3061.         var mid_x = Math.round(button_up.w/2);
  3062.         gb.DrawLine(mid_x-4, button_down.h-11, mid_x+0, button_down.h-6, 2.0, g_textcolor&0x44ffffff);
  3063.         gb.DrawLine(mid_x+0, button_down.h-7, mid_x+3, button_down.h-11, 2.0, g_textcolor&0x44ffffff);
  3064.     };
  3065.     button_down.img_normal.ReleaseGraphics(gb);
  3066.  
  3067.     button_down.img_hover = gdi.CreateImage(button_down.w, button_down.h);
  3068.     gb = button_down.img_hover.GetGraphics();
  3069.     // Draw Themed Scrollbar (lg/col)
  3070.     try {
  3071.         scrollbar.theme.SetPartAndStateId(1, 6);
  3072.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h);
  3073.     } catch(e) {
  3074.         gb.SetSmoothingMode(2);
  3075.         var mid_x = Math.round(button_up.w/2);
  3076.         gb.DrawLine(mid_x-4, button_down.h-11, mid_x+0, button_down.h-6, 2.0, g_textcolor&0x88ffffff);
  3077.         gb.DrawLine(mid_x+0, button_down.h-7, mid_x+3, button_down.h-11, 2.0, g_textcolor&0x88ffffff);
  3078.     };
  3079.     button_down.img_hover.ReleaseGraphics(gb);
  3080.  
  3081.     button_down.img_down = gdi.CreateImage(button_down.w, button_down.h);
  3082.     gb = button_down.img_down.GetGraphics();
  3083.     // Draw Themed Scrollbar (lg/col)
  3084.     try {
  3085.         scrollbar.theme.SetPartAndStateId(1, 7);
  3086.         scrollbar.theme.DrawThemeBackground(gb, 0, 0, button_down.w, button_down.h);
  3087.     } catch(e) {
  3088.         gb.SetSmoothingMode(2);
  3089.         var mid_x = Math.round(button_up.w/2);
  3090.         gb.DrawLine(mid_x-4, button_down.h-11, mid_x+0, button_down.h-6, 2.0, g_textcolor);
  3091.         gb.DrawLine(mid_x+0, button_down.h-7, mid_x+3, button_down.h-11, 2.0, g_textcolor);
  3092.     };
  3093.     button_down.img_down.ReleaseGraphics(gb);
  3094.  
  3095.     scrollbar.arr_buttons.splice(0, scrollbar.arr_buttons.length);
  3096.     for(i=0;i<scrollbar.button_total;i++) {
  3097.         switch(i) {
  3098.          case 0:
  3099.             scrollbar.arr_buttons.push(new button(button_up.img_normal, button_up.img_hover, button_up.img_down));
  3100.             break;
  3101.          case 1:
  3102.             scrollbar.arr_buttons.push(new button(button_down.img_normal, button_down.img_hover, button_down.img_down));
  3103.             break;            
  3104.         };
  3105.     };
  3106. };
  3107.  
  3108. //=================================================// Init Icons and Images (no_cover ...)
  3109. function init_icons() {
  3110.     var gb;
  3111.     var gui_font;
  3112.    
  3113.     glass_reflect_img = draw_glass_reflect(200, 200);
  3114.  
  3115.     nocover = gdi.CreateImage(200, 200);
  3116.     gb = nocover.GetGraphics();
  3117.     gb.SetSmoothingMode(2);
  3118.     gb.FillSolidRect(0,0,200,200,g_textcolor);
  3119.     gb.FillGradRect(0,0,200,200,90,g_backcolor&0xbbffffff,g_backcolor,1.0);
  3120.     gb.SetTextRenderingHint(3);
  3121.     gui_font = gdi.Font("Segoe UI", 108, 1);
  3122.     gb.DrawString("NO", gui_font, g_textcolor&0x25ffffff, 0, 0, 200, 110, cc_stringformat);
  3123.     gui_font = gdi.Font("Segoe UI", 48, 1);
  3124.     gb.DrawString("COVER", gui_font, g_textcolor&0x20ffffff, 1, 70, 200, 110, cc_stringformat);
  3125.     gb.FillSolidRect(24, 155, 152, 20, g_textcolor&0x15ffffff);
  3126.     nocover.ReleaseGraphics(gb);
  3127.  
  3128.     streamcover = gdi.CreateImage(200, 200);
  3129.     gb = streamcover.GetGraphics();
  3130.     gb.SetSmoothingMode(2);
  3131.     gb.FillSolidRect(0,0,200,200,g_textcolor);
  3132.     gb.FillGradRect(0,0,200,200,90,g_backcolor&0xbbffffff,g_backcolor,1.0);
  3133.     gb.SetTextRenderingHint(3);
  3134.     gui_font = gdi.Font("Segoe UI", 42, 0);
  3135.     gb.DrawString("stream", gui_font, g_backcolor, 1, 2, 200, 190, cc_stringformat);
  3136.     gb.DrawString("stream", gui_font, g_textcolor&0x99ffffff, 1, 0, 200, 190, cc_stringformat);
  3137.     streamcover.ReleaseGraphics(gb);
  3138.  
  3139.     loading = gdi.CreateImage(200, 200);
  3140.     gb = loading.GetGraphics();
  3141.     gb.SetSmoothingMode(2);
  3142.     gb.FillSolidRect(0,0,200,200,g_textcolor);
  3143.     gb.FillGradRect(0,0,200,200,90,g_backcolor&0xbbffffff,g_backcolor,1.0);
  3144.     gb.SetTextRenderingHint(3);
  3145.     gui_font = gdi.Font("Segoe UI", 40, 0);
  3146.     gb.DrawString("loading...", gui_font, g_backcolor, 1, 2, 200, 190, cc_stringformat);
  3147.     gb.DrawString("loading...", gui_font, g_textcolor&0x99ffffff, 1, 0, 200, 190, cc_stringformat);
  3148.     loading.ReleaseGraphics(gb);
  3149.    
  3150.     // Show Now Playing button
  3151.     nowplaying_button_normal = gdi.CreateImage(20, 20);
  3152.     gb = nowplaying_button_normal.GetGraphics();
  3153.     gb.SetSmoothingMode(2);
  3154.     gb.FillEllipse(6, 8, 8, 6, RGB(140,140,140));
  3155.     gb.DrawLine(10, 1, 13, 9, 1.0, RGB(140,140,140));
  3156.     gb.DrawLine(11, 2, 14, 3, 2.0, RGB(140,140,140));
  3157.     gb.DrawLine(14, 3, 15, 5, 1.0, RGB(140,140,140));
  3158.     gb.SetSmoothingMode(0);
  3159.     nowplaying_button_normal.ReleaseGraphics(gb);
  3160.    
  3161.     nowplaying_button_hover = gdi.CreateImage(20, 20);
  3162.     gb = nowplaying_button_hover.GetGraphics();
  3163.     gb.SetSmoothingMode(2);
  3164.     gb.FillEllipse(6, 8, 8, 6, RGB(180,180,180));
  3165.     gb.DrawLine(10, 1, 13, 9, 1.0, RGB(180,180,180));
  3166.     gb.DrawLine(11, 2, 14, 3, 2.0, RGB(180,180,180));
  3167.     gb.DrawLine(14, 3, 15, 5, 1.0, RGB(180,180,180));
  3168.     gb.SetSmoothingMode(0);
  3169.     nowplaying_button_hover.ReleaseGraphics(gb);
  3170.    
  3171.     nowplaying_button_down = gdi.CreateImage(20, 20);
  3172.     gb = nowplaying_button_down.GetGraphics();
  3173.     gb.SetSmoothingMode(2);
  3174.     gb.FillEllipse(6, 8, 8, 6, RGB(220,220,220));
  3175.     gb.DrawLine(10, 1, 13, 9, 1.0, RGB(220,220,220));
  3176.     gb.DrawLine(11, 2, 14, 3, 2.0, RGB(220,220,220));
  3177.     gb.DrawLine(14, 3, 15, 5, 1.0, RGB(220,220,220));
  3178.     gb.SetSmoothingMode(0);
  3179.     nowplaying_button_down.ReleaseGraphics(gb);
  3180.        
  3181.     // Settings Menu button
  3182.     bt_settings_off = gdi.CreateImage(30, 20);
  3183.     gb = bt_settings_off.GetGraphics();
  3184.     gui_font = gdi.Font("Tahoma", 28, 1);
  3185.     gb.SetTextRenderingHint(3);
  3186.     gb.DrawString("*", gui_font, RGB(150,150,150), 0, 2, 20, 20, lc_stringformat);
  3187.     gb.SetSmoothingMode(2);
  3188.     gb.FillEllipse(2,3,12,10,RGB(140,140,140));
  3189.     gb.DrawEllipse(5,5,6,6,2.0,RGBA(0,0,0,200));
  3190.     gb.DrawEllipse(2,3,12,10,1.0,RGBA(0,0,0,80));
  3191.     gb.SetSmoothingMode(0);
  3192.     gb.DrawLine(16+8-4, 8-2+2, 16+8+4, 8-2+2, 1.0, RGB(140,140,140));
  3193.     gb.DrawLine(16+8-3, 8-1+2, 16+8+3, 8-1+2, 1.0, RGB(140,140,140));
  3194.     gb.DrawLine(16+8-2, 8-0+2, 16+8+2, 8-0+2, 1.0, RGB(140,140,140));
  3195.     gb.DrawLine(16+8-1, 8+1+2, 16+8+1, 8+1+2, 1.0, RGB(140,140,140));
  3196.     gb.FillSolidRect(16+8-0, 8+2+2, 1, 1, RGB(140,140,140));
  3197.     bt_settings_off.ReleaseGraphics(gb);
  3198.  
  3199.     bt_settings_ov = gdi.CreateImage(30, 20);
  3200.     gb = bt_settings_ov.GetGraphics();
  3201.     gui_font = gdi.Font("Tahoma", 28, 1);
  3202.     gb.SetTextRenderingHint(3);
  3203.     gb.DrawString("*", gui_font, RGB(190,190,190), 0, 2, 20, 20, lc_stringformat);
  3204.     gb.SetSmoothingMode(2);
  3205.     gb.FillEllipse(2,3,12,10,RGB(180,180,180));
  3206.     gb.DrawEllipse(5,5,6,6,2.0,RGBA(0,0,0,220));
  3207.     gb.DrawEllipse(2,3,12,10,1.0,RGBA(0,0,0,140));
  3208.     gb.SetSmoothingMode(0);
  3209.     gb.DrawLine(16+8-4, 8-2+2, 16+8+4, 8-2+2, 1.0, RGB(180,180,180));
  3210.     gb.DrawLine(16+8-3, 8-1+2, 16+8+3, 8-1+2, 1.0, RGB(180,180,180));
  3211.     gb.DrawLine(16+8-2, 8-0+2, 16+8+2, 8-0+2, 1.0, RGB(180,180,180));
  3212.     gb.DrawLine(16+8-1, 8+1+2, 16+8+1, 8+1+2, 1.0, RGB(180,180,180));
  3213.     gb.FillSolidRect(16+8-0, 8+2+2, 1, 1, RGB(180,180,180));
  3214.     bt_settings_ov.ReleaseGraphics(gb);
  3215.    
  3216.     bt_settings_on = gdi.CreateImage(30, 20);
  3217.     gb = bt_settings_on.GetGraphics();
  3218.     gui_font = gdi.Font("Tahoma", 28, 1);
  3219.     gb.SetTextRenderingHint(3);
  3220.     gb.DrawString("*", gui_font, RGB(230,230,230), 0, 2, 20, 20, lc_stringformat);
  3221.     gb.SetSmoothingMode(2);
  3222.     gb.FillEllipse(2,3,12,10,RGB(180,180,180));
  3223.     gb.DrawEllipse(5,5,6,6,2.0,RGBA(0,0,0,240));
  3224.     gb.DrawEllipse(2,3,12,10,1.0,RGBA(0,0,0,160));
  3225.     gb.SetSmoothingMode(0);
  3226.     gb.DrawLine(16+8-4, 8-2+2, 16+8+4, 8-2+2, 1.0, RGB(220,220,220));
  3227.     gb.DrawLine(16+8-3, 8-1+2, 16+8+3, 8-1+2, 1.0, RGB(220,220,220));
  3228.     gb.DrawLine(16+8-2, 8-0+2, 16+8+2, 8-0+2, 1.0, RGB(220,220,220));
  3229.     gb.DrawLine(16+8-1, 8+1+2, 16+8+1, 8+1+2, 1.0, RGB(220,220,220));
  3230.     gb.FillSolidRect(16+8-0, 8+2+2, 1, 1, RGB(220,220,220));
  3231.     bt_settings_on.ReleaseGraphics(gb);
  3232.    
  3233.     // Lock Playlist button
  3234.     lock_button_normal = gdi.CreateImage(20, 20);
  3235.     gb = lock_button_normal.GetGraphics();
  3236.     gb.SetSmoothingMode(2);
  3237.     gb.DrawEllipse(7, 2, 6, 6, 1.0, RGB(140,140,140));
  3238.     gb.SetSmoothingMode(0);
  3239.     gb.FillSolidRect(6, 7, 9, 6, RGB(140,140,140));
  3240.     gb.FillSolidRect(10, 9, 1, 2, RGB(20,20,20));
  3241.     lock_button_normal.ReleaseGraphics(gb);
  3242.    
  3243.     lock_button_hover = gdi.CreateImage(20, 20);
  3244.     gb = lock_button_hover.GetGraphics();
  3245.     gb.SetSmoothingMode(2);
  3246.     gb.DrawEllipse(7, 2, 6, 6, 1.0, RGB(180,180,180));
  3247.     gb.SetSmoothingMode(0);
  3248.     gb.FillSolidRect(6, 7, 9, 6, RGB(180,180,180));
  3249.     gb.FillSolidRect(10, 9, 1, 2, RGB(20,20,20));
  3250.     lock_button_hover.ReleaseGraphics(gb);
  3251.    
  3252.     lock_button_down = gdi.CreateImage(20, 20);
  3253.     gb = lock_button_down.GetGraphics();
  3254.     gb.SetSmoothingMode(2);
  3255.     gb.DrawEllipse(7, 2, 6, 6, 1.0, RGB(220,220,220));
  3256.     gb.SetSmoothingMode(0);
  3257.     gb.FillSolidRect(6, 7, 9, 6, RGB(220,220,220));
  3258.     gb.FillSolidRect(10, 9, 1, 2, RGB(20,20,20));
  3259.     lock_button_down.ReleaseGraphics(gb);
  3260.  
  3261.     toolbar.buttons.splice(0, toolbar.buttons.length);
  3262.     for(var i=0;i<toolbar.button_total;i++) {
  3263.         switch(i) {
  3264.          case 0:
  3265.             toolbar.buttons.push(new button(nowplaying_button_normal, nowplaying_button_hover, nowplaying_button_down));
  3266.             break;
  3267.          case 1:
  3268.             toolbar.buttons.push(new button(bt_settings_off, bt_settings_ov, bt_settings_on));
  3269.             break;
  3270.          case 2:
  3271.             toolbar.buttons.push(new button(lock_button_normal, lock_button_hover, lock_button_down));
  3272.             break;
  3273.         };
  3274.     };
  3275. };
  3276.  
  3277. function recalc_datas() {
  3278.    
  3279.     if(toolbar.lock) {
  3280.         toolbar.delta = toolbar.collapsed_y*-1;
  3281.         toolbar.state = true;
  3282.     };
  3283.    
  3284.     if(panel.vertical_mode) {
  3285.                
  3286.         if(panel.flat_mode) {
  3287.             cover.margin = panel.show_text ? 28 : 12;
  3288.             if(scrollbar.show) {
  3289.                 cover.pad_right_mid = cover.default_pad_right_mid - 26 + vscrollbar.default_w;
  3290.             } else {
  3291.                 cover.pad_right_mid = cover.default_pad_right_mid - 26;
  3292.             }
  3293.         } else {
  3294.             cover.margin = cover.margin_default;
  3295.             if(scrollbar.show) {
  3296.                 cover.pad_right_mid = cover.default_pad_right_mid + vscrollbar.default_w;
  3297.             } else {
  3298.                 cover.pad_right_mid = cover.default_pad_right_mid;
  3299.             }
  3300.         };
  3301.         cover.h = ww - cover.pad_left_mid - cover.pad_right_mid;
  3302.         if(cover.h>cover.max_size) cover.h = cover.max_size;
  3303.         cover.w = cover.h;
  3304.        
  3305.         if(panel.flat_mode) {
  3306.             list.nbvis = Math.floor(wh/(cover.h+cover.margin*0)) + 2 + 20;
  3307.             if(list.nbvis/2==Math.floor(list.nbvis/2)) {
  3308.                 list.nbvis--;
  3309.             }
  3310.             list.mid = Math.floor(list.nbvis/2);
  3311.             list.nb_cover_to_draw = Math.floor(wh/(cover.h+cover.margin*0)) + 2;
  3312.         } else {
  3313.             list.nbvis = Math.floor(wh/(cover.h-cover.normal_delta*2)) + 2 + 20;
  3314.             if(list.nbvis/2==Math.floor(list.nbvis/2)) {
  3315.                 list.nbvis--;
  3316.             }
  3317.             list.mid = Math.floor(list.nbvis/2);
  3318.             list.nb_cover_to_draw = Math.floor(wh/(cover.h-cover.normal_delta*2)) + 2;
  3319.         };
  3320.        
  3321.         if(scrollbar.themed) {
  3322.             scrollbar.theme = window.CreateThemeManager("scrollbar");
  3323.         } else {
  3324.             scrollbar.theme = false;
  3325.         };
  3326.         init_vscrollbar_buttons();
  3327.      
  3328.         button_up.x = ww - button_up.w;
  3329.         button_up.y = 0;
  3330.         button_down.x = ww - button_down.w;
  3331.         button_down.y = wh - button_down.h;
  3332.         vscrollbar.y = button_up.h;
  3333.         vscrollbar.h = wh - button_up.h - button_down.h;
  3334.         cursor.x = ww-vscrollbar.w;
  3335.         cursor.y = vscrollbar.y;
  3336.         cursor.w = vscrollbar.w;
  3337.  
  3338.     } else {
  3339.        
  3340.         if(panel.flat_mode) {
  3341.             cover.margin = 10;
  3342.         } else {
  3343.             cover.margin = cover.margin_default;
  3344.         };
  3345.        
  3346.         // mid cover (max size)
  3347.         if(scrollbar.show) {
  3348.             cover.pad_bot_mid = cover.default_pad_bot_mid - (panel.flat_mode?0:5);
  3349.         } else {
  3350.             cover.pad_bot_mid = cover.default_pad_bot_mid - hscrollbar.default_h - (panel.flat_mode?0:5);
  3351.         }
  3352.         if(panel.show_text) {
  3353.             cover.pad_top_mid = cover.default_pad_top_mid - (panel.flat_mode?16:0);
  3354.         } else {
  3355.             cover.pad_top_mid = cover.default_pad_top_mid - 16;
  3356.             cover.pad_bot_mid -= (panel.flat_mode?10:0);
  3357.         };
  3358.         cover.w = wh - cover.pad_top_mid - cover.pad_bot_mid;
  3359.         if(cover.w>cover.max_size) cover.w = cover.max_size;
  3360.         cover.h = cover.w;
  3361.        
  3362.         if(panel.flat_mode) {
  3363.             list.nbvis = Math.floor(ww/(cover.w+cover.margin*0)) + 2 + 20;
  3364.             if(list.nbvis/2==Math.floor(list.nbvis/2)) {
  3365.                 list.nbvis--;
  3366.             }
  3367.             list.mid = Math.floor(list.nbvis/2);
  3368.             list.nb_cover_to_draw = Math.floor(ww/(cover.w+cover.margin*0)) + 2;
  3369.         } else {
  3370.             list.nbvis = Math.floor(ww/(cover.w-cover.normal_delta*2)) + 2 + 20;
  3371.             if(list.nbvis/2==Math.floor(list.nbvis/2)) {
  3372.                 list.nbvis--;
  3373.             }
  3374.             list.mid = Math.floor(list.nbvis/2);
  3375.             list.nb_cover_to_draw = Math.floor(ww/(cover.w-cover.normal_delta*2)) + 2;
  3376.         };
  3377.        
  3378.         if(scrollbar.themed) {
  3379.             scrollbar.theme = window.CreateThemeManager("scrollbar");
  3380.         } else {
  3381.             scrollbar.theme = false;
  3382.         };
  3383.         init_hscrollbar_buttons();
  3384.      
  3385.         button_up.x = 0;
  3386.         button_up.y = wh - hscrollbar.h;
  3387.         button_down.x = ww - button_down.w;
  3388.         button_down.y = wh - hscrollbar.h;
  3389.         hscrollbar.x = button_up.w;
  3390.         hscrollbar.w = ww - button_up.w - button_down.w;
  3391.         cursor.y = wh - hscrollbar.h;
  3392.         cursor.x = hscrollbar.x;
  3393.         cursor.h = hscrollbar.h;
  3394.     };
  3395. };
  3396.  
  3397. function redraw_stub_images() {
  3398.     if(gdi.Image(images.nocover)) {
  3399.         nocover_img = FormatCover(gdi.Image(images.nocover), cover.w, cover.h);
  3400.     } else {
  3401.         nocover_img = FormatCover(nocover, cover.w, cover.h);
  3402.     };
  3403.     if(gdi.Image(images.stream)) {
  3404.         streamcover_img = FormatCover(gdi.Image(images.stream), cover.w, cover.h);      
  3405.     } else {
  3406.         streamcover_img = FormatCover(streamcover, cover.w, cover.h);
  3407.     };
  3408.     if(gdi.Image(images.loading)) {
  3409.         loading_img = FormatCover(gdi.Image(images.loading), cover.w, cover.h);
  3410.     } else {
  3411.         loading_img = FormatCover(loading, cover.w, cover.h);
  3412.     };
  3413. };
  3414.  
  3415. function SelectGroupItems(start_id, start_gh_id, setfocus) {
  3416.     var count = 0;
  3417.     var affectedItems = Array();
  3418.    
  3419.     if(!utils.IsKeyPressed(VK_CONTROL)) plman.ClearPlaylistSelection(panel.active_playlist);
  3420.    
  3421.     if(start_gh_id<list.total_gh-1) {
  3422.         var last_id = list.hlist[start_gh_id+1];
  3423.     } else {
  3424.         var last_id = list.total;
  3425.     };
  3426.     for(var i = start_id; i < last_id; i++) {
  3427.         affectedItems.push(i);
  3428.         if(++count>9999) break;
  3429.     };
  3430.     plman.SetPlaylistSelection(panel.active_playlist, affectedItems, true);
  3431.     if(setfocus) {
  3432.         plman.SetPlaylistFocusItem(panel.active_playlist, start_id);
  3433.     };
  3434.     CollectGarbage();
  3435. };
  3436.  
  3437. function ShowSelected() {
  3438.     if(panel.lock_playlist) return true;
  3439.  
  3440.     if(plman.PlaylistItemCount(plman.ActivePlaylist)==0 || !fb.GetFocusItem(false)) return true;
  3441.     plman.ClearPlaylistSelection(plman.ActivePlaylist);
  3442.     var pid = plman.GetPlaylistFocusItemIndex(plman.ActivePlaylist);
  3443.     plman.SetPlaylistFocusItem(plman.ActivePlaylist, pid);
  3444.     plman.SetPlaylistSelectionSingle(plman.ActivePlaylist, pid, true);
  3445.     if(pid>=0 && pid<list.total) {
  3446.         refresh_spv(plman.ActivePlaylist, true);
  3447.     };
  3448. };
  3449.  
  3450. function ShowNowPlaying() {
  3451.     if(panel.lock_playlist) return true;
  3452.     if(fb.IsPlaying) {
  3453.         if(plman.PlaylistItemCount(plman.PlayingPlaylist)==0) {
  3454.             return true;
  3455.         };
  3456.         plman.ClearPlaylistSelection(plman.PlayingPlaylist);
  3457.         list.nowplaying = plman.GetPlayingItemLocation();
  3458.         var pid = list.nowplaying.PlaylistItemIndex;
  3459.         if(pid>=0 && pid<plman.PlaylistItemCount(plman.PlayingPlaylist)) {
  3460.             plman.SetPlaylistFocusItem(plman.PlayingPlaylist, pid);
  3461.             plman.SetPlaylistSelectionSingle(plman.PlayingPlaylist, pid, true);
  3462.             plman.ActivePlaylist = plman.PlayingPlaylist;
  3463.             refresh_spv(plman.PlayingPlaylist, true);
  3464.         };
  3465.     } else {
  3466.         if(plman.PlaylistItemCount(plman.ActivePlaylist)==0 || !fb.GetFocusItem(false)) return true;
  3467.         plman.ClearPlaylistSelection(plman.ActivePlaylist);
  3468.         var pid = plman.GetPlaylistFocusItemIndex(plman.ActivePlaylist);
  3469.         plman.SetPlaylistFocusItem(plman.ActivePlaylist, pid);
  3470.         plman.SetPlaylistSelectionSingle(plman.ActivePlaylist, pid, true);
  3471.         if(pid>=0 && pid<list.total) {
  3472.             refresh_spv(plman.ActivePlaylist, true);
  3473.         };
  3474.     };
  3475. };
  3476.  
  3477. function ShowSearchedItem(pls, pid) {
  3478.     if(list.total==0 || !fb.GetFocusItem(false)) return true;
  3479.     if(pid<0) {
  3480.         pid = plman.GetPlaylistFocusItemIndex(pls);
  3481.     };
  3482.  
  3483.     plman.SetPlaylistFocusItem(pls, pid);
  3484.     plman.ClearPlaylistSelection(pls);
  3485.     plman.SetPlaylistSelectionSingle(pls, pid, true);
  3486.     refresh_spv(pls, true);
  3487.  
  3488.     if(panel.lock_playlist) {
  3489.         incsearch_timer_lock = window.SetTimeout(function() {
  3490.             var mid_idx = Math.floor(list.nbvis/2);
  3491.             list.item[mid_idx].checkstate("mid", list.item[mid_idx].x+5, list.item[mid_idx].y+5, mid_idx);
  3492.             incsearch_timer_lock && window.ClearTimeout(incsearch_timer_lock);
  3493.             incsearch_timer_lock = false;
  3494.         }, 100);
  3495.     };
  3496. };
  3497.  
  3498. function IncrementalSearch() {
  3499.     var count=0;
  3500.     var groupkey;
  3501.     var chr;
  3502.     var gstart;
  3503.     var pid = -1;
  3504.     var grp_first_item_id;
  3505.    
  3506.     // exit if no search string in cache
  3507.     if(g_search_string.length<=0) return true;
  3508.    
  3509.     // 1st char of the search string
  3510.     var first_chr = g_search_string.substring(0,1);  
  3511.     var len = g_search_string.length;
  3512.    
  3513.     // which start point for the search
  3514.     if(list.total_gh>500) {
  3515.         grp_first_item_id = list.hlist[Math.floor(list.total_gh/2)];
  3516.         groupkey = tf_group_key.EvalWithMetadb(list.handlelist.Item(grp_first_item_id));
  3517.         chr = groupkey.substring(0,1);
  3518.         if(first_chr.charCodeAt(first_chr) > chr.charCodeAt(chr)) {
  3519.             gstart = Math.floor(list.total_gh/2);
  3520.         } else {
  3521.             gstart = 0;
  3522.         };
  3523.     } else {
  3524.         gstart = 0;
  3525.     };
  3526.        
  3527.     var format_str = "";
  3528.     for(var i=gstart;i<list.total_gh;i++) {
  3529.         grp_first_item_id = list.hlist[i];
  3530.         groupkey = tf_group_key.EvalWithMetadb(list.handlelist.Item(grp_first_item_id));
  3531.         format_str = groupkey.substring(0,len).toUpperCase();
  3532.         if(format_str==g_search_string) {
  3533.             pid = list.hlist[i];
  3534.             break;
  3535.         };
  3536.     };
  3537.    
  3538.     if(pid>=0) { // found!
  3539.         plman.ClearPlaylistSelection(panel.active_playlist);
  3540.         ShowSearchedItem(panel.active_playlist, pid);
  3541.     } else {
  3542.         list.inc_search_noresult = true;
  3543.         window.Repaint();
  3544.     };
  3545.    
  3546.     clear_incsearch_timer && window.ClearTimeout(clear_incsearch_timer);
  3547.     clear_incsearch_timer = window.SetTimeout(function () {
  3548.         // reset incremental search string after 2 seconds without any key pressed
  3549.         var tt_x = Math.floor((ww / 2) - ((g_search_string.length*13)+(10*2)) / 2);
  3550.         var tt_y = Math.floor(wh/2) - 30;
  3551.         var tt_w = ((g_search_string.length*13)+(10*2));
  3552.         var tt_h = 60;
  3553.         g_search_string = "";
  3554.         window.RepaintRect(0, tt_y-2, ww, tt_h+4);
  3555.         clear_incsearch_timer && window.ClearTimeout(clear_incsearch_timer);
  3556.         clear_incsearch_timer = false;
  3557.         list.inc_search_noresult = false;
  3558.     }, 1000);
  3559. };
  3560.  
  3561. //=================================================// Item Context Menu
  3562. function new_context_menu(x, y, id, array_id) {
  3563.          
  3564.     var _menu = window.CreatePopupMenu();
  3565.     var Context = fb.CreateContextMenuManager();
  3566.    
  3567.     var _child01 = window.CreatePopupMenu();
  3568.     var _child02 = window.CreatePopupMenu();
  3569.    
  3570.     list.metadblist_selection = plman.GetPlaylistSelectedItems(panel.active_playlist);
  3571.     Context.InitContext(list.metadblist_selection);
  3572.     Context.BuildMenu(_menu, 1, -1);
  3573.  
  3574.     _menu.AppendMenuItem(MF_SEPARATOR, 0, "");
  3575.     _menu.AppendMenuItem(MF_STRING | MF_POPUP, _child01.ID, "Selection...");
  3576.  
  3577.     _child01.AppendMenuItem((fb.IsAutoPlaylist(panel.active_playlist))?MF_DISABLED|MF_GRAYED:MF_STRING, 1000, "Remove");
  3578.     _child01.AppendMenuItem(MF_STRING | MF_POPUP, _child02.ID, "Add to...");
  3579.  
  3580.     _child02.AppendMenuItem(MF_STRING, 2000, "a New playlist...");
  3581.     _child02.AppendMenuItem(MF_SEPARATOR, 0, "");
  3582.     var pl_count = fb.PlaylistCount;
  3583.     for(var i=0;i<pl_count;i++) {
  3584.         if(i!=panel.active_playlist && !fb.IsAutoPlaylist(i)) {
  3585.             _child02.AppendMenuItem(MF_STRING, 2001+i, plman.GetPlaylistName(i));
  3586.         };
  3587.     };
  3588.  
  3589.     var ret = _menu.TrackPopupMenu(x, y);
  3590.     if(ret<800) {
  3591.         Context.ExecuteByID(ret - 1);
  3592.     } else if(ret<1000) {
  3593.         switch (ret) {
  3594.            case 880:
  3595.  
  3596.                 break;
  3597.             case 890:
  3598.  
  3599.                 break;
  3600.         };
  3601.     } else {
  3602.         switch (ret) {
  3603.             case 1000:
  3604.                 plman.RemovePlaylistSelection(panel.active_playlist, false);
  3605.                 break;
  3606.             case 2000:
  3607.                 fb.RunMainMenuCommand("File/New playlist");
  3608.                 plman.InsertPlaylistItems(plman.PlaylistCount-1, 0, list.metadblist_selection, false);
  3609.                 break;
  3610.             default:
  3611.                 var insert_index = plman.PlaylistItemCount(ret-2001);
  3612.                 plman.InsertPlaylistItems((ret-2001), insert_index, list.metadblist_selection, false);
  3613.         };
  3614.     };
  3615. };
  3616.  
  3617. function settings_menu(x, y) {
  3618.     var idx;
  3619.     var _menu = window.CreatePopupMenu();
  3620.     var _appearance = window.CreatePopupMenu();
  3621.    
  3622.     var current_pl_name = plman.GetPlaylistName(plman.ActivePlaylist);
  3623.     var lock_enabled = (current_pl_name!="CoverFlow View" && list.total_gh>0);
  3624.    
  3625.     _menu.AppendMenuItem(MF_STRING, 99, "Lock Toolbar");
  3626.     _menu.CheckMenuItem(99, toolbar.lock?1:0);
  3627.     _menu.AppendMenuItem((lock_enabled || panel.lock_playlist)?MF_STRING:MF_DISABLED|MF_GRAYED, 1, "Lock to Current Playlist");
  3628.     _menu.CheckMenuItem(1, panel.lock_playlist?1:0);
  3629.     _menu.AppendMenuItem(MF_SEPARATOR, 0, "");
  3630.     _menu.AppendMenuItem(MF_STRING, 5, "CoverFlow Mode");
  3631.     _menu.AppendMenuItem(MF_STRING, 6, "Flat Mode");
  3632.     _menu.CheckMenuRadioItem(5, 6, panel.flat_mode?6:5);
  3633.     _menu.AppendMenuItem(MF_SEPARATOR, 0, "");
  3634.    
  3635.     _appearance.AppendTo(_menu, MF_STRING, "Appearance");  
  3636.     _appearance.AppendMenuItem(MF_STRING, 2, "Show Scrollbar");
  3637.     _appearance.CheckMenuItem(2, scrollbar.show?1:0);
  3638.     _appearance.AppendMenuItem(MF_STRING, 3, "Themed Scrollbar Style");
  3639.     _appearance.CheckMenuItem(3, scrollbar.themed?1:0);
  3640.     _appearance.AppendMenuItem(MF_STRING, 4, "Use Scroll Effect");
  3641.     _appearance.CheckMenuItem(4, panel.scroll_effect?1:0);
  3642.     _appearance.AppendMenuItem(MF_STRING, 7, "Use Custom Colors");
  3643.     _appearance.CheckMenuItem(7, panel.custom_colors?1:0);
  3644.     if(!panel.vertical_mode) {
  3645.         _appearance.AppendMenuItem(MF_STRING, 8, "Show Album Info");
  3646.         _appearance.CheckMenuItem(8, panel.show_text?1:0);
  3647.         _appearance.AppendMenuItem(MF_STRING, 9, "Show Floor Reflection");
  3648.         _appearance.CheckMenuItem(9, cover.draw_reflection?1:0);
  3649.     };
  3650.     if(panel.flat_mode) {
  3651.         // tracks_counter_show: window.GetProperty("*USER.total.tracks.visible", true),
  3652.         _appearance.AppendMenuItem(MF_STRING, 10, "Show Tracks Counter");
  3653.         _appearance.CheckMenuItem(10, panel.tracks_counter_show?1:0);
  3654.     };
  3655.    
  3656.     _menu.AppendMenuItem(MF_SEPARATOR, 0, "");
  3657.     _menu.AppendMenuItem((list.total>0)?MF_STRING:MF_DISABLED|MF_GRAYED, 22, "Refresh CoverFlow");
  3658.     _menu.AppendMenuItem(MF_SEPARATOR, 0, "");
  3659.     _menu.AppendMenuItem(MF_STRING, 20, "Properties");
  3660.     _menu.AppendMenuItem(MF_STRING, 21, "Configure...");
  3661.     idx = _menu.TrackPopupMenu(x, y);
  3662.    
  3663.     switch(idx) {
  3664.         case 1:
  3665.             if(panel.lock_playlist) {
  3666.                 // unlock, set ActivePlaylist with locked playlist
  3667.                 panel.lock_playlist = false;
  3668.                 window.SetProperty("SYSTEM.panel.lock.playlist", panel.lock_playlist);
  3669.                 plman.ActivePlaylist = panel.active_playlist;
  3670.             } else {
  3671.                 //ShowSelected();
  3672.                 //window.Repaint();
  3673.                 // lock current playlist
  3674.                 panel.lock_playlist = true;
  3675.                 window.SetProperty("SYSTEM.panel.lock.playlist", panel.lock_playlist);
  3676.                 panel.active_playlist = plman.ActivePlaylist;
  3677.                 window.SetProperty("SYSTEM.panel.active.playlist", panel.active_playlist);
  3678.                 //
  3679.                 var mid_idx = Math.floor(list.nbvis/2);
  3680.                 mid_idx = list.focus_id_item_idx;
  3681.                 //mid_idx = list.marker_id;
  3682.                 list.item[mid_idx].checkstate("mid", list.item[mid_idx].x+5, list.item[mid_idx].y+5, mid_idx);
  3683.             };
  3684.             break;
  3685.         case 2:
  3686.             if(list.total_gh>=2) {
  3687.                 scrollbar.show = !scrollbar.show;
  3688.                 if(scrollbar.show) {
  3689.                     scrollbar.visible = true;
  3690.                 } else {
  3691.                     scrollbar.visible = false;
  3692.                 };
  3693.             } else {
  3694.                 scrollbar.visible = false;
  3695.             };
  3696.             window.SetProperty("SYSTEM.scrollbar.visible", scrollbar.show);
  3697.             //
  3698.             recalc_datas();
  3699.             redraw_stub_images();
  3700.             g_image_cache = new image_cache;
  3701.             CollectGarbage();
  3702.             on_playlist_switch();
  3703.             break;
  3704.         case 3:
  3705.             scrollbar.themed = !scrollbar.themed;
  3706.             window.SetProperty("SYSTEM.scrollbar.themed", scrollbar.themed);
  3707.             if(scrollbar.themed) {
  3708.                 scrollbar.theme = window.CreateThemeManager("scrollbar");
  3709.             } else {
  3710.                 scrollbar.theme = false;
  3711.             };
  3712.             if(panel.vertical_mode) {
  3713.                 init_vscrollbar_buttons();
  3714.             } else {
  3715.                 init_hscrollbar_buttons();
  3716.             };
  3717.             set_scroller();
  3718.             window.Repaint();
  3719.             break;
  3720.         case 4:
  3721.             panel.scroll_effect = !panel.scroll_effect;
  3722.             window.SetProperty("SYSTEM.panel.scroll.effect", panel.scroll_effect);
  3723.             window.Repaint();
  3724.             break;
  3725.         case 5:
  3726.         case 6:
  3727.             panel.flat_mode = !panel.flat_mode;
  3728.             window.SetProperty("SYSTEM.panel.flat.mode", panel.flat_mode);
  3729.             //
  3730.             recalc_datas();
  3731.             redraw_stub_images();
  3732.             g_image_cache = new image_cache;
  3733.             CollectGarbage();
  3734.             on_playlist_switch();
  3735.             break;
  3736.         case 7:
  3737.             panel.custom_colors = !panel.custom_colors;
  3738.             window.SetProperty("SYSTEM.panel.custom.colors", panel.custom_colors);
  3739.             on_colors_changed();
  3740.             break;
  3741.         case 8:
  3742.             panel.show_text = !panel.show_text;
  3743.             window.SetProperty("SYSTEM.panel.album.info", panel.show_text);
  3744.             //
  3745.             recalc_datas();
  3746.             redraw_stub_images();
  3747.             g_image_cache = new image_cache;
  3748.             CollectGarbage();
  3749.             on_playlist_switch();
  3750.             break;
  3751.         case 9:
  3752.             cover.draw_reflection = !cover.draw_reflection;
  3753.             window.SetProperty("SYSTEM.cover.draw.reflection", cover.draw_reflection);
  3754.             window.Repaint();
  3755.             break;
  3756.         case 10:
  3757.             panel.tracks_counter_show = !panel.tracks_counter_show;
  3758.             window.SetProperty("*USER.total.tracks.visible", panel.tracks_counter_show),
  3759.             window.Repaint();
  3760.             break;
  3761.         case 20:
  3762.             window.ShowProperties();
  3763.             break;
  3764.         case 21:
  3765.             window.ShowConfigure();
  3766.             break;
  3767.         case 22:
  3768.             redraw_stub_images();
  3769.             g_image_cache = new image_cache;
  3770.             CollectGarbage();
  3771.             on_playlist_switch();
  3772.             break;
  3773.         case 99:
  3774.             toolbar.lock = !toolbar.lock;
  3775.             window.SetProperty("SYSTEM.toolbar.lock", toolbar.lock);
  3776.             break;
  3777.         default:
  3778.  
  3779.     };
  3780.     _appearance.Dispose();
  3781.     _menu.Dispose();
  3782.     g_menu_displayed = false;
  3783.     // toolbar collapse
  3784.     if(!toolbar.lock) {
  3785.         if(toolbar.delta==0) {
  3786.             toolbar.timerID_on && window.ClearTimeout(toolbar.timerID_on);
  3787.             toolbar.timerID_on = false;
  3788.         };
  3789.         if(toolbar.state) {
  3790.             if(!toolbar.timerID_off) {
  3791.                 if(toolbar.delta == toolbar.collapsed_y*-1) {
  3792.                     toolbar.timerID_off = window.SetTimeout(function() {
  3793.                         if(!toolbar.timerID2) {
  3794.                             toolbar.timerID2 = window.SetInterval(function() {
  3795.                                 toolbar.delta -= toolbar.step;
  3796.                                 if(toolbar.delta <= 0) {
  3797.                                     toolbar.delta = 0;
  3798.                                     toolbar.state = false;
  3799.                                     window.ClearInterval(toolbar.timerID2);
  3800.                                     toolbar.timerID2 = false;
  3801.                                 };
  3802.                                 window.RepaintRect(0, 0, ww, 30);
  3803.                             }, 30);
  3804.                         } ;
  3805.                         toolbar.timerID_off && window.ClearTimeout(toolbar.timerID_off);
  3806.                         toolbar.timerID_off = false;
  3807.                     }, 400);
  3808.                 };
  3809.             };  
  3810.         };
  3811.     };
  3812.     return true;
  3813. }
  3814.  
  3815. //=================================================// Drag'n'Drop Callbacks
  3816. var wsh_dragging = false;
  3817.  
  3818. function on_drag_enter() {
  3819.     wsh_dragging = true;
  3820. };
  3821.  
  3822. function on_drag_leave() {
  3823.     wsh_dragging = false;
  3824. };
  3825.  
  3826. function on_drag_over(action, x, y, mask) {
  3827.     on_mouse_move(x, y);
  3828. };
  3829.  
  3830. function on_drag_drop(action, x, y, mask) {
  3831.     wsh_dragging = false;
  3832.     // We are going to process the dropped items to a playlist
  3833.     action.ToPlaylist();
  3834.     action.Playlist = plman.ActivePlaylist;
  3835.     action.ToSelect = false;
  3836. };
RAW Paste Data