<commit_before>/*
 A (very) simple UI lib built on top of OpenCV drawing primitives.

 Copyright (c) 2016 <NAME> <<EMAIL>>
 Licensed under the MIT license.
*/

#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "cvui.h"

namespace cvui
{

// This is an internal namespace with all functions
// that actually render each one of the UI components
namespace render {
	const int IDLE = 0;
	const int OVER = 1;
	const int PRESSED = 2;

	void button(int theState, cv::Mat& theWhere, cv::Rect& theShape, const cv::String& theLabel) {
		// Outline
		cv::rectangle(theWhere, theShape, cv::Scalar(0x33, 0x33, 0x33));

		// Border
		theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
		cv::rectangle(theWhere, theShape, cv::Scalar(0x52, 0x52, 0x52));

		// Inside
		theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
		cv::rectangle(theWhere, theShape, theState == IDLE ? cv::Scalar(0x42, 0x42, 0x42) : (theState == OVER ? cv::Scalar(0x52, 0x52, 0x52) : cv::Scalar(0x32, 0x32, 0x32)), cv::FILLED);
	}

	void buttonLabel(int theState, cv::Mat& theWhere, cv::Rect theRect, const cv::String& theLabel, cv::Size& theTextSize) {
		cv::Point aPos(theRect.x + 10, theRect.y + theTextSize.height + 4);
		cv::putText(theWhere, theLabel, aPos, cv::FONT_HERSHEY_SIMPLEX, theState == PRESSED ? 0.39 : 0.4, cv::Scalar(0xCE, 0xCE, 0xCE), 1, cv::LINE_AA);
	}

