// Some basic functions to begin

fn Pi() {
	return 3.14159265;
}
fn atan_base(z) {
	return z - z*z*z/3 + z*z*z*z*z/5 - z*z*z*z*z*z*z/7 + z*z*z*z*z*z*z*z*z/9 
			 - z*z*z*z*z*z*z*z*z*z*z/11 + z*z*z*z*z*z*z*z*z*z*z*z*z/13;
}
fn atan(z) {
	if (z*z < 1)
		return atan_base(z);
	else if (z > 0)
		return Pi()/2 - atan_base(1/z);
	else 
		return 3*Pi()/2 - atan_base(1/z);		
}
fn ToRad(angle) {
	if (angle > 0)
		return angle*Pi()/180;
	else
		return (360+angle)*Pi()/180;
}
fn abs(a) {
	if (a > 0)
		return a;
	else
		return -a;
}
fn double(n) {
	n += 1.1;
	n -= 1.1;
	return n;
}

fn PaintEllipse(w, left, top, right, bottom, width, color)
{
	if (width < 1)
		width = 1;
	a = (right-left)/2.;
	b = (bottom-top)/2.;
	width_2 = width/2.;
	delta = Pi()/20.;
	maxi = 2.*Pi();
	for (i = 0; i < maxi; i += delta) {
		if (i == 0) {
			x0 = left + a + (a - width_2);
			y0 = top  + b;
		} else {
			x0 = x1;
			y0 = y1;
		}
		x1 = left + a + (a - width_2) * cos(i + delta);
		y1 = top  + b + (b - width_2) * sin(i + delta);
		w.DrawLine(x0, y0, x1, y1, width, color);
	}
}

fn DrawCircle(w, cx, cy, R, width, color) {
	PaintEllipse(w, cx-R-width/2., cy-R-width/2., cx+R+width/2., cy+R+width/2., width, color);
}

fn PaintArc(w, cx, cy, R, ang0, ang1, direction, width, color)
{
	if (direction == -1) {
		c = ang0;
		ang0 = ang1;
		ang1 = c;
	}
	ang0 = ang0*Pi()/180;
	ang1 = ang1*Pi()/180;
	delta = 3*Pi()/180;
	if (ang0 > ang1)
		ang1 += 2*Pi();
	for (i = ang0; i < ang1; i += delta) {
		if (i == ang0) {
			x0 = cx + R*cos(i);
			y0 = cy - R*sin(i);
		} else {
			x0 = x1;
			y0 = y1;
		}
		x1 = cx + R*cos(i + delta);
		y1 = cy - R*sin(i + delta);
		w.DrawLine(x0, y0, x1, y1, width, color);
	}
}

fn FillEllipse(w, left, top, right, bottom, background)
{
	a = (right-left)/2.;
	b = (bottom-top)/2.;
	if (a <= 0.5 || b <= 0.5) {
		w.DrawLine(left, top, right, bottom, 1, background);
		return;
	}
	delta = Pi()/10.;
	x0 = left + a;
	y0 = top  + b;
	
	for (i = delta; i < Pi()/2.; i += delta) {
		x1 = a * cos(i);
		y1 = b * sin(i);
		w.DrawRect(x0-x1 , y0-y1, 2*x1 , 2*y1, background);
	}
	width = min(a, b)/4.;
	if (width > 1)
		PaintEllipse(w, left, top, right, bottom, width, background);
}

fn FillCircle(w, cx, cy, R, color) {
	FillEllipse(w, cx-R, cy-R, cx+R, cy+R, color);
}

fn DrawEditField(w, &r, cy, text, SetFrame, UseHistory, UseUp, UseBrowse, SetEditable, NotNull)
{
	DrawCtrlFrame(w, r, SetFrame);
	w.DrawRect(r, :SWhite);
	n = r.bottom - r.top;
	leftPos = r.left;
	if (UseHistory) {
		DrawEdgeButton(w, RectC(leftPos, r.top, n, n));
		w.DrawImage((n - 7) / 2 + leftPos, (n - 8) / 2 + r.top, "CtrlImg::SmallLeft");	
		leftPos += n;
		DrawEdgeButton(w, RectC(leftPos, r.top, n, n));
		w.DrawImage((n - 7) / 2 + leftPos, (n - 8) / 2 + r.top, "CtrlImg::SmallRight");	
		leftPos += n;
	}
	if (UseUp) {
		DrawEdgeButton(w, RectC(leftPos, r.top, n, n));
		w.DrawImage((n - 8) / 2 + leftPos, (n - 6) / 2 + r.top, "CtrlImg::SmallUp");	
		leftPos += n;
	}
	if (UseBrowse) {
		DrawEdgeButton(w, RectC(leftPos, r.top, n, n));
		w.DrawImage((n - 7) / 2 + leftPos, (n - 6) / 2 + r.top, "ClassicCtrlsImg::RA");
		leftPos += n;
	}
	DrawEdgeButton(w, RectC(r.right - n, r.top, n, n));
	w.DrawImage((n - 7) / 2 + r.right - n, (n - 8) / 2 + r.top, "CtrlImg::SmallRight");
	w.DrawText(leftPos + 3, (cy - GetTextSize("", Arial(10)).cy) / 2,
		(SetEditable ? "" : "R/O ")+ (NotNull ? "!" : "") + text, Arial(10), :SMagenta);	
}

