コード例 #1
0
// TODO: Make border radius true 1-point wide, even for low poly scenarios (by adjusting the inner radius intelligently, not just -1)
void DrawCircle(Vector2n Position, Vector2n Size, Color BackgroundColor, Color BorderColor)
{
	glDisable(GL_TEXTURE_2D);

	const auto TwoPi = std::atan(1) * 8;

	const uint32 x = 64;

	glBegin(GL_TRIANGLE_FAN);
		glColor3dv(BorderColor.GetComponents());
		glVertex2i(Position.X(), Position.Y());
		for (int i = 0; i <= x; ++i)
		{
			glVertex2d(Position.X() + std::sin(TwoPi * i / x) * Size.X() / 2, Position.Y() + std::cos(TwoPi * i / x) * Size.Y() / 2);
		}
	glEnd();

	glBegin(GL_TRIANGLE_FAN);
		glColor3dv(BackgroundColor.GetComponents());
		glVertex2i(Position.X(), Position.Y());
		for (int i = 0; i <= x; ++i)
		{
			glVertex2d(Position.X() + std::sin(TwoPi * i / x) * (Size.X() / 2 - 1), Position.Y() + std::cos(TwoPi * i / x) * (Size.Y() / 2 - 1));
		}
	glEnd();

	glEnable(GL_TEXTURE_2D);
}
コード例 #2
0
ファイル: Widget.cpp プロジェクト: mikalv/Conception
bool Widget::IsHit(const Vector2n ParentPosition) const
{
	if (!m_Visible)
		return false;

	bool Hit = (   ParentPosition.X() >= GetPosition().X()
				&& ParentPosition.Y() >= GetPosition().Y()
				&& ParentPosition.X() <  GetPosition().X() + GetDimensions().X()
				&& ParentPosition.Y() <  GetPosition().Y() + GetDimensions().Y());

	return Hit;
}
コード例 #3
0
Vector2n TypingModule::GetInsertionPosition(Vector2n PointerPosition) const
{
	DimensionsStream Stream;
	Stream << m_Typed;
	Vector2n Dimensions = Stream.GetDimensions();

	//Vector2n InsertionOffset(-m_Typed.length() * charWidth / 2 + charWidth, lineHeight * 3 / 2);
	//Vector2n InsertionOffset(-m_Typed.length() * charWidth / 2, 0);
	Vector2n InsertionOffset(Dimensions.X() / -2, Dimensions.Y() / -2 + lineHeight / 2);
	//Vector2n InsertionOffset(0, 0);

	return PointerPosition + InsertionOffset;
}
コード例 #4
0
ファイル: MenuWidget.hpp プロジェクト: shurcooL/Conception
template <typename T> void MenuWidget<T>::SetSelectedEntryId(Vector2n LocalPosition)
{
    decltype(m_SelectedEntryId) NewSelectedEntryId;

    if (LocalPosition.Y() < 0)
        NewSelectedEntryId = 0;
    else
        NewSelectedEntryId = LocalPosition.Y() / lineHeight;
    if (NewSelectedEntryId > m_Entries.size() - 1)
        NewSelectedEntryId = m_Entries.size() - 1;

    SetSelectedEntryId(NewSelectedEntryId);
}
コード例 #5
0
ファイル: OpenGLStream.cpp プロジェクト: mikalv/Conception
OpenGLStream::OpenGLStream(Vector2n CaretPosition, Color Foreground)
	: ConceptStream(),
	  m_CaretPosition(CaretPosition),
	  m_LineStartX(CaretPosition.X()),
	  m_Foreground(Foreground),
	  m_BackgroundColor(1.0, 1.0, 1.0)
{
}
コード例 #6
0
void DrawBoxBorderless(Vector2n Position, Vector2n Size, Color Color)
{
	glDisable(GL_TEXTURE_2D);

	glBegin(GL_QUADS);
		glColor3dv(Color.GetComponents());
		glVertex2i(Position.X(), Position.Y());
		glVertex2i(Position.X(), Position.Y() + Size.Y());
		glVertex2i(Position.X() + Size.X(), Position.Y() + Size.Y());
		glVertex2i(Position.X() + Size.X(), Position.Y());
	glEnd();

	glEnable(GL_TEXTURE_2D);
}
コード例 #7
0
decltype(TextFieldWidget::m_CaretPosition) TextFieldWidget::GetNearestCaretPosition(Vector2n LocalPosition)
{
	if (LocalPosition.X() < 0)
		LocalPosition.X() = 0;
	if (LocalPosition.Y() < 0)
		LocalPosition.Y() = 0;

	uint32 LineNumber = static_cast<uint32>(LocalPosition.Y()) / lineHeight;

	return GetNearestCaretPosition(LineNumber, static_cast<uint32>(LocalPosition.X()));
}
コード例 #8
0
ファイル: Main.cpp プロジェクト: mikalv/Conception
// Main function
int main(int argc, char * argv[])
{
	/*{
		PointerState test;

		test.UpdateButtonState(0) = true;
		test.UpdateButtonState(1) = true;
		test.UpdateButtonState(2) = true;

		PointerState test2(test);

		test2.UpdateButtonState(2) = false;

		std::cout << test.GetButtonState(2) << &std::endl;
		std::cout << test2.GetButtonState(2) << &std::endl;

		return 0;
	}*/
#if 0
	{
		std::function<void()> Test = []() { std::cout << "Hi from anon func.\n"; };
		//std::function<ConceptString(const std::vector<ConceptId> &)> Test = [](const std::vector<ConceptId> & Parameters){ return ConceptString({FindConcept("<"), GetParameterIfExists(Parameters, 0), FindConcept(">")}); };

		// Call Test()
		//Test();

		printf("size of func %ld\n", sizeof(Test));

		return 0;
	}
#endif







	// Set env vars
	std::string GoPath;		// This has to exist even after putenv() call because putenv simply adds a pointer rather than copying the value
	std::string Path = "PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/go/bin";
	{
		// Initialize the value of GoPath
		GoPath = "GOPATH=";
		// Get current working directory
		{
			auto cwd = getcwd(nullptr, 0);
			if (nullptr == cwd) {
				printf("Fatal Error: getcwd() failed.");
				exit(1);
			}

			printf("Current-working-dir is '%s' (should be the folder where README.md is).\n", cwd);
			GoPath = GoPath + cwd + "/GoLand";
			GoPath += ":";
			GoPath = GoPath + cwd + "/GoLanding";
			Path = Path + ":" + cwd + "/GoLand/bin";
			free(cwd);
		}

		putenv(const_cast<char *>("DYLD_INSERT_LIBRARIES="));		// HACK: Const cast
		putenv(const_cast<char *>("TERM=xterm"));		// HACK: Const cast
		putenv(const_cast<char *>(GoPath.c_str()));		// HACK: Const cast
		// HACK: Add go/bin to $PATH by hardcoding the whole PATH for OS X
		putenv(const_cast<char *>(Path.c_str()));		// HACK: Const cast
	}

	glfwInit();
	// Verify the GLFW library and header versions match
	{
		int Major, Minor, Revision;
		glfwGetVersion(&Major, &Minor, &Revision);

		bool Match = (GLFW_VERSION_MAJOR == Major && GLFW_VERSION_MINOR == Minor && GLFW_VERSION_REVISION == Revision);

		if (!Match)
		{
			std::cerr << "Error: GLFW library and header versions do not match." << std::endl;

			throw 0;
		}
		else
		{
			std::cout << "Using GLFW " << Major << "." << Minor << "." << Revision << "." << std::endl;
		}
	}

	// Open main window
	{
		GLFWvidmode DesktopMode;
		glfwGetDesktopMode(&DesktopMode);

		glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 32);

		const bool Fullscreen = static_cast<bool>(0);
		const Vector2n WindowDimensons(1536, 960);

		if (!Fullscreen) {
			glfwOpenWindow(WindowDimensons.X(), WindowDimensons.Y(), DesktopMode.RedBits, DesktopMode.GreenBits, DesktopMode.BlueBits, 0, 0, 0, GLFW_WINDOW);
			glfwSetWindowPos((DesktopMode.Width - WindowDimensons.X()) / 2, (DesktopMode.Height - WindowDimensons.Y()) / 2);		// Center the window
		} else {
			glfwOpenWindow(DesktopMode.Width, DesktopMode.Height, DesktopMode.RedBits, DesktopMode.GreenBits, DesktopMode.BlueBits, 0, 0, 0, GLFW_FULLSCREEN);
			glfwEnable(GLFW_MOUSE_CURSOR);
		}

		{
			std::ostringstream x;
			x << "CPU Count: " << glfwGetNumberOfProcessors() << std::endl
			  << "GL Renderer: " << glGetString(GL_VENDOR) << " " << glGetString(GL_RENDERER) << " " << glGetString(GL_VERSION) << std::endl
			  << "GLFW_ACCELERATED: " << glfwGetWindowParam(GLFW_ACCELERATED) << std::endl
			  << "GLFW_RED_BITS: " << glfwGetWindowParam(GLFW_RED_BITS) << std::endl
			  << "GLFW_GREEN_BITS: " << glfwGetWindowParam(GLFW_GREEN_BITS) << std::endl
			  << "GLFW_BLUE_BITS: " << glfwGetWindowParam(GLFW_BLUE_BITS) << std::endl
			  << "GLFW_ALPHA_BITS: " << glfwGetWindowParam(GLFW_ALPHA_BITS) << std::endl
			  << "GLFW_DEPTH_BITS: " << glfwGetWindowParam(GLFW_DEPTH_BITS) << std::endl
			  << "GLFW_STENCIL_BITS: " << glfwGetWindowParam(GLFW_STENCIL_BITS) << std::endl
			  << "GLFW_REFRESH_RATE: " << glfwGetWindowParam(GLFW_REFRESH_RATE) << std::endl
			  << "GLFW_FSAA_SAMPLES: " << glfwGetWindowParam(GLFW_FSAA_SAMPLES) << std::endl;
			std::cout << x.str();
		}

		{
			//glfwSetWindowTitle("Conception");
			glfwSwapInterval(1);					// Set Vsync
			glfwDisable(GLFW_AUTO_POLL_EVENTS);

			glfwEnable(GLFW_KEY_REPEAT);
			glfwDisable(GLFW_SYSTEM_KEYS);
		}
	}

	{
		InputManager InputManager;
		g_InputManager = &InputManager;

		ConceptionApp MainApp(InputManager);
		//LiveEditorApp MainApp(InputManager);
		//ConceptionTestApp MainApp(InputManager);
		//MultitouchTestApp MainApp(InputManager);
		//SentienceApp MainApp(InputManager);

		glfwSetWindowTitle(MainApp.GetTitle().c_str());

		// Perform the layout of UI widgets
		MainApp.Layout();

		// OpenGL settings
		InitializeOpenGL();

		std::cout << std::endl;		// Done loading

		// Main loop
		while (glfwGetWindowParam(GLFW_OPENED))
		{
			auto CurrentTime = glfwGetTime();
			static auto LastTime = CurrentTime;
			auto TimePassed = CurrentTime - LastTime;
			LastTime = CurrentTime;

			// DEBUG: Moved to top of loop to enable debug printing from input handling code
			glClear(GL_COLOR_BUFFER_BIT);		// Clear frame

			// Process input
			{
				// Populate InputEventQueue
				if (MainApp.ShouldRedrawRegardless())
					glfwPollEvents();
				else {
					glfwWaitEvents();
					//if (glfwGetTime() - LastTime >= 1) printf("Slept for %f secs\n", glfwGetTime() - LastTime);
					LastTime = glfwGetTime();
				}
				//InputManager.ProcessTimePassed(TimePassed);

				MainApp.ProcessEventQueue(InputManager.ModifyInputEventQueue());
				MainApp.ProcessTimePassed(TimePassed);
			}

			// Render
			{
				// DEBUG: Moved to top of loop to enable debug printing from input handling code
				///glClear(GL_COLOR_BUFFER_BIT);		// Clear frame

				MainApp.Render();
			}

			// Display new frame
			glfwSwapBuffers();
			//glFinish();

			///printf("%f ms frame\n", TimePassed * 1000);

			// Use less CPU in background
			if (!glfwGetWindowParam(GLFW_ACTIVE))
			{
				glfwSleep(0.100);
			}
		}
	}

	// Clean up
	OglUtilsKillFont();
	glfwTerminate();

	std::cout << "\nReturning 0 from main().\n";
	return 0;
}
コード例 #9
0
ファイル: ListWidget.hpp プロジェクト: prinsmike/Conception
template <typename T> void ListWidget<T>::UpdateDimensions()
{
	Vector2n Dimensions;

	for (auto & Entry : m_List)
	{
		Dimensions.X() = std::max<sint32>(Dimensions.X(), Concept::GetDimensions(Entry).X());
		Dimensions.Y() += Concept::GetDimensions(Entry).Y();
	}

	// TEST
	if (!m_TypingModule.GetString().empty())
	{
		for (auto & Pointer : GetGestureRecognizer().GetConnected())
		{
			if (Pointer::VirtualCategory::POINTING == Pointer->GetVirtualCategory())
			{
				Dimensions.X() = std::max<sint32>(Dimensions.X(), static_cast<sint32>(m_TypingModule.GetString().length() * charWidth));
				Dimensions.Y() += 1 * lineHeight;
				break;
			}
		}
	}

	Vector2n MinDimensions(3 * charWidth, lineHeight);
	Dimensions.X() = std::max<sint32>(Dimensions.X(), MinDimensions.X());
	Dimensions.Y() = std::max<sint32>(Dimensions.Y(), MinDimensions.Y());

	SetDimensions(Dimensions);
}
コード例 #10
0
void ConceptStringBoxWidget::Render()
{
	Color BackgroundColor(1.0, 1.0, 1.0);
	Color BorderColor(0.3, 0.3, 0.3);

	/*if (CheckHover(WidgetManager) && CheckActive(WidgetManager))
	{
	}
	else if ((CheckHover(WidgetManager) && !CheckAnyActive(WidgetManager)) || (!CheckHover(WidgetManager) && CheckActive(WidgetManager)))
	{
		BorderColor[0] = 0.898;
		BorderColor[1] = 0.765;
		BorderColor[2] = 0.396;
	}
	else
	{
	}*/
	//if (CheckHover())
	// HACK
	if (HasTypingFocus())
	{
		BorderColor[0] = 0.898;
		BorderColor[1] = 0.765;
		BorderColor[2] = 0.396;
	}

	/*glBegin(GL_QUADS);
		glVertex2d(m_Position.X(), m_Position.Y());
		glVertex2d(m_Position.X(), m_Position.Y() + 30);
		glVertex2d(m_Position.X() + 30, m_Position.Y() + 30);
		glVertex2d(m_Position.X() + 30, m_Position.Y());
	glEnd();*/
	DrawAroundBox(GetPosition(), GetDimensions(), BackgroundColor, BorderColor);

	glColor3d(0, 0, 0);
	OpenGLStream OpenGLStream(GetPosition());
	//OpenGLStream << m_Content.substr(0, m_CaretPosition);
	// TODO: Optimize this somehow?
	OpenGLStream << decltype(m_Content)(m_Content.begin(), m_Content.begin() + m_CaretPosition);

	// TEST
	if (!m_TypingModule.GetString().empty())
	{
		for (auto & Pointer : GetGestureRecognizer().GetConnected())
		{
			if (Pointer::VirtualCategory::POINTING == Pointer->GetVirtualCategory())
			{
				//Vector2n GlobalPosition(Pointer->GetPointerState().GetAxisState(0).GetPosition(), Pointer->GetPointerState().GetAxisState(1).GetPosition());
				//Vector2n LocalPosition(GlobalToLocal(GlobalPosition));

				//auto ConceptId = FindOrCreateConcept(Entry);

				OpenGLStream << m_TypingModule.GetString();
			}
		}
	}

	Vector2n CaretPosition = OpenGLStream.GetCaretPosition();

	//OpenGLStream << m_Content.substr(m_CaretPosition);
	// TODO: Optimize this somehow?
	OpenGLStream << decltype(m_Content)(m_Content.begin() + m_CaretPosition, m_Content.end());

	//if (CheckHover())
	// HACK
	if (HasTypingFocus())
	{
		// Draw caret
		//if (static_cast<int>(glfwGetTime() * 2) % 2)
		{
			glPushMatrix();
			glTranslated(CaretPosition.X(), CaretPosition.Y(), 0);
			glColor3d(0, 0, 0);
			glBegin(GL_QUADS);
				glVertex2d(-1, 0);
				glVertex2d(-1, lineHeight);
				glVertex2d(+1, lineHeight);
				glVertex2d(+1, 0);
			glEnd();
			glPopMatrix();
		}
	}
}
コード例 #11
0
void DrawAroundBox(Vector2n Position, Vector2n Size, Color BackgroundColor, Color BorderColor)
{
	glDisable(GL_TEXTURE_2D);

	glBegin(GL_QUADS);
		glColor3dv(BorderColor.GetComponents());
		glVertex2i(-1 + Position.X(), -1 + Position.Y());
		glVertex2i(-1 + Position.X(), +1 + Position.Y() + Size.Y());
		glVertex2i(+1 + Position.X() + Size.X(), +1 + Position.Y() + Size.Y());
		glVertex2i(+1 + Position.X() + Size.X(), -1 + Position.Y());
	glEnd();

	glBegin(GL_QUADS);
		glColor3dv(BackgroundColor.GetComponents());
		glVertex2i(Position.X(), Position.Y());
		glVertex2i(Position.X(), Position.Y() + Size.Y());
		glVertex2i(Position.X() + Size.X(), Position.Y() + Size.Y());
		glVertex2i(Position.X() + Size.X(), Position.Y());
	glEnd();

	glEnable(GL_TEXTURE_2D);
}
コード例 #12
0
// TODO: Make a more direct implementation
void DrawInnerRoundedBox(Vector2n Position, Vector2n Size, uint32 Radius, Color BackgroundColor, Color BorderColor)
{
	DrawCircle(Position + Vector2n(Radius, Radius), Vector2n(Radius * 2, Radius * 2), BackgroundColor, BorderColor);
	
	if (   Size.X() < Radius * 2
		|| Size.Y() < Radius * 2)
	{
		return;
	}

	DrawCircle(Position + Vector2n(Size.X(), 0) + Vector2n(-Radius, Radius), Vector2n(Radius * 2, Radius * 2), BackgroundColor, BorderColor);
	DrawCircle(Position + Vector2n(0, Size.Y()) + Vector2n(Radius, -Radius), Vector2n(Radius * 2, Radius * 2), BackgroundColor, BorderColor);
	DrawCircle(Position + Size - Vector2n(Radius, Radius), Vector2n(Radius * 2, Radius * 2), BackgroundColor, BorderColor);

	{
		Position += Vector2n(Radius, 0);
		Size -= Vector2n(Radius * 2, 0);

		// DUPLICATION: A tweaked copy of DrawBox()
		{
			glDisable(GL_TEXTURE_2D);

			glBegin(GL_QUADS);
				glColor3dv(BorderColor.GetComponents());
				glVertex2i(Position.X(), Position.Y());
				glVertex2i(Position.X(), Position.Y() + Size.Y());
				glVertex2i(Position.X() + Size.X(), Position.Y() + Size.Y());
				glVertex2i(Position.X() + Size.X(), Position.Y());
			glEnd();

			glBegin(GL_QUADS);
				glColor3dv(BackgroundColor.GetComponents());
				glVertex2i(Position.X(), +1 + Position.Y());
				glVertex2i(Position.X(), -1 + Position.Y() + Size.Y());
				glVertex2i(Position.X() + Size.X(), -1 + Position.Y() + Size.Y());
				glVertex2i(Position.X() + Size.X(), +1 + Position.Y());
			glEnd();

			glEnable(GL_TEXTURE_2D);
		}
	}

	{
		Position += Vector2n(-Radius, Radius);
		Size += Vector2n(Radius * 2, -Radius * 2);

		// DUPLICATION: A tweaked copy of DrawBox()
		{
			glDisable(GL_TEXTURE_2D);

			glBegin(GL_QUADS);
				glColor3dv(BorderColor.GetComponents());
				glVertex2i(Position.X(), Position.Y());
				glVertex2i(Position.X(), Position.Y() + Size.Y());
				glVertex2i(Position.X() + Size.X(), Position.Y() + Size.Y());
				glVertex2i(Position.X() + Size.X(), Position.Y());
			glEnd();

			glBegin(GL_QUADS);
				glColor3dv(BackgroundColor.GetComponents());
				glVertex2i(+1 + Position.X(), Position.Y());
				glVertex2i(+1 + Position.X(), Position.Y() + Size.Y());
				glVertex2i(-1 + Position.X() + Size.X(), Position.Y() + Size.Y());
				glVertex2i(-1 + Position.X() + Size.X(), Position.Y());
			glEnd();

			glEnable(GL_TEXTURE_2D);
		}
	}
}
コード例 #13
0
void DrawInnerBox(Vector2n Position, Vector2n Size, Color BackgroundColor, Color BorderColor)
{
	if (   0 == Size.X()
		|| 0 == Size.Y())
	{
		return;
	}

	glDisable(GL_TEXTURE_2D);

	const auto OuterDistance = 1.5;
	glBegin(GL_POLYGON);
		glColor3dv(BorderColor.GetComponents());
		glVertex2d(Position.X() + OuterDistance, Position.Y());
		glVertex2d(Position.X(), Position.Y() + OuterDistance);
		glVertex2d(Position.X(), Position.Y() - OuterDistance + Size.Y());
		glVertex2d(Position.X() + OuterDistance, Position.Y() + Size.Y());
		glVertex2d(Position.X() - OuterDistance + Size.X(), Position.Y() + Size.Y());
		glVertex2d(Position.X() + Size.X(), Position.Y() - OuterDistance + Size.Y());
		glVertex2d(Position.X() + Size.X(), Position.Y() + OuterDistance);
		glVertex2d(Position.X() - OuterDistance + Size.X(), Position.Y());
	glEnd();

	const auto InnerDistance = sqrt(2.0) + 0.5;
	glBegin(GL_POLYGON);
		glColor3dv(BackgroundColor.GetComponents());
		glVertex2d(Position.X() + InnerDistance, Position.Y() + 1);
		glVertex2d(Position.X() + 1, Position.Y() + InnerDistance);
		glVertex2d(Position.X() + 1, Position.Y() - InnerDistance + Size.Y());
		glVertex2d(Position.X() + InnerDistance, Position.Y() - 1 + Size.Y());
		glVertex2d(Position.X() - InnerDistance + Size.X(), Position.Y() - 1 + Size.Y());
		glVertex2d(Position.X() - 1 + Size.X(), Position.Y() - InnerDistance + Size.Y());
		glVertex2d(Position.X() - 1 + Size.X(), Position.Y() + InnerDistance);
		glVertex2d(Position.X() - InnerDistance + Size.X(), Position.Y() + 1);
	glEnd();

	glEnable(GL_TEXTURE_2D);
}
コード例 #14
0
void TextFieldWidget::Render()
{
	//Color BackgroundColor(1.0, 1.0, 1.0);
	Color BackgroundColor = m_BackgroundColor;
	Color BorderColor(0.3, 0.3, 0.3);

	/*if (CheckHover(WidgetManager) && CheckActive(WidgetManager))
	{
	}
	else if ((CheckHover(WidgetManager) && !CheckAnyActive(WidgetManager)) || (!CheckHover(WidgetManager) && CheckActive(WidgetManager)))
	{
		BorderColor[0] = 0.898;
		BorderColor[1] = 0.765;
		BorderColor[2] = 0.396;
	}
	else
	{
	}*/
	//if (CheckHover())
	// HACK
	if (HasTypingFocus())
	{
		BorderColor[0] = 0.898;
		BorderColor[1] = 0.765;
		BorderColor[2] = 0.396;
	}

	/*glBegin(GL_QUADS);
		glVertex2d(m_Position.X(), m_Position.Y());
		glVertex2d(m_Position.X(), m_Position.Y() + 30);
		glVertex2d(m_Position.X() + 30, m_Position.Y() + 30);
		glVertex2d(m_Position.X() + 30, m_Position.Y());
	glEnd();*/
	DrawAroundBox(GetPosition(), GetDimensions(), BackgroundColor, BorderColor);

	// TEST
	auto ContentWithInsertion = m_Content;
	if (!m_TypingModule.GetString().empty())
	{
		for (auto & Pointer : GetGestureRecognizer().GetConnected())
		{
			if (Pointer::VirtualCategory::POINTING == Pointer->GetVirtualCategory())
			{
				Vector2n GlobalPosition(Pointer->GetPointerState().GetAxisState(0).GetPosition(), Pointer->GetPointerState().GetAxisState(1).GetPosition());
				Vector2n LocalPosition(GlobalToLocal(GlobalPosition));
				LocalPosition = m_TypingModule.GetInsertionPosition(LocalPosition);

				auto InsertionPosition = GetNearestCaretPosition(LocalPosition);
				ContentWithInsertion.insert(InsertionPosition, m_TypingModule.GetString());
			}
		}
	}

	glColor3d(0, 0, 0);
	OpenGLStream OpenGLStream(GetPosition());
	OpenGLStream << ContentWithInsertion.substr(0, std::min(m_CaretPosition, m_SelectionPosition));

	Vector2n CaretPosition;

	// Remember caret position at selection front
	if (std::min(m_CaretPosition, m_SelectionPosition) == m_CaretPosition)
	{
		CaretPosition = OpenGLStream.GetCaretPosition();
	}

	// Draw selected text as highlighted
	if (HasTypingFocus())
	{
		OpenGLStream.SetBackgroundColor(Color(static_cast<uint8>(195), 212, 242));
	}
	else
	{
		OpenGLStream.SetBackgroundColor(Color(static_cast<uint8>(212), 212, 212));
	}
	auto SelectionLength = std::max(m_CaretPosition, m_SelectionPosition) - std::min(m_CaretPosition, m_SelectionPosition);
	OpenGLStream << ContentWithInsertion.substr(std::min(m_CaretPosition, m_SelectionPosition), SelectionLength);
	OpenGLStream.SetBackgroundColor(Color(1.0, 1.0, 1.0));

	// Remember caret position at selection back
	if (std::max(m_CaretPosition, m_SelectionPosition) == m_CaretPosition)
	{
		CaretPosition = OpenGLStream.GetCaretPosition();
	}

	OpenGLStream << ContentWithInsertion.substr(std::max(m_CaretPosition, m_SelectionPosition));

	//if (CheckHover())
	// HACK
	if (HasTypingFocus())
	{
		// Draw caret
		//if (static_cast<int>(glfwGetTime() * 2) % 2)
		{
			glPushMatrix();
			glTranslated(CaretPosition.X(), CaretPosition.Y(), 0);
			glColor3d(0, 0, 0);
			glBegin(GL_QUADS);
				glVertex2d(-1, 0);
				glVertex2d(-1, lineHeight);
				glVertex2d(+1, lineHeight);
				glVertex2d(+1, 0);
			glEnd();
			glPopMatrix();
		}
	}
}