// *****************************************************************************************************************************************
// headerBar object by Br3tt aka Falstaff (c)2015
// *****************************************************************************************************************************************

oBorder = function() {
    this.leftId = arguments[0];
    this.rightId = arguments[1];
    this.percent = arguments[2];
    
    this.isHover = function(x, y) {
        return (x >= this.x - 3 && x <= this.x + this.w + 2 && y >= this.y && y <= this.y + this.h);
    };
    
    this.on_mouse = function(event, x, y) {
        this.ishover = (x >= this.x - 3 && x <= this.x + this.w + 2 && y >= this.y && y <= this.y + this.h);
        switch(event) {
            case "down":
                if(this.ishover) {
                    this.sourceX = x;
                    this.drag = true;
                };
                break;
            case "up":
                this.drag = false;
                break;
            case "move":
                if(this.drag) {
                    this.delta = x - this.sourceX;
                };
                break;
        };
    };
};

oColumn = function() {
    this.label = arguments[0];
    this.tf = arguments[1];
    this.tf2 = arguments[2];
    this.percent = arguments[3];
    this.ref = arguments[4];
    this.align = Math.round(arguments[5]);
    this.sortOrder = arguments[6];
    this.DT_align = (this.align == 0 ? DT_LEFT : (this.align == 2 ? DT_RIGHT : DT_CENTER));
    this.minWidth = zoom(32, g_dpi);
    this.drag = false;
    
    this.isHover = function(x, y) {
        return (x > this.x && x < this.x + this.w && y >= this.y && y <= this.y + this.h);
    };

    this.on_mouse = function(event, x, y) {
        this.ishover = (x > this.x + 2 && x < this.x + this.w - 2 && y >= this.y && y <= this.y + this.h);
        switch(event) {
            case "down":
                if(this.ishover && this.percent > 0) {
                    this.drag = true;
                };
                break;
            case "up":
                this.drag = false;
                break;
        };
    };
};