ctrl EditFile {
	group "Input fields";

	GetMinSize() { sz = XMinSize(); sz.cy += 6; return sz; }
	GetStdSize() { sz = GetMinSize(); sz.cx *= 10; return sz; }
	
	Text  SetTitle @1;
	bool  SelLoad = false @2;
	Font  SetFont = StdFont() @3;
	bool  SetEditable = true @4 ? "Editable";
	bool  UseUp = false;
	bool  UseBrowse = true;
	bool  UseHistory = false;
	Frame SetFrame = InsetFrame() @5;
	Text  Tip @6;
	bool  WantFocus = true @7;
	bool  NotNull = false;

	Paint(w) {
		r = GetRect();
		DrawEditField(w, r, GetSize().cy, "File name", .SetFrame, .UseHistory, .UseUp, .UseBrowse, .SetEditable, .NotNull);
	}
}

ctrl EditFolder {
	group "Input fields";

	GetMinSize() { sz = XMinSize(); sz.cy += 6; return sz; }
	GetStdSize() { sz = GetMinSize(); sz.cx *= 10; return sz; }
	
	Text  SetTitle @1;
	bool  SelLoad = false @2;
	Font  SetFont = StdFont() @3;
	bool  SetEditable = true @4 ? "Editable";
	bool  UseUp = false;
	bool  UseBrowse = true;
	bool  UseHistory = false;
	Frame SetFrame = InsetFrame() @5;
	Text  Tip @6;
	bool  WantFocus = true @7;
	bool  NotNull = false;

	Paint(w) {
		r = GetRect();
		DrawEditField(w, r, GetSize().cy, "Folder name", .SetFrame, .UseHistory, .UseUp, .UseBrowse, .SetEditable, .NotNull);
	}
}

enum_property ImageFit {
	"0" : "BestFit",
	"1" : "FillFrame",
	"2" : "NoScale",
	"3" : "RepeatToFill"
};

enum_property ImageAngle {
	"0" : "0º",
	"1" : "90º",
	"2" : "180º",
	"3" : "270º"
};

ctrl StaticImage {
	group "Static";

	GetMinSize() { return Size(0, 0); }
	GetStdSize() { return Size(64, 24); }

	Frame      SetFrame @1;
	ImageFit   SetFit;
	ImageAngle SetAngle;
	Color      SetBackground;
	bool 	   UseAsBackground = false;

	Paint(w) {
		r = GetRect();

		DrawCtrlFrame(w, r, .SetFrame);

		sz = Size(r.right - r.left, r.bottom - r.top);

		DeflateRect(r);
		sz = Size(r.right - r.left, r.bottom - r.top);
		w.DrawRect(r.left, r.top, sz.cx, sz.cy, .SetBackground);
		switch(.SetAngle) {
		case "0":
			img = "Controls4U:Controls4U.iml:ImageSample";
			break;
		case "1":
			img = "Controls4U:Controls4U.iml:ImageSample_90";
			break;
		case "2":
			img = "Controls4U:Controls4U.iml:ImageSample_180";
			break;
		case "3":
			img = "Controls4U:Controls4U.iml:ImageSample_270";
			break;			
		}
		if (.SetFit == "0") {
			imagesize = GetImageSize(img);
			rectaspect  = sz.cx/sz.cy; 
			imageaspect = imagesize.cx/imagesize.cy;
			if (rectaspect > imageaspect) 
				w.DrawImage(r.left+(sz.cx-imageaspect*sz.cy)/2, r.top, imageaspect*sz.cy, sz.cy, img);
			else
				w.DrawImage(r.left, r.top+(sz.cy-sz.cx/imageaspect)/2, sz.cx, sz.cx/imageaspect, img);
		} else if (.SetFit == "1") {
			w.DrawImage(r.left, r.top, sz.cx, sz.cy, img);
		} else if (.SetFit == "2") {
			w.DrawImage(r.left, r.top, img);
		} else if (.SetFit == "3") {
			imagesize = GetImageSize(img);
			top = r.top;
			for (left = r.left; left < r.right; left += imagesize.cx) 
				for (top = r.top; top < r.bottom; top += imagesize.cy) 
					w.DrawImage(left, top, img);
		}
		if (.UseAsBackground) { 
			PaintCenterText(w, (r.right+r.left)/2,   (r.top+r.bottom)/2,   "Background", Arial(11), :SBlack);
			PaintCenterText(w, 1+(r.right+r.left)/2, 1+(r.top+r.bottom)/2, "Background", Arial(11), :SWhite);
		}
	}
}

enum_property LineOrientation {
	"\"|\"",
	"\"-\"",
	"\"/\"",
	"\"\\\\\""
};

ctrl StaticLine {
	group "Static";

	GetMinSize() { return Size(0, 0); }
	GetStdSize() { return Size(64, 24); }
	
	int SetWidth = 1;
	LineOrientation SetOrientation = "\"|\"";
	Color SetColor = :SBlack;	

	Paint(w) {
		r = GetRect();
		sz = GetSize();
		if (.SetOrientation == "\"|\"")
			w.DrawLine((r.right-r.left)/2, r.top, (r.right-r.left)/2, r.bottom, .SetWidth, .SetColor);
		else if (.SetOrientation == "\"-\"")
			w.DrawLine(r.left, (r.bottom-r.top)/2, r.right, (r.bottom-r.top)/2, .SetWidth, .SetColor);
		else if (.SetOrientation == "\"/\"")
			w.DrawLine(r.left, r.bottom, r.right, r.top, .SetWidth, .SetColor);
		else 
			w.DrawLine(r.left, r.top, r.right, r.bottom, .SetWidth, .SetColor);					
	}
}