	void counter(cv::Mat& theWhere, cv::Rect& theShape, const cv::String& theValue) {
		int aBaseline = 0;

		cv::rectangle(theWhere, theShape, cv::Scalar(0x29, 0x29, 0x29), cv::FILLED); // fill
		cv::rectangle(theWhere, theShape, cv::Scalar(0x45, 0x45, 0x45)); // border

		cv::Size aTextSize = getTextSize(theValue, cv::FONT_HERSHEY_SIMPLEX, 0.4, 1, &aBaseline);

		cv::Point aPos(theShape.x + theShape.width / 2 - aTextSize.width / 2, theShape.y + aTextSize.height / 2 + theShape.height / 2);
		cv::putText(theWhere, theValue, aPos, cv::FONT_HERSHEY_SIMPLEX, 0.4, cv::Scalar(0xCE, 0xCE, 0xCE), 1, cv::LINE_AA);
	}
}

// Variables to keep track of mouse events and stuff
static bool mouseJustReleased = false;
static bool mousePressed = false;
static cv::Point mouse;
static char buffer[200];
	
void init(const cv::String& theWindowName) {
	cv::setMouseCallback(theWindowName, handleMouse, NULL);
}

bool button(cv::Mat& theWhere, int theX, int theY, const cv::String& theLabel) {
	// Calculate the space that the label will fill
	int aBaseline = 0;
	cv::Size aTextSize = getTextSize(theLabel, cv::FONT_HERSHEY_SIMPLEX, 0.4, 1, &aBaseline);
	
	// Make the button bit enough to house the label
	cv::Rect aRect(theX, theY, aTextSize.width + 20, aTextSize.height + 15);
	
	// Check the state of the button (idle, pressed, etc.)
	bool aMouseIsOver = aRect.contains(mouse);

	if (aMouseIsOver) {
		if (mousePressed) {
			render::button(render::PRESSED, theWhere, aRect, theLabel);
			render::buttonLabel(render::PRESSED, theWhere, aRect, theLabel, aTextSize);
		} else {
			render::button(render::OVER, theWhere, aRect, theLabel);
			render::buttonLabel(render::OVER, theWhere, aRect, theLabel, aTextSize);
		}
	} else {
		render::button(render::IDLE, theWhere, aRect, theLabel);
		render::buttonLabel(render::IDLE, theWhere, aRect, theLabel, aTextSize);
	}

	// Tell if the button was clicked or not
	return aMouseIsOver && mouseJustReleased;
}

bool checkbox(cv::Mat& theWhere, int theX, int theY, const cv::String& theLabel, bool *theState) {
	cv::Rect aRect(theX, theY, 20, 20);
	cv::Rect aHitArea(theX, theY, aRect.width + theLabel.length() * 8, 20);
	bool aMouseIsOver = aHitArea.contains(mouse);

	if (aMouseIsOver) {
		cv::rectangle(theWhere, aRect, cv::Scalar(255, 0, 0), cv::FILLED);

		if (mouseJustReleased) {
			*theState = !(*theState);
		}
	} else {
		cv::rectangle(theWhere, aRect, cv::Scalar(190, 0, 0), cv::FILLED);
	}

	if (*theState) {
		text(theWhere, theX + 5, theY + 15, "X", 0.5);
	}

	text(theWhere, theX + 25, theY + 15, theLabel, 0.4);

	return *theState;
}

void text(cv::Mat& theWhere, int theX, int theY, const cv::String& theText, double theFontScale) {
	cv::Point aPos(theX, theY);
	cv::putText(theWhere, theText, aPos, cv::FONT_HERSHEY_SIMPLEX, theFontScale, cv::Scalar(0xCE, 0xCE, 0xCE), 1, cv::LINE_AA);
}

int counter(cv::Mat& theWhere, int theX, int theY, int *theValue) {
	cv::Rect aShape(theX + 30, theY + 1, 50, 22);

	if (cvui::button(theWhere, theX, theY, "-")) {
		(*theValue)--;
	}
	
	sprintf_s(buffer, "%d", *theValue);<commit_msg>Checkbox rendering<commit_after>/*
 A (very) simple UI lib built on top of OpenCV drawing primitives.

 Copyright (c) 2016 <NAME> <<EMAIL>>
 Licensed under the MIT license.
*/

#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "cvui.h"

namespace cvui
{

// This is an internal namespace with all functions
// that actually render each one of the UI components
namespace render {
	const int IDLE = 0;
	const int OVER = 1;
	const int PRESSED = 2;

	void button(int theState, cv::Mat& theWhere, cv::Rect& theShape, const cv::String& theLabel) {
		// Outline
		cv::rectangle(theWhere, theShape, cv::Scalar(0x33, 0x33, 0x33));

		// Border
		theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
		cv::rectangle(theWhere, theShape, cv::Scalar(0x52, 0x52, 0x52));

		// Inside
		theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
		cv::rectangle(theWhere, theShape, theState == IDLE ? cv::Scalar(0x42, 0x42, 0x42) : (theState == OVER ? cv::Scalar(0x52, 0x52, 0x52) : cv::Scalar(0x32, 0x32, 0x32)), cv::FILLED);
	}

	void buttonLabel(int theState, cv::Mat& theWhere, cv::Rect theRect, const cv::String& theLabel, cv::Size& theTextSize) {
		cv::Point aPos(theRect.x + 10, theRect.y + theTextSize.height + 4);
		cv::putText(theWhere, theLabel, aPos, cv::FONT_HERSHEY_SIMPLEX, theState == PRESSED ? 0.39 : 0.4, cv::Scalar(0xCE, 0xCE, 0xCE), 1, cv::LINE_AA);
	}

	void counter(cv::Mat& theWhere, cv::Rect& theShape, const cv::String& theValue) {
		int aBaseline = 0;

		cv::rectangle(theWhere, theShape, cv::Scalar(0x29, 0x29, 0x29), cv::FILLED); // fill
		cv::rectangle(theWhere, theShape, cv::Scalar(0x45, 0x45, 0x45)); // border

		cv::Size aTextSize = getTextSize(theValue, cv::FONT_HERSHEY_SIMPLEX, 0.4, 1, &aBaseline);

		cv::Point aPos(theShape.x + theShape.width / 2 - aTextSize.width / 2, theShape.y + aTextSize.height / 2 + theShape.height / 2);
		cv::putText(theWhere, theValue, aPos, cv::FONT_HERSHEY_SIMPLEX, 0.4, cv::Scalar(0xCE, 0xCE, 0xCE), 1, cv::LINE_AA);
	}

	void checkbox(int theState, cv::Mat& theWhere, cv::Rect& theShape) {
		// Outline
		cv::rectangle(theWhere, theShape, theState == IDLE ? cv::Scalar(0x63, 0x63, 0x63) : cv::Scalar(0x80, 0x80, 0x80));

		// Border
		theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
		cv::rectangle(theWhere, theShape, cv::Scalar(0x17, 0x17, 0x17));

		// Inside
		theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
		cv::rectangle(theWhere, theShape, cv::Scalar(0x29, 0x29, 0x29), cv::FILLED);
	}

	void checkboxCheck(cv::Mat& theWhere, cv::Rect& theShape) {
		theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
		cv::rectangle(theWhere, theShape, cv::Scalar(0xFF, 0xBF, 0x75), cv::FILLED);
	}
}

// Variables to keep track of mouse events and stuff
static bool mouseJustReleased = false;
static bool mousePressed = false;
static cv::Point mouse;
static char buffer[200];
	
void init(const cv::String& theWindowName) {
	cv::setMouseCallback(theWindowName, handleMouse, NULL);
}

bool button(cv::Mat& theWhere, int theX, int theY, const cv::String& theLabel) {
	// Calculate the space that the label will fill
	int aBaseline = 0;
	cv::Size aTextSize = getTextSize(theLabel, cv::FONT_HERSHEY_SIMPLEX, 0.4, 1, &aBaseline);
	
	// Make the button bit enough to house the label
	cv::Rect aRect(theX, theY, aTextSize.width + 20, aTextSize.height + 15);
	
	// Check the state of the button (idle, pressed, etc.)
	bool aMouseIsOver = aRect.contains(mouse);

	if (aMouseIsOver) {
		if (mousePressed) {
			render::button(render::PRESSED, theWhere, aRect, theLabel);
			render::buttonLabel(render::PRESSED, theWhere, aRect, theLabel, aTextSize);
		} else {
			render::button(render::OVER, theWhere, aRect, theLabel);
			render::buttonLabel(render::OVER, theWhere, aRect, theLabel, aTextSize);
		}
	} else {
		render::button(render::IDLE, theWhere, aRect, theLabel);
		render::buttonLabel(render::IDLE, theWhere, aRect, theLabel, aTextSize);
	}

	// Tell if the button was clicked or not
	return aMouseIsOver && mouseJustReleased;
}

bool checkbox(cv::Mat& theWhere, int theX, int theY, const cv::String& theLabel, bool *theState) {
	int aBaseline = 0;
	cv::Rect aRect(theX, theY, 15, 15);
	cv::Size aTextSize = getTextSize(theLabel, cv::FONT_HERSHEY_SIMPLEX, 0.4, 1, &aBaseline);
	cv::Rect aHitArea(theX, theY, aRect.width + aTextSize.width, aRect.height);
	bool aMouseIsOver = aHitArea.contains(mouse);

	if (aMouseIsOver) {
		render::checkbox(render::OVER, theWhere, aRect);

		if (mouseJustReleased) {
			*theState = !(*theState);
		}
	} else {
		render::checkbox(render::IDLE, theWhere, aRect);
	}

	cv::Point aPos(theX + aRect.width + 8, theY + aRect.height / 2 + aTextSize.height / 2 + 2);
	cv::putText(theWhere, theLabel, aPos, cv::FONT_HERSHEY_SIMPLEX, 0.4, cv::Scalar(0xCE, 0xCE, 0xCE), 1, cv::LINE_AA);

	if (*theState) {
		render::checkboxCheck(theWhere, aRect);
	}

	return *theState;
}

void text(cv::Mat& theWhere, int theX, int theY, const cv::String& theText, double theFontScale) {
	cv::Point aPos(theX, theY);
	cv::putText(theWhere, theText, aPos, cv::FONT_HERSHEY_SIMPLEX, theFontScale, cv::Scalar(0xCE, 0xCE, 0xCE), 1, cv::LINE_AA);
}

int counter(cv::Mat& theWhere, int theX, int theY, int *theValue) {
	cv::Rect aShape(theX + 30, theY + 1, 50, 22);

	if (cvui::button(theWhere, theX, theY, "-")) {
		(*theValue)--;
	}
	
	sprintf_s(buffer, "%d", *theValue);
{'fraction_non_alphanumeric': 0.1591000401767778, 'fraction_numerical': 0.03425070309361189, 'mean_word_length': 4.969424460431655, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1703577', 'n_tokens_mistral': 4180, 'n_tokens_neox': 3757, 'n_words': 953}