// *****************************************************************************************************************************************
// SETTINGS functions by Br3tt aka Falstaff (c)2015
// *****************************************************************************************************************************************

// =================================================================== // Objects linked functions
function settings_checkboxes_action(id, status, parentId) {
	var fin;
	switch (parentId) {
	case 0: // page 0 : General
		switch (id) {
		case 0:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("SYSTEM.TopBar.Visible", status);
			resize_panels();
			full_repaint();
			break;
		case 1:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("SYSTEM.HeaderBar.Locked", status);
			if (!cHeaderBar.locked) {
				p.headerBar.visible = false;
			};
			resize_panels();
			full_repaint();
			break;
		case 2:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("SYSTEM.PlaylistManager.Visible", status);
			resize_panels();
			full_repaint();
			break;
		case 3:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("CUSTOM Show Scrollbar", status);
			resize_panels();
			full_repaint();
			break;
		case 4:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("SYSTEM.Media Library Playlist", status);
			if (status) {
				checkMediaLibrayPlaylist();
			} else {
				if (plman.GetPlaylistName(0) == "Media Library") {
					plman.RemovePlaylist(0);
				};
			};
			break;
		case 5:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("CUSTOM Historic Playlist enabled", status);
			if (status) {
				addToHistoricPlaylist(null);
			} else {
				var total = plman.PlaylistCount;
				for (var i = 0; i < total; i++) {
					if (plman.GetPlaylistName(i) == "Historic") {
						plman.RemovePlaylist(i);
						break;
					};
				};
			};
		case 6:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("CUSTOM.Enable Statistics (write to file)", status);
			break;
		case 7:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("CUSTOM Enable Smooth Scrolling", status);
			break;
		case 8:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("SYSTEM.Enable Touch Scrolling", status);
			break;
		};
		break;
	case 1: // page 1 : Columns
		switch (id) {
		case 0:
			var idx = p.settings.pages[1].elements[0].selectedId;
			// all size changes are in percent / ww
			if (p.headerBar.columns[idx].percent == 0) {
				p.settings.pages[1].elements[8].status = true;
				var newColumnSize = 8000;
				p.headerBar.columns[idx].percent = newColumnSize;
				var totalColsToResizeDown = 0;
				var last_idx = 0;
				fin = p.headerBar.columns.length;
				for (var k = 0; k < fin; k++) {
					if (k != idx && p.headerBar.columns[k].percent > newColumnSize) {
						totalColsToResizeDown++;
						last_idx = k;
					};
				};
				var minus_value = Math.floor(newColumnSize / totalColsToResizeDown);
				var reste = newColumnSize - (minus_value * totalColsToResizeDown);
				fin = p.headerBar.columns.length;
				for (var k = 0; k < fin; k++) {
					if (k != idx && p.headerBar.columns[k].percent > newColumnSize) {
						p.headerBar.columns[k].percent = Math.abs(p.headerBar.columns[k].percent) - minus_value;
						if (reste > 0 && k == last_idx) {
							p.headerBar.columns[k].percent = Math.abs(p.headerBar.columns[k].percent) - reste;
						};
					};
					p.headerBar.columns[k].w = Math.abs(p.headerBar.w * p.headerBar.columns[k].percent / 100000);
				};
				p.headerBar.saveColumns();
			} else {
				// check if it's not the last column visible, otherwise, we coundn't hide it!
				var nbvis = 0;
				fin = p.headerBar.columns.length;
				for (var k = 0; k < fin; k++) {
					if (p.headerBar.columns[k].percent > 0) {
						nbvis++;
					};
				};
				if (nbvis > 1) {
					p.settings.pages[1].elements[8].status = false;
					var RemovedColumnSize = Math.abs(p.headerBar.columns[idx].percent);
					p.headerBar.columns[idx].percent = 0;
					var totalColsToResizeUp = 0;
					var last_idx = 0;
					fin = p.headerBar.columns.length;
					for (var k = 0; k < fin; k++) {
						if (k != idx && p.headerBar.columns[k].percent > 0) {
							totalColsToResizeUp++;
							last_idx = k;
						};
					};
					var add_value = Math.floor(RemovedColumnSize / totalColsToResizeUp);
					var reste = RemovedColumnSize - (add_value * totalColsToResizeUp);
					fin = p.headerBar.columns.length;
					for (var k = 0; k < fin; k++) {
						if (k != idx && p.headerBar.columns[k].percent > 0) {
							p.headerBar.columns[k].percent = Math.abs(p.headerBar.columns[k].percent) + add_value;
							if (reste > 0 && k == last_idx) {
								p.headerBar.columns[k].percent = Math.abs(p.headerBar.columns[k].percent) + reste;
							};
						};
						p.headerBar.columns[k].w = Math.abs(p.headerBar.w * p.headerBar.columns[k].percent / 100000);
					};
					p.headerBar.saveColumns();
				};
			};
			p.headerBar.initColumns();

			// set minimum rows / cover column size
			if (p.headerBar.columns[idx].ref == "Cover") { // cover column added or removed
				if (p.headerBar.columns[idx].w > 0) {
					cover.column = true;
					cGroup.count_minimum = Math.ceil((p.headerBar.columns[idx].w) / cTrack.height);
					if (cGroup.count_minimum < cGroup.default_count_minimum)
						cGroup.count_minimum = cGroup.default_count_minimum;
				} else {
					cover.column = false;
					cGroup.count_minimum = cGroup.default_count_minimum;
				};
				cover.previous_max_size = p.headerBar.columns[idx].w;
				g_image_cache = new image_cache;
				CollectGarbage();
				update_playlist(properties.collapseGroupsByDefault);
			} else {
				full_repaint();
			};
			break;
		};
		break;
	case 2: // page 2 : Groups
		switch (id) {
		case 16:
			if (status) {
				p.list.groupby[p.settings.pages[parentId].elements[0].selectedId].showCover = "1";
			} else {
				p.list.groupby[p.settings.pages[parentId].elements[0].selectedId].showCover = "0";
			};
			p.list.saveGroupBy();
			break;
		case 17:
			if (status) {
				p.list.groupby[p.settings.pages[parentId].elements[0].selectedId].autoCollapse = "1";
			} else {
				p.list.groupby[p.settings.pages[parentId].elements[0].selectedId].autoCollapse = "0";
			};
			p.list.saveGroupBy();
			break;
		};
		break;
	case 3: // page 3 : Appearance
		switch (id) {
		case 0:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("CUSTOM Show Wallpaper", status);
			// refresh wallpaper
			if (fb.IsPlaying) {
				p.wallpaperImg = setWallpaperImg(properties.wallpaperpath, fb.GetNowPlaying());
			} else {
				p.wallpaperImg = null;
			};
			break;
		case 4:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("CUSTOM Wallpaper Blurred", status);
			// refresh wallpaper
			if (fb.IsPlaying) {
				p.wallpaperImg = setWallpaperImg(properties.wallpaperpath, fb.GetNowPlaying());
			} else {
				p.wallpaperImg = null;
			};
			break;
		case 11:
			eval(p.settings.pages[parentId].elements[id].linkedVariable + " = " + status);
			window.SetProperty("SYSTEM.Enable Custom Colors", status);
			p.settings.refreshColors();
			p.list.setItemColors();
			p.playlistManager.setColors();
			break;
		};
		break;
	};
};

function settings_radioboxes_action(id, status, parentId) {
	var pid = parentId;
	switch (pid) {
	case 0:
		switch (id) {
		case 9:
			p.settings.pages[pid].elements[9].status = true;
			p.settings.pages[pid].elements[10].status = false;
			properties.defaultPlaylistItemAction = "Play";
			window.SetProperty("SYSTEM.Default Playlist Action", properties.defaultPlaylistItemAction);
			break;
		case 10:
			p.settings.pages[pid].elements[9].status = false;
			p.settings.pages[pid].elements[10].status = true;
			properties.defaultPlaylistItemAction = "Add to playback queue";
			window.SetProperty("SYSTEM.Default Playlist Action", properties.defaultPlaylistItemAction);
			break;
		};
		full_repaint();
		break;
	case 1:
		var selectedColumnId = p.settings.pages[1].elements[0].selectedId;
		switch (id) {
		case 5:
			p.settings.pages[pid].elements[5].status = true;
			p.settings.pages[pid].elements[6].status = false;
			p.settings.pages[pid].elements[7].status = false;
			p.headerBar.columns[selectedColumnId].align = 0;
			p.headerBar.saveColumns();
			break;
		case 6:
			p.settings.pages[pid].elements[5].status = false;
			p.settings.pages[pid].elements[6].status = true;
			p.settings.pages[pid].elements[7].status = false;
			p.headerBar.columns[selectedColumnId].align = 1;
			p.headerBar.saveColumns();
			break;
		case 7:
			p.settings.pages[pid].elements[5].status = false;
			p.settings.pages[pid].elements[6].status = false;
			p.settings.pages[pid].elements[7].status = true;
			p.headerBar.columns[selectedColumnId].align = 2;
			p.headerBar.saveColumns();
			break;
		};
		full_repaint();
		break;
	case 2:
		var selectedPatternId = p.settings.pages[2].elements[0].selectedId;
		switch (id) {
			// collapsed height
		case 6:
			p.settings.pages[pid].elements[6].status = true;
			p.settings.pages[pid].elements[7].status = false;
			p.settings.pages[pid].elements[8].status = false;
			p.settings.pages[pid].elements[9].status = false;
			p.settings.pages[pid].elements[10].status = false;
			if (!p.settings.pages[pid].elements[11].status) {
				p.settings.pages[pid].elements[11].status = true;
				p.settings.pages[pid].elements[12].status = false;
				p.settings.pages[pid].elements[13].status = false;
				p.settings.pages[pid].elements[14].status = false;
				p.settings.pages[pid].elements[15].status = false;
				p.list.groupby[selectedPatternId].expandedHeight = 0;
			};
			p.list.groupby[selectedPatternId].collapsedHeight = 0;
			p.list.saveGroupBy();
			break;
		case 7:
			p.settings.pages[pid].elements[6].status = false;
			p.settings.pages[pid].elements[7].status = true;
			p.settings.pages[pid].elements[8].status = false;
			p.settings.pages[pid].elements[9].status = false;
			p.settings.pages[pid].elements[10].status = false;
			if (p.settings.pages[pid].elements[11].status) {
				p.settings.pages[pid].elements[11].status = false;
				p.settings.pages[pid].elements[12].status = true;
				p.settings.pages[pid].elements[13].status = false;
				p.settings.pages[pid].elements[14].status = false;
				p.settings.pages[pid].elements[15].status = false;
				p.list.groupby[selectedPatternId].expandedHeight = 1;
			};
			p.list.groupby[selectedPatternId].collapsedHeight = 1;
			p.list.saveGroupBy();
			break;
		case 8:
			p.settings.pages[pid].elements[6].status = false;
			p.settings.pages[pid].elements[7].status = false;
			p.settings.pages[pid].elements[8].status = true;
			p.settings.pages[pid].elements[9].status = false;
			p.settings.pages[pid].elements[10].status = false;
			if (p.settings.pages[pid].elements[11].status) {
				p.settings.pages[pid].elements[11].status = false;
				p.settings.pages[pid].elements[12].status = false;
				p.settings.pages[pid].elements[13].status = true;
				p.settings.pages[pid].elements[14].status = false;
				p.settings.pages[pid].elements[15].status = false;
				p.list.groupby[selectedPatternId].expandedHeight = 2;
			};
			p.list.groupby[selectedPatternId].collapsedHeight = 2;
			p.list.saveGroupBy();
			break;
		case 9:
			p.settings.pages[pid].elements[6].status = false;
			p.settings.pages[pid].elements[7].status = false;
			p.settings.pages[pid].elements[8].status = false;
			p.settings.pages[pid].elements[9].status = true;
			p.settings.pages[pid].elements[10].status = false;
			if (p.settings.pages[pid].elements[11].status) {
				p.settings.pages[pid].elements[11].status = false;
				p.settings.pages[pid].elements[12].status = false;
				p.settings.pages[pid].elements[13].status = false;
				p.settings.pages[pid].elements[14].status = true;
				p.settings.pages[pid].elements[15].status = false;
				p.list.groupby[selectedPatternId].expandedHeight = 3;
			};
			p.list.groupby[selectedPatternId].collapsedHeight = 3;
			p.list.saveGroupBy();
			break;
		case 10:
			p.settings.pages[pid].elements[6].status = false;
			p.settings.pages[pid].elements[7].status = false;
			p.settings.pages[pid].elements[8].status = false;
			p.settings.pages[pid].elements[9].status = false;
			p.settings.pages[pid].elements[10].status = true;
			if (p.settings.pages[pid].elements[11].status) {
				p.settings.pages[pid].elements[11].status = false;
				p.settings.pages[pid].elements[12].status = false;
				p.settings.pages[pid].elements[13].status = false;
				p.settings.pages[pid].elements[14].status = false;
				p.settings.pages[pid].elements[15].status = true;
				p.list.groupby[selectedPatternId].expandedHeight = 4;
			};
			p.list.groupby[selectedPatternId].collapsedHeight = 4;
			p.list.saveGroupBy();
			break;
			// expanded height
		case 11:
			p.settings.pages[pid].elements[11].status = true;
			p.settings.pages[pid].elements[12].status = false;
			p.settings.pages[pid].elements[13].status = false;
			p.settings.pages[pid].elements[14].status = false;
			p.settings.pages[pid].elements[15].status = false;
			if (!p.settings.pages[pid].elements[6].status) {
				p.settings.pages[pid].elements[6].status = true;
				p.settings.pages[pid].elements[7].status = false;
				p.settings.pages[pid].elements[8].status = false;
				p.settings.pages[pid].elements[9].status = false;
				p.settings.pages[pid].elements[10].status = false;
				p.list.groupby[selectedPatternId].collapsedHeight = 0;
			};
			p.list.groupby[selectedPatternId].expandedHeight = 0;
			p.list.saveGroupBy();
			break;
		case 12:
			p.settings.pages[pid].elements[11].status = false;
			p.settings.pages[pid].elements[12].status = true;
			p.settings.pages[pid].elements[13].status = false;
			p.settings.pages[pid].elements[14].status = false;
			p.settings.pages[pid].elements[15].status = false;
			if (p.settings.pages[pid].elements[6].status) {
				p.settings.pages[pid].elements[6].status = false;
				p.settings.pages[pid].elements[7].status = true;
				p.settings.pages[pid].elements[8].status = false;
				p.settings.pages[pid].elements[9].status = false;
				p.settings.pages[pid].elements[10].status = false;
				p.list.groupby[selectedPatternId].collapsedHeight = 1;
			};
			p.list.groupby[selectedPatternId].expandedHeight = 1;
			p.list.saveGroupBy();
			break;
		case 13:
			p.settings.pages[pid].elements[11].status = false;
			p.settings.pages[pid].elements[12].status = false;
			p.settings.pages[pid].elements[13].status = true;
			p.settings.pages[pid].elements[14].status = false;
			p.settings.pages[pid].elements[15].status = false;
			if (p.settings.pages[pid].elements[6].status) {
				p.settings.pages[pid].elements[6].status = false;
				p.settings.pages[pid].elements[7].status = false;
				p.settings.pages[pid].elements[8].status = true;
				p.settings.pages[pid].elements[9].status = false;
				p.settings.pages[pid].elements[10].status = false;
				p.list.groupby[selectedPatternId].collapsedHeight = 2;
			};
			p.list.groupby[selectedPatternId].expandedHeight = 2;
			p.list.saveGroupBy();
			break;
		case 14:
			p.settings.pages[pid].elements[11].status = false;
			p.settings.pages[pid].elements[12].status = false;
			p.settings.pages[pid].elements[13].status = false;
			p.settings.pages[pid].elements[14].status = true;
			p.settings.pages[pid].elements[15].status = false;
			if (p.settings.pages[pid].elements[6].status) {
				p.settings.pages[pid].elements[6].status = false;
				p.settings.pages[pid].elements[7].status = false;
				p.settings.pages[pid].elements[8].status = false;
				p.settings.pages[pid].elements[9].status = true;
				p.settings.pages[pid].elements[10].status = false;
				p.list.groupby[selectedPatternId].collapsedHeight = 3;
			};
			p.list.groupby[selectedPatternId].expandedHeight = 3;
			p.list.saveGroupBy();
			break;
		case 15:
			p.settings.pages[pid].elements[11].status = false;
			p.settings.pages[pid].elements[12].status = false;
			p.settings.pages[pid].elements[13].status = false;
			p.settings.pages[pid].elements[14].status = false;
			p.settings.pages[pid].elements[15].status = true;
			if (p.settings.pages[pid].elements[6].status) {
				p.settings.pages[pid].elements[6].status = false;
				p.settings.pages[pid].elements[7].status = false;
				p.settings.pages[pid].elements[8].status = false;
				p.settings.pages[pid].elements[9].status = false;
				p.settings.pages[pid].elements[10].status = true;
				p.list.groupby[selectedPatternId].collapsedHeight = 4;
			};
			p.list.groupby[selectedPatternId].expandedHeight = 4;
			p.list.saveGroupBy();
			break;
		case 22:
			p.settings.pages[pid].elements[22].status = true;
			p.settings.pages[pid].elements[23].status = false;
			p.list.groupby[selectedPatternId].collapseGroupsByDefault = "1";
			p.list.saveGroupBy();
			break;
		case 23:
			p.settings.pages[pid].elements[22].status = false;
			p.settings.pages[pid].elements[23].status = true;
			p.list.groupby[selectedPatternId].collapseGroupsByDefault = "0";
			p.list.saveGroupBy();
			break;
		};
		full_repaint();
		break;
	case 3:
		switch (id) {
			// wpp image
		case 1:
			p.settings.pages[pid].elements[1].status = true;
			p.settings.pages[pid].elements[2].status = false;
			p.settings.pages[pid].elements[3].status = false;
			properties.wallpapermode = 0;
			window.SetProperty("CUSTOM Wallpaper Type", properties.wallpapermode);
			break;
		case 2:
			p.settings.pages[pid].elements[1].status = false;
			p.settings.pages[pid].elements[2].status = true;
			p.settings.pages[pid].elements[3].status = false;
			properties.wallpapermode = 4;
			window.SetProperty("CUSTOM Wallpaper Type", properties.wallpapermode);
			break;
		case 3:
			p.settings.pages[pid].elements[1].status = false;
			p.settings.pages[pid].elements[2].status = false;
			p.settings.pages[pid].elements[3].status = true;
			properties.wallpapermode = -1;
			window.SetProperty("CUSTOM Wallpaper Type", properties.wallpapermode);
			break;
			// wpp alpha shading
		case 5:
			p.settings.pages[pid].elements[5].status = true;
			p.settings.pages[pid].elements[6].status = false;
			p.settings.pages[pid].elements[7].status = false;
			p.settings.pages[pid].elements[8].status = false;
			p.settings.pages[pid].elements[9].status = false;
			properties.wallpaperalpha = 125;
			window.SetProperty("CUSTOM Wallpaper Alpha", properties.wallpaperalpha);
			break;
		case 6:
			p.settings.pages[pid].elements[5].status = false;
			p.settings.pages[pid].elements[6].status = true;
			p.settings.pages[pid].elements[7].status = false;
			p.settings.pages[pid].elements[8].status = false;
			p.settings.pages[pid].elements[9].status = false;
			properties.wallpaperalpha = 150;
			window.SetProperty("CUSTOM Wallpaper Alpha", properties.wallpaperalpha);
			break;
		case 7:
			p.settings.pages[pid].elements[5].status = false;
			p.settings.pages[pid].elements[6].status = false;
			p.settings.pages[pid].elements[7].status = true;
			p.settings.pages[pid].elements[8].status = false;
			p.settings.pages[pid].elements[9].status = false;
			properties.wallpaperalpha = 175;
			window.SetProperty("CUSTOM Wallpaper Alpha", properties.wallpaperalpha);
			break;
		case 8:
			p.settings.pages[pid].elements[5].status = false;
			p.settings.pages[pid].elements[6].status = false;
			p.settings.pages[pid].elements[7].status = false;
			p.settings.pages[pid].elements[8].status = true;
			p.settings.pages[pid].elements[9].status = false;
			properties.wallpaperalpha = 200;
			window.SetProperty("CUSTOM Wallpaper Alpha", properties.wallpaperalpha);
			break;
		case 9:
			p.settings.pages[pid].elements[5].status = false;
			p.settings.pages[pid].elements[6].status = false;
			p.settings.pages[pid].elements[7].status = false;
			p.settings.pages[pid].elements[8].status = false;
			p.settings.pages[pid].elements[9].status = true;
			properties.wallpaperalpha = 225;
			window.SetProperty("CUSTOM Wallpaper Alpha", properties.wallpaperalpha);
			break;
		};
		// set wallpaper
		if (fb.IsPlaying) {
			p.wallpaperImg = setWallpaperImg(properties.wallpaperpath, fb.GetNowPlaying());
		} else {
			p.wallpaperImg = null;
		};
		full_repaint();
		break;
	};
};