fn PaintArrowEnd(sw, x0, y0, x1, y1, width, color, direction)
{
	wd = width;
	if (width == 1) {
		alen = 16;
		awidth = 2;
	} else {				
		alen = 9*wd;
		awidth = 1.5*wd;
	}
	if (!direction)
		alen = -alen;
	num = width*20/5;
	if (x0 == x1) {
		for (i = 0; i <= num; ++i)
			sw.DrawLine(x0, y0, x0 + awidth*(1 - 2*i/num), y0 + alen, 1, color);
		sw.DrawLine(x0 + awidth, y0 + alen, x0 - awidth, y0 + alen, 1, color);
	} else if (y0 == y1) {
		for (i = 0; i <= num; ++i)
			sw.DrawLine(x0, y0, x0 + alen, y0 - awidth*(1 - 2*i/num), 1, color);
		sw.DrawLine(x0 + alen, y0 - awidth, x0 + alen, y0 + awidth, 1, color);
	} else {
		t = atan((y1-y0)/(x1-x0));
		xa = alen*cos(t);
		ya = alen*sin(t);
		xb = awidth*sin(t);
		yb = awidth*cos(t);
		for (i = 0; i <= num; ++i) {
			fact = 1 - 2.*i/num;
			if (i % 4 > 0 && i < num)
				wid = 2;
			else
				wid = 1;
			sw.DrawLine(x0, y0, x0+xa+xb*fact, y0+ya-yb*fact, wid, color);
		}
		sw.DrawLine(x0+xa+xb, y0+ya-yb, x0+xa-xb, y0+ya+yb, 1, color);				
	}
}

enum_property ArrowOrientation {
	"\"|\"",
	"\"-\"",
	"\"/\"",
	"\"\\\\\"",
	"\"┐_\"",
	"\"_┌\"",
	"\"└┐\"",
	"\"┌┘\""	
};

enum_property ArrowEnds {
	"\"<-\"",
	"\"->\"",
	"\"<->\"",
	"\"-\""
};

ctrl StaticArrow {
	group "Static";

	GetMinSize() { return Size(0, 0); }
	GetStdSize() { return Size(64, 24); }
	
	int SetWidth = 1;
	ArrowOrientation SetOrientation = "|";
	ArrowEnds SetEnds = "<-";
	Color SetColor = :SBlack;	
	
	Paint(sw) {
		true = 1;
		false = 0;
		r = GetRect();
		sz = GetSize();
		color = .SetColor;
		width = .SetWidth;
		
		if (.SetOrientation == "\"|\"")
			orientation = "|";
		else if (.SetOrientation == "\"-\"")
			orientation = "-";
		else if (.SetOrientation == "\"/\"")
			orientation = "/";
		else if (.SetOrientation == "\"|\"")
			orientation = "|";
		else if (.SetOrientation == "\"\\\\\"")
			orientation = "\\";
		else if (.SetOrientation == "\"┐_\"")
			orientation = "┐_";
		else if (.SetOrientation == "\"_┌\"")
			orientation = "_┌";
		else if (.SetOrientation == "\"└┐\"")
			orientation = "└┐";
		else 
			orientation = "┌┘";																		
		
		if (.SetEnds == "\"<-\"")
			ends = "<-";
		else if (.SetEnds == "\"->\"")
			ends = "->";
		else if (.SetEnds == "\"<->\"")
			ends = "<->";
		else
			ends = "-";		
		
		if (orientation == "|") {
			x0 = x1 = (r.right+r.left)/2;
			y0 = r.top;
			y1 = r.bottom;
		} else if (orientation == "-") {
			x0 = r.left;
			y0 = y1 = (r.bottom+r.top)/2;
			x1 = r.right;
		} else if (orientation == "/") {
			x0 = r.left;
			y0 = r.bottom;
			x1 = r.right;
			y1 = r.top;
		} else if (orientation == "┐_") {
			x0 = r.left;
			y0 = r.top + 2*width;
			x1 = r.right;
			y1 = r.bottom - 2*width;
			middle = (r.left+r.right)/2;
		} else if (orientation == "_┌") {
			x0 = r.left;
			y0 = r.bottom - 2*width;
			x1 = r.right;
			y1 = r.top + 2*width;
			middle = (r.left + r.right)/2;
		} else if (orientation == "└┐") {
			x0 = r.left + 2*width;
			y0 = r.top;
			x1 = r.right - 2*width;
			y1 = r.bottom;
			middle = (r.top + r.bottom)/2;
		} else if (orientation == "┌┘") {
			x1 = r.left  + 2*width;
			y1 = r.bottom;
			x0 = r.right - 2*width;
			y0 = r.top;
			middle = (r.top + r.bottom)/2;
		} else {
			x0 = r.left;
			y0 = r.top;
			x1 = r.right;
			y1 = r.bottom;
		}
		if (ends == "<-" || ends == "<->") {
			if (x0 == x1 || orientation == "|" || orientation == "└┐" || orientation == "┌┘") {
				PaintArrowEnd(sw, x0, y0, x0, y1, width, color, true);
				y0 += 9*width;
			} else if (y0 == y1 || orientation == "-" || orientation == "┐_" || orientation == "_┌") {
				PaintArrowEnd(sw, x0, y0, x1, y0, width, color, true);
				x0 += 9*width;
			} else { 
				PaintArrowEnd(sw, x0, y0, x1, y1, width, color, true);
				t = atan((y1-y0)/(x1-x0));
				x0 += 8*width*cos(t);
				y0 += 8*width*sin(t);
			}
		}
		if (ends == "->" || ends == "<->") {	// Same as other but swapping points
			if (x0 == x1 || orientation == "|" || orientation == "└┐" || orientation == "┌┘") {
				PaintArrowEnd(sw, x1, y1, x1, y0, width, color, false);
				y1 -= 9*width;
			} else if (y0 == y1 || orientation == "-" || orientation == "┐_" || orientation == "_┌") {
				PaintArrowEnd(sw, x1, y1, x0, y1, width, color, false);
				x1 -= 9*width;
			} else { 
				PaintArrowEnd(sw, x1, y1, x0, y0, width, color, false);
				t = atan((y1-y0)/(x1-x0));
				x1 -= 9*width*cos(t);
				y1 -= 9*width*sin(t);			
			}
		}		
		if (orientation == "|") 
			sw.DrawLine(x0, y0, x1, y1, width, color);
		else if (orientation == "-") 
			sw.DrawLine(x0, y0, x1, y1, width, color);
		else if (orientation == "/") {
			sw.DrawLine(x0, y0, x1, y1, width, color);
		} else if (orientation == "┐_") {
			middle = (r.left+r.right)/2;
			sw.DrawLine(x0, y0, middle, y0, width, color);
			sw.DrawLine(middle, y0, middle, y1, width, color);
			sw.DrawLine(middle, y1, x1,     y1, width, color);
		} else if (orientation == "_┌") {
			middle = (r.left + r.right)/2;
			sw.DrawLine(x0,     y0, middle, y0, width, color);
			sw.DrawLine(middle, y0, middle, y1, width, color);
			sw.DrawLine(middle, y1, x1,     y1, width, color);
		} else if (orientation == "└┐") {
			middle = (r.top + r.bottom)/2;
			sw.DrawLine(x0, y0,     x0, middle, width, color);
			sw.DrawLine(x0, middle, x1, middle, width, color);
			sw.DrawLine(x1, middle, x1, y1,     width, color);
		} else if (orientation == "┌┘") {
			middle = (r.top + r.bottom)/2;
			sw.DrawLine(x0, y0,     x0, middle, width, color);
			sw.DrawLine(x0, middle, x1, middle, width, color);
			sw.DrawLine(x1, middle, x1, y1,     width, color);
		} else {
			sw.DrawLine(x0, y0, x1, y1, width, color);				
		}
	}
}

