//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//controltype_button_event
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LRESULT controltype_button_event(control *c, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	controltype_button_details *details = (controltype_button_details *) c->controldetails;

	switch (msg)
	{
		case WM_DROPFILES:
		{
			char buffer[MAX_PATH];
			variables_set(false, "DroppedFile", get_dragged_file(buffer, wParam));
			agent_notify(details->agents[ (details->is_twostate ? CONTROLTYPE_TWOSTATEBUTTON_AGENT_ONDROP : CONTROLTYPE_BUTTON_AGENT_ONDROP)], NOTIFY_CHANGE, NULL);
			break;
		}

		case WM_LBUTTONDOWN:
		case WM_RBUTTONDOWN:
		case WM_MBUTTONDOWN:
		case WM_LBUTTONDBLCLK:
		case WM_RBUTTONDBLCLK:
		case WM_MBUTTONDBLCLK:

			//If this is a switchbutton that is not writable, break
			if (details->is_twostate == true
				&& details->agents[CONTROLTYPE_TWOSTATEBUTTON_AGENT_VALUECHANGE] != NULL
				&& details->agents[CONTROLTYPE_TWOSTATEBUTTON_AGENT_VALUECHANGE]->writable == false)
			{
				break;
			}
			
			//Notify the agents of events
			details->pressed = details->hilite = true;
			style_draw_invalidate(c);
			if (false == details->is_twostate)
			{
				//Action button - Mouse down - TRIGGER type
				int mouse_agent = CONTROLTYPE_BUTTON_AGENT_MOUSEDOWN;
				if	( ((msg == WM_LBUTTONDOWN) || (msg == WM_LBUTTONDBLCLK)) &&
					(details->agents[CONTROLTYPE_BUTTON_AGENT_LMOUSEDOWN] != NULL))
						mouse_agent = CONTROLTYPE_BUTTON_AGENT_LMOUSEDOWN;
				else
				if	( ((msg == WM_RBUTTONDOWN) || (msg == WM_RBUTTONDBLCLK)) &&
					(details->agents[CONTROLTYPE_BUTTON_AGENT_RMOUSEDOWN] != NULL))
						mouse_agent = CONTROLTYPE_BUTTON_AGENT_RMOUSEDOWN;
				else
				if	( ((msg == WM_MBUTTONDOWN) || (msg == WM_MBUTTONDBLCLK)) &&
					(details->agents[CONTROLTYPE_BUTTON_AGENT_MMOUSEDOWN] != NULL))
						mouse_agent = CONTROLTYPE_BUTTON_AGENT_MMOUSEDOWN;

				agent_notify(details->agents[mouse_agent], NOTIFY_CHANGE, NULL);
			}
			break;

		case WM_KILLFOCUS:
		case WM_LBUTTONUP:
		case WM_RBUTTONUP:
		case WM_MBUTTONUP:

			//If this is a switchbutton that is not writable, break
			if (details->is_twostate == true
				&& details->agents[CONTROLTYPE_TWOSTATEBUTTON_AGENT_VALUECHANGE] != NULL
				&& details->agents[CONTROLTYPE_TWOSTATEBUTTON_AGENT_VALUECHANGE]->writable == false)
			{
				break;
			}

			if (details->pressed)
			{
				bool trigger = details->hilite;
				details->pressed = details->hilite = false;
				style_draw_invalidate(c);
				if (trigger)
				{
					//Notify the agents of events
					if (details->is_twostate)
					{
						details->is_on = false == details->is_on;
						//Value change - BOOL type
						agent_notify(details->agents[CONTROLTYPE_TWOSTATEBUTTON_AGENT_VALUECHANGE], NOTIFY_CHANGE, (void *) &details->is_on);
						//Pressed/Unpressed - TRIGGER type
						agent_notify(details->agents[(details->is_on ? CONTROLTYPE_TWOSTATEBUTTON_AGENT_PRESSED : CONTROLTYPE_TWOSTATEBUTTON_AGENT_UNPRESSED)], NOTIFY_CHANGE, NULL);
					}
					else
					{
						//Action button - Mouse up - TRIGGER type
						int mouse_agent = CONTROLTYPE_BUTTON_AGENT_MOUSEUP;
						if ( (msg == WM_LBUTTONUP) && (details->agents[CONTROLTYPE_BUTTON_AGENT_LMOUSEUP] != NULL)) mouse_agent = CONTROLTYPE_BUTTON_AGENT_LMOUSEUP;
						else if ( (msg == WM_RBUTTONUP) && (details->agents[CONTROLTYPE_BUTTON_AGENT_RMOUSEUP] != NULL)) mouse_agent = CONTROLTYPE_BUTTON_AGENT_RMOUSEUP;
						else if ( (msg == WM_MBUTTONUP) && (details->agents[CONTROLTYPE_BUTTON_AGENT_MMOUSEUP] != NULL)) mouse_agent = CONTROLTYPE_BUTTON_AGENT_MMOUSEUP;

						agent_notify(details->agents[mouse_agent], NOTIFY_CHANGE, NULL);

					}
				}
			}
			break;

		case WM_MOUSEMOVE:
			if (details->pressed)
			{
				RECT r; GetClientRect(hwnd, &r);
				POINT pt;
				pt.x = (short)LOWORD(lParam);
				pt.y = (short)HIWORD(lParam);
				bool over = PtInRect(&r, pt);
				if (over != details->hilite)
				{
					details->hilite = over;
					style_draw_invalidate(c);
				}
			}
			break;

		case WM_PAINT:
			styledrawinfo d;

			//Begin drawing
			if (style_draw_begin(c, d))
			{
				//Paint background according to the current style on the bitmap ...
				int style_index = STYLETYPE_NONE;
				switch (c->windowptr->style)
				{
				case STYLETYPE_TOOLBAR:
					style_index = (details->hilite || details->is_on) ? STYLETYPE_INSET : STYLETYPE_TOOLBAR; break;
				case STYLETYPE_INSET:
					style_index = (details->hilite || details->is_on) ? STYLETYPE_TOOLBAR : STYLETYPE_INSET; break;
				case STYLETYPE_FLAT:
					style_index = (details->hilite || details->is_on) ? STYLETYPE_SUNKEN : STYLETYPE_FLAT; break;
				case STYLETYPE_SUNKEN:
					style_index = (details->hilite || details->is_on) ? STYLETYPE_FLAT : STYLETYPE_SUNKEN; break;
				}
				
				if (c->windowptr->has_custom_style)
				{
					if (details->hilite || details->is_on)
						style_draw_box(
							d.rect,
							d.buffer,
							STYLETYPE_INSET,
							c->windowptr->is_bordered
						);
					else
						style_draw_box(
							d.rect,
							d.buffer,
							c->windowptr->styleptr,
							c->windowptr->is_bordered
						);

				}
				else
				style_draw_box(
					d.rect,
					d.buffer,
					style_index,
					c->windowptr->is_bordered
					);
				
				//Draw the image, dependant on state and availability of second image
				if (details->agents[CONTROLTYPE_BUTTON_IMAGE_WHENPRESSED] && (details->hilite || details->is_on))
				{
					d.apply_sat_hue = false == (details->hilite || details->is_on);
					agent_notify(details->agents[CONTROLTYPE_BUTTON_IMAGE_WHENPRESSED], NOTIFY_DRAW, &d);
				}
				else if (details->agents[CONTROLTYPE_BUTTON_IMAGE])
				{
					d.apply_sat_hue = false == (details->hilite || details->is_on);
					agent_notify(details->agents[CONTROLTYPE_BUTTON_IMAGE], NOTIFY_DRAW, &d);
				}

				//Draw the caption
				if (details->caption)
				{
					int vpad = style_bevel_width + 1;
					if (c->windowptr->is_bordered) vpad += style_border_width;
					if (vpad < 2) vpad = 2;

					int hpad = vpad;
					if (0 == (details->settings & DT_CENTER)) hpad += 1;
					d.rect.left  += hpad;
					d.rect.right -= hpad;

					if (!(details->settings & DT_VCENTER))
					{
						d.rect.top += vpad;
						d.rect.bottom -= vpad;
					}
					if (c->windowptr->has_custom_style)
						if (details->hilite || details->is_on)
						style_draw_text(
							d.rect,
							d.buffer,
							STYLETYPE_INSET,
							details->caption,
							details->settings,
							plugin_enableshadows
							);
						else
						style_draw_text(
							d.rect,
							d.buffer,
							c->windowptr->styleptr,
							details->caption,
							details->settings,
							plugin_enableshadows
							);
					else
					style_draw_text(
						d.rect,
						d.buffer,
						style_index,
						details->caption,
						details->settings,
						plugin_enableshadows
						);
				}
			}
			//End drawing
			style_draw_end(d);
			break;

	}

	return 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//controltype_label_event
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LRESULT controltype_label_event(control *c, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	controltype_label_details *details = (controltype_label_details *) c->controldetails;

	switch (msg)
	{
	case WM_DROPFILES:
	{
		char buffer[MAX_PATH];
		variables_set(false, "DroppedFile", get_dragged_file(buffer, wParam));
		agent_notify(details->agents[CONTROLTYPE_LABEL_AGENT_ONDROP], NOTIFY_CHANGE, NULL);
		break;
	}

	case WM_PAINT:
		styledrawinfo d;

		//Begin drawing
		if (style_draw_begin(c, d))
		{
			//Paint background according to the current style on the bitmap ...
			if (c->windowptr->has_custom_style)
				style_draw_box(
					d.rect,
					d.buffer,
					c->windowptr->styleptr,
					c->windowptr->is_bordered
				);
			else
				style_draw_box(
					d.rect,
					d.buffer,
					c->windowptr->style,
					c->windowptr->is_bordered
				);

			//Draw the title bar
			if (details->has_titlebar)
			{
				RECT titlebar = d.rect;
				int b = d.rect.top+FRAME_TITLEBAR_HEIGHT;
				titlebar.bottom = b < d.rect.bottom ? b : d.rect.bottom;
				style_draw_box(titlebar, d.buffer, STYLETYPE_TOOLBAR, c->windowptr->is_bordered);
			}

			//Draw the image
			if (details->agents[CONTROLTYPE_LABEL_AGENT_IMAGE])
			{
				agent_notify(details->agents[CONTROLTYPE_LABEL_AGENT_IMAGE], NOTIFY_DRAW, &d);
			}

			//Draw the caption
			if (details->caption)
			{
				int vpad = style_bevel_width + 1;
				if (c->windowptr->is_bordered) vpad += style_border_width;
				if (vpad < 2) vpad = 2;

				int hpad = vpad;
				if (0 == (details->settings & DT_CENTER)) hpad += 1;
				d.rect.left  += hpad;
				d.rect.right -= hpad;

				if (!(details->settings & DT_VCENTER))
				{
					if (details->has_titlebar)
						d.rect.top += (FRAME_TITLEBAR_HEIGHT-style_font_height)/2;
					else
						d.rect.top += vpad;

					d.rect.bottom -= vpad;
				}
				else
				{
					if (details->has_titlebar)
						d.rect.top += FRAME_TITLEBAR_HEIGHT;
				}

				if (c->windowptr->has_custom_style)
					style_draw_text(
						d.rect,
						d.buffer,
						c->windowptr->styleptr,
						details->caption,
						details->settings,
						plugin_enableshadows
					);
				else
					style_draw_text(
						d.rect,
						d.buffer,
						c->windowptr->style,
						details->caption,
						details->settings,
						plugin_enableshadows
					);
			}
		}
		//End drawing
		style_draw_end(d);
		break;

	case WM_RBUTTONUP:
	case WM_NCRBUTTONUP:
		agent_notify(details->agents[CONTROLTYPE_LABEL_AGENT_RIGHTMOUSEUP], NOTIFY_CHANGE, NULL);
		break;

	case SLIT_ADD:
	case SLIT_REMOVE:
	case SLIT_UPDATE:
		SlitWndProc(c, hwnd, msg, wParam, lParam);
		break;

	}
	return 0;
}