function settings_listboxes_action(pageId, id, selectedId) {
	switch (pageId) {
	case 1:
		switch (id) {
		case 0:
			try {
				// if textbox was active (edit = true) before new click on the listbox entry, save the new input before updating the textboxes
				p.settings.pages[1].elements[1].inputbox.check("down", 0, 0);
				p.settings.pages[1].elements[2].inputbox.check("down", 0, 0);
				p.settings.pages[1].elements[3].inputbox.check("down", 0, 0);
				p.settings.pages[1].elements[4].inputbox.check("down", 0, 0);
				// update textboxes values / selected column Id in the listbox
				p.settings.pages[1].elements[0].selectedId = selectedId;
				var txtbox_value = p.headerBar.columns[selectedId].label;
				p.settings.pages[1].elements[1].inputbox.text = txtbox_value;
				p.settings.pages[1].elements[1].inputbox.default_text = txtbox_value;
				txtbox_value = p.headerBar.columns[selectedId].tf;
				p.settings.pages[1].elements[2].inputbox.text = txtbox_value;
				p.settings.pages[1].elements[2].inputbox.default_text = txtbox_value;
				txtbox_value = p.headerBar.columns[selectedId].tf2;
				p.settings.pages[1].elements[3].inputbox.text = txtbox_value;
				p.settings.pages[1].elements[3].inputbox.default_text = txtbox_value;
				txtbox_value = p.headerBar.columns[selectedId].sortOrder;
				p.settings.pages[1].elements[4].inputbox.text = txtbox_value;
				p.settings.pages[1].elements[4].inputbox.default_text = txtbox_value;
				// update radio buttons values / selected column Id in the listbox
				switch (p.headerBar.columns[selectedId].align) {
				case 0: // Left align
					p.settings.pages[1].elements[5].status = true;
					p.settings.pages[1].elements[6].status = false;
					p.settings.pages[1].elements[7].status = false;
					break;
				case 1: // Center align
					p.settings.pages[1].elements[5].status = false;
					p.settings.pages[1].elements[6].status = true;
					p.settings.pages[1].elements[7].status = false;
					break;
				case 2: // Right align
					p.settings.pages[1].elements[5].status = false;
					p.settings.pages[1].elements[6].status = false;
					p.settings.pages[1].elements[7].status = true;
					break;
				};
				// update checkbox status / selected column Id in the listbox
				p.settings.pages[1].elements[0].status = (p.headerBar.columns[selectedId].percent > 0);
			} catch (e) {
				fb.trace("WSH Error catched: settings_listboxes_action");
			};
			full_repaint();
			break;
		};
		break;
	case 2:
		var txtbox_value = "";
		switch (id) {
		case 0:
			try {
				// if textbox was active (edit = true) before new click on the listbox entry, save the new input before updating the textboxes
				p.settings.pages[2].elements[1].inputbox.check("down", 0, 0);
				p.settings.pages[2].elements[2].inputbox.check("down", 0, 0);
				p.settings.pages[2].elements[3].inputbox.check("down", 0, 0);
				p.settings.pages[2].elements[4].inputbox.check("down", 0, 0);
				p.settings.pages[2].elements[5].inputbox.check("down", 0, 0);
				p.settings.pages[2].elements[18].inputbox.check("down", 0, 0);
				p.settings.pages[2].elements[19].inputbox.check("down", 0, 0);
				p.settings.pages[2].elements[20].inputbox.check("down", 0, 0);
				p.settings.pages[2].elements[21].inputbox.check("down", 0, 0);
				// update textboxes values / selected column Id in the listbox
				p.settings.pages[2].elements[0].selectedId = selectedId;
				//
				txtbox_value = p.list.groupby[selectedId].label;
				p.settings.pages[2].elements[1].inputbox.text = txtbox_value;
				p.settings.pages[2].elements[1].inputbox.default_text = txtbox_value;
				txtbox_value = p.list.groupby[selectedId].tf;
				p.settings.pages[2].elements[2].inputbox.text = txtbox_value;
				p.settings.pages[2].elements[2].inputbox.default_text = txtbox_value;
				txtbox_value = p.list.groupby[selectedId].sortOrder;
				p.settings.pages[2].elements[3].inputbox.text = txtbox_value;
				p.settings.pages[2].elements[3].inputbox.default_text = txtbox_value;

				txtbox_value = p.list.groupby[selectedId].playlistFilter;
				p.settings.pages[2].elements[4].inputbox.text = txtbox_value;
				p.settings.pages[2].elements[4].inputbox.default_text = txtbox_value;
				txtbox_value = p.list.groupby[selectedId].extraRows;
				p.settings.pages[2].elements[5].inputbox.text = txtbox_value;
				p.settings.pages[2].elements[5].inputbox.default_text = txtbox_value;

				txtbox_value = p.list.groupby[selectedId].l1;
				p.settings.pages[2].elements[18].inputbox.text = txtbox_value;
				p.settings.pages[2].elements[18].inputbox.default_text = txtbox_value;
				txtbox_value = p.list.groupby[selectedId].r1;
				p.settings.pages[2].elements[19].inputbox.text = txtbox_value;
				p.settings.pages[2].elements[19].inputbox.default_text = txtbox_value;
				txtbox_value = p.list.groupby[selectedId].l2;
				p.settings.pages[2].elements[20].inputbox.text = txtbox_value;
				p.settings.pages[2].elements[20].inputbox.default_text = txtbox_value;
				txtbox_value = p.list.groupby[selectedId].r2;
				p.settings.pages[2].elements[21].inputbox.text = txtbox_value;
				p.settings.pages[2].elements[21].inputbox.default_text = txtbox_value;

				// update radio buttons values / selected column Id in the listbox
				switch (Math.floor(p.list.groupby[selectedId].collapsedHeight)) {
					// collapsed height
				case 0:
					p.settings.pages[2].elements[6].status = true;
					p.settings.pages[2].elements[7].status = false;
					p.settings.pages[2].elements[8].status = false;
					p.settings.pages[2].elements[9].status = false;
					p.settings.pages[2].elements[10].status = false;
					break;
				case 1:
					p.settings.pages[2].elements[6].status = false;
					p.settings.pages[2].elements[7].status = true;
					p.settings.pages[2].elements[8].status = false;
					p.settings.pages[2].elements[9].status = false;
					p.settings.pages[2].elements[10].status = false;
					break;
				case 2:
					p.settings.pages[2].elements[6].status = false;
					p.settings.pages[2].elements[7].status = false;
					p.settings.pages[2].elements[8].status = true;
					p.settings.pages[2].elements[9].status = false;
					p.settings.pages[2].elements[10].status = false;
					break;
				case 3:
					p.settings.pages[2].elements[6].status = false;
					p.settings.pages[2].elements[7].status = false;
					p.settings.pages[2].elements[8].status = false;
					p.settings.pages[2].elements[9].status = true;
					p.settings.pages[2].elements[10].status = false;
					break;
				case 4:
					p.settings.pages[2].elements[6].status = false;
					p.settings.pages[2].elements[7].status = false;
					p.settings.pages[2].elements[8].status = false;
					p.settings.pages[2].elements[9].status = false;
					p.settings.pages[2].elements[10].status = true;
					break;
				};
				switch (Math.floor(p.list.groupby[selectedId].expandedHeight)) {
					// expanded height
				case 0:
					p.settings.pages[2].elements[11].status = true;
					p.settings.pages[2].elements[12].status = false;
					p.settings.pages[2].elements[13].status = false;
					p.settings.pages[2].elements[14].status = false;
					p.settings.pages[2].elements[15].status = false;
					break;
				case 1:
					p.settings.pages[2].elements[11].status = false;
					p.settings.pages[2].elements[12].status = true;
					p.settings.pages[2].elements[13].status = false;
					p.settings.pages[2].elements[14].status = false;
					p.settings.pages[2].elements[15].status = false;
					break;
				case 2:
					p.settings.pages[2].elements[11].status = false;
					p.settings.pages[2].elements[12].status = false;
					p.settings.pages[2].elements[13].status = true;
					p.settings.pages[2].elements[14].status = false;
					p.settings.pages[2].elements[15].status = false;
					break;
				case 3:
					p.settings.pages[2].elements[11].status = false;
					p.settings.pages[2].elements[12].status = false;
					p.settings.pages[2].elements[13].status = false;
					p.settings.pages[2].elements[14].status = true;
					p.settings.pages[2].elements[15].status = false;
					break;
				case 4:
					p.settings.pages[2].elements[11].status = false;
					p.settings.pages[2].elements[12].status = false;
					p.settings.pages[2].elements[13].status = false;
					p.settings.pages[2].elements[14].status = false;
					p.settings.pages[2].elements[15].status = true;
					break;
				};
				switch (Math.floor(p.list.groupby[selectedId].collapseGroupsByDefault)) {
					// default group status
				case 0:
					p.settings.pages[2].elements[22].status = false;
					p.settings.pages[2].elements[23].status = true;
					break;
				case 1:
					p.settings.pages[2].elements[22].status = true;
					p.settings.pages[2].elements[23].status = false;
					break;
				};

			} catch (e) {
				fb.trace("WSH Error catched: settings_listboxes_action");
			};
			full_repaint();
			break;
		};
		break;
	};
};

function settings_textboxes_action(pageId, elementId) {
	switch (pageId) {
	case 1: // Columns
		var selectedColumnId = p.settings.pages[pageId].elements[0].selectedId;
		switch (elementId) {
		case 1:
			var label = p.headerBar.columns[selectedColumnId].label;
			var new_label = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_label == "")
				new_label = label;
			if (new_label) {
				p.headerBar.columns[selectedColumnId].label = new_label;
				p.headerBar.saveColumns();
				// update listbox array
				p.settings.pages[pageId].elements[0].arr.splice(0, p.settings.pages[pageId].elements[0].arr.length);
				var fin = p.headerBar.columns.length;
				for (var i = 0; i < fin; i++) {
					p.settings.pages[pageId].elements[0].arr.push(p.headerBar.columns[i].ref);
				};
				full_repaint();
			};
			break;
		case 2:
			var tf = p.headerBar.columns[selectedColumnId].tf;
			var new_tf = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_tf == "")
				new_tf = tf;
			if (new_tf) {
				p.headerBar.columns[selectedColumnId].tf = new_tf;
				p.headerBar.saveColumns();
			};
			break;
		case 3:
			var tf2 = p.headerBar.columns[selectedColumnId].tf2;
			var new_tf2 = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_tf2 == "")
				new_tf2 = tf2;
			if (new_tf2) {
				p.headerBar.columns[selectedColumnId].tf2 = new_tf2;
				p.headerBar.saveColumns();
			};
			break;
		case 4:
			var sortOrder = p.headerBar.columns[selectedColumnId].sortOrder;
			var new_sortOrder = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_sortOrder == "")
				new_sortOrder = sortOrder;
			if (new_sortOrder) {
				p.headerBar.columns[selectedColumnId].sortOrder = new_sortOrder;
				p.headerBar.saveColumns();
			};
			break;
		};
		break;
	case 2: // Groups
		var selectedColumnId = p.settings.pages[pageId].elements[0].selectedId;
		switch (elementId) {
		case 1:
			var label = p.list.groupby[selectedColumnId].label;
			var new_label = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_label == "")
				new_label = label;
			if (new_label) {
				p.list.groupby[selectedColumnId].label = new_label;
				p.list.saveGroupBy();
				// update listbox array
				p.settings.pages[pageId].elements[0].arr.splice(0, p.settings.pages[pageId].elements[0].arr.length);
				var fin = p.list.groupby.length;
				for (var i = 0; i < fin; i++) {
					p.settings.pages[pageId].elements[0].arr.push(p.list.groupby[i].label);
				};
				full_repaint();
			};
			break;
		case 2:
			var tf = p.list.groupby[selectedColumnId].tf;
			var new_tf = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_tf == "")
				new_tf = tf;
			if (new_tf) {
				p.list.groupby[selectedColumnId].tf = new_tf;
				p.list.saveGroupBy();
			};
			break;
		case 3:
			var sortOrder = p.list.groupby[selectedColumnId].sortOrder;
			var new_sortOrder = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_sortOrder == "")
				new_sortOrder = sortOrder;
			if (new_sortOrder) {
				p.list.groupby[selectedColumnId].sortOrder = new_sortOrder;
				p.list.saveGroupBy();
			};
			break;
		case 4:
			var playlistFilter = p.list.groupby[selectedColumnId].playlistFilter;
			var new_playlistFilter = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_playlistFilter == "")
				new_playlistFilter = playlistFilter;
			if (new_playlistFilter) {
				p.list.groupby[selectedColumnId].playlistFilter = new_playlistFilter;
				p.list.saveGroupBy();
			};
			break;
		case 5:
			var extraRows = p.list.groupby[selectedColumnId].extraRows;
			var new_extraRows = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_extraRows == "")
				new_extraRows = extraRows;
			if (new_extraRows) {
				p.list.groupby[selectedColumnId].extraRows = new_extraRows;
				p.list.saveGroupBy();
			};
			break;
		case 18:
			var l1 = p.list.groupby[selectedColumnId].l1;
			var new_l1 = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_l1 == "")
				new_l1 = l1;
			if (new_l1) {
				p.list.groupby[selectedColumnId].l1 = new_l1;
				p.list.saveGroupBy();
			};
			break;
		case 19:
			var r1 = p.list.groupby[selectedColumnId].r1;
			var new_r1 = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_r1 == "")
				new_r1 = r1;
			if (new_r1) {
				p.list.groupby[selectedColumnId].r1 = new_r1;
				p.list.saveGroupBy();
			};
			break;
		case 20:
			var l2 = p.list.groupby[selectedColumnId].l2;
			var new_l2 = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_l2 == "")
				new_l2 = l2;
			if (new_l2) {
				p.list.groupby[selectedColumnId].l2 = new_l2;
				p.list.saveGroupBy();
			};
			break;
		case 21:
			var r2 = p.list.groupby[selectedColumnId].r2;
			var new_r2 = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_r2 == "")
				new_r2 = r2;
			if (new_r2) {
				p.list.groupby[selectedColumnId].r2 = new_r2;
				p.list.saveGroupBy();
			};
			break;
		};
		break;
	case 3: // Appearance
		switch (elementId) {
		case 10:
			var label = properties.wallpaperpath;
			var new_label = p.settings.pages[pageId].elements[elementId].inputbox.text;
			if (new_label == "")
				new_label = label;
			if (new_label) {
				properties.wallpaperpath = new_label;
				window.SetProperty("CUSTOM Default Wallpaper Path", properties.wallpaperpath);
				// refresh wallpaper
				if (fb.IsPlaying) {
					p.wallpaperImg = setWallpaperImg(properties.wallpaperpath, fb.GetNowPlaying());
				} else {
					p.wallpaperImg = null;
				};
			};
			break;
		};
		break;
	};
};