ctrl StaticRectangle {
	group "Static";

	GetMinSize() { return Size(0, 0); }
	GetStdSize() { return Size(64, 24); }
	
	int SetWidth = 1;
	Color SetColor = :SBlack;	
	Color SetBackground = Null;
	
	Paint(w) {
		r = GetRect();
		w.DrawRect(r.left, r.top, r.right, r.bottom, .SetBackground);
		w.DrawRect(r.left, r.top, r.right, r.top + .SetWidth, .SetColor);
		w.DrawRect(r.right - .SetWidth, r.top , r.right, r.bottom , .SetColor);
		w.DrawRect(r.left, r.bottom - .SetWidth, r.right, r.bottom, .SetColor);
		w.DrawRect(r.left, r.top, r.left + .SetWidth, r.bottom, .SetColor);
	}
}

ctrl StaticFrame {
	group "Static";

	GetMinSize() { return Size(0, 0); }
	GetStdSize() { return Size(64, 24); }
	
	Frame SetFrame = InsetFrame();
	Color SetBackground = Null;
	
	Paint(w) {
		r = GetRect();
		w.DrawRect(r.left, r.top, r.right, r.bottom, .SetBackground);
		DrawCtrlFrame(w, r, .SetFrame);
	}
}
	
ctrl StaticEllipse {
	group "Static";

	GetMinSize() { return Size(0, 0); }
	GetStdSize() { return Size(64, 24); }
	
	int SetWidth = 1;
	Color SetColor = :SBlack;	
	Color SetBackground = Null;
		
	Paint(w) {
		r = GetRect();
		FillEllipse(w, r.left, r.top, r.right, r.bottom, .SetBackground);
		PaintEllipse(w, r.left, r.top, r.right, r.bottom, .SetWidth, .SetColor);
	}
}

fn PaintPtr(w, cmx, cmy, pos, m, d, color, cf) {
	dx = m * sin(pos * 2 * Pi());
	dy = m * cos(pos * 2 * Pi());

	sx = cmx - dx * 35 / 2.0;
	sy = cmy + dy * 35 / 2.0;
	ex = cmx + dx * cf;
	ey = cmy - dy * cf;

	w.DrawLine(sx, sy, ex, ey, d, color);
}

enum_property HourType {
	"0" : "No",
	"1" : "Square",
	"2" : "Rectangle"
};

enum_property NumberType {
	"0" : "No",
	"1" : "Small",
	"2" : "Big",
	"3" : "BigSmall",
	"4" : "Big4"
};

enum_property ColorType {
	"0" : "WhiteType",
	"1" : "BlackType"
};