oHeaderBar = function() {
    this.visible = true;
    this.columns = [];
    this.borders = [];
    this.totalColumns = window.GetProperty("SYSTEM.HeaderBar.TotalColumns", 0);
    this.borderDragged = false;
    this.borderDraggedId = -1;
    this.columnDragged = 0;
    this.columnDraggedId = null;
    this.columnRightClicked = -1;
    this.resetSortIndicators = function() {
        this.sortedColumnId = -1;
        this.sortedColumnDirection = 1;
    };
    this.resetSortIndicators();

    this.borderHover = false;
    this.clickX = 0;

    this.setButtons = function() {
		var gfx_font = gdi.Font("guifx v2 transports", 15, 0);
	
		if(properties.themed) {
			var color_txt = g_syscolor_button_txt;
            var color_bg = g_syscolor_button_bg;
		}; else {
			var color_txt = g_color_normal_txt;
            var color_bg = g_color_normal_bg;
		};
		
        // normal playlistManager slide Image
        this.slide_open_normal = gdi.CreateImage(cScrollBar.width, this.h);
        var gb = this.slide_open_normal.GetGraphics();
            gb.FillSolidRect(0, 0, cScrollBar.width, this.h, g_color_normal_txt & 0x15ffffff);
            gb.SetTextRenderingHint(4);
            gb.DrawString(String.fromCharCode(161), g_font_wd3_headerBar, color_txt, 0, 0, cScrollBar.width, this.h, cc_stringformat);
        this.slide_open_normal.ReleaseGraphics(gb);

        // hover playlistManager slide Image
        this.slide_open_hover = gdi.CreateImage(cScrollBar.width, this.h);
        gb = this.slide_open_hover.GetGraphics();
            gb.FillSolidRect(0, 0, cScrollBar.width, this.h, g_color_normal_txt & 0x30ffffff);
            gb.SetTextRenderingHint(4);
            gb.DrawString(String.fromCharCode(161), g_font_wd3_headerBar, color_bg, 0, 0, cScrollBar.width, this.h, cc_stringformat);
        this.slide_open_hover.ReleaseGraphics(gb);

        // down playlistManager slide Image
        this.slide_open_down = gdi.CreateImage(cScrollBar.width, this.h);
        gb = this.slide_open_down.GetGraphics();
            gb.FillSolidRect(0, 0, cScrollBar.width, this.h, g_color_normal_txt & 0x30ffffff);
            gb.SetTextRenderingHint(4);
            gb.DrawString(String.fromCharCode(161), g_font_wd3_headerBar, color_txt, 0, 0, cScrollBar.width, this.h, cc_stringformat);
        this.slide_open_down.ReleaseGraphics(gb);

        // normal playlistManager close Image
        this.slide_close_normal = gdi.CreateImage(cScrollBar.width, this.h);
        var gb = this.slide_close_normal.GetGraphics();
            gb.FillSolidRect(0, 0, cScrollBar.width, this.h, g_color_normal_txt & 0x15ffffff);
            gb.SetTextRenderingHint(4);
            gb.DrawString(String.fromCharCode(162), g_font_wd3_headerBar, color_txt, 0, 0, cScrollBar.width, this.h, cc_stringformat);
        this.slide_close_normal.ReleaseGraphics(gb);

        // hover playlistManager close Image
        this.slide_close_hover = gdi.CreateImage(cScrollBar.width, this.h);
        gb = this.slide_close_hover.GetGraphics();
            gb.FillSolidRect(0, 0, cScrollBar.width, this.h, g_color_normal_txt & 0x30ffffff);
            gb.SetTextRenderingHint(4);
            gb.DrawString(String.fromCharCode(162), g_font_wd3_headerBar, color_bg, 0, 0, cScrollBar.width, this.h, cc_stringformat);
        this.slide_close_hover.ReleaseGraphics(gb);

        // down playlistManager close Image
        this.slide_close_down = gdi.CreateImage(cScrollBar.width, this.h);
        gb = this.slide_close_down.GetGraphics();
            gb.FillSolidRect(0, 0, cScrollBar.width, this.h, g_color_normal_txt & 0x30ffffff);
            gb.SetTextRenderingHint(4);
            gb.DrawString(String.fromCharCode(162), g_font_wd3_headerBar, color_txt, 0, 0, cScrollBar.width, this.h, cc_stringformat);
        this.slide_close_down.ReleaseGraphics(gb);

        if(cPlaylistManager.visible) {
            this.button = new button(this.slide_close_normal, this.slide_close_hover, this.slide_close_down);
        }; else {
            this.button = new button(this.slide_open_normal, this.slide_open_hover, this.slide_open_down);
        };
    };
    
    this.setSize = function(x, y, w, h) {
        this.x = x;
        this.y = y;
        this.w = w - cScrollBar.width;
        this.h = cHeaderBar.height;
        this.setButtons();
        this.txtHeight = cHeaderBar.txtHeight;
        this.borderWidth = cHeaderBar.borderWidth;
    };
    
    this.repaint = function() {
        full_repaint();
    };

    this.calculateColumns = function() {
        var tmp = this.x;

        // calc column metrics for calculating border metrics as well
        for(var i = 0; i < this.totalColumns; i++) {
            if(this.columns[i].percent > 0) {
                this.columns[i].x = tmp;
                this.columns[i].y = this.y;
                this.columns[i].w = Math.abs(this.w * this.columns[i].percent / 100000);
                this.columns[i].h = this.h;
                if(i != this.columnDraggedId || (this.columnDragged == 1)) {
                    // start >> on last column, adjust width of last drawn column to fit headerbar width!
                    if(this.columns[i].x + this.columns[i].w >= this.x + this.w) {  // if last col width go ahead of the max width (1 pixel more!) downsize col width !
                        this.columns[i].w = (this.x + this.w) - this.columns[i].x + 1; // +1 to fit the whole headerbar width due to the -1 in draw width of each column in DrawRect below
                    };
                    if(this.columns[i].x + this.columns[i].w < this.x + this.w && this.columns[i].x + this.columns[i].w > this.x + this.w - 4) { // if there is a gap of 1 pixel at the end, fill it!
                        this.columns[i].w = (this.x + this.w) - this.columns[i].x + 1;
                    };
                    // end <<
                };
                tmp = this.columns[i].x + this.columns[i].w;
            }; else {
                this.columns[i].x = tmp;
                this.columns[i].y = this.y;
                this.columns[i].w = 0;
                this.columns[i].h = this.h;
            };
        };
    };
    
    this.drawHiddenPanel = function(gr) {
        gr.FillSolidRect(this.x, this.y, this.w + cScrollBar.width, 1, g_color_normal_txt & 0x15ffffff);
    }

    this.drawColumns = function(gr) {
        var j = 0, tmp = this.x, cx = 0, cy = 0, cw = 0, sx = 0,bx = 0;
       
        // tweak to only reset mouse cursor to arrowafter a column sorting
        if(this.columnDragged_saved==3 && this.columnDragged==0) {
            this.columnDragged_saved = 0;
        };

        // calc column metrics for calculating border metrics as well
        this.calculateColumns();

        // draw borders and left column from each one!
        tmp = this.x;
        for(var i = 0; i < this.borders.length; i++) {
            j = this.borders[i].leftId;
            this.borders[i].x = this.columns[j].x + this.columns[j].w - 1;
            this.borders[i].y = this.columns[j].y;
            this.borders[i].w = this.borderWidth;
            this.borders[i].h = this.columns[j].h;
            bx = Math.floor(this.borders[i].x - 1);
            
            if(this.columns[j].percent > 0) {
                cx = tmp;
                cy = this.y;
                cw = (bx - cx);
                if(j != this.columnDraggedId || (this.columnDragged == 1)) {
                    // draw column header bg
                    if(this.columnRightClicked == j) {
                        gr.FillSolidRect(cx, cy, cw, this.h, g_color_normal_txt & 0x30ffffff);
                    }; else { // normal box
                        if(this.columnDragged == 1 && j == this.columnDraggedId) {
                            gr.FillSolidRect(cx, cy, cw, this.h, g_color_normal_txt & 0x30ffffff);
                        }; else {
                            gr.FillSolidRect(cx, cy, cw, this.h, g_color_normal_txt & 0x15ffffff);
                        };
                    };
                    // draw column header infos
                    if(this.columns[j].tf != "null" || this.columns[j].sortOrder != "null") {
                        // draw sort indicator (direction)
                        if(j == this.sortedColumnId) {
                            sx = Math.floor(cx + this.columns[j].w / 2 - 3);
                            sh = cy + 1;
                            images.sortdirection && gr.DrawImage(images.sortdirection, sx, sh, images.sortdirection.Width, images.sortdirection.Height, 0, 0, images.sortdirection.Width, images.sortdirection.Height, (this.sortedColumnDirection > 0 ? 180 : 0), 130);
                        };
                    };
                    gr.GdiDrawText(this.columns[j].label, gdi.Font(g_fname, this.txtHeight, 1), g_color_normal_txt, cx + (this.borderWidth*2), cy + 1, cw - (this.borderWidth*4) - 1, this.h, this.columns[j].DT_align | DT_VCENTER | DT_CALCRECT | DT_NOPREFIX | DT_END_ELLIPSIS);
                }; else if(j == this.columnDraggedId && this.columnDragged == 2) {
                    gr.FillGradRect(cx, cy, cw, this.h, 90, RGBA(0,0,0,60), 0, 1.0);
                };
            };
            
            if(this.borders[i].drag) {
                gr.FillSolidRect(Math.floor(bx - 0), this.y, this.borders[i].w, this.h, g_color_normal_txt);
            };
            tmp = bx + this.borderWidth;
        };

        // draw last colum at the right of the last border Object
        for(j = this.totalColumns - 1; j >= 0; j--) {
            if(this.columns[j].percent > 0) {
                cx = tmp;
                cy = this.y;
                cw = (this.w - this.borderWidth - cx);
                if(j != this.columnDraggedId || (this.columnDragged == 1)) {
                    // draw last column bg
                    if(this.columnRightClicked == j) {
                        gr.FillSolidRect(cx, cy, cw, this.h, g_color_normal_txt & 0x30ffffff);
                    }; else { // normal box
                        if(this.columnDragged == 1 && j == this.columnDraggedId) {
                            gr.FillSolidRect(cx, cy, cw, this.h, g_color_normal_txt & 0x30ffffff);
                        }; else {
                            gr.FillSolidRect(cx, cy, cw, this.h, g_color_normal_txt & 0x15ffffff);
                        };
                    };
                    // draw last column header info
                    if(this.columns[j].tf != "null" || this.columns[j].sortOrder != "null") {
                        // draw sort indicator (direction)
                        if(j == this.sortedColumnId) {
                            sx = Math.floor(cx + this.columns[j].w / 2 - 3);
                            sh = cy + 1;
                            images.sortdirection && gr.DrawImage(images.sortdirection, sx, sh, images.sortdirection.Width, images.sortdirection.Height, 0, 0, images.sortdirection.Width, images.sortdirection.Height, (this.sortedColumnDirection > 0 ? 180 : 0), 130);
                        };
                    };
                    gr.GdiDrawText(this.columns[j].label, gdi.Font(g_fname, this.txtHeight, 1), g_color_normal_txt, cx + (this.borderWidth*2), cy + 1, cw - (this.borderWidth*4) - 1, this.h, this.columns[j].DT_align | DT_VCENTER | DT_CALCRECT | DT_NOPREFIX | DT_END_ELLIPSIS);
                }; else if(j == this.columnDraggedId && this.columnDragged == 2) {
                    gr.FillGradRect(cx, cy, cw, this.h, 90, RGBA(0,0,0,70), 0, 1.0);
                };
                break;
            };
        };
        
        // draw dragged column header (last item drawn to be always on the top)
        if(this.columnDragged > 1 && this.columnDraggedId != null) {
            cx = Math.floor(mouse_x - this.clickX) + 2;
            cy = this.y + 3;
            // shadow
            gr.FillSolidRect(cx+4, cy+3, Math.floor(this.columns[this.columnDraggedId].w - 2), this.h, RGBA(0,0,0,10));
            gr.FillSolidRect(cx+3, cy+2, Math.floor(this.columns[this.columnDraggedId].w - 2), this.h, RGBA(0,0,0,15));
            gr.FillSolidRect(cx+2, cy+1, Math.floor(this.columns[this.columnDraggedId].w - 2), this.h, RGBA(0,0,0,30));
            // header bg
            gr.FillSolidRect(cx, cy, Math.floor(this.columns[this.columnDraggedId].w - 2), this.h, g_color_normal_txt & 0x66ffffff);
            gr.DrawRect(cx, cy + 1, Math.floor(this.columns[this.columnDraggedId].w - 2), this.h - 2, 2.0, g_color_normal_txt);
            gr.DrawRect(cx+1, cy + 2, Math.floor(this.columns[this.columnDraggedId].w - 5), this.h - 5, 1.0, blendColors(g_color_normal_txt, g_color_normal_bg, 0.55));
            // header text info
            gr.GdiDrawText(this.columns[this.columnDraggedId].label, gdi.Font(g_fname, this.txtHeight, 1), g_color_normal_bg, cx + (this.borderWidth*2), cy + 1, this.columns[this.columnDraggedId].w - (this.borderWidth*4) - 2, this.h, this.columns[this.columnDraggedId].DT_align | DT_VCENTER | DT_CALCRECT | DT_NOPREFIX | DT_END_ELLIPSIS);
        };
        // draw settings button
        this.button.draw(gr, this.x + this.w, this.y, 255);
    };
    
    this.saveColumns = function() {
        var tmp;
        for(var j = 0; j < 7; j++) {
            tmp = "";
            for(var i = 0; i < this.columns.length; i++) {
                switch(j) {
                    case 0:
                        tmp = tmp + this.columns[i].label;
                        break;
                    case 1:
                        tmp = tmp + this.columns[i].tf;
                        break;
                    case 2:
                        tmp = tmp + this.columns[i].tf2;
                        break;
                    case 3:
                        tmp = tmp + this.columns[i].percent;
                        break;
                    case 4:
                        tmp = tmp + this.columns[i].ref;
                        break;
                    case 5:
                        tmp = tmp + this.columns[i].align;
                        break;
                    case 6:
                        tmp = tmp + this.columns[i].sortOrder;
                        break;
                };
                // add separator ';'
                if(i < this.columns.length - 1) {
                    tmp = tmp + "^^";
                };
            };
            switch(j) {
                case 0:
                    window.SetProperty("SYSTEM.HeaderBar.label", tmp);
                    break;
                case 1:
                    window.SetProperty("SYSTEM.HeaderBar.tf", tmp);
                    break;
                case 2:
                    window.SetProperty("SYSTEM.HeaderBar.tf2", tmp);
                    break;
                case 3:
                    window.SetProperty("SYSTEM.HeaderBar.percent", tmp);
                    break;
                case 4:
                    window.SetProperty("SYSTEM.HeaderBar.ref", tmp);
                    break;
                case 5:
                    window.SetProperty("SYSTEM.HeaderBar.align", tmp);
                    break;
                case 6:
                    window.SetProperty("SYSTEM.HeaderBar.sort", tmp);
                    break;
            };
        };
        this.initColumns();
    };
    
    this.initColumns = function() {
        var borderPercent = 0;
        var previousColumnToDrawId = -1;
        var totalColumnsToDraw = 0;
        this.columns.splice(0, this.columns.length);
        this.borders.splice(0, this.borders.length);
        if(this.totalColumns == 0) {
            // INITIALIZE columns and Properties
            var fields = [];
            var tmp, percent;
            for(var i = 0; i < 7; i++) {
                switch(i) {
                    case 0:
                        fields.push(new Array("Cover", "State", "Index", "#", "Title", "Year", "Artist", "Album", "Genre", "Mood", "Rating", "Plays", "Bitrate", "Time"));
                        break;
                    case 1:
                        fields.push(new Array("null","null","$num(%list_index%,$len(%list_total%))","$if2(%tracknumber%,-)","$if2(%title%,%filename_ext%)","$if(%date%,$year($replace(%date%,/,-,.,-)),'-')","$if(%length%,%artist%,'Stream')","$if2(%album%,$if(%length%,'Single','Web radios'))","$if2(%genre%,'Other')","$rgb(255,120,170)$if(%mood%,1,0)","$rgb(255,255,50)$if2(%rating%,0)","$if2(%play_counter%,$if2(%play_count%,0))","$if(%__bitrate_dynamic%, $if(%isplaying%,$select($add($mod(%_time_elapsed_seconds%,2),1),%__bitrate_dynamic%,%__bitrate_dynamic%)'K',$if($stricmp($left(%codec_profile%,3),'VBR'),%codec_profile%,%__bitrate%'K')),' '$if($stricmp($left(%codec_profile%,3),'VBR'),%codec_profile%,%__bitrate%'K'))","$if(%isplaying%,$if(%length%,-%playback_time_remaining%,'0:00'),$if2(%length%,'00:00'))"));
                        break;
                    case 2:
                          fields.push(new Array("null","null","null","null","$if(%length%,%artist%,)","null","null","$if2(%genre%,'Other')","null","null","null","null","null","%__bitrate% kbps"));
                        break;
                    case 3:
                        fields.push(new Array("0","5000","0","5000","70000","0","0","0","0","0","10000","0","0","10000"));
                        break;
                    case 4:
                        fields.push(new Array("Cover","State","Index","Tracknumber","Title","Date","Artist","Album","Genre","Mood","Rating","Playcount","Bitrate","Duration"));
                        break;
                    case 5:
                        fields.push(new Array("0","1","1","2","0","2","0","0","0","1","1","2","1","2"));
                        break;
                    case 6:
                        fields.push(new Array("%album artist% | $if(%album%,%date%,'9999') | %album% | %discnumber% | %tracknumber% | %title%","%album artist% | $if(%album%,%date%,'9999') | %album% | %discnumber% | %tracknumber% | %title%","null","%tracknumber% | %album artist% | $if(%album%,%date%,'9999') | %album% | %discnumber% | %title%","%title% | %album artist% | $if(%album%,%date%,'9999') | %album% | %discnumber% | %tracknumber%","%date% | %album artist% | %album% | %discnumber% | %tracknumber% | %title%","%artist% | $if(%album%,%date%,'9999') | %album% | %discnumber% | %tracknumber% | %title%","$if2(%album%,%artist%) | $if(%album%,%date%,'9999') | %album artist% | %discnumber% | %tracknumber% | %title%","%genre% | %album artist% | $if(%album%,%date%,'9999') | %album% | %discnumber% | %tracknumber% | %title%","%mood% | %album artist% | $if(%album%,%date%,'9999') | %album% | %discnumber% | %tracknumber% | %title%","%rating% | %album artist% | $if(%album%,%date%,'9999') | %album% | %discnumber% | %tracknumber% | %title%","$if2(%play_counter%,$if2(%play_count%,0)) | %album artist% | $if(%album%,%date%,'9999') | %album% | %discnumber% | %tracknumber% | %title%","%__bitrate% | %album artist% | $if(%album%,%date%,'9999') | %album% | %discnumber% | %tracknumber% | %title%","$if2(%length%,' 0:00') | %album artist% | $if(%album%,%date%,'9999') | %album% | %discnumber% | %tracknumber% | %title%"));
                        break;
                };
                // convert array to csv string
                tmp = "";
                for(var j = 0; j < fields[i].length; j++) {
                    tmp = tmp + fields[i][j];
                    if(j < fields[i].length - 1) {
                        tmp = tmp + "^^";
                    };
                };
                // save CSV string into window Properties
                switch(i) {
                    case 0:
                        window.SetProperty("SYSTEM.HeaderBar.label", tmp);
                        break;
                    case 1:
                        window.SetProperty("SYSTEM.HeaderBar.tf", tmp);
                        break;
                    case 2:
                        window.SetProperty("SYSTEM.HeaderBar.tf2", tmp);
                        break;
                    case 3:
                        window.SetProperty("SYSTEM.HeaderBar.percent", tmp);
                        break;
                    case 4:
                        window.SetProperty("SYSTEM.HeaderBar.ref", tmp);
                        break;
                    case 5:
                        window.SetProperty("SYSTEM.HeaderBar.align", tmp);
                        break;
                    case 6:
                        window.SetProperty("SYSTEM.HeaderBar.sort", tmp);
                        break;
                };
            };
            // create column Objects
            this.totalColumns = fields[0].length;
            window.SetProperty("SYSTEM.HeaderBar.TotalColumns", this.totalColumns);
            for(var k = 0; k < this.totalColumns; k++) {
                this.columns.push(new oColumn(fields[0][k],fields[1][k],fields[2][k],fields[3][k],fields[4][k],fields[5][k],fields[6][k]));
                if(this.columns[k].percent > 0) {
                    if(previousColumnToDrawId >= 0) {
                        this.borders.push(new oBorder(previousColumnToDrawId, k, borderPercent));
                    };
                    borderPercent += Math.round(this.columns[k].percent);
                    previousColumnToDrawId = k;
                };
            };
            
        }; else {
            var fields = [];
            var tmp;
            // LOAD columns from Properties
            for(var i = 0; i < 7; i++) {
                switch(i) {
                    case 0:
                        tmp = window.GetProperty("SYSTEM.HeaderBar.label", "?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?");
                        break;
                    case 1:
                        tmp = window.GetProperty("SYSTEM.HeaderBar.tf", "?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?");
                        break;
                    case 2:
                        tmp = window.GetProperty("SYSTEM.HeaderBar.tf2", "?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?");
                        break;
                    case 3:
                        tmp = window.GetProperty("SYSTEM.HeaderBar.percent", "0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0");
                        break;
                    case 4:
                        tmp = window.GetProperty("SYSTEM.HeaderBar.ref", "?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?");
                        break;
                    case 5:
                        tmp = window.GetProperty("SYSTEM.HeaderBar.align", "0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0");
                        break;
                    case 6:
                        tmp = window.GetProperty("SYSTEM.HeaderBar.sort", "?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?^^?");
                        break;
                };
                fields.push(tmp.split("^^"));
            };
            for(var k = 0; k < this.totalColumns; k++) {
                this.columns.push(new oColumn(fields[0][k],fields[1][k],fields[2][k],fields[3][k],fields[4][k],fields[5][k],fields[6][k]));
                if(this.columns[k].percent > 0) {
                    if(previousColumnToDrawId >= 0) {
                        this.borders.push(new oBorder(previousColumnToDrawId, k, borderPercent));
                    };
                    borderPercent += Math.round(this.columns[k].percent);
                    previousColumnToDrawId = k;
                };
            };
            this.calculateColumns();
        };
    };
    
    this.buttonCheck = function(event, x, y) {
        if(!dragndrop.moved) {
            if(!this.columnDragged && !this.borderDragged) {

        		var state = this.button.checkstate(event, x, y);
        		switch(event) {
                case "down":
                    if(state == ButtonStates.down) {
                        this.buttonClicked = true;
                    };
                    break;
                case "up":
        			if(this.buttonClicked && state == ButtonStates.hover) {
                        togglePlaylistManager();
                        this.button.state = ButtonStates.hover;
        			};
                    this.buttonClicked = false;
                    break;
                case "leave":
                    this.button.state = ButtonStates.normal;
                    break;
                };
        		return state;
            };
        };
    };
    
    this.on_mouse = function(event, x, y, delta) {
        var tmp = "", percents = [];

        if(!p.scrollbar.clicked) {

            this.ishover = (x >= this.x && x <= this.x + this.w && y >= this.y && y <= this.y + this.h);
            
            // check settings button + toolbar if button not hover
    		if(this.buttonCheck(event, x, y) != ButtonStates.hover) {
                switch(event) {
                    case "down":
                        if(this.ishover) {
                            // check borders:
                            for(var i = 0; i < this.borders.length; i++) {
                                this.borders[i].on_mouse(event, x, y);
                                if(this.borders[i].drag) {
                                    this.borderDragged = true;
                                    this.borderDraggedId = i;
                                    full_repaint();
                                };
                            };
                            // if no click on a border (no border drag), check columns:
                            if(!this.borderDragged) {
                                for(var i = 0; i < this.columns.length; i++) {
                                    this.columns[i].on_mouse(event, x, y);
                                    if(this.columns[i].drag) {
                                        this.clickX = x - this.columns[i].x;
                                        if(this.columns[i].tf != "null" || this.columns[i].sortOrder != "null") {
                                            this.columnDragged = 1;
                                            window.SetCursor(IDC_ARROW);
                                        }; else {
                                            this.columnDragged = 2;
                                            window.SetCursor(IDC_SIZEALL);
                                        };
                                        this.columnDraggedId = i;
                                        this.columnDraggedIdHistoric = i;
                                        this.repaint();
                                        break;
                                    };
                                }; 
                            };
                        };
                        break;
                    case "up":
                        if(this.borderDragged) {
                            for(var i = 0; i < this.borders.length; i++) {
                                if(this.borders[i].drag) {
                                    // save updated left & right columns 'percent' properties
                                    tmp = window.GetProperty("SYSTEM.HeaderBar.percent", "0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0^^0");
                                    percents = tmp.split("^^");
                                    percents[Math.round(this.borders[i].leftId)] = this.columns[this.borders[i].leftId].percent.toString();
                                    percents[Math.round(this.borders[i].rightId)] = this.columns[this.borders[i].rightId].percent.toString();
                                    // save new percent CSV string to window Properties
                                    tmp = "";
                                    for(var j = 0; j < percents.length; j++) {
                                        tmp = tmp + percents[j];
                                        if(j < percents.length - 1) {
                                            tmp = tmp + "^^";
                                        };
                                    };
                                    window.SetProperty("SYSTEM.HeaderBar.percent", tmp);
                                    // update border object status
                                    this.borders[i].on_mouse(event, x, y);
                                    this.repaint();
                                };
                            };
                            this.borderDragged = false;
                            this.borderDraggedId = -1;
                            this.on_mouse("move", x, y); // call "Move" to set mouse cursor if border hover
                        }; else if(this.columnDragged > 0) {
                            if(this.columnDragged==1) {
                                if(this.columnDraggedId == 0) {
                                    this.columns[0].on_mouse(event, x, y);
                                };
                                if(this.columnDraggedId > 0 || (this.columnDraggedId == 0 && this.columns[this.columnDraggedId].isHover(x,y))) {
                                    window.SetCursor(IDC_WAIT);
                                    this.sortedColumnDirection = (this.columnDraggedId == this.sortedColumnId) ? (0 - this.sortedColumnDirection) : 1;
                                    this.sortedColumnId = this.columnDraggedId;
                                    this.columns[this.columnDraggedId].drag = false;
                                    this.columnDragged = 3;
                                    this.columnDragged_saved = 3;
                                    cHeaderBar.sortRequested = true;
                                    plman.UndoBackup(plman.ActivePlaylist);
                                    if(this.columns[this.columnDraggedId].sortOrder != "null") {
                                        plman.SortByFormatV2(plman.ActivePlaylist, this.columns[this.columnDraggedId].sortOrder, this.sortedColumnDirection);
                                    }; else {
                                        plman.SortByFormatV2(plman.ActivePlaylist, this.columns[this.columnDraggedId].tf, this.sortedColumnDirection);
                                    };
                                    update_playlist(properties.collapseGroupsByDefault);
                                }; else {
                                    this.columns[this.columnDraggedId].drag = false;
                                    this.columnDragged = 0;
                                    this.columnDragged_saved = 0;
                                };
                            }; else {
                                for(var i = 0; i < this.columns.length; i++) {
                                    this.columns[i].on_mouse(event, x, y);
                                };
                                this.columnDragged = 0;
                                this.on_mouse("move", x, y); // call "Move" to set mouse cursor if border hover
                            };
                            this.columnDraggedId = null;
                            this.repaint();
                        };
                        break;
                    case "right":
                        if(this.ishover) {
                            this.columnRightClicked = -1;
                            for(var i = 0; i < this.columns.length; i++) {
                                if(this.columns[i].percent > 0 && this.columns[i].isHover(x, y)) {
                                    this.columnRightClicked = i;
                                    this.repaint();
                                    break;
                                };
                            };
                            if(!utils.IsKeyPressed(VK_SHIFT)) {
                                this.contextMenu(x, y, this.columnRightClicked);
                            };
                        };
                        break;
                    case "move":
                        this.borderHover = false;
                        for(var i = 0; i < this.borders.length; i++) {
                            if(this.borders[i].isHover(x, y)) {
                                this.borderHover = true;
                                break;
                            };
                        };
                        if(this.columnDragged < 1) {
                            if(this.borderHover || this.borderDragged) {
                                window.SetCursor(IDC_SIZEWE);
                            }; else if(p.playlistManager.inputbox) {
                                if(!p.playlistManager.inputbox.ibeam_set) window.SetCursor(IDC_ARROW);
                            }; else {
                                window.SetCursor(IDC_ARROW);
                            };
                        };
                        if(this.borderDragged) {
                            for(var i = 0; i < this.borders.length; i++) {
                                this.borders[i].on_mouse(event, x, y);
                                var d = this.borders[i].delta;
                                if(this.borders[i].drag) {
                                    var toDoLeft = (this.columns[this.borders[i].leftId].w + d > this.columns[this.borders[i].leftId].minWidth);
                                    var toDoRight = (this.columns[this.borders[i].rightId].w - d > this.columns[this.borders[i].rightId].minWidth);
                                    if(toDoLeft && toDoRight) { // ok, we can resize the left and the right columns
                                        this.columns[this.borders[i].leftId].w += d;
                                        this.columns[this.borders[i].rightId].w -= d;
                                        var addedPercent = Math.abs(this.columns[this.borders[i].leftId].percent) + Math.abs(this.columns[this.borders[i].rightId].percent);
                                        this.columns[this.borders[i].leftId].percent = Math.abs(this.columns[this.borders[i].leftId].w / this.w * 100000);
                                        this.columns[this.borders[i].rightId].percent = addedPercent - this.columns[this.borders[i].leftId].percent;
                                        this.borders[i].sourceX = x;
                                        full_repaint();
                                    };
                                };
                            };
                        }; else if(this.columnDraggedId != 0 && (this.columnDragged == 1 || this.columnDragged == 2)) {
                            this.columnDragged = 2;
                            window.SetCursor(IDC_SIZEALL);
                            for(var i = 1; i < this.columns.length; i++) {
                                if(this.columns[i].percent > 0) {
                                    if(i != this.columnDraggedId) {
                                        if((x > mouse_x && x > this.columns[i].x && i > this.columnDraggedId) || (x < mouse_x && x < this.columns[i].x + this.columns[i].w && i < this.columnDraggedId)) {
                                            var tmpCol = this.columns[this.columnDraggedId];
                                            this.columns[this.columnDraggedId] = this.columns[i];
                                            this.columns[i] = tmpCol;
                                            // move sortColumnId too !
                                            if(i == this.sortedColumnId) {
                                                this.sortedColumnId = this.columnDraggedId;
                                            }; else if(this.columnDraggedId == this.sortedColumnId) {
                                                this.sortedColumnId = i;
                                            };
                                            this.columnDraggedId = i;
                                            break;
                                        }; 
                                    };
                                };
                            };
                            this.saveColumns();            
                            full_repaint();
                        };
                        break;
                    case "leave":
                        full_repaint();
                        break;
                };
            };
        };
    };

    this.contextMenu = function(x, y, column_index) {
        var idx;
        var _menu = window.CreatePopupMenu();
        var _this = window.CreatePopupMenu();
        var _groups = window.CreatePopupMenu();
        var _sorts = window.CreatePopupMenu();
        var _patterns = window.CreatePopupMenu();
        var _collapsed_height = window.CreatePopupMenu();
        var _expanded_height = window.CreatePopupMenu();
        var _columns = window.CreatePopupMenu();
        var tmp = "", percents = [];

        // check if active playlist is filtered in group patterns
        var pl_name = plman.GetPlaylistName(plman.ActivePlaylist);
        var found = false;
        var default_pattern_index = -1;
        var playlist_pattern_index = -1;
        if(properties.enablePlaylistFilter) {
            // get Filtered groupBy pattern
            for(var m=0; m < p.list.groupby.length; m++) {
                if(default_pattern_index > -1 && found) {
                    break;
                }; else if(p.list.groupby[m].playlistFilter.length > 0) {
                    var arr_pl = p.list.groupby[m].playlistFilter.split(";");
                    for(var n=0; n < arr_pl.length; n++) {
                        if(default_pattern_index < 0 && arr_pl[n] == "*") {
                            default_pattern_index = m;
                            playlist_pattern_index = (playlist_pattern_index < 0 ? m : playlist_pattern_index);
                        };
                        if(arr_pl[n] == pl_name) {
                            found = true;
                            playlist_pattern_index = m;
                        };
                    };
                };
            };
        };

        // main Menu entries
        if(fb.IsPlaying) {
            _menu.AppendMenuItem(MF_STRING, 10, "Show Now Playing Track");
            _menu.AppendMenuSeparator();
        };
        _menu.AppendMenuItem(MF_STRING, 11, "Panel Settings...");

        // Groups submenu entries
        _menu.AppendMenuSeparator();
        _menu.AppendMenuItem(MF_STRING, 13, "Edit Groups...");
        _groups.AppendTo(_menu, MF_STRING, "Groups");
        _groups.AppendMenuItem(MF_STRING, 18, "Enable Groups");
        _groups.CheckMenuItem(18, properties.showgroupheaders);
        
        if(properties.showgroupheaders) {
            _groups.AppendMenuItem(MF_STRING, 19, "Enable Playlist Filter");
            _groups.CheckMenuItem(19, properties.enablePlaylistFilter);

            _groups.AppendMenuSeparator();
            _patterns.AppendTo(_groups, MF_STRING, "Change Group Pattern");
            var groupByMenuIdx = 20;
            var totalGroupBy = p.list.groupby.length;
            for(var i = 0; i < totalGroupBy; i++) {
                _patterns.AppendMenuItem(((!found && default_pattern_index < 0) ? MF_STRING : MF_GRAYED | MF_DISABLED), groupByMenuIdx + i, p.list.groupby[i].label);
            };
            if(!found && default_pattern_index < 0) {
                _patterns.CheckMenuRadioItem(groupByMenuIdx, groupByMenuIdx + totalGroupBy - 1, cGroup.pattern_idx + groupByMenuIdx);
            }; else {
                _patterns.CheckMenuRadioItem(groupByMenuIdx, groupByMenuIdx + totalGroupBy - 1, playlist_pattern_index + groupByMenuIdx);
            };
            
            _sorts.AppendTo(_groups, MF_STRING, "Apply Group Sorting");
            var sortByMenuIdx = 50;
            for(var i = 0; i < totalGroupBy; i++) {
                _sorts.AppendMenuItem((p.list.groupby[i].sortOrder != "null" && ((!found && default_pattern_index < 0) || playlist_pattern_index == i) ? MF_STRING : MF_GRAYED | MF_DISABLED), sortByMenuIdx + i, p.list.groupby[i].label);
            };
            _groups.AppendMenuSeparator();
            _groups.AppendMenuItem(p.list.totalRows > 0 && !properties.autocollapse && cGroup.expanded_height > 0 && cGroup.collapsed_height > 0 ? MF_STRING  : MF_GRAYED | MF_DISABLED, 80, "Collapse All");
            _groups.AppendMenuItem(p.list.totalRows > 0 && !properties.autocollapse && cGroup.expanded_height > 0 && cGroup.collapsed_height > 0 ? MF_STRING  : MF_GRAYED | MF_DISABLED, 90, "Expand All");

        };
        
        // Columns submenu entries
        var columnMenuIdx = 100;
        _menu.AppendMenuSeparator();
        _menu.AppendMenuItem(MF_STRING, 12, "Edit columns...");
        _columns.AppendTo(_menu, MF_STRING, "Columns");
        _columns.AppendMenuItem(MF_STRING, 99, "Show Row Extra-Line Infos");
        _columns.CheckMenuItem(99, cList.enableExtraLine ? 1 : 0);
        _columns.AppendMenuSeparator();
        for(var i = 0; i < this.columns.length; i++) {
            if(i == column_index) {
                _columns.AppendMenuItem(MF_STRING, columnMenuIdx + i, "["+this.columns[i].label+"]");
            }; else {
                _columns.AppendMenuItem(MF_STRING, columnMenuIdx + i, this.columns[i].label);
            };
            _columns.CheckMenuItem(columnMenuIdx + i, this.columns[i].w > 0 ? 1 : 0);
        };
        

        idx = _menu.TrackPopupMenu(x, y);
        switch(true) {
            case (idx==10):
                p.list.showNowPlaying();
                break;
            case (idx==11):
                p.settings.currentPageId = 0;
                var arr = [];
                for(var i = 0; i < p.headerBar.columns.length; i++) {
                    arr.push(p.headerBar.columns[i].ref);
                };
                for(i = 0; i < p.settings.pages.length; i++) {
                    p.settings.pages[i].reSet();
                };
                p.settings.pages[1].elements[0].reSet(arr);
                cSettings.visible = true;
                break;
            case (idx==12):
                p.settings.currentPageId = 1;
                var arr = [];
                for(var i = 0; i < p.headerBar.columns.length; i++) {
                    arr.push(p.headerBar.columns[i].ref);
                };
                for(i = 0; i < p.settings.pages.length; i++) {
                    p.settings.pages[i].reSet();
                };
                p.settings.pages[1].elements[0].reSet(arr);
                p.settings.pages[1].elements[0].showSelected(column_index);
                cSettings.visible = true;
                break;
            case (idx==13):
                p.settings.currentPageId = 2;
                var arr = [];
                for(var i = 0; i < p.list.groupby.length; i++) {
                    arr.push(p.list.groupby[i].label);
                };
                for(i = 0; i < p.settings.pages.length; i++) {
                    p.settings.pages[i].reSet();
                };
                p.settings.pages[2].elements[0].reSet(arr);
                p.settings.pages[2].elements[0].showSelected(cGroup.pattern_idx);
                cSettings.visible = true;
                break;
            case (idx==18):
                if(properties.showgroupheaders) {
                    properties.showgroupheaders = false;
                }; else {
                    properties.showgroupheaders = true;
                };
                window.SetProperty("*GROUP: Show Group Headers", properties.showgroupheaders);

                if(cGroup.collapsed_height > 0) {
                    cGroup.collapsed_height = 0;
                    cGroup.expanded_height = 0;
                    // disable autocollapse when there is no group!
                    properties.autocollapse = false;
                    window.SetProperty("SYSTEM.Auto-Collapse", properties.autocollapse);
                }; else {
                    cGroup.collapsed_height = cGroup.default_collapsed_height;
                    cGroup.expanded_height = cGroup.default_expanded_height;
                };

                // refresh playlist
                p.list.updateHandleList(plman.ActivePlaylist, false);
                p.list.setItems(true);
                p.scrollbar.setCursor(p.list.totalRowVisible, p.list.totalRows, p.list.offset);
                p.playlistManager.refresh("", false, false, false);
                break;
            case (idx==19):
                properties.enablePlaylistFilter = !properties.enablePlaylistFilter;
                window.SetProperty("SYSTEM.Enable Playlist Filter", properties.enablePlaylistFilter);
                // refresh playlist
                p.list.updateHandleList(plman.ActivePlaylist, false);
                p.list.setItems(true);
                p.scrollbar.setCursor(p.list.totalRowVisible, p.list.totalRows, p.list.offset);
                p.playlistManager.refresh("", false, false, false);
                break;
            case (idx>=20 && idx <50):
                cGroup.pattern_idx = idx - groupByMenuIdx;
                window.SetProperty("SYSTEM.Groups.Pattern Index", cGroup.pattern_idx);
                // if a Playlist Filter is defined for the Active Playlist (current), DO NOT try to change current pattern!
                if(!found && default_pattern_index < 0) { // no filter found, we can apply selected pattern and sort the playlist
                    plman.SortByFormatV2(plman.ActivePlaylist, p.list.groupby[cGroup.pattern_idx].sortOrder, 1);
                    p.list.updateHandleList(plman.ActivePlaylist, false);
                    p.list.setItems(true);
                    p.scrollbar.setCursor(p.list.totalRowVisible, p.list.totalRows, p.list.offset);
                    full_repaint();
                };
                break;
            case (idx>=50 && idx <80):
                if((!found && default_pattern_index < 0) || playlist_pattern_index == idx - sortByMenuIdx) { 
                    plman.SortByFormatV2(plman.ActivePlaylist, p.list.groupby[idx - sortByMenuIdx].sortOrder, 1);
                };
                break;
            case (idx==80):
                resize_panels();
                p.list.updateHandleList(plman.ActivePlaylist, true);
                p.list.setItems(true);
                p.scrollbar.setCursor(p.list.totalRowVisible, p.list.totalRows, p.list.offset);
                break;
            case (idx==90):
                resize_panels();
                p.list.updateHandleList(plman.ActivePlaylist, false);
                p.list.setItems(true);
                p.scrollbar.setCursor(p.list.totalRowVisible, p.list.totalRows, p.list.offset);
                break;
            case (idx==99):
                cList.enableExtraLine = !cList.enableExtraLine;
                window.SetProperty("SYSTEM.Enable Extra Line", cList.enableExtraLine);
                resize_panels();
                p.list.updateHandleList(plman.ActivePlaylist, false);
                p.list.setItems(true);
                p.scrollbar.setCursor(p.list.totalRowVisible, p.list.totalRows, p.list.offset);
                break;
            case (idx>=100 && idx<=200):
                // all size changes are in percent / ww
                if(this.columns[idx-100].percent == 0) {
                    var newColumnSize = 8000;
                    this.columns[idx-100].percent = newColumnSize;
                    var totalColsToResizeDown = 0;
                    var last_idx = 0;
                    for(var k = 0; k < this.columns.length; k++) {
                        if(k != idx - 100 && this.columns[k].percent > newColumnSize) {
                            totalColsToResizeDown++;
                            last_idx = k;
                        };
                    };
                    var minus_value = Math.floor(newColumnSize / totalColsToResizeDown);
                    var reste = newColumnSize - (minus_value * totalColsToResizeDown);
                    for(var k = 0; k < this.columns.length; k++) {
                        if(k != idx - 100 && this.columns[k].percent > newColumnSize) {
                            this.columns[k].percent = Math.abs(this.columns[k].percent) - minus_value;
                            if(reste > 0 && k == last_idx) {
                                this.columns[k].percent = Math.abs(this.columns[k].percent) - reste;
                            };
                        };
                        this.columns[k].w = Math.abs(this.w * this.columns[k].percent / 100000);
                    };
                    this.saveColumns();
                }; else {
                    // check if it's not the last column visible, otherwise, we coundn't hide it!
                    var nbvis = 0;
                    for(var k = 0; k < this.columns.length; k++) {
                        if(this.columns[k].percent > 0) {
                            nbvis++;
                        };
                    };
                    if(nbvis > 1) {
                        var RemovedColumnSize = Math.abs(this.columns[idx-100].percent);
                        this.columns[idx-100].percent = 0;
                        var totalColsToResizeUp = 0;
                        var last_idx = 0;
                        for(var k = 0; k < this.columns.length; k++) {
                            if(k != idx - 100 && this.columns[k].percent > 0) {
                                totalColsToResizeUp++;
                                last_idx = k;
                            };
                        };
                        var add_value = Math.floor(RemovedColumnSize / totalColsToResizeUp);
                        var reste = RemovedColumnSize - (add_value * totalColsToResizeUp);
                        for(var k=0; k < this.columns.length; k++) {
                            if(k != idx - 100 && this.columns[k].percent > 0) {
                                this.columns[k].percent = Math.abs(this.columns[k].percent) + add_value;
                                if(reste > 0 && k == last_idx) {
                                    this.columns[k].percent = Math.abs(this.columns[k].percent) + reste;
                                };
                            };
                            this.columns[k].w = Math.abs(this.w * this.columns[k].percent / 100000);
                        };
                        this.saveColumns();
                    };
                };
                this.initColumns();

                // set minimum rows / cover column size
                if(this.columns[0].w > 0) {
                    cover.column = true;
                    cGroup.count_minimum = Math.ceil( (this.columns[0].w) / cTrack.height);
                    if(cGroup.count_minimum < cGroup.default_count_minimum) cGroup.count_minimum = cGroup.default_count_minimum;

                    cover.previous_max_size = this.columns[0].w;
                    g_image_cache = new image_cache;
                    CollectGarbage();
                }; else {
                    cover.column = false;
                    cGroup.count_minimum = cGroup.default_count_minimum;
                };
                update_playlist(properties.collapseGroupsByDefault);
                break;
        };
        _menu.Dispose();
        this.columnRightClicked = -1;
        full_repaint();
        return true;
    };
};