// =================================================================== // Objects

oCheckBox = function (id, x, y, label, linkedVariable, func, parentPageId) {
	this.objType = "CB";
	this.id = id;
	this.x = x;
	this.y = y;
	this.parentPageId = parentPageId;
	this.ly = this.y - (p.settings.pages[this.parentPageId].offset * cSettings.rowHeight);
	this.label = label;
	this.linkedVariable = linkedVariable;
	this.status = eval(linkedVariable);
	this.prevStatus = this.status;
	var gfunc = func;

	this.setButtons = function () {
		// normal unchecked box
		this.checkbox_normal_off = gdi.CreateImage(zoom(16, 300), zoom(16, 300));
		var gb = this.checkbox_normal_off.GetGraphics();
		gb.SetSmoothingMode(2);
		gb.DrawEllipse(zoom(2, 300), zoom(2, 300), zoom(12, 300), zoom(12, 300), zoom(2.0, 300), p.settings.color1);
		this.checkbox_normal_off.ReleaseGraphics(gb);
		// hover unchecked box
		this.checkbox_hover_off = gdi.CreateImage(zoom(16, 300), zoom(16, 300));
		gb = this.checkbox_hover_off.GetGraphics();
		gb.SetSmoothingMode(2);
		gb.DrawEllipse(zoom(2, 300), zoom(2, 300), zoom(12, 300), zoom(12, 300), zoom(2.0, 300), p.settings.color2);
		this.checkbox_hover_off.ReleaseGraphics(gb);
		// normal checked box
		this.checkbox_normal_on = gdi.CreateImage(zoom(16, 300), zoom(16, 300));
		var gb = this.checkbox_normal_on.GetGraphics();
		gb.SetSmoothingMode(2);
		gb.DrawEllipse(zoom(2, 300), zoom(2, 300), zoom(12, 300), zoom(12, 300), zoom(2.0, 300), p.settings.color1);
		gb.FillEllipse(zoom(4, 300), zoom(4, 300), zoom(8, 300), zoom(8, 300), p.settings.color1);
		this.checkbox_normal_on.ReleaseGraphics(gb);
		// hover checked box
		this.checkbox_hover_on = gdi.CreateImage(zoom(16, 300), zoom(16, 300));
		gb = this.checkbox_hover_on.GetGraphics();
		gb.SetSmoothingMode(2);
		gb.DrawEllipse(zoom(2, 300), zoom(2, 300), zoom(12, 300), zoom(12, 300), zoom(2.0, 300), p.settings.color2);
		gb.FillEllipse(zoom(4, 300), zoom(4, 300), zoom(8, 300), zoom(8, 300), p.settings.color2);
		this.checkbox_hover_on.ReleaseGraphics(gb);

		var button_zoomSize = g_z16;
		// button
		if (this.status) {
			this.button = new button(this.checkbox_normal_on.Resize(button_zoomSize, button_zoomSize, 7), this.checkbox_hover_on.Resize(button_zoomSize, button_zoomSize, 7), this.checkbox_hover_on.Resize(button_zoomSize, button_zoomSize, 7));
		} else {
			this.button = new button(this.checkbox_normal_off.Resize(button_zoomSize, button_zoomSize, 7), this.checkbox_hover_off.Resize(button_zoomSize, button_zoomSize, 7), this.checkbox_hover_off.Resize(button_zoomSize, button_zoomSize, 7));
		};
	};
	this.setButtons();

	this.draw = function (gr) {
		this.status = eval(this.linkedVariable);
		if (this.status != this.prevStatus) {
			var button_zoomSize = g_z16;
			if (this.status) {
				this.button.update(this.checkbox_normal_on.Resize(button_zoomSize, button_zoomSize, 7), this.checkbox_hover_on.Resize(button_zoomSize, button_zoomSize, 7), this.checkbox_hover_on.Resize(button_zoomSize, button_zoomSize, 7));
			} else {
				this.button.update(this.checkbox_normal_off.Resize(button_zoomSize, button_zoomSize, 7), this.checkbox_hover_off.Resize(button_zoomSize, button_zoomSize, 7), this.checkbox_hover_off.Resize(button_zoomSize, button_zoomSize, 7));
			};
			this.prevStatus = this.status;
		};
		this.ly = this.y - (p.settings.pages[this.parentPageId].offset * cSettings.rowHeight);
		if (this.ly > cSettings.topBarHeight) {
			var button_y = this.ly - 1 + Math.ceil((p.settings.txtHeight + 10 - this.button.h) / 2);
			this.button.draw(gr, this.x, button_y, 255);
			var label_x = this.x + this.button.w + zoom(5, g_dpi);
			gr.gdiDrawText(this.label, gdi.Font(p.settings.fontname, p.settings.txtHeight, 1), (this.status ? p.settings.color2 : p.settings.color1), label_x, this.ly, p.settings.w, p.settings.txtHeight + 10, g_LDT);
		};
	};

	this.on_mouse = function (event, x, y, delta) {
		if (this.ly <= cSettings.topBarHeight) {
			return;
		};
		var state = this.button.checkstate(event, x, y);
		switch (event) {
		case "up":
			if (state == ButtonStates.hover) {
				this.status = !this.status;
				eval(gfunc + "(" + this.id + "," + this.status + "," + this.parentPageId + ")");
			};
			break;
		};
		return state;
	};

	this.on_key = function (event, vkey) {};

	this.on_char = function (code) {};

	this.on_focus = function (is_focused) {};
};

oRadioButton = function (id, x, y, label, linkedVariable, func, parentPageId) {
	this.objType = "RB";
	this.id = id;
	this.x = x;
	this.y = y;
	this.parentPageId = parentPageId;
	this.ly = this.y - (p.settings.pages[this.parentPageId].offset * cSettings.rowHeight);
	this.label = label;
	this.status = eval(linkedVariable);
	this.prevStatus = this.status;
	var gfunc = func;

	this.setButtons = function () {
		// normal unchecked box
		this.radiobt_normal_off = gdi.CreateImage(zoom(16, 300), zoom(16, 300));
		var gb = this.radiobt_normal_off.GetGraphics();
		gb.SetSmoothingMode(2);
		gb.DrawEllipse(zoom(2, 300), zoom(2, 300), zoom(12, 300), zoom(12, 300), zoom(2.0, 300), p.settings.color1);
		this.radiobt_normal_off.ReleaseGraphics(gb);
		// hover unchecked box
		this.radiobt_hover_off = gdi.CreateImage(zoom(16, 300), zoom(16, 300));
		gb = this.radiobt_hover_off.GetGraphics();
		gb.SetSmoothingMode(2);
		gb.DrawEllipse(zoom(2, 300), zoom(2, 300), zoom(12, 300), zoom(12, 300), zoom(2.0, 300), p.settings.color2);
		this.radiobt_hover_off.ReleaseGraphics(gb);
		// normal checked box
		this.radiobt_normal_on = gdi.CreateImage(zoom(16, 300), zoom(16, 300));
		var gb = this.radiobt_normal_on.GetGraphics();
		gb.SetSmoothingMode(2);
		gb.DrawEllipse(zoom(2, 300), zoom(2, 300), zoom(12, 300), zoom(12, 300), zoom(2.0, 300), p.settings.color1);
		gb.FillEllipse(zoom(4, 300), zoom(4, 300), zoom(8, 300), zoom(8, 300), p.settings.color1);
		this.radiobt_normal_on.ReleaseGraphics(gb);
		// hover checked box
		this.radiobt_hover_on = gdi.CreateImage(zoom(16, 300), zoom(16, 300));
		gb = this.radiobt_hover_on.GetGraphics();
		gb.SetSmoothingMode(2);
		gb.DrawEllipse(zoom(2, 300), zoom(2, 300), zoom(12, 300), zoom(12, 300), zoom(2.0, 300), p.settings.color2);
		gb.FillEllipse(zoom(4, 300), zoom(4, 300), zoom(8, 300), zoom(8, 300), p.settings.color2);
		this.radiobt_hover_on.ReleaseGraphics(gb);

		var button_zoomSize = g_z16;
		// button
		if (this.status) {
			this.button = new button(this.radiobt_normal_on.Resize(button_zoomSize, button_zoomSize, 7), this.radiobt_hover_on.Resize(button_zoomSize, button_zoomSize, 7), this.radiobt_hover_on.Resize(button_zoomSize, button_zoomSize, 7));
		} else {
			this.button = new button(this.radiobt_normal_off.Resize(button_zoomSize, button_zoomSize, 7), this.radiobt_hover_off.Resize(button_zoomSize, button_zoomSize, 7), this.radiobt_hover_off.Resize(button_zoomSize, button_zoomSize, 7));
		};
	};
	this.setButtons();

	this.draw = function (gr) {
		var button_zoomSize = g_z16;
		if (this.status) {
			this.button.update(this.radiobt_normal_on.Resize(button_zoomSize, button_zoomSize, 7), this.radiobt_hover_on.Resize(button_zoomSize, button_zoomSize, 7), this.radiobt_hover_on.Resize(button_zoomSize, button_zoomSize, 7));
		} else {
			this.button.update(this.radiobt_normal_off.Resize(button_zoomSize, button_zoomSize, 7), this.radiobt_hover_off.Resize(button_zoomSize, button_zoomSize, 7), this.radiobt_hover_off.Resize(button_zoomSize, button_zoomSize, 7));
		};
		this.ly = this.y - (p.settings.pages[this.parentPageId].offset * cSettings.rowHeight);
		if (this.ly > cSettings.topBarHeight) {
			var button_y = this.ly - 1 + Math.ceil((p.settings.txtHeight + 10 - this.button.h) / 2);
			this.button.draw(gr, this.x, button_y, 255);
			var label_x = this.x + this.button.w + zoom(5, g_dpi);
			gr.gdiDrawText(this.label, gdi.Font(p.settings.fontname, p.settings.txtHeight, 1), (this.status ? p.settings.color2 : p.settings.color1), label_x, this.ly, p.settings.w, p.settings.txtHeight + 10, g_LDT);
		};
	};

	this.on_mouse = function (event, x, y, delta) {
		if (this.ly <= cSettings.topBarHeight) {
			return;
		};
		var state = this.button.checkstate(event, x, y);
		switch (event) {
		case "up":
			if (state == ButtonStates.hover) {
				eval(gfunc + "(" + this.id + "," + this.status + "," + this.parentPageId + ")");
			};
			break;
		};
		return state;
	};

	this.on_key = function (event, vkey) {};

	this.on_char = function (code) {};

	this.on_focus = function (is_focused) {};
};

oTextBox = function (id, x, y, w, h, label, value, func, parentPageId) {
	this.objType = "TB";
	this.id = id;
	this.x = x;
	this.y = y;
	this.parentPageId = parentPageId;
	this.ly = this.y - (p.settings.pages[this.parentPageId].offset * cSettings.rowHeight);
	this.w = w;
	this.h = h;
	this.label = label;
	this.value = value;
	var gfunc = func;

	this.inputbox = new oInputbox(this.w, this.h, this.value, "", RGB(0, 0, 0), RGB(240, 240, 240), RGB(180, 180, 180), RGBA(150, 150, 150, 200), gfunc + "(" + this.parentPageId + ", " + this.id + ")", "p.settings.pages[" + this.parentPageId + "].elements[" + this.id + "]", this.id, p.settings.txtHeight, 255);
	this.inputbox.autovalidation = false;

	this.repaint = function () {
		window.RepaintRect(this.x, this.ly, this.w, this.h * 2);
	};

	this.draw = function (gr) {
		this.ly = this.y - (p.settings.pages[this.parentPageId].offset * cSettings.rowHeight);
		if (this.ly + this.h > cSettings.topBarHeight) {
			gr.gdiDrawText(this.label, gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, this.x, this.ly, p.list.w - p.settings.pages[this.parentPageId].scrollbarWidth - 10, this.h, g_LDT);
			this.inputbox.draw(gr, this.x, this.ly + this.h);
		};
	};

	this.on_mouse = function (event, x, y, delta) {
		if (this.ly + this.h <= cSettings.topBarHeight) {
			return;
		};
		if (!p.settings.pages[1].elements[0].ishover) {
			if (this.ly > cSettings.topBarHeight + zoom(5, g_dpi)) {
				this.inputbox.check(event, x, y, delta);
			};
		};
	};

	this.on_key = function (event, vkey) {
		switch (event) {
		case "down":
			this.inputbox.on_key_down(vkey);
			break;
		};

		var kmask = GetKeyboardMask();
		// specific action on RETURN for the textbox Object
		if (kmask == KMask.none && vkey == VK_RETURN) {
			if (this.inputbox.edit) {
				this.inputbox.edit = false;
				this.inputbox.text_selected = "";
				this.inputbox.select = false;
				this.inputbox.default_text = this.inputbox.text; // set default text to new value validated
				this.inputbox.repaint();
			};
		};
		// specific action on TAB for the textbox Object
		if (this.inputbox.edit && !g_textbox_tabbed) {
			if (vkey == VK_TAB && (kmask == KMask.none || kmask == KMask.shift)) {
				// cancel textbox edit on current
				this.inputbox.edit = false;
				this.inputbox.text_selected = "";
				this.inputbox.select = false;
				this.inputbox.default_text = this.inputbox.text; // set default text to new value validated
				this.inputbox.SelBegin = 0;
				this.inputbox.SelEnd = 0;
				this.inputbox.repaint();

				if (kmask == KMask.none) {
					// scan elements to find objectType = "TB" / TextBox
					var first_textbox_id = -1;
					var next_textbox_id = -1;
					var fin = p.settings.pages[this.parentPageId].elements.length;
					for (var i = 0; i < fin; i++) {
						if (p.settings.pages[this.parentPageId].elements[i].objType == "TB") {
							if (first_textbox_id < 0) {
								first_textbox_id = i;
							};
							if (next_textbox_id < 0 && i > this.id) {
								next_textbox_id = i;
								break;
							};
						};
					};
					if (next_textbox_id < 0) {
						next_textbox_id = first_textbox_id;
					};
				} else {
					// scan elements to find objectType = "TB" / TextBox
					var first_textbox_id = -1;
					var next_textbox_id = -1;
					var debut = p.settings.pages[this.parentPageId].elements.length - 1;
					for (var i = debut; i >= 0; i--) {
						if (p.settings.pages[this.parentPageId].elements[i].objType == "TB") {
							if (first_textbox_id < 0) {
								first_textbox_id = i;
							};
							if (next_textbox_id < 0 && i < this.id) {
								next_textbox_id = i;
								break;
							};
						};
					};
					if (next_textbox_id < 0) {
						next_textbox_id = first_textbox_id;
					};
				};

				// set focus and edit mode to the next textbox found
				p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.on_focus(true);
				p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.edit = true;
				p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.Cpos = p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.text.length; // this.GetCPos(x);
				p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.anchor = p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.Cpos;
				p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.SelBegin = p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.Cpos;
				p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.SelEnd = p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.Cpos;
				p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.repaint();
				p.settings.pages[this.parentPageId].elements[next_textbox_id].inputbox.resetCursorTimer();
				g_textbox_tabbed = true;
				// then check if scroll required (update page offset to show the new activated textbox)
				var next_ly = p.settings.pages[this.parentPageId].elements[next_textbox_id].ly;
				if (next_ly < p.settings.pages[this.parentPageId].y + cSettings.rowHeight * 2) {
					var d = Math.ceil((p.settings.pages[this.parentPageId].y + cSettings.rowHeight * 2 - next_ly) / cSettings.rowHeight);
					p.settings.pages[this.parentPageId].offset -= d;
					if (p.settings.pages[this.parentPageId].offset < 0)
						p.settings.pages[this.parentPageId].offset = 0;
					p.settings.pages[this.parentPageId].scrollbar.reSet(p.settings.pages[this.parentPageId].total_rows, cSettings.rowHeight, p.settings.pages[this.parentPageId].offset);
					full_repaint();
				} else if (next_ly > p.settings.pages[this.parentPageId].y + p.settings.pages[this.parentPageId].h - cSettings.rowHeight * 3) {
					var maxOffset = p.settings.pages[this.parentPageId].total_rows - p.settings.pages[this.parentPageId].totalRowsVis;
					var d = Math.ceil((next_ly - (p.settings.pages[this.parentPageId].y + p.settings.pages[this.parentPageId].h) + cSettings.rowHeight * 3) / cSettings.rowHeight);
					p.settings.pages[this.parentPageId].offset += d;
					if (p.settings.pages[this.parentPageId].offset >= maxOffset)
						p.settings.pages[this.parentPageId].offset = maxOffset;
					p.settings.pages[this.parentPageId].scrollbar.reSet(p.settings.pages[this.parentPageId].total_rows, cSettings.rowHeight, p.settings.pages[this.parentPageId].offset);
					full_repaint();
				};
			};
		};
	};

	this.on_char = function (code) {
		this.inputbox.on_char(code);
	};

	this.on_focus = function (is_focused) {
		this.inputbox.on_focus(is_focused);
	};
};