ctrl StaticClock {
	group "Progress";
	GetMinSize() { return Size(80, 80); }
	GetStdSize() { return Size(150, 150); }
	
	HourType SetHourType = 1;
	NumberType SetNumberType = 1;
	ColorType SetColorType = 0;
	bool Seconds = true;	
	bool SetAuto = false;	
	Text Tip;
	Frame SetFrame = BlackFrame();

	Paint(w) {
		r = GetRect();
		ro = GetRect();
		
		if (.SetColorType == "0") {
			backColor = :SWhite;
			letterColor = :SBlack;
		} else {
			backColor = :SBlack;
			letterColor = :SWhite;
		}
		r.right = r.bottom = min(r.right, r.bottom);
		bigF = r.right/200;
		hs = 20;
		width = r.right - r.left;
		height = r.bottom - r.top;
		
		FillEllipse(w, r.left, r.top, r.right, r.bottom, backColor);
		
		cmx = width / 2;
		cmy = height / 2;
		cf = min(cmy, cmx) - 2;
		
		if (.SetHourType != "0") {
			for(i = 1; i <= 60; i++) {
				x = cmx + (0.95 * sin(i * Pi() / 30.0) * cf);
				y = cmy - (0.95 * cos(i * Pi() / 30.0) * cf);
				if (.SetHourType == "1") {
					if(i % 5 == 0)
						w.DrawRect(x, y, 3*bigF, 3*bigF, letterColor);
					else
						w.DrawRect(x, y, 2*bigF, 2*bigF, letterColor);
				} else if (.SetHourType == "2") {
					if(i % 5 == 0) {
						x2 = cmx + (0.7 * sin(i * Pi() / 30.0) * cf);
						y2 = cmy - (0.7 * cos(i * Pi() / 30.0) * cf);
						w.DrawLine(x, y, x2, y2, 4*bigF, :Gray);
						w.DrawLine(x, y, x2, y2, 2*bigF, letterColor);
					} else {
						x2 = cmx + (0.8 * sin(i * Pi() / 30.0) * cf);
						y2 = cmy - (0.8 * cos(i * Pi() / 30.0) * cf);
						w.DrawLine(x, y, x2, y2, 1*bigF, :SGray);
					}
				}
			}
		}
		if (.SetNumberType != "0") {
			if (.SetHourType == "0") 
				numberPos = 1;
			else if (.SetHourType == "1") 
				numberPos = 0.96;
			else if (.SetHourType == "2") 
				numberPos = 0.75;
			
			if (.SetNumberType == "1")  {
				numberd = numberPos - 0.2;	
				fnt4 = Arial(14*bigF);
				fnt = Arial(14*bigF);
			} else if (.SetNumberType == "2")  {
				numberd = numberPos - 0.2;
				fnt4 = Arial(20*bigF);
				fnt = Arial(20*bigF);
			} else if (.SetNumberType == "3")  {
				numberd = numberPos - 0.2;
				fnt4 = Arial(20*bigF);
				fnt = Arial(14*bigF);
			} else if (.SetNumberType == "4")  {
				numberd = numberPos - 0.2;
				fnt4 = Arial(20*bigF);
			}
			for(i = 1; i <= 12; i++) {
				x = cmx + (numberd * sin(i * Pi() / 6.0) * cf);
				y = cmy - (numberd * cos(i * Pi() / 6.0) * cf);
				if (i % 3 == 0)
					PaintCenterText(w, x, y, to_string(i), fnt4, letterColor);
				else if (.SetNumberType != "4")
					PaintCenterText(w, x, y, to_string(i), fnt, letterColor);
			}
		}
		hour = 10;
		minute = 34;
		second = 15;

		tm = hour * 3600 + minute * 60 + second;
		PaintPtr(w, cmx, cmy, tm / 3600 / 12, 0.5, 5, Color(200, 200, 200), cf);
		PaintPtr(w, cmx, cmy, tm / 3600 / 12, 0.5, 2, letterColor, cf);
		PaintPtr(w, cmx, cmy, tm / 3600, 0.6, 3, Color(200, 200, 200), cf);
		PaintPtr(w, cmx, cmy, tm / 3600, 0.6, 1, letterColor, cf);
		if (.Seconds)
			PaintPtr(w, cmx, cmy, tm / 60, 0.75, 1, Color(200, 200, 200), cf);

		DrawCtrlFrame(w, ro, .SetFrame);
	}
}
	
fn PaintMarks(w, cx, cy, R, ang0, ang1, direction, step, bigF, color)
{
	if (direction == -1) {
		c = ang0;
		ang0 = ang1;
		ang1 = c;
	}
	ang0 = ToRad(ang0);
	ang1 = ToRad(ang1);
	step = ToRad(step);
	if (ang0 > ang1)
		ang1 += 2*Pi();
	width = 6*bigF;
	for (i = ang0; i <= ang1+0.1; i += step) {
		x0 = cx + (R-width/2+1)*cos(i);
		y0 = cy - (R-width/2+1)*sin(i);
		x1 = cx + 0.93*R*cos(i);
		y1 = cy - 0.93*R*sin(i);
		w.DrawLine(x0, y0, x1, y1, width, color);
	}
}

fn AngAdd(ang, val)
{
	ang += val;
	while (ang >= 360)
		ang -= 360;
	while (ang < 0)
		ang += 360;
	return ang;
}

fn PaintNumbers(w, cx, cy, R, a0, step, direction, minv, maxv, stepv, bigF, color)
{
	a0 = ToRad(a0);
	step = ToRad(step);
	fnt = Arial(13*bigF);
	while (minv <= maxv) {
		x = cx + 0.8*R*cos(a0);
		y = cy - 0.8*R*sin(a0);
		PaintCenterText(w, x, y, to_string(minv), fnt, color);
		a0 += step*direction;
		minv += stepv;
	}
}

fn PaintHand(w, cx, cy, R, val, bigF, colorType)
{
	if (colorType == "0") {
		letterColor = :SBlack;
	} else {
		letterColor = :SWhite;
	}
	val = ToRad(val);
	x0 = cx + 0.90*R*cos(val);
	y0 = cy - 0.90*R*sin(val);
	x1 = cx;
	y1 = cy;
	w.DrawLine(x0, y0, x1, y1, 5*bigF, :SLtGray);
	x2 = cx + 0.4*R*cos(val);
	y2 = cy - 0.4*R*sin(val);
	w.DrawLine(x0, y0, x2, y2, 4*bigF, letterColor);
	x3 = cx - 0.3*R*cos(val);
	y3 = cy + 0.3*R*sin(val);
	w.DrawLine(x1, y1, x3, y3, 5*bigF, letterColor);
	
	left = cx-bigF*18;
	right = cx+bigF*18;
	top = cy-bigF*18;
	bottom = cy+bigF*18;
	FillEllipse(w, left, top, right, bottom, :SLtGray);
	
	left = cx-bigF*15;
	right = cx+bigF*15;
	top = cy-bigF*15;
	bottom = cy+bigF*15;
	FillEllipse(w, left, top, right, bottom, :SBlack);
}

ctrl Meter {
	group "Progress";
	GetMinSize() { return Size(50, 50); }
	GetStdSize() { return Size(150, 100); }
	
	double SetMin = 0;
	double SetMax = 100;
	double SetPeak = 80;
	double SetStep = 20;	
	double SetAngleBegin = 130;
	double SetAngleEnd = 50;
	Text SetText = "";
	bool ClockWise = true;
	bool SetNumber = true;
	ColorType SetColorType = 0;
	Text Tip;
	Frame SetFrame = BlackFrame();

	Paint(w) {
		r = GetRect();
		
		if (.SetColorType == "0") {
			backColor = :SWhite;
			letterColor = :SBlack;
		} else {
			backColor = :SBlack;
			letterColor = :SWhite;
		}
		
		w.DrawRect(r, backColor);
		width = r.right - r.left;
		bigF = width/200;
		bigH = (r.bottom-r.top)/100;
		
		if (.ClockWise)
			direction = -1;
		else
			direction = 1;
		a = .SetAngleBegin;
		b = .SetAngleEnd;
		cosa = cos(ToRad(a));
		cosb = cos(ToRad(b));
		sina = sin(ToRad(a));
		sinb = sin(ToRad(b));
		minx = cosa;
		maxx = cosa;
		miny = sina;
		maxy = sina;
		angminx = a;
		angminy = a;
		if (cosb < minx) {
			minx = cosb;
			angminx = b;
		}
		if (cosb > maxx) 
			maxx = cosb;
		if (sinb > miny) {
			miny = sinb;
			angminy = b;
		}
		if (sinb < maxy)
			maxy = sinb;
		maxgrad = 0;
		for (ang = a; ang != b; ang = AngAdd(ang, direction)) {
			maxgrad++;
			if (ang == 180) {
				minx = -1;
				angminx = 180;
			} else if (ang == 0) {
				maxx = 1;
				angmaxx = 0; 
			} else if (ang == 90) {
				miny = 1;
				angminy = 90;
			} else if (ang == 270)
				maxy = -1;
		}
		if (maxx == minx)
			return;	// Error
		rate = width/(maxx - minx);
		cx = -minx*rate;
		R = 0.92*abs(rate*minx/cos(ToRad(angminx)));
		if (abs(miny) >= abs(maxy))
			cy = 1.08*R*miny;
		else
			cy = r.bottom + 1.08*R*maxy;
		
		PaintArc(w, cx, cy, R, a, b, direction, 0.8*bigF, letterColor);
		
		if (.SetPeak < .SetMax && .SetPeak > .SetMin) {
			valpk = .SetPeak*maxgrad/(.SetMax-.SetMin);
			for (i = 0.93; i < 0.98; i+= 0.004)
				PaintArc(w, cx, cy, i*R, a + valpk*direction, b, direction, 2*bigF, :SLtRed);
			fsize = 7*min(bigF, bigH);
			fnt = Arial(fsize);
			txtx = cx + R*cos(ToRad(b))/2;
			txty = cy - R*sin(ToRad(b))/2;
			PaintCenterText(w, txtx, txty, "PEAK", fnt, :Gray);
			w.DrawImage(txtx - fsize, txty + fsize, 1.8*fsize, 1.8*fsize, "Controls4U:Controls4U.iml:LightOff");	
		}
		stepa = .SetStep*maxgrad/(.SetMax-.SetMin);	
		PaintMarks(w, cx, cy, R, a, b, direction, stepa, bigF, letterColor);
		if (.SetNumber)
			PaintNumbers(w, cx, cy, R, a, stepa, direction, .SetMin, .SetMax, .SetStep, bigF, letterColor);
			   
		fnt = Arial(20*min(bigF, bigH));
		angtxt = ToRad(a + maxgrad*direction/2);
		txtx = cx + R*cos(angtxt)/2;
		txty = cy - R*sin(angtxt)/2;
		PaintCenterText(w, txtx, txty, .SetText, fnt, letterColor);
		
		val = .SetMin + 0.8*(.SetMax-.SetMin);
		vala = val*maxgrad/(.SetMax-.SetMin);
		PaintHand(w, cx, cy, R, a + vala*direction, bigF, .SetColorType);
		
		DrawCtrlFrame(w, r, .SetFrame);
	}
}


ctrl FileBrowser {
	group "Complex";

	GetMinSize() { return Size(0, 0); }
	GetStdSize() { return Size(200, 100); }

	Frame SetFrame @1;
	bool SetBrowseFiles = true @2 ? "Editable";	
	bool SetReadOnly = false;
	bool SetUseTrashBin = true;
	bool SetBrowseLinks = true;
	bool SetDeleteReadOnly = false;
	bool SetAskBeforeDelete = true;
	bool SetDragAndDrop = true;

	Paint(w) {
		outer = GetRect();
		r = outer;
		DeflateRect(r);
		
		re = RectC(r.left, r.top, r.right, r.top+20);
		DrawEditField(w, re, 20, "Folder name", 1, 1, 1, 0, 1, 1);
		
		r.top += 24;
		sz = Size(r.right - r.left, r.bottom - r.top);
		
		w.DrawSmartText(r.left, r.top, "Folders", StdFont(), :SBlack);
		w.DrawRect(r.left, r.top+18, r.right, r.bottom, :SWhite);
		w.DrawImage(r.left, r.top+18, "Controls4U:Controls4U.iml:FileBrowser_Folders");
		if (.SetBrowseFiles) {
			middle = r.left + (r.right-r.left)/2;
			w.DrawLine(middle-4, r.top, middle-3, r.bottom, 2, :SWhiteGray);
			w.DrawRect(middle-2, r.top, 4, r.bottom, :SLtGray);
			w.DrawLine(middle+2, r.top, middle+2, r.bottom, 2, :SGray);
			w.DrawImage(middle + 3, r.top, "Controls4U:Controls4U.iml:FileBrowser_Files");
		}
		DrawCtrlFrame(w, outer, .SetFrame);
	}
}