oSlider = function (id, w, h, range, color_mode, value, parentPageId, parentWidgetId) {
	this.id = id;
	this.parentPageId = parentPageId;
	this.parentWidgetId = parentWidgetId;
	this.w = w;
	this.h = h;
	this.range = range;
	this.value = value;
	this.colorMode = color_mode;
	this.cw = 7;
	this.ch = this.h + 4;
	//
	this.ratio = 1;
	this.Zx = 0;
	this.Zy = 0;
	this.Zw = 0;
	this.Zh = 0;
	this.Zcx = 0;
	this.Zcy = 0;
	this.Zcw = 0;
	this.Zch = 0;
	//
	this.drag = false;
	this.dragX = 0;

	this.setValue = function (x) {
		this.ratioValue = (x - this.Zx) / this.Zw;
		var v = Math.floor(this.range * this.ratioValue);
		return v;
	};

	this.setCursorPos = function (v) {
		this.ratioPos = v / this.range;
		var Zcx = Math.floor(((this.Zw - this.Zcw) * this.ratioPos) - (this.Zcw / 2) * 0);
		return Zcx;
	};

	this.adjustSize = function () {
		this.Zw = zoom(this.w, g_dpi);
		this.Zh = zoom(this.h, g_dpi);
		this.Zcw = zoom(this.cw, g_dpi);
		this.Zch = zoom(this.ch, g_dpi);
		this.Zcx = this.setCursorPos(this.value);
	};
	this.adjustSize();

	this.draw = function (gr, x, y) {
		// bar x, y
		this.Zx = x;
		this.Zy = y;
		// cursor Y
		this.Zcy = this.Zy - Math.floor((this.Zch - this.Zh) / 2);
		// draw slider bar
		var widget_x = p.settings.pages[this.parentPageId].elements[this.parentWidgetId].x;
		this.left_padding = widget_x + g_z10;
		left_padding = 0;
		switch (this.colorMode) {
		case "R":
			gr.FillSolidRect(left_padding + this.Zx, this.Zy, this.Zw, this.Zh, RGB(255, 0, 0));
			break;
		case "G":
			gr.FillSolidRect(left_padding + this.Zx, this.Zy, this.Zw, this.Zh, RGB(0, 255, 0));
			break;
		case "B":
			gr.FillSolidRect(left_padding + this.Zx, this.Zy, this.Zw, this.Zh, RGB(0, 0, 255));
			break;
		};
		gr.FillGradRect(left_padding + this.Zx - 1, this.Zy, this.Zw, this.Zh, 0, RGB(0, 0, 0), 0, 1.0);

		// draw cursor
		if (p.settings.pages[this.parentPageId].elements[this.parentWidgetId].colorEnabled) {
			var cursor_color = (p.settings.colorWidgetFocusedId == this.parentWidgetId ? (p.settings.colorSliderFocusedId == this.id ? RGB(255, 255, 255) : RGB(180, 180, 180)) : RGB(180, 180, 180));
			gr.FillSolidRect(this.Zx + this.Zcx, this.Zcy, this.Zcw, this.Zch, cursor_color);
			gr.DrawRect(this.Zx + this.Zcx, this.Zcy, this.Zcw - 1, this.Zch - 1, 1.0, RGB(30, 30, 30));
		} else {
			var cursor_color = RGB(180, 180, 180);
			gr.FillSolidRect(this.Zx + 0, this.Zcy, this.Zcw, this.Zch, cursor_color);
			gr.DrawRect(this.Zx + 0, this.Zcy, this.Zcw - 1, this.Zch - 1, 1.0, RGB(30, 30, 30));
		};

	};

	this.isHoverCursor = function (x, y) {
		var widget_x = p.settings.pages[this.parentPageId].elements[this.parentWidgetId].x;
		this.left_padding = widget_x + g_z10;
		var tmp = (x >= this.left_padding + this.Zcx - 1 && x <= this.left_padding + this.Zcx + this.Zcw + 1 && y >= this.Zcy && y <= this.Zcy + this.Zch);
		return tmp;
	};

	this.isHoverBar = function (x, y) {
		return (x >= this.Zx && x <= this.Zx + this.Zw && y >= this.Zy && y <= this.Zy + this.Zh);
	};

	this.on_mouse = function (event, x, y, delta) {
		if (p.settings.pages[this.parentPageId].elements[this.parentWidgetId].colorEnabled) {
			switch (event) {
			case "down":
				if (this.isHoverBar(x, y) && !this.isHoverCursor(x, y)) {
					this.drag = true;
					this.dragX = x;
					this.value = this.setValue(x);
					this.Zcx = this.setCursorPos(this.value);
					p.settings.pages[this.parentPageId].elements[this.parentWidgetId].repaint();
				} else if (this.isHoverCursor(x, y)) {
					this.drag = true;
					this.dragX = x;
				};
				break;
			case "up":
				if (this.drag) {
					p.settings.color_updated = true;
					p.settings.colorWidgetFocusedId = this.parentWidgetId;
					p.settings.colorSliderFocusedId = this.id;
					//
					this.drag = false;
					this.dragX = 0;
					//
					p.settings.pages[this.parentPageId].elements[this.parentWidgetId].repaint();
				};
				break;
			case "move":
				if (this.drag) {
					if (x >= this.Zx && x <= this.Zx + this.Zw) {
						this.value = this.setValue(x);
						this.Zcx = this.setCursorPos(this.value);
						p.settings.pages[this.parentPageId].elements[this.parentWidgetId].repaint();
					};
				};
				break;
			};
		};
	};

	this.on_key = function (event, vkey) {
		if (!p.timer_onKey) {
			switch (vkey) {
			case VK_LEFT:
				var prev_value = this.value;
				this.value = this.value > 0 ? this.value - 1 : 0;
				if (prev_value != this.value)
					p.settings.color_updated = true;
				this.Zcx = this.setCursorPos(this.value);
				p.settings.pages[this.parentPageId].elements[this.parentWidgetId].repaint();
				break;
			case VK_RIGHT:
				var prev_value = this.value;
				this.value = this.value < this.range ? this.value + 1 : this.range;
				if (prev_value != this.value)
					p.settings.color_updated = true;
				this.Zcx = this.setCursorPos(this.value);
				p.settings.pages[this.parentPageId].elements[this.parentWidgetId].repaint();
				break;
			};
			p.timer_onKey = window.SetTimeout(function () {
					p.timer_onKey && window.ClearTimeout(p.timer_onKey);
					p.timer_onKey = false;
				}, 150);
		};
	};
};

oWidget = function (id, x, y, w, h, label, color_id, func, parentPageId) {
	this.objType = "WG";
	this.id = id;
	this.label = label;
	this.color_id = color_id;
	this.parentPageId = parentPageId;
	this.x = x;
	this.y = y;
	this.w = w;
	this.h = h;
	var gfunc = func;
	this.sliders = [];
	this.slider_y = 0;

	var slider_w = zoom(190, g_dpi);
	var slider_h = g_z6;
	var slider_range = 255.0;
	switch (this.parentPageId) {
	case 3:
		switch (this.color_id) {
		case 0:
			var arr = window.GetProperty("SYSTEM.COLOR TEXT NORMAL", "180-180-180").split("-");
			break;
		case 1:
			var arr = window.GetProperty("SYSTEM.COLOR TEXT SELECTED", "200-210-255").split("-");
			break;
		case 2:
			var arr = window.GetProperty("SYSTEM.COLOR BACKGROUND NORMAL", "25-25-35").split("-");
			break;
		case 3:
			var arr = window.GetProperty("SYSTEM.COLOR BACKGROUND SELECTED", "130-150-255").split("-");
			break;
		case 4:
			var arr = window.GetProperty("SYSTEM.COLOR HIGHLIGHT", "255-175-50").split("-");
			break;
		};
		break;
	};
	this.sliders.push(new oSlider(0, slider_w, slider_h, slider_range, "R", arr[0], this.parentPageId, this.id));
	this.sliders.push(new oSlider(1, slider_w, slider_h, slider_range, "G", arr[1], this.parentPageId, this.id));
	this.sliders.push(new oSlider(2, slider_w, slider_h, slider_range, "B", arr[2], this.parentPageId, this.id));

	this.repaint = function () {
		this.ly = Math.floor(this.y - (p.settings.pages[this.parentPageId].offset * cSettings.rowHeight));
		window.RepaintRect(this.x, this.ly, this.w, this.h + this.slider_y);
	};

	this.refresh = function () {
		switch (this.parentPageId) {
		case 3:
			switch (this.color_id) {
			case 0:
				var arr = window.GetProperty("SYSTEM.COLOR TEXT NORMAL", "180-180-180").split("-");
				break;
			case 1:
				var arr = window.GetProperty("SYSTEM.COLOR TEXT SELECTED", "200-210-255").split("-");
				break;
			case 2:
				var arr = window.GetProperty("SYSTEM.COLOR BACKGROUND NORMAL", "25-25-35").split("-");
				break;
			case 3:
				var arr = window.GetProperty("SYSTEM.COLOR BACKGROUND SELECTED", "130-150-255").split("-");
				break;
			case 4:
				var arr = window.GetProperty("SYSTEM.COLOR HIGHLIGHT", "255-175-50").split("-");
				break;
			};
			break;
		};
		for (var v = 0; v < 3; v++) {
			this.sliders[v].value = arr[v];
			this.sliders[v].Zcx = this.sliders[v].setCursorPos(arr[v]);
		};
	};

	this.draw = function (gr) {
		gr.SetSmoothingMode(0);

		this.ly = Math.floor(this.y - (p.settings.pages[this.parentPageId].offset * cSettings.rowHeight));

		// check if color is enabled in current settings page
		switch (this.parentPageId) {
		case 3:
			this.colorEnabled = properties.enableCustomColors;
			break;
		default:
			this.colorEnabled = true;
		};

		// draw widget label
		var label_y = g_z10;
		gr.gdiDrawText(this.label, gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, this.x, this.ly - label_y, p.settings.w, cSettings.rowHeight, g_LDT);

		// draw sliders
		this.slider_y = label_y + zoom(20, g_dpi);
		var mode_w = Math.ceil(gr.CalcTextWidth("GG", gdi.Font(g_fname, g_fsize - 1, 0)));
		var cube_left_padding = Math.ceil(gr.CalcTextWidth(" 255 ", gdi.Font(g_fname, g_fsize - 1, 0)));
		var slider_left_padding = zoom(5, g_dpi) + mode_w;
		var sliders_spacing = zoom(20, g_dpi);

		var fin = this.sliders.length;
		for (var i = 0; i < fin; i++) {
			switch (i) {
			case 0:
				this.sliders[i].draw(gr, this.x + slider_left_padding, Math.floor(this.ly + this.slider_y + sliders_spacing * 0));
				gr.gdiDrawText("R", gdi.Font(g_fname, g_fsize - 2, 0), g_color_normal_txt, this.x + g_z10, this.ly + this.slider_y + sliders_spacing * 0 + zoom(1, g_dpi), mode_w, slider_h, g_LDT);
				gr.gdiDrawText((this.colorEnabled ? this.sliders[i].value : "0"), gdi.Font(g_fname, g_fsize - 2, 0), g_color_normal_txt, this.x + label_y + this.sliders[0].Zw + label_y + zoom(5, g_dpi), this.ly + this.slider_y + sliders_spacing * 0 + zoom(1, g_dpi), cube_left_padding, slider_h, g_LDT);
				break;
			case 1:
				this.sliders[i].draw(gr, this.x + slider_left_padding, Math.floor(this.ly + this.slider_y + sliders_spacing * 1));
				gr.gdiDrawText("G", gdi.Font(g_fname, g_fsize - 2, 0), g_color_normal_txt, this.x + g_z10, this.ly + this.slider_y + sliders_spacing * 1 + zoom(1, g_dpi), mode_w, slider_h, g_LDT);
				gr.gdiDrawText((this.colorEnabled ? this.sliders[i].value : "0"), gdi.Font(g_fname, g_fsize - 2, 0), g_color_normal_txt, this.x + label_y + this.sliders[0].Zw + label_y + zoom(5, g_dpi), this.ly + this.slider_y + sliders_spacing * 1 + zoom(1, g_dpi), cube_left_padding, slider_h, g_LDT);
				break;
			case 2:
				this.sliders[i].draw(gr, this.x + slider_left_padding, Math.floor(this.ly + this.slider_y + sliders_spacing * 2));
				gr.gdiDrawText("B", gdi.Font(g_fname, g_fsize - 2, 0), g_color_normal_txt, this.x + g_z10, this.ly + this.slider_y + sliders_spacing * 2 + zoom(1, g_dpi), mode_w, slider_h, g_LDT);
				gr.gdiDrawText((this.colorEnabled ? this.sliders[i].value : "0"), gdi.Font(g_fname, g_fsize - 2, 0), g_color_normal_txt, this.x + label_y + this.sliders[0].Zw + label_y + zoom(5, g_dpi), this.ly + this.slider_y + sliders_spacing * 2 + zoom(1, g_dpi), cube_left_padding, slider_h, g_LDT);
				break;
			};
		};

		// draw color cube
		var cubx = this.x + label_y + this.sliders[0].Zw + label_y + cube_left_padding + g_z2;
		var cuby = this.ly + this.slider_y;
		var cubw = (sliders_spacing * 2 + this.sliders[0].Zh);
		var cubh = cubw;

		if (this.colorEnabled) {
			gr.FillSolidRect(cubx, cuby, cubw, cubh, RGB(this.sliders[0].value, this.sliders[1].value, this.sliders[2].value));
			gr.FillGradRect(cubx, cuby, cubw, cubh, 45, RGBA(0, 0, 0, 20), RGBA(255, 255, 255, 20), 1.0);
			gr.DrawRect(cubx, cuby, cubw - 1, cubh - 1, 1.0, p.settings.color1);
		} else {
			gr.FillSolidRect(cubx, cuby, cubw, cubh, RGB(250, 250, 250));
			gr.DrawRect(cubx, cuby, cubw - 1, cubh - 1, 1.0, RGB(255, 50, 50));
			gr.SetSmoothingMode(2);
			gr.DrawLine(cubx, cuby, cubx + cubw - 1, cuby + cubh - 1, 1.0, RGB(255, 50, 50));
			gr.SetSmoothingMode(0);
		};
		// widget frame
		this.w = slider_left_padding + this.sliders[0].Zw + cube_left_padding + cubw + g_z10;
		this.h = sliders_spacing * 2 + this.sliders[0].Zh * 1 + label_y * 2;
		gr.DrawRect(this.x, this.ly + this.slider_y - label_y, this.w, this.h, 1.0, p.settings.color1);
	};

	this.isHoverCursor = function (x, y) {
		return (x >= this.Zcx && x <= this.Zcx + this.Zcw && y >= this.Zcy && y <= this.Zcy + this.Zch);
	};

	this.isHoverBar = function (x, y) {
		return (x >= this.Zx && x <= this.Zx + this.Zw && y >= this.Zy && y <= this.Zy + this.Zh);
	};

	this.updateColor = function () {
		switch (this.parentPageId) {
		case 3:
			switch (this.color_id) {
			case 0:
				if (properties.enableCustomColors) {
					g_color_normal_txt = RGB(this.sliders[0].value, this.sliders[1].value, this.sliders[2].value);
				};
				var rgb_str = this.sliders[0].value + "-" + this.sliders[1].value + "-" + this.sliders[2].value;
				window.SetProperty("SYSTEM.COLOR TEXT NORMAL", rgb_str);
				break;
			case 1:
				if (properties.enableCustomColors) {
					g_color_selected_txt = RGB(this.sliders[0].value, this.sliders[1].value, this.sliders[2].value);
				};
				var rgb_str = this.sliders[0].value + "-" + this.sliders[1].value + "-" + this.sliders[2].value;
				window.SetProperty("SYSTEM.COLOR TEXT SELECTED", rgb_str);
				break;
			case 2:
				if (properties.enableCustomColors) {
					g_color_normal_bg = RGB(this.sliders[0].value, this.sliders[1].value, this.sliders[2].value);
				};
				var rgb_str = this.sliders[0].value + "-" + this.sliders[1].value + "-" + this.sliders[2].value;
				window.SetProperty("SYSTEM.COLOR BACKGROUND NORMAL", rgb_str);
				break;
			case 3:
				if (properties.enableCustomColors) {
					g_color_selected_bg = RGB(this.sliders[0].value, this.sliders[1].value, this.sliders[2].value);
				};
				var rgb_str = this.sliders[0].value + "-" + this.sliders[1].value + "-" + this.sliders[2].value;
				window.SetProperty("SYSTEM.COLOR BACKGROUND SELECTED", rgb_str);
				break;
			case 4:
				if (properties.enableCustomColors) {
					g_color_highlight = RGB(this.sliders[0].value, this.sliders[1].value, this.sliders[2].value);
				};
				var rgb_str = this.sliders[0].value + "-" + this.sliders[1].value + "-" + this.sliders[2].value;
				window.SetProperty("SYSTEM.COLOR HIGHLIGHT", rgb_str);
				break;
			};
			p.settings.refreshColors();
			p.list.setItemColors();
			p.playlistManager.setColors();
			break;
		};
	};

	this.on_mouse = function (event, x, y, delta) {
		// check sliders
		var fin = this.sliders.length;
		for (var i = 0; i < fin; i++) {
			this.sliders[i].on_mouse(event, x, y);
		};
		if (p.settings.color_updated) { // if a slider has been moved, color is to update
			this.updateColor();
		} else {
			// if click and not slider moved or clicked, slider focus to RESET
			if (event == "up") {
				// reset slider focus
				p.settings.colorWidgetFocusedId = -1;
				p.settings.colorSliderFocusedId = -1;
				full_repaint();
			};
		};
	};

	this.on_key = function (event, vkey) {
		// if this widget has the focus, check on_key on the slider (to move it left or right)
		if (p.settings.colorWidgetFocusedId == this.id) {
			if (p.settings.colorSliderFocusedId > -1) {
				this.sliders[p.settings.colorSliderFocusedId].on_key(event, vkey);
				if (p.settings.color_updated) { // if a slider has been moved, color is to update
					this.updateColor();
				};
			};
		};
	};

	this.on_char = function (code) {};

	this.on_focus = function (is_focused) {};
};