ctrl FirefoxBrowser {
	group "Complex";

	GetMinSize() { return Size(0, 0); }
	GetStdSize() { return Size(140, 140); }

	Frame 	SetFrame @1;
	bool	SetStatus = true;

	Paint(w) {
		r = GetRect();

		DrawCtrlFrame(w, r, .SetFrame);

		sz = Size(r.right - r.left, r.bottom - r.top);

		DeflateRect(r);
		sz = Size(r.right - r.left, r.bottom - r.top);
		w.DrawRect(r.left, r.top, sz.cx, sz.cy, :SWhite);
		img = "Controls4U:Controls4U.iml:Icon_Firefox";
		w.DrawImage(r.left, r.top, img);
	}
}

ctrl IExplorerBrowser {
	group "Complex";

	GetMinSize() { return Size(0, 0); }
	GetStdSize() { return Size(130, 130); }

	Frame 	SetFrame @1;
	bool	SetStatus = true;

	Paint(w) {
		r = GetRect();

		DrawCtrlFrame(w, r, .SetFrame);

		sz = Size(r.right - r.left, r.bottom - r.top);

		DeflateRect(r);
		sz = Size(r.right - r.left, r.bottom - r.top);
		w.DrawRect(r.left, r.top, sz.cx, sz.cy, :SWhite);
		img = "Controls4U:Controls4U.iml:Icon_IExplorer";
		w.DrawImage(r.left, r.top, img);
	}
}

ctrl VLCPlayer {
	group "Complex";

	GetMinSize() { return Size(0, 0); }
	GetStdSize() { return Size(120, 120); }

	Frame 	SetFrame @1;
	bool	SetStatus = true;

	Paint(w) {
		r = GetRect();

		DrawCtrlFrame(w, r, .SetFrame);

		sz = Size(r.right - r.left, r.bottom - r.top);

		DeflateRect(r);
		sz = Size(r.right - r.left, r.bottom - r.top);
		w.DrawRect(r.left, r.top, sz.cx, sz.cy, :SWhite);
		img = "Controls4U:Controls4U.iml:Icon_VLC";
		w.DrawImage(r.left, r.top, img);
	}
}

fn PaintMarksK(w, cx, cy, R, begin, end, ang0, ang1, direction, minorstep, nminor, nmajor, bigF, color) {
	if (direction == -1) {
		c = ang1;
		ang1 = ang0;
		ang0 = c;
	}
	ang0 = ToRad(ang0);
	minorstep = ToRad(minorstep);
	width = bigF;
	inum = 0;
	imin = nminor;
	for (iang = ang0; inum < nmajor+2; iang += minorstep) {
		if (imin >= nminor) {
			imin = 0;
			x0 = cx + end*R*cos(iang);
			y0 = cy - end*R*sin(iang);
			x1 = cx + begin*R*cos(iang);
			y1 = cy - begin*R*sin(iang);
			w.DrawLine(x0, y0, x1, y1, width, color);
			inum++;			
		} else {
			x0 = cx + (begin+end)*R*cos(iang)/2.;
			y0 = cy - (begin+end)*R*sin(iang)/2.;
			FillCircle(w, x0, y0, 0.2*(end-begin)*R, color);
			imin++;			
		}
	}
}

fn PaintNumbersK(w, cx, cy, R, a0, step, direction, minv, maxv, stepv, bigF, color) {
	range = maxv - minv;
	a0 = ToRad(a0);
	step = ToRad(step);
	fnt = Arial(3+(4*bigF));
	strmaxv = "";
	strminv = "";
	strmaxv = to_string(int(maxv));//FormatDoubleAdjust(maxv, range);
	while (strminv != strmaxv) {
		x = cx + 0.8*R*cos(a0);
		y = cy - 0.8*R*sin(a0);
		strminv = to_string(int(minv));//FormatDoubleAdjust(minv, range);
		fsz = GetTextSize(strminv, fnt);
		w.DrawText(x-fsz.cx/2, y-fsz.cy/2, strminv, fnt, color);
		a0 += step*direction;
		minv += stepv;
	}
}

fn PaintRugged(w, cx, cy, angle, r, rugg, numRug, color) {
	angle = 0;
	deltaAngle = 360./numRug;
	
	iang = angle;
	for (i = 0; i <= numRug; i++) {
		if (deltaAngle > 360)
			deltaAngle -= 360;
		
		PaintArc(w, cx, cy, r-rugg/2-1, iang, iang+0.6*deltaAngle, 1, rugg+1, color);
		PaintArc(w, cx, cy, r, 			iang, iang+0.6*deltaAngle, 1, 1, :SGray);
		riang = ToRad(iang);
		w.DrawLine(cx+r*cos(riang), cx-r*sin(riang), cx+(r-rugg)*cos(riang), cx-(r-rugg)*sin(riang), 1, :SGray);
		iang += deltaAngle;
	}
}

enum_property ColorTypeKnob {	
	"0" : "SimpleWhiteType",
	"1" : "SimpleBlackType",
	"2" : "WhiteType",
	"3" : "BlackType"
};

enum_property Mark {
	"0" : "NoMark",
	"1" : "Line",
	"2" : "Circle"
};

enum_property Style {
	"0" : "Simple",
	"1" : "Rugged"
};