oListBox = function (id, object_name, x, y, w, h, row_height, label, arr, selectedId, func, parentObject, parentPageId, offset) {
	this.objType = "LB";
	this.rowHeight = row_height;
	this.id = id;
	this.objectName = object_name;
	this.parentObject = parentObject;
	this.x = x;
	this.y = y;
	this.parentPageId = parentPageId;
	this.ly = this.y - (p.settings.pages[this.parentPageId].offset * cSettings.rowHeight);
	this.w = w;
	this.h = 3 * this.rowHeight;
	this.totalRows = Math.floor(this.h / this.rowHeight);
	this.label = label;
	this.offset = offset;
	this.arr = arr;
	this.total = this.arr.length;
	this.selectedId = selectedId;
	var gfunc = func;
	// scrollbar instance
	this.scrollbar = new oScrollBar(this.id, this.objectName + ".scrollbar", this.x + this.w - cScrollBar.width, this.ly, cScrollBar.width, this.h, this.arr.length, this.rowHeight, this.offset, this.objectName, true, 3, false);
	this.scrollbar.setCustomColors(RGB(240, 240, 240), RGB(0, 0, 0));
	this.scrollbarWidth = 0;

	this.repaint = function () {
		window.RepaintRect(this.x, this.ly, this.w, this.h);
	};

	this.showSelected = function (rowId) {
		this.selectedId = rowId;
		if (this.scrollbar.visible) {
			var max_offset = this.total - this.totalRows;
			this.offset = rowId > max_offset ? max_offset : rowId;
			this.scrollbar.updateCursorPos(this.offset);
		} else {
			this.offset = 0;
		};
		eval(gfunc + "(" + this.parentPageId + ", " + this.id + ", " + this.selectedId + ")");
	};

	this.reSet = function (list_array) {
		this.arr = list_array;
		this.total = this.arr.length;
		this.max = (this.total > this.totalRows ? this.totalRows : this.total);
		// scrollbar reset
		this.scrollbar.reSet(this.total, this.rowHeight, this.offset);
		if (this.scrollbar.visible) {
			this.scrollbarWidth = this.scrollbar.w;
		} else {
			this.scrollbarWidth = 0;
		};
	};
	this.reSet(this.arr);

	this.resize = function (x, y, w, h, arr) {
		this.x = x;
		this.y = y;
		this.ly = this.y - (p.settings.pages[this.parentPageId].offset * cSettings.rowHeight);
		this.w = w;
		this.h = 3 * this.rowHeight;

		this.arr = arr;
		this.total = this.arr.length;
		this.max = (this.total > this.totalRows ? this.totalRows : this.total);
		this.offset = 0;

		// scrollbar resize
		this.scrollbar.reSize(this.x + this.w - cScrollBar.width, this.ly, cScrollBar.width, this.h, this.arr.length, this.rowHeight, this.offset);
		if (this.scrollbar.visible) {
			this.scrollbarWidth = this.scrollbar.w;
		} else {
			this.scrollbarWidth = 0;
		};
	};

	this.draw = function (gr) {
		var row = 0;
		this.ly = this.y - (p.settings.pages[this.parentPageId].offset * cSettings.rowHeight);

		this.scrollbar.y = this.ly;
		// scrollbar reset
		this.scrollbar.reSet(this.total, this.rowHeight, this.offset);
		if (this.scrollbar.visible) {
			this.scrollbarWidth = this.scrollbar.w;
		} else {
			this.scrollbarWidth = 0;
		};

		var text_padding = 5;

		// listbox bg
		if (this.label.length > 0) {
			gr.gdiDrawText(this.label, gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, this.x, this.ly - this.rowHeight - g_z2, this.w, this.rowHeight, g_LDT);
		};
		gr.FillSolidRect(this.x, this.ly, this.w, this.h + 1, RGB(240, 240, 240));
		gr.DrawRect(this.x - 1, this.ly - 1, this.w + 1, this.h + 2, 1.0, RGB(180, 180, 180));

		// scrollbar
		if (this.scrollbar.visible)
			this.scrollbar.draw(gr);

		// items
		var isCustom = false;
		var fin = this.max + this.offset;
		for (var i = this.offset; i < fin; i++) {
			gr.SetSmoothingMode(0);
			switch (this.parentPageId) {
			case 1:
				isCustom = (p.headerBar.columns[i].ref.substr(0, 6) == "Custom");
				break;
			case 2:
				isCustom = (p.list.groupby[i].ref.substr(0, 6) == "Custom");
				break;
			};
			if (i == this.selectedId)
				gr.FillSolidRect(this.x + 1, this.ly + row * this.rowHeight + 1, this.w - this.scrollbarWidth - 2, this.rowHeight - 1, RGBA(150, 150, 150, 200));
			gr.gdiDrawText((isCustom ? "[" : "") + this.arr[i] + (isCustom ? "]" : ""), gdi.Font(p.settings.fontname, p.settings.txtHeight, (i == this.selectedId ? 1 : 0)), (i == this.selectedId ? RGB(0, 0, 0) : RGB(0, 0, 0)), this.x + text_padding, this.ly + row * this.rowHeight, this.w - this.scrollbarWidth - text_padding * 2, this.rowHeight, g_LDT);
			row++;
		};
	};

	this.isHoverObject = function (x, y) {
		var test = (x >= this.x && x <= this.x + this.w && y >= this.ly && y <= this.ly + this.h);
		return test;
	};

	this.on_mouse = function (event, x, y, delta) {
		this.ishover = this.isHoverObject(x, y);
		var maxHeight = this.max * this.rowHeight;
		this.ishoverRow = (x >= this.x && x <= this.x + this.w - this.scrollbarWidth && y >= this.ly && y <= this.ly + maxHeight);

		switch (event) {
		case "down":
			if (this.scrollbar.visible)
				this.scrollbar.check(event, x, y, delta);
			// get row number clicked
			if (y > cSettings.topBarHeight + cSettings.rowHeight) {
				if (this.ishoverRow) {
					var new_selectedId = Math.floor((y - this.ly) / this.rowHeight) + this.offset;
					eval(gfunc + "(" + this.parentPageId + ", " + this.id + ", " + new_selectedId + ")");
				};
			};
			break;
		case "dblclk":
			this.on_mouse("down", x, y);
			break;
		case "up":
			if (this.scrollbar.visible)
				this.scrollbar.check(event, x, y, delta);
			break;
		case "right":
			// get row number right-clicked
			if (y > cSettings.topBarHeight + cSettings.rowHeight) {
				if (this.ishoverRow) {
					var new_selectedId = Math.floor((y - this.ly) / this.rowHeight) + this.offset;
					eval(gfunc + "(" + this.parentPageId + ", " + this.id + ", " + new_selectedId + ")");
					this.contextMenu(x, y, new_selectedId);
				};
			};
			break;
		case "move":
			if (this.scrollbar.visible)
				this.scrollbar.check(event, x, y, delta);
			break;
		case "wheel":
			if (this.ishover) {
				if (this.scrollbar.visible && this.ishover)
					this.scrollbar.check(event, x, y, delta);
			};
			break;
		};
	};

	this.on_key = function (event, vkey) {
		switch (event) {
		case "down":
			switch (vkey) {
			case VK_UP:
				var new_selectedId = (this.selectedId > 0 ? this.selectedId - 1 : 0);
				eval(gfunc + "(" + this.parentPageId + ", " + this.id + ", " + new_selectedId + ")");
				var row_idx = this.selectedId - this.offset;
				if (row_idx <= 0) {
					this.showSelected(new_selectedId);
				};
				break;
			case VK_DOWN:
				var new_selectedId = (this.selectedId < this.arr.length - 1 ? this.selectedId + 1 : this.arr.length - 1);
				eval(gfunc + "(" + this.parentPageId + ", " + this.id + ", " + new_selectedId + ")");
				var row_idx = this.selectedId - this.offset;
				if (row_idx > 2) { // 2 = max index row of the listbox, because listbox height is 3 rows
					this.showSelected(new_selectedId);
				};
				break;
			};
			break;
		};
	};

	this.on_char = function (code) {};

	this.on_focus = function (is_focused) {};

	this.contextMenu = function (x, y, id) {
		var fin;
		var idx;
		var _menu = window.CreatePopupMenu();

		switch (this.parentPageId) {
		case 1:
			if (p.headerBar.totalColumns < properties.max_columns) {
				var source_ref = p.headerBar.columns[id].ref;
				if (source_ref != "Cover" && source_ref != "State" && source_ref != "Mood" && source_ref != "Rating") {
					_menu.AppendMenuItem(MF_STRING, 10, "Duplicate this Column");
				};
			};
			break;
		case 2:
			if (p.list.totalGroupBy < properties.max_patterns) {
				_menu.AppendMenuItem(MF_STRING, 20, "Duplicate this Pattern");
			};
			break;
		};

		idx = _menu.TrackPopupMenu(x, y);
		switch (true) {
		case (idx == 10):
			// action
			var no_user = 1;
			var tmp_array = [];
			// copy columns array to a tmp array in order to sort it
			fin = p.headerBar.columns.length;
			for (var i = 0; i < fin; i++) {
				tmp_array.push(p.headerBar.columns[i].ref);
			};
			tmp_array.sort();
			// get free number to affect to the new User column to create
			fin = tmp_array.length;
			for (var i = 0; i < fin; i++) {
				if (tmp_array[i].substr(0, 6) == "Custom") {
					if (tmp_array[i].substr(tmp_array[i].length - 2, 2) == num(no_user, 2)) {
						no_user++;
					};
				};
			};

			var c0 = p.headerBar.columns[id].label;
			var c1 = p.headerBar.columns[id].tf;
			var c2 = p.headerBar.columns[id].tf2;
			var c3 = p.headerBar.columns[id].align;
			var c4 = p.headerBar.columns[id].sortOrder;
			var c5 = p.headerBar.columns[id].enableCustomColor;
			var c6 = p.headerBar.columns[id].customColor;

			p.headerBar.columns.push(new oColumn("copy of " + c0, c1, c2, 0, "Custom " + num(no_user, 2), c3, c4, c5, c6));
			p.headerBar.totalColumns++;
			window.SetProperty("SYSTEM.HeaderBar.TotalColumns", p.headerBar.totalColumns);
			var arr = [];
			fin = p.headerBar.columns.length;
			for (var i = 0; i < fin; i++) {
				arr.push(p.headerBar.columns[i].ref);
			};
			p.settings.pages[1].elements[0].reSet(arr);
			p.headerBar.saveColumns();
			p.settings.pages[1].elements[0].showSelected(p.headerBar.columns.length - 1);
			full_repaint();
			break;
		case (idx == 20):
			// action
			var c0 = p.list.groupby[id].label;
			var c1 = p.list.groupby[id].tf;
			var c2 = p.list.groupby[id].sortOrder;
			var c3 = p.list.groupby[id].playlistFilter;
			var c4 = p.list.groupby[id].extraRows;
			var c5 = p.list.groupby[id].collapsedHeight;
			var c6 = p.list.groupby[id].expandedHeight;
			var c7 = p.list.groupby[id].showCover;
			var c8 = p.list.groupby[id].autoCollapse;
			var c9 = p.list.groupby[id].l1;
			var c10 = p.list.groupby[id].r1;
			var c11 = p.list.groupby[id].l2;
			var c12 = p.list.groupby[id].r2;

			p.list.groupby.push(new oGroupBy("copy of " + c0, c1, c2, "Custom", c3, c4, c5, c6, c7, c8, c9, c10, c11, c12));
			p.list.totalGroupBy++;
			window.SetProperty("SYSTEM.Groups.TotalGroupBy", p.list.totalGroupBy);
			var arr = [];
			fin = p.list.groupby.length;
			for (var i = 0; i < fin; i++) {
				arr.push(p.list.groupby[i].label);
			};
			p.settings.pages[2].elements[0].reSet(arr);
			p.list.saveGroupBy();
			p.settings.pages[2].elements[0].showSelected(p.list.groupby.length - 1);
			full_repaint();
			break;
		};
		_menu.Dispose();
		return true;
	};
};

oPage = function (id, objectName, label, nbrows) {
	this.id = id;
	this.objectName = objectName;
	this.label = label;
	this.elements = [];
	this.offset = 0;
	this.rows = [];
	this.total_rows = nbrows;
	this.x = p.settings.x;
	this.y = p.settings.y + cSettings.topBarHeight;
	this.w = p.settings.w;
	this.h = p.settings.h - cSettings.topBarHeight;
	this.totalRowsVis = Math.floor((this.h - cHeaderBar.height) / cSettings.rowHeight);
	// scrollbar instance
	this.scrollbar = new oScrollBar(this.id, this.objectName + ".scrollbar", p.settings.x + p.settings.w - cScrollBar.width, p.settings.y + cSettings.topBarHeight + cHeaderBar.height, cScrollBar.width, p.settings.h - cSettings.topBarHeight - cHeaderBar.height, this.total_rows, cSettings.rowHeight, this.offset, this.objectName, true, 3, false);
	this.scrollbar.setCustomColors(g_color_normal_bg, g_color_normal_txt);
	this.scrollbarWidth = 0;

	this.repaint = function () {
		full_repaint();
	};

	this.init = function () {
		var txtbox_x = 20;
		switch (this.id) {
		case 0: // General
			var rh = cSettings.rowHeight;
			// Layout options
			this.elements.push(new oCheckBox(0, 20, cSettings.topBarHeight + rh * 2.25, "Show Information Panel (toggle = CTRL+I)", "cTopBar.visible", "settings_checkboxes_action", this.id));
			this.elements.push(new oCheckBox(1, 20, cSettings.topBarHeight + rh * 3.25, "Show Header Toolbar (toggle = CTRL+T)", "cHeaderBar.locked", "settings_checkboxes_action", this.id));
			this.elements.push(new oCheckBox(2, 20, cSettings.topBarHeight + rh * 4.25, "Show Playlist Manager (toggle = TAB key)", "cPlaylistManager.visible", "settings_checkboxes_action", this.id));
			this.elements.push(new oCheckBox(3, 20, cSettings.topBarHeight + rh * 5.25, "Show Playlist Scrollbar", "properties.showscrollbar", "settings_checkboxes_action", this.id));
			// Playlists options
			this.elements.push(new oCheckBox(4, 20, cSettings.topBarHeight + rh * 7.25, "Show Media Library (always on top)", "cPlaylistManager.mediaLibraryPlaylist", "settings_checkboxes_action", this.id));
			this.elements.push(new oCheckBox(5, 20, cSettings.topBarHeight + rh * 8.25, "Show Plays Historic", "cPlaylistManager.enableHistoricPlaylist", "settings_checkboxes_action", this.id));
			// Tagging options
			this.elements.push(new oCheckBox(6, 20, cSettings.topBarHeight + rh * 10.25, "Enable Playback Statistics (write to file)", "opt_stats", "settings_checkboxes_action", this.id));
			// Behaviour options
			this.elements.push(new oCheckBox(7, 20, cSettings.topBarHeight + rh * 12.25, "Smooth Scrolling", "properties.smoothscrolling", "settings_checkboxes_action", this.id));
			this.elements.push(new oCheckBox(8, 20, cSettings.topBarHeight + rh * 13.25, "Touch Scrolling Control (disable drag'n drop)", "properties.enableTouchControl", "settings_checkboxes_action", this.id));

			// Create radio buttons
			var spaceBetween_w = zoom(70, g_dpi);
			this.elements.push(new oRadioButton(9, txtbox_x, cSettings.topBarHeight + rh * 15.25, "Play", (properties.defaultPlaylistItemAction == "Play"), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(10, txtbox_x + spaceBetween_w, cSettings.topBarHeight + rh * 15.25, "Enqueue", (properties.defaultPlaylistItemAction == "Add to playback queue"), "settings_radioboxes_action", this.id));

			break;
		case 1: // Columns
			// Create Columns ListBox object
			var arr = [];
			var rh = cSettings.rowHeight;
			var fin = p.headerBar.columns.length;
			for (var i = 0; i < fin; i++) {
				arr.push(p.headerBar.columns[i].label);
			};
			var listBoxRowHeight = zoom(21, g_dpi);
			var listBoxHeight = Math.floor(wh - (cSettings.topBarHeight + rh * 1.75 + p.settings.txtHeight) - 25);
			var listBoxWidth = zoom(100, g_dpi);
			var listBoxCurrentId = 0;
			this.elements.push(new oListBox(0, "p.settings.pages[" + this.id.toString() + "].elements[0]", 20, Math.floor(cSettings.topBarHeight + rh * 1.75 + p.settings.txtHeight), listBoxWidth + cScrollBar.width, listBoxHeight, listBoxRowHeight, "Columns", arr, listBoxCurrentId, "settings_listboxes_action", "p.settings.pages[" + this.id.toString() + "]", this.id, 0));

			// Create TextBoxes
			var txtbox_value = p.headerBar.columns[listBoxCurrentId].label;
			this.elements.push(new oTextBox(1, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * 6.25), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Label", txtbox_value, "settings_textboxes_action", this.id));
			txtbox_value = p.headerBar.columns[listBoxCurrentId].tf;
			this.elements.push(new oTextBox(2, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * 8.25), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Title Format (enter 'null' for nothing)", txtbox_value, "settings_textboxes_action", this.id));
			txtbox_value = p.headerBar.columns[listBoxCurrentId].tf2;
			this.elements.push(new oTextBox(3, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * 10.25), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Extra Line Title Format (enter 'null' for nothing)", txtbox_value, "settings_textboxes_action", this.id));
			txtbox_value = p.headerBar.columns[listBoxCurrentId].sortOrder;
			this.elements.push(new oTextBox(4, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * 12.25), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Sort Order (enter 'null' for nothing)", txtbox_value, "settings_textboxes_action", this.id));

			// Create radio buttons
			var spaceBetween_w = zoom(80, g_dpi);
			this.elements.push(new oRadioButton(5, txtbox_x, cSettings.topBarHeight + rh * 15.25, "Left", (p.headerBar.columns[listBoxCurrentId].align == 0), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(6, txtbox_x + spaceBetween_w, cSettings.topBarHeight + rh * 15.25, "Center", (p.headerBar.columns[listBoxCurrentId].align == 1), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(7, txtbox_x + spaceBetween_w * 2, cSettings.topBarHeight + rh * 15.25, "Right", (p.headerBar.columns[listBoxCurrentId].align == 2), "settings_radioboxes_action", this.id));

			// checkbox : activate columns Y/N
			this.elements.push(new oCheckBox(0, txtbox_x, cSettings.topBarHeight + rh * 5.25, "Visible", "p.headerBar.columns[p.settings.pages[1].elements[0].selectedId].percent == 0 ? false : true", "settings_checkboxes_action", this.id));

			break;
		case 2: // Groups
			// Create Groups Pattern ListBox object
			var arr = [];
			var rh = cSettings.rowHeight;
			var fin = p.list.groupby.length;
			for (var i = 0; i < fin; i++) {
				arr.push(p.list.groupby[i].label);
			};
			var listBoxRowHeight = zoom(21, g_dpi);
			var listBoxHeight = Math.floor(wh - (cSettings.topBarHeight + rh * 1.75 + p.settings.txtHeight) - 25);
			var listBoxWidth = zoom(170, g_dpi);
			var listBoxCurrentId = cGroup.pattern_idx;
			this.elements.push(new oListBox(0, "p.settings.pages[" + this.id.toString() + "].elements[0]", 20, Math.floor(cSettings.topBarHeight + rh * 1.75 + p.settings.txtHeight), listBoxWidth + cScrollBar.width, listBoxHeight, listBoxRowHeight, "Group by", arr, listBoxCurrentId, "settings_listboxes_action", "p.settings.pages[" + this.id.toString() + "]", this.id, 0));

			// Create TextBoxes
			var txtbox_value = p.list.groupby[listBoxCurrentId].label;
			this.elements.push(new oTextBox(1, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * 4.5), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Label", txtbox_value, "settings_textboxes_action", this.id));
			txtbox_value = p.list.groupby[listBoxCurrentId].tf;
			this.elements.push(new oTextBox(2, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * 6.5), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Title Format (enter 'null' for nothing)", txtbox_value, "settings_textboxes_action", this.id));
			txtbox_value = p.list.groupby[listBoxCurrentId].sortOrder;
			this.elements.push(new oTextBox(3, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * 8.5), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Sort Order (enter 'null' for nothing)", txtbox_value, "settings_textboxes_action", this.id));

			txtbox_value = p.list.groupby[listBoxCurrentId].playlistFilter;
			this.elements.push(new oTextBox(4, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * 11.0), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Playlist Filter ('*' = default pattern, 'null' = nothing)", txtbox_value, "settings_textboxes_action", this.id));
			txtbox_value = p.list.groupby[listBoxCurrentId].extraRows;
			this.elements.push(new oTextBox(5, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * 13.0), 30, cHeaderBar.height, "Extra Rows To Add", txtbox_value, "settings_textboxes_action", this.id));
			// Create radio buttons / group header COLLAPSED height
			var spaceBetween_w = zoom(50, g_dpi);
			// force value if set to an unauthirized one [0;4]
			if (p.list.groupby[listBoxCurrentId].collapsedHeight < 0 || p.list.groupby[listBoxCurrentId].collapsedHeight > 4) {
				p.list.groupby[listBoxCurrentId].collapsedHeight = (p.list.groupby[listBoxCurrentId].collapsedHeight < 0 ? 0 : 4);
				p.list.saveGroupBy();
			};
			var v = p.list.groupby[listBoxCurrentId].collapsedHeight;
			this.elements.push(new oRadioButton(6, txtbox_x, cSettings.topBarHeight + rh * 16.0, "0", (v == 0), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(7, txtbox_x + spaceBetween_w, cSettings.topBarHeight + rh * 16.0, "1", (v == 1), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(8, txtbox_x + spaceBetween_w * 2, cSettings.topBarHeight + rh * 16.0, "2", (v == 2), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(9, txtbox_x + spaceBetween_w * 3, cSettings.topBarHeight + rh * 16.0, "3", (v == 3), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(10, txtbox_x + spaceBetween_w * 4, cSettings.topBarHeight + rh * 16.0, "4", (v == 4), "settings_radioboxes_action", this.id));
			// Create radio buttons / group header EXPANDED height
			var spaceBetween_w = zoom(50, g_dpi);
			// force value if set to an unauthirized one [0;4]
			if (p.list.groupby[listBoxCurrentId].expandedHeight < 0 || p.list.groupby[listBoxCurrentId].expandedHeight > 4) {
				p.list.groupby[listBoxCurrentId].expandedHeight = (p.list.groupby[listBoxCurrentId].expandedHeight < 0 ? 0 : 4);
				p.list.saveGroupBy();
			};
			var v = p.list.groupby[listBoxCurrentId].expandedHeight;
			this.elements.push(new oRadioButton(11, txtbox_x, cSettings.topBarHeight + rh * 17.5, "0", (v == 0), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(12, txtbox_x + spaceBetween_w, cSettings.topBarHeight + rh * 17.5, "1", (v == 1), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(13, txtbox_x + spaceBetween_w * 2, cSettings.topBarHeight + rh * 17.5, "2", (v == 2), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(14, txtbox_x + spaceBetween_w * 3, cSettings.topBarHeight + rh * 17.5, "3", (v == 3), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(15, txtbox_x + spaceBetween_w * 4, cSettings.topBarHeight + rh * 17.5, "4", (v == 4), "settings_radioboxes_action", this.id));
			// Create checkbox Cover Art in Group Header ON/OFF
			this.elements.push(new oCheckBox(16, txtbox_x, cSettings.topBarHeight + rh * 19.5, "Enable Cover", "p.list.groupby[p.settings.pages[2].elements[0].selectedId].showCover == 0 ? false : true", "settings_checkboxes_action", this.id));
			// Create checkbox Auto-Collpase ON/OFF
			this.elements.push(new oCheckBox(17, txtbox_x, cSettings.topBarHeight + rh * 21.25, "Enable Auto-Collapse", "p.list.groupby[p.settings.pages[2].elements[0].selectedId].autoCollapse == 0 ? false : true", "settings_checkboxes_action", this.id));

			var GHF_delta = 13.0;
			var txtbox_value = p.list.groupby[listBoxCurrentId].l1;
			this.elements.push(new oTextBox(18, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * (12.0 + GHF_delta)), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Header line 1, left field", txtbox_value, "settings_textboxes_action", this.id));
			txtbox_value = p.list.groupby[listBoxCurrentId].r1;
			this.elements.push(new oTextBox(19, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * (14.0 + GHF_delta)), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Header line 1, right field", txtbox_value, "settings_textboxes_action", this.id));
			txtbox_value = p.list.groupby[listBoxCurrentId].l2;
			this.elements.push(new oTextBox(20, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * (16.0 + GHF_delta)), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Header line 2, left field", txtbox_value, "settings_textboxes_action", this.id));
			txtbox_value = p.list.groupby[listBoxCurrentId].r2;
			this.elements.push(new oTextBox(21, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * (18.0 + GHF_delta)), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Header line 2, right field", txtbox_value, "settings_textboxes_action", this.id));

			// Create radio buttons for Defaul Group Status (Collapsed OR Expanded)
			var spaceBetween_w = zoom(90, g_dpi);
			this.elements.push(new oRadioButton(22, txtbox_x, cSettings.topBarHeight + rh * 23.0, "Collapsed", (p.list.groupby[p.settings.pages[2].elements[0].selectedId].collapseGroupsByDefault == "1"), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(23, txtbox_x + spaceBetween_w, cSettings.topBarHeight + rh * 23.0, "Expanded", (p.list.groupby[p.settings.pages[2].elements[0].selectedId].collapseGroupsByDefault == "0"), "settings_radioboxes_action", this.id));

			break;
		case 3: // Appearance
			var rh = cSettings.rowHeight;
			// Create checkbox enable wpp
			this.elements.push(new oCheckBox(0, 20, cSettings.topBarHeight + rh * 2.25, "Enabled", "properties.showwallpaper", "settings_checkboxes_action", this.id));

			// Create radio buttons / Wpp Image
			var spaceBetween_w = zoom(80, g_dpi);
			// force value if set to an unauthirized one (default = 0 <=> front album cover)
			if (properties.wallpapermode != 0 && properties.wallpapermode != 4 && properties.wallpapermode != -1) {
				properties.wallpapermode = 0;
				window.SetProperty("CUSTOM Wallpaper Type", properties.wallpapermode);
			};
			this.elements.push(new oRadioButton(1, txtbox_x, cSettings.topBarHeight + rh * 4.0, "Album", (properties.wallpapermode == 0), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(2, txtbox_x + spaceBetween_w, cSettings.topBarHeight + rh * 4.0, "Artist", (properties.wallpapermode == 4), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(3, txtbox_x + spaceBetween_w * 2, cSettings.topBarHeight + rh * 4.0, "Default", (properties.wallpapermode == -1), "settings_radioboxes_action", this.id));

			// Create checkbox blur effect
			this.elements.push(new oCheckBox(4, 20, cSettings.topBarHeight + rh * 5.75, "Blurred", "properties.wallpaperblurred", "settings_checkboxes_action", this.id));

			// Create radio buttons / Wpp alpha shading
			var spaceBetween_w = zoom(65, g_dpi);
			// force alpha value to an authorized value (default = 175 <=> 70%)
			if (properties.wallpaperalpha != 125 && properties.wallpaperalpha != 150 && properties.wallpaperalpha != 172 && properties.wallpaperalpha != 200 && properties.wallpaperalpha != 225) {
				properties.wallpaperalpha = 175;
				window.SetProperty("CUSTOM Wallpaper Alpha", properties.wallpaperalpha);
			};
			this.elements.push(new oRadioButton(5, txtbox_x, cSettings.topBarHeight + rh * 7.5, "50%", (properties.wallpaperalpha == 125), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(6, txtbox_x + spaceBetween_w, cSettings.topBarHeight + rh * 7.5, "60%", (properties.wallpaperalpha == 150), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(7, txtbox_x + spaceBetween_w * 2, cSettings.topBarHeight + rh * 7.5, "70%", (properties.wallpaperalpha == 175), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(8, txtbox_x + spaceBetween_w * 3, cSettings.topBarHeight + rh * 7.5, "80%", (properties.wallpaperalpha == 200), "settings_radioboxes_action", this.id));
			this.elements.push(new oRadioButton(9, txtbox_x + spaceBetween_w * 4, cSettings.topBarHeight + rh * 7.5, "90%", (properties.wallpaperalpha == 225), "settings_radioboxes_action", this.id));

			// Create TextBox Wpp path of default image
			var txtbox_value = properties.wallpaperpath;
			this.elements.push(new oTextBox(10, txtbox_x, Math.ceil(cSettings.topBarHeight + rh * 8.25), ww - txtbox_x - 20 - this.scrollbarWidth, cHeaderBar.height, "Default Wallpaper Path", txtbox_value, "settings_textboxes_action", this.id));

			// Create checkbox Use custom colors
			this.elements.push(new oCheckBox(11, 20, cSettings.topBarHeight + rh * 11.0, "Enable Custom Colors", "properties.enableCustomColors", "settings_checkboxes_action", this.id));

			// Color Widgets for Custom Colors
			var wgt_w = zoom(300, g_dpi);
			var wgt_h = zoom(65, g_dpi)
				var left_padding = zoom(20, g_dpi);
			this.elements.push(new oWidget(12, txtbox_x + left_padding, Math.floor(cSettings.topBarHeight + rh * 12.00), wgt_w, wgt_h, "Custom Color - Normal Text", 0, "settings_HSLwidgets_action", this.id));
			this.elements.push(new oWidget(13, txtbox_x + left_padding, Math.floor(cSettings.topBarHeight + rh * 15.25), wgt_w, wgt_h, "Custom Color - Selected Text", 1, "settings_HSLwidgets_action", this.id));
			this.elements.push(new oWidget(14, txtbox_x + left_padding, Math.floor(cSettings.topBarHeight + rh * 18.50), wgt_w, wgt_h, "Custom Color - Normal Background", 2, "settings_HSLwidgets_action", this.id));
			this.elements.push(new oWidget(15, txtbox_x + left_padding, Math.floor(cSettings.topBarHeight + rh * 21.75), wgt_w, wgt_h, "Custom Color - Selected Background", 3, "settings_HSLwidgets_action", this.id));
			this.elements.push(new oWidget(16, txtbox_x + left_padding, Math.floor(cSettings.topBarHeight + rh * 25.00), wgt_w, wgt_h, "Custom Color - Highlight", 4, "settings_HSLwidgets_action", this.id));
			break;
		};
	};

	this.reSet = function () {
		this.elements.splice(0, this.elements.length);
		// scrollbar reset
		this.offset = 0;
		this.scrollbar.reSet(this.total_rows, cSettings.rowHeight, this.offset);
		if (this.scrollbar.visible) {
			this.scrollbarWidth = this.scrollbar.w;
		} else {
			this.scrollbarWidth = 0;
		};
		this.init();
	};

	this.setSize = function () {
		this.x = p.settings.x;
		this.y = p.settings.y + cSettings.topBarHeight;
		this.w = p.settings.w;
		this.h = p.settings.h - cSettings.topBarHeight;

		this.elements.splice(0, this.elements.length);

		// scrollbar resize
		this.offset = 0;
		this.scrollbar.reSize(p.settings.x + p.settings.w - cScrollBar.width, p.settings.y + cSettings.topBarHeight + cHeaderBar.height, cScrollBar.width, p.settings.h - cSettings.topBarHeight - cHeaderBar.height, this.total_rows, cSettings.rowHeight, this.offset);
		if (this.scrollbar.visible) {
			this.scrollbarWidth = this.scrollbar.w;
		} else {
			this.scrollbarWidth = 0;
		};
		this.init();
	};

	this.draw = function (gr) {

		var fin = this.elements.length;
		for (var i = 0; i < fin; i++) {
			this.elements[i].draw(gr);
		};

		// draw extra elements
		var rh = cSettings.rowHeight;
		var txtbox_x = 20;

		switch (this.id) {
		case 0:
			gr.gdiDrawText("Layout", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 1.5 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Playlist Manager", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 6.5 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Tagging", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 9.5 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Behaviour", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 11.5 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Default Playlist Action", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 14.5 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			break;
		case 1:
			var listBoxWidth = zoom(100, g_dpi);
			gr.gdiDrawText("Status", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 4.5 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Text Alignment", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 14.5 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);

			// new column button
			var nx = 20 + listBoxWidth + zoom(30, g_dpi);
			var ny = Math.floor(cSettings.topBarHeight + rh * 2.1) - (this.offset * cSettings.rowHeight);
			if (p.headerBar.columns.length < properties.max_columns) {
				p.settings.newbutton.draw(gr, nx, ny, 255);
			} else {
				gr.DrawImage(p.settings.newColumn_no, nx, ny, p.settings.newColumn_no.Width, p.settings.newColumn_no.Height, 0, 0, p.settings.newColumn_no.Width, p.settings.newColumn_no.Height, 0, 255);
			};
			// delete user column button
			var spaceBetween_w = g_z10;
			var dx = 20 + listBoxWidth + zoom(30, g_dpi);
			var dy = Math.floor(cSettings.topBarHeight + rh * 2.1 + zoom(5, g_dpi) + p.settings.newColumn_no.Height) - (this.offset * cSettings.rowHeight);
			var idx = p.settings.pages[1].elements[0].selectedId;
			var ref = p.headerBar.columns[idx].ref;
			if (ref.substr(0, 6) == "Custom") {
				p.settings.delbutton.draw(gr, dx, dy, 255);
			} else {
				gr.DrawImage(p.settings.delColumn_no, dx, dy, p.settings.delColumn_no.Width, p.settings.delColumn_no.Height, 0, 0, p.settings.delColumn_no.Width, p.settings.delColumn_no.Height, 0, 255);
			};
			break;
		case 2:
			var listBoxWidth = zoom(170, g_dpi);
			// new pattern button
			var nx = 20 + listBoxWidth + zoom(30, g_dpi);
			var ny = Math.floor(cSettings.topBarHeight + rh * 2.1) - (this.offset * cSettings.rowHeight);
			if (p.headerBar.columns.length < properties.max_columns) {
				p.settings.newbuttonPattern.draw(gr, nx, ny, 255);
			} else {
				gr.DrawImage(p.settings.newPattern_no, nx, ny, p.settings.newPattern_no.Width, p.settings.newPattern_no.Height, 0, 0, p.settings.newPattern_no.Width, p.settings.newPattern_no.Height, 0, 255);
			};
			// delete pattern button
			var spaceBetween_w = g_z10;
			var dx = 20 + listBoxWidth + zoom(30, g_dpi);
			var dy = Math.floor(cSettings.topBarHeight + rh * 2.1 + zoom(5, g_dpi) + p.settings.newPattern_no.Height) - (this.offset * cSettings.rowHeight);
			var idx = p.settings.pages[2].elements[0].selectedId;
			var ref = p.list.groupby[idx].ref;
			if (ref.substr(0, 6) == "Custom") {
				p.settings.delbuttonPattern.draw(gr, dx, dy, 255);
			} else {
				gr.DrawImage(p.settings.delPattern_no, dx, dy, p.settings.delPattern_no.Width, p.settings.delPattern_no.Height, 0, 0, p.settings.delPattern_no.Width, p.settings.delPattern_no.Height, 0, 255);
			};

			gr.FillSolidRect(txtbox_x, cSettings.topBarHeight + rh * 10.75 - (this.offset * cSettings.rowHeight), p.settings.w - 20 * 2 - cScrollBar.width, cHeaderBar.borderWidth, p.settings.color1);

			gr.gdiDrawText("Collapsed Row Height", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 15.25 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Expanded Row Height", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 16.75 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Cover Art Status", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 18.75 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Auto-Collapse Status", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 20.5 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Default Group Status", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 22.25 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);

			var GHF_delta = 13.0;
			gr.gdiDrawText("Group Header Fields", gdi.Font(p.settings.fontname, p.settings.txtHeight * 1.5, 5), p.settings.color2, txtbox_x, cSettings.topBarHeight + rh * (11.0 + GHF_delta) - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);

			break;
		case 3:
			gr.gdiDrawText("Wallpaper Status", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 1.5 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Wallpaper Image", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 3.25 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Wallpaper Effects", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 5.0 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Wallpaper Alpha Shading", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 6.75 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			gr.gdiDrawText("Customize Panel Colors", gdi.Font(p.settings.fontname, p.settings.txtHeight, 5), p.settings.color1, txtbox_x, cSettings.topBarHeight + rh * 10.25 - (this.offset * cSettings.rowHeight), p.settings.w - 10, p.settings.txtHeight + 10, g_LDT);
			break;
		};

		// draw scrollbar
		if (this.scrollbarWidth > 0) {
			this.scrollbar.drawXY(gr, p.settings.x + p.settings.w - cScrollBar.width, p.settings.y + cSettings.topBarHeight + cHeaderBar.height);
		};
	};

	this.newButtonCheck = function (event, x, y) {
		var fin;

		if (p.headerBar.columns.length >= properties.max_columns)
			return;

		var state = p.settings.newbutton.checkstate(event, x, y);
		switch (event) {
		case "up":
			if (state == ButtonStates.hover) {
				// action
				var no_user = 1;
				var tmp_array = [];
				// copy columns array to a tmp array in order to sort it
				fin = p.headerBar.columns.length;
				for (var i = 0; i < fin; i++) {
					tmp_array.push(p.headerBar.columns[i].ref);
				};
				tmp_array.sort();
				// get free number to affect to the new User column to create
				fin = tmp_array.length;
				for (var i = 0; i < fin; i++) {
					if (tmp_array[i].substr(0, 6) == "Custom") {
						if (tmp_array[i].substr(tmp_array[i].length - 2, 2) == num(no_user, 2)) {
							no_user++;
						};
					};
				};

				p.headerBar.columns.push(new oColumn("Custom " + num(no_user, 2), "null", "null", 0, "Custom " + num(no_user, 2), 0, "null"));
				p.headerBar.totalColumns++;
				window.SetProperty("SYSTEM.HeaderBar.TotalColumns", p.headerBar.totalColumns);
				var arr = [];
				fin = p.headerBar.columns.length;
				for (var i = 0; i < fin; i++) {
					arr.push(p.headerBar.columns[i].ref);
				};
				p.settings.pages[1].elements[0].reSet(arr);
				p.headerBar.saveColumns();
				p.settings.pages[1].elements[0].showSelected(p.headerBar.columns.length - 1);
				full_repaint();
			};
			break;
		};
		return state;
	};

	this.delButtonCheck = function (event, x, y) {
		var fin;

		if (p.headerBar.columns.length <= 14)
			return;

		var state = p.settings.delbutton.checkstate(event, x, y);
		switch (event) {
		case "up":
			if (state == ButtonStates.hover) {
				// action
				var idx = p.settings.pages[1].elements[0].selectedId;
				var ref = p.headerBar.columns[idx].ref;
				if (ref.substr(0, 6) == "Custom") {
					// if the column is visible, percent are to be adjusted on other visible columns before deletinf it
					if (p.headerBar.columns[idx].percent > 0) {
						// check if it's not the last column visible, otherwise, we coundn't hide it!
						var nbvis = 0;
						fin = p.headerBar.columns.length;
						for (var k = 0; k < fin; k++) {
							if (p.headerBar.columns[k].percent > 0) {
								nbvis++;
							};
						};
						if (nbvis > 1) {
							var RemovedColumnSize = Math.abs(p.headerBar.columns[idx].percent);
							p.headerBar.columns[idx].percent = 0;
							var totalColsToResizeUp = 0;
							var last_idx = 0;
							fin = p.headerBar.columns.length;
							for (var k = 0; k < fin; k++) {
								if (k != idx && p.headerBar.columns[k].percent > 0) {
									totalColsToResizeUp++;
									last_idx = k;
								};
							};
							var add_value = Math.floor(RemovedColumnSize / totalColsToResizeUp);
							var reste = RemovedColumnSize - (add_value * totalColsToResizeUp);
							fin = p.headerBar.columns.length;
							for (var k = 0; k < fin; k++) {
								if (k != idx && p.headerBar.columns[k].percent > 0) {
									p.headerBar.columns[k].percent = Math.abs(p.headerBar.columns[k].percent) + add_value;
									if (reste > 0 && k == last_idx) {
										p.headerBar.columns[k].percent = Math.abs(p.headerBar.columns[k].percent) + reste;
									};
								};
								p.headerBar.columns[k].w = Math.abs(p.headerBar.w * p.headerBar.columns[k].percent / 100000);
							};
						} else {
							// it's the last column visible, delete not possile for now !!!
							return false;
						};
					};
					// ok, NOW we can delete this column, let's do it!
					var tmp_array = p.headerBar.columns.slice(0, p.headerBar.columns.length);
					p.headerBar.columns.splice(0, p.headerBar.columns.length);
					fin = tmp_array.length;
					for (var i = 0; i < fin; i++) {
						if (i != idx) {
							p.headerBar.columns.push(tmp_array[i]);
						};
					};
					//
					p.headerBar.totalColumns--;
					window.SetProperty("SYSTEM.HeaderBar.TotalColumns", p.headerBar.totalColumns);
					var arr = [];
					fin = p.headerBar.columns.length;
					for (var i = 0; i < fin; i++) {
						arr.push(p.headerBar.columns[i].ref);
					};
					p.settings.pages[1].elements[0].reSet(arr);
					p.headerBar.saveColumns();
					var new_idx = (idx == 0 ? 0 : idx - 1);
					p.settings.pages[1].elements[0].showSelected(new_idx);
					full_repaint();
				} else {
					// we could not delete a native column!
					return false;
				};
			};
			break;
		};
		return state;
	};

	this.newButtonPatternCheck = function (event, x, y) {
		var fin;

		if (p.list.groupby.length >= properties.max_patterns)
			return;

		var state = p.settings.newbuttonPattern.checkstate(event, x, y);
		switch (event) {
		case "up":
			if (state == ButtonStates.hover) {
				// action
				p.list.groupby.push(new oGroupBy("Pattern to customize", "null", "null", "Custom", "null", "0", "2", "3", "1", "0", "-", "-", "-", "-", "0"));
				p.list.totalGroupBy++;
				window.SetProperty("SYSTEM.Groups.TotalGroupBy", p.list.totalGroupBy);
				var arr = [];
				fin = p.list.groupby.length;
				for (var i = 0; i < fin; i++) {
					arr.push(p.list.groupby[i].label);
				};
				p.settings.pages[2].elements[0].reSet(arr);
				p.list.saveGroupBy();
				p.settings.pages[2].elements[0].showSelected(p.list.groupby.length - 1);
				full_repaint();
			};
			break;
		};
		return state;
	};

	this.delButtonPatternCheck = function (event, x, y) {
		var fin;

		if (p.headerBar.columns.length <= 2)
			return;

		var state = p.settings.delbuttonPattern.checkstate(event, x, y);
		switch (event) {
		case "up":
			if (state == ButtonStates.hover) {
				// action
				var idx = p.settings.pages[2].elements[0].selectedId;
				var ref = p.list.groupby[idx].ref;
				if (ref.substr(0, 6) == "Custom") {
					var tmp_array = p.list.groupby.slice(0, p.list.groupby.length);
					p.list.groupby.splice(0, p.list.groupby.length);
					fin = tmp_array.length;
					for (var i = 0; i < fin; i++) {
						if (i != idx) {
							p.list.groupby.push(tmp_array[i]);
						};
					};
					p.list.totalGroupBy--;
					window.SetProperty("SYSTEM.Groups.TotalGroupBy", p.list.totalGroupBy);
					var arr = [];
					fin = p.list.groupby.length;
					for (var i = 0; i < fin; i++) {
						arr.push(p.list.groupby[i].label);
					};
					p.settings.pages[2].elements[0].reSet(arr);
					p.list.saveGroupBy();
					var new_idx = (idx == 0 ? 0 : idx - 1);
					p.settings.pages[2].elements[0].showSelected(new_idx);

					// reset pattern index after removing the selected one
					if (idx == cGroup.pattern_idx) {
						cGroup.pattern_idx = 0;
						window.SetProperty("SYSTEM.Groups.Pattern Index", cGroup.pattern_idx);
						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();
				} else {
					// we could not delete a native "Group By" pattern!
					return false;
				};
			};
			break;
		};
		return state;
	};

	this.on_mouse = function (event, x, y, delta) {
		this.ishover = (x >= this.x && x <= this.x + this.w && y >= this.y && y <= this.y + this.h);
		switch (this.id) {
		case 1:
			var isHoverListBox = this.elements[0].isHoverObject(x, y);
			break;
		case 2:
			var isHoverListBox = this.elements[0].isHoverObject(x, y);
			break;
		default:
			var isHoverListBox = false;
		};

		switch (event) {
		case "dblclk":
			this.on_mouse("down", x, y);
			break;
		case "down":
		case "up":
		case "move":
		case "wheel":
			if (this.ishover) {
				if (!isHoverListBox) {
					if (this.scrollbar.visible) {
						this.scrollbar.check(event, x, y, delta);
					};
				};
			};
			break;
		};

		switch (this.id) {
		case 1:
			if (this.delButtonCheck(event, x, y) != ButtonStates.hover) {
				if (this.newButtonCheck(event, x, y) != ButtonStates.hover) {
					var fin = this.elements.length;
					for (var i = 0; i < fin; i++) {
						this.elements[i].on_mouse(event, x, y, delta);
					};
				};
			};
			break;
		case 2:
			if (this.delButtonPatternCheck(event, x, y) != ButtonStates.hover) {
				if (this.newButtonPatternCheck(event, x, y) != ButtonStates.hover) {
					var fin = this.elements.length;
					for (var i = 0; i < fin; i++) {
						this.elements[i].on_mouse(event, x, y, delta);
					};
				};
			};
			break;
		default:
			var fin = this.elements.length;
			for (var i = 0; i < fin; i++) {
				this.elements[i].on_mouse(event, x, y, delta);
			};
		};
	};
};

oSettings = function () {
	// inputbox variables
	var temp_bmp = gdi.CreateImage(1, 1);
	var temp_gr = temp_bmp.GetGraphics();
	var g_timer_cursor = false;
	var g_cursor_state = true;

	this.pages = [];
	this.currentPageId = 0;
	this.tabButtons = [];

	// font
	this.fontname = "segoe ui";
	// var for custom color settings (widgets/sliders)
	this.color_updated = false;
	this.colorWidgetFocusedId = -1;
	this.colorSliderFocusedId = -1;

	this.setColors = function () {
		// colors
		this.color0 = blendColors(g_color_normal_bg, g_color_normal_txt, 0.15);
		this.color1 = blendColors(g_color_normal_bg, g_color_normal_txt, 0.5);
		this.color2 = g_color_normal_txt;
		this.color3 = g_color_normal_bg;
	};
	this.setColors();

	this.repaint = function () {
		full_repaint();
	};

	this.setButtons = function () {

		var pic = gdi.CreateImage(500, 200);
		gpic = pic.GetGraphics();
		var button_zoomSize = 0,
		button_zoomSizeW = 0,
		button_zoomSizeH = 0,
		rect_w = 0;
		var lineWidth = zoom(1.5, g_dpi);
		this.font = gdi.Font("segoe ui", zoom(12, g_dpi), 1);

		// Add a Custom Column
		rect_w = gpic.CalcTextWidth("Delete Column", this.font) + zoom(30, g_dpi);
		this.newColumn_off = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.newColumn_off.GetGraphics();
		gb.setSmoothingMode(2);
		gb.FillRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), this.color1);
		gb.SetTextRenderingHint(5);
		gb.DrawString("New Column", this.font, this.color2, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.newColumn_off.ReleaseGraphics(gb);

		rect_w = gpic.CalcTextWidth("Delete Column", this.font) + zoom(30, g_dpi);
		this.newColumn_ov = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.newColumn_ov.GetGraphics();
		gb.setSmoothingMode(2);
		gb.DrawRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), lineWidth, this.color1);
		gb.SetTextRenderingHint(3);
		gb.DrawString("New Column", this.font, this.color2, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.newColumn_ov.ReleaseGraphics(gb);

		rect_w = gpic.CalcTextWidth("Delete Column", this.font) + zoom(30, g_dpi);
		this.newColumn_no = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.newColumn_no.GetGraphics();
		gb.setSmoothingMode(2);
		gb.FillRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), this.color0);
		gb.SetTextRenderingHint(5);
		gb.DrawString("New Column", this.font, this.color3, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.newColumn_no.ReleaseGraphics(gb);

		this.newbutton = new button(this.newColumn_off, this.newColumn_ov, this.newColumn_ov);

		// Delete a Custom Column
		rect_w = gpic.CalcTextWidth("Delete Column", this.font) + zoom(30, g_dpi);
		this.delColumn_off = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.delColumn_off.GetGraphics();
		gb.setSmoothingMode(2);
		gb.FillRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), this.color1);
		gb.SetTextRenderingHint(5);
		gb.DrawString("Delete Column", this.font, this.color2, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.delColumn_off.ReleaseGraphics(gb);

		rect_w = gpic.CalcTextWidth("Delete Column", this.font) + zoom(30, g_dpi);
		this.delColumn_ov = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.delColumn_ov.GetGraphics();
		gb.setSmoothingMode(2);
		gb.DrawRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), lineWidth, this.color1);
		gb.SetTextRenderingHint(3);
		gb.DrawString("Delete Column", this.font, this.color2, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.delColumn_ov.ReleaseGraphics(gb);

		rect_w = gpic.CalcTextWidth("Delete Column", this.font) + zoom(30, g_dpi);
		this.delColumn_no = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.delColumn_no.GetGraphics();
		gb.setSmoothingMode(2);
		gb.FillRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), this.color0);
		gb.SetTextRenderingHint(5);
		gb.DrawString("Delete Column", this.font, this.color3, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.delColumn_no.ReleaseGraphics(gb);

		this.delbutton = new button(this.delColumn_off, this.delColumn_ov, this.delColumn_ov);

		// Add a Custom "Group By" Pattern
		rect_w = gpic.CalcTextWidth("Delete Pattern", this.font) + zoom(30, g_dpi);
		this.newPattern_off = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.newPattern_off.GetGraphics();
		gb.setSmoothingMode(2);
		gb.FillRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), this.color1);
		gb.SetTextRenderingHint(5);
		gb.DrawString("New Pattern", this.font, this.color2, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.newPattern_off.ReleaseGraphics(gb);

		rect_w = gpic.CalcTextWidth("Delete Pattern", this.font) + zoom(30, g_dpi);
		this.newPattern_ov = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.newPattern_ov.GetGraphics();
		gb.setSmoothingMode(2);
		gb.DrawRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), lineWidth, this.color1);
		gb.SetTextRenderingHint(3);
		gb.DrawString("New Pattern", this.font, this.color2, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.newPattern_ov.ReleaseGraphics(gb);

		rect_w = gpic.CalcTextWidth("Delete Pattern", this.font) + zoom(30, g_dpi);
		this.newPattern_no = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.newPattern_no.GetGraphics();
		gb.setSmoothingMode(2);
		gb.FillRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), this.color0);
		gb.SetTextRenderingHint(5);
		gb.DrawString("New Pattern", this.font, this.color3, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.newPattern_no.ReleaseGraphics(gb);

		this.newbuttonPattern = new button(this.newPattern_off, this.newPattern_ov, this.newPattern_ov);

		// Delete a Custom "Group By" Pattern
		rect_w = gpic.CalcTextWidth("Delete Pattern", this.font) + zoom(30, g_dpi);
		this.delPattern_off = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.delPattern_off.GetGraphics();
		gb.setSmoothingMode(2);
		gb.FillRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), this.color1);
		gb.SetTextRenderingHint(5);
		gb.DrawString("Delete Pattern", this.font, this.color2, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.delPattern_off.ReleaseGraphics(gb);

		rect_w = gpic.CalcTextWidth("Delete Pattern", this.font) + zoom(30, g_dpi);
		this.delPattern_ov = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.delPattern_ov.GetGraphics();
		gb.setSmoothingMode(2);
		gb.DrawRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), lineWidth, this.color1);
		gb.SetTextRenderingHint(3);
		gb.DrawString("Delete Pattern", this.font, this.color2, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.delPattern_ov.ReleaseGraphics(gb);

		rect_w = gpic.CalcTextWidth("Delete Pattern", this.font) + zoom(30, g_dpi);
		this.delPattern_no = gdi.CreateImage(rect_w, zoom(32, g_dpi));
		gb = this.delPattern_no.GetGraphics();
		gb.setSmoothingMode(2);
		gb.FillRoundRect(1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), zoom(5, g_dpi), zoom(5, g_dpi), this.color0);
		gb.SetTextRenderingHint(5);
		gb.DrawString("Delete Pattern", this.font, this.color3, 1, 1, rect_w - lineWidth * 2, zoom(28, g_dpi), cc_stringformat);
		this.delPattern_no.ReleaseGraphics(gb);

		this.delbuttonPattern = new button(this.delPattern_off, this.delPattern_ov, this.delPattern_ov);

		// Close Settings Button (BACK)
		this.close_off = gdi.CreateImage(zoom(25, 300), zoom(25, 300));
		gb = this.close_off.GetGraphics();
		gb.setSmoothingMode(2);
		gb.DrawEllipse(zoom(1, 300), zoom(1, 300), zoom(22, 300), zoom(22, 300), zoom(2.0, 300), this.color2);
		gb.DrawEllipse(0, 0, zoom(24, 300), zoom(24, 300), 1.0, RGBA(0, 0, 0, 100));
		gb.DrawEllipse(zoom(2, 300), zoom(2, 300), zoom(20, 300), zoom(20, 300), zoom(1.0, 300), RGBA(0, 0, 0, 50));
		gb.setSmoothingMode(0);
		gb.FillSolidRect(zoom(6, 300), zoom(12, 300), zoom(13, 300), zoom(2.0, 300), this.color2);
		gb.DrawLine(zoom(6, 300), zoom(12, 300), zoom(11, 300), zoom(7, 300), zoom(1.0, 300), this.color2);
		gb.DrawLine(zoom(7, 300), zoom(12, 300), zoom(12, 300), zoom(7, 300), zoom(1.0, 300), this.color2);
		gb.DrawLine(zoom(6, 300), zoom(13, 300), zoom(11, 300), zoom(18, 300), zoom(1.0, 300), this.color2);
		gb.DrawLine(zoom(7, 300), zoom(13, 300), zoom(12, 300), zoom(18, 300), zoom(1.0, 300), this.color2);
		this.close_off.ReleaseGraphics(gb);

		this.close_ov = gdi.CreateImage(zoom(25, 300), zoom(25, 300));
		gb = this.close_ov.GetGraphics();
		gb.setSmoothingMode(2);
		gb.DrawEllipse(zoom(1, 300), zoom(1, 300), zoom(22, 300), zoom(22, 300), zoom(2.0, 300), this.color1);
		gb.DrawEllipse(0, 0, zoom(24, 300), zoom(24, 300), 1.0, RGBA(0, 0, 0, 50));
		gb.DrawEllipse(zoom(2, 300), zoom(2, 300), zoom(20, 300), zoom(20, 300), zoom(1.0, 300), RGBA(0, 0, 0, 25));
		gb.setSmoothingMode(0);
		gb.FillSolidRect(zoom(6, 300), zoom(12, 300), zoom(13, 300), zoom(2.0, 300), this.color1);
		gb.DrawLine(zoom(6, 300), zoom(12, 300), zoom(11, 300), zoom(7, 300), zoom(1.0, 300), this.color1);
		gb.DrawLine(zoom(7, 300), zoom(12, 300), zoom(12, 300), zoom(7, 300), zoom(1.0, 300), this.color1);
		gb.DrawLine(zoom(6, 300), zoom(13, 300), zoom(11, 300), zoom(18, 300), zoom(1.0, 300), this.color1);
		gb.DrawLine(zoom(7, 300), zoom(13, 300), zoom(12, 300), zoom(18, 300), zoom(1.0, 300), this.color1);
		this.close_ov.ReleaseGraphics(gb);

		button_zoomSize = Math.ceil(25 * g_dpi / 100);
		this.closebutton = new button(this.close_off.Resize(button_zoomSize, button_zoomSize, 7), this.close_ov.Resize(button_zoomSize, button_zoomSize, 7), this.close_ov.Resize(button_zoomSize, button_zoomSize, 7));

		pic.ReleaseGraphics(gpic);
	};

	this.refreshColors = function () {
		get_colors();
		this.setColors();
		this.setButtons();

		for (var p = 0; p < this.pages.length; p++) {
			this.pages[p].scrollbar.setCustomColors(g_color_normal_bg, g_color_normal_txt);
			for (var e = 0; e < this.pages[p].elements.length; e++) {
				switch (this.pages[p].elements[e].objType) {
				case "CB":
				case "RB":
					this.pages[p].elements[e].setButtons();
					break;
				};
			};
		};
		full_repaint();
	};

	this.setSize = function (x, y, w, h) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
		this.txtHeight = zoom(12, g_dpi);

		this.setButtons();

		if (this.pages.length <= 0) {
			this.pages.push(new oPage(0, "p.settings.pages[0]", "General", 16));
			this.pages.push(new oPage(1, "p.settings.pages[1]", "Columns", 16));
			this.pages.push(new oPage(2, "p.settings.pages[2]", "Groups", 33));
			this.pages.push(new oPage(3, "p.settings.pages[3]", "Appearance", 28));
		};
		var fin = this.pages.length;
		for (var i = 0; i < fin; i++) {
			this.pages[i].setSize();
		};
	};

	this.draw = function (gr) {
		var padding = 10;
		var titleTxtHeight = zoom(21, g_dpi);
		var tx = 20,
		ty = cSettings.topBarHeight - zoom(1, g_dpi),
		tw = 0,
		th = this.txtHeight + zoom(10, g_dpi) + cHeaderBar.borderWidth,
		tpad = 10 + cSettings.tabPaddingWidth,
		cx = 0,
		cw = 0;
		var tabFont = gdi.Font(this.fontname, this.txtHeight, 3);

		// draw main background
		gr.FillSolidRect(this.x, this.y, this.w, this.h, g_color_normal_bg);
		gr.SetSmoothingMode(2);

		// draw current page content
		this.pages[this.currentPageId].draw(gr);

		gr.FillSolidRect(this.x, this.y + (ty + th), this.w - cScrollBar.width, zoom(4, g_dpi), g_color_normal_bg);
		gr.FillGradRect(this.x, this.y + (ty + th) + zoom(4, g_dpi), this.w - cScrollBar.width, g_z10, 87, g_color_normal_bg, 0, 1.0);

		// draw top background
		gr.FillSolidRect(this.x, this.y, this.w, (ty + th), blendColors(g_color_normal_bg, g_color_normal_txt, 0.05));
		gr.FillGradRect(this.x, this.y + (ty + th) - zoom(4, g_dpi), this.w, zoom(4, g_dpi), 87, 0, RGBA(0, 0, 0, 20), 1.0);

		// draw close button
		this.closebutton.draw(gr, this.x + 13, this.y + 10, 255);
		// draw Panel Title
		var title_x = this.x + this.closebutton.w + 20;
		gr.SetTextRenderingHint(3);
		gr.DrawString("Panel Settings", gdi.Font(this.fontname, titleTxtHeight, 3), this.color2, title_x, this.y + 6, this.w - 50, cSettings.topBarHeight + 10, lt_stringformat);
		// draw panel version
		var version_x = this.x;
		gr.DrawString("v" + g_script_version, gdi.Font(g_fname, g_fsize - 1, 0), this.color1, version_x, this.y, this.w - 4, ty + th - 4, rb_stringformat);
		gr.SetSmoothingMode(0);

		// draw page switcher (tabs!)
		this.tabButtons.splice(0, this.tabButtons.length);
		var gt = null;
		var fin = this.pages.length;
		for (var i = 0; i < fin; i++) {
			tw = gr.CalcTextWidth(this.pages[i].label, tabFont);
			if (i == this.currentPageId) {
				cx = tx;
				cw = tw + tpad * 2;
			};

			// image off
			tmp_tab_img_off = gdi.CreateImage(tw + tpad * 2, th + 4);
			gt = tmp_tab_img_off.GetGraphics();
			gt.SetTextRenderingHint(3);
			gt.DrawString(this.pages[i].label, tabFont, this.color1, tpad, 1, tw + tpad, th, lc_stringformat);
			tmp_tab_img_off.ReleaseGraphics(gt);
			// image on
			tmp_tab_img_on = gdi.CreateImage(tw + tpad * 2, th + 4);
			gt = tmp_tab_img_on.GetGraphics();
			gt.SetTextRenderingHint(3);
			tmp_tab_img_on.ReleaseGraphics(gt);
			// create tab button object
			this.tabButtons.push(new button(tmp_tab_img_off, tmp_tab_img_on, tmp_tab_img_on));

			this.tabButtons[i].draw(gr, tx, ty - 3, 255);
			tx += tw + tpad * 2;
		};

		// active tab bg
		gr.FillSolidRect(cx + zoom(1, g_dpi), ty - g_z2, cw - zoom(1, g_dpi), th + zoom(4.0, g_dpi), g_color_normal_bg);

		// draw tab lineart
		var lineStrength = zoom(1.0, g_dpi);
		gr.FillSolidRect(0, ty + th, cx + lineStrength, lineStrength, this.color1);
		gr.FillSolidRect(cx, ty - zoom(3.0, g_dpi), lineStrength, th + zoom(4.0, g_dpi), this.color1);
		gr.FillSolidRect(cx, ty - zoom(3.0, g_dpi), cw, lineStrength, this.color1);
		gr.FillSolidRect(cx + cw, ty - zoom(3.0, g_dpi), lineStrength, th + zoom(4.0, g_dpi), this.color1);
		gr.FillSolidRect(cx + cw, ty + th, ww - cw - cx, lineStrength, this.color1);
		// active tab text
		gr.SetTextRenderingHint(3);
		gr.DrawString(this.pages[this.currentPageId].label, tabFont, this.color2, cx + tpad, ty - 2, cw + tpad, th, lc_stringformat);

		var tmp_tab_img = null;

		gr.SetSmoothingMode(0);
	};

	this.closeButtonCheck = function (event, x, y) {
		var state = this.closebutton.checkstate(event, x, y);
		switch (event) {
		case "up":
			if (state == ButtonStates.hover) {
				// action
				p.settings.colorWidgetFocusedId = -1;
				p.settings.colorSliderFocusedId = -1;
				cSettings.visible = false;
				this.closebutton.state = ButtonStates.normal;
				resize_panels();
				properties.collapseGroupsByDefault = (p.list.groupby[cGroup.pattern_idx].collapseGroupsByDefault == 0 ? false : true);
				update_playlist(properties.collapseGroupsByDefault);
				p.playlistManager.refresh("", false, false, false);
				full_repaint();
			};
			break;
		};
		return state;
	};

	this.on_mouse = function (event, x, y, delta) {
		var state = null,
		found = false,
		fin = "";
		if (this.closeButtonCheck(event, x, y) != ButtonStates.hover) {
			fin = this.tabButtons.length;
			for (var i = 0; i < fin; i++) {
				state = this.tabButtons[i].checkstate(event, x, y);
				switch (event) {
				case "up":
					if (state == ButtonStates.hover) {
						// action
						found = true;
						this.currentPageId = i;
						this.tabButtons[i].state = ButtonStates.normal;
						full_repaint();
					};
					break;
				};
			};
			if (!found) {
				this.color_updated = false;
				this.pages[this.currentPageId].on_mouse(event, x, y, delta);
			};
		};
	};

	this.on_focus = function (is_focused) {};
};