ctrl Knob {
	group "Input fields";
	
	GetMinSize() { return Size(50, 50); }
	GetStdSize() { return Size(100, 100); }
	
	ColorTypeKnob SetColorType = 0;
	Mark SetMark = 1;
	Style SetStyle = 0;
	bool SetNumber = true;
	bool SetInterlocking = false;
	double SetMin = 0;
	double SetMax = 100;
	double SetMajorStep = 20;
	double SetMinorStep = 10;
	double SetAngleBegin = 225;
	double SetAngleEnd = 315;
	double SetKeyStep = 1;
	
	bool ClockWise = true;
	Text Tip;

	Paint(w) {
		sz = GetSize();
		maxgrad = abs(.SetAngleEnd - .SetAngleBegin);
		if (.ClockWise)
			maxgrad = 360 - maxgrad;
		dangle = 135;
		if (.ClockWise)
			dangle = .SetAngleBegin - dangle;
		else
			dangle = .SetAngleBegin + dangle;
		angle = ToRad(dangle);
		r = min(sz.cx/2., sz.cy/2.);
		cx = r;
		cy = r;
		
		if (.ClockWise)
			direction = -1;
		else
			direction = 1;
		
		if (.SetMajorStep == 0)
			.SetMajorStep = .SetMax-.SetMin;
		
		.SetMajorStep = (.SetMax-.SetMin)/int((.SetMax-.SetMin)/.SetMajorStep);
		
		if (.SetMinorStep > .SetMajorStep || .SetMinorStep == 0)
			.SetMinorStep = .SetMajorStep;
		
		//minorstep = (maxv-minv)/((nmajor+1)*(nminor+1));
		if (.SetMinorStep == 0) {
			nminor = 0;
			//.SetMinorStep = 0;
		} else {
			nminor = int(.SetMajorStep/.SetMinorStep) - 1;
			.SetMinorStep = .SetMajorStep/int(.SetMajorStep/.SetMinorStep);
		}
		//majorstep = (maxv-minv)/(nmajor+1);
		nmajor = int((.SetMax-.SetMin)/.SetMajorStep) - 1;
		
		//minorstep = (.SetMax-.SetMin)/((.SetMajorMarks+1)*(.SetMinorMarks+1));
		//majorstep = (.SetMax-.SetMin)/(.SetMajorMarks+1);
		minorstepa = .SetMinorStep*maxgrad/double(.SetMax-.SetMin);	// Step in angle
		majorstepa = .SetMajorStep*maxgrad/double(.SetMax-.SetMin);	
	
		if (.SetNumber) {
			PaintNumbersK(w, cx, cy, r, .SetAngleBegin, majorstepa, direction, .SetMin, .SetMax, .SetMajorStep, r/40., :SBlack);
			PaintMarksK(w, cx, cy, r, 0.65, 0.73, .SetAngleBegin, .SetAngleEnd, direction, minorstepa, nminor, nmajor, r/40., :SBlack);
			r *= 0.65;
		} else {
			PaintMarksK(w, cx, cy, r, 0.9, 1, .SetAngleBegin, .SetAngleEnd, direction, minorstepa, nminor, nmajor, r/40., :SBlack);
			r *= 0.9;
		}		
		capt = 0;
		fill = (.SetColorType == "0" || .SetColorType == "2") ? :SWhite : Color(20, 20, 20);
		rugg = 0;
		if (.SetStyle == "1") 
			rugg = 0.5+0.04*r;
		ruggColor = fill;
		if (.SetColorType == "2")
			ruggColor = :SLtGray;
		if (.SetStyle == "1") 
			PaintRugged(w, cx, cy, dangle, r-capt, rugg, r/5, ruggColor);

		realR = r-capt-rugg;
		if (.SetColorType == "0" || .SetColorType == "1") {
			FillCircle(w, cx, cy, realR, fill);
					
			lineColor = (.SetColorType == "0") ? Color(20, 20, 20) : :SWhite;
			if (.SetMark == "1")
				w.DrawLine(cx+(r-capt)*cos(angle), cy-(r-capt)*sin(angle), 
						    cx+0.5*r*cos(angle), cy-0.5*r*sin(angle), r/25., lineColor);
			else if (.SetMark == "2")
				DrawCircle(w, cx+0.7*r*cos(angle), cy-0.7*r*sin(angle), 0.15*r, 1, lineColor);
		} else if (.SetColorType == "2" || .SetColorType == "3") {
			wm = sz.cx;
			if (.SetColorType == "2")
				w.DrawImage(cx-realR, cx-realR, 2*realR, 2*realR, "Controls4U:Controls4U.iml:Handle");
			else
				w.DrawImage(cx-realR, cx-realR, 2*realR, 2*realR, "Controls4U:Controls4U.iml:HandleBlack");
		}
		lineColor = (colorType == WhiteType) ? :SBlack : :SWhite;
		almostColor = (colorType == WhiteType) ? Color(220, 220, 220) : Color(60, 60, 60);
		if (.SetMark == "1")
			w.DrawLine(cx+realR*cos(angle), cy-realR*sin(angle), 
						    cx+0.5*r*cos(angle), cy-0.5*r*sin(angle), r/25., lineColor);
		else if (.SetMark == "2") {
			ccx = cx+0.7*r*cos(angle);
			ccy = cy-0.7*r*sin(angle);
			if (.SetColorType == "2") 
				w.DrawImage(ccx-0.15*r, ccy-0.15*r, 2*0.15*r, 2*0.15*r, "Controls4U:Controls4U.iml:Digit");
			else 
				w.DrawImage(ccx-0.15*r, ccy-0.15*r, 2*0.15*r, 2*0.15*r, "Controls4U:Controls4U.iml:DigitBlack");
		}
	}
}

