forked from Bananymous/banan-os
				
			
		
			
				
	
	
		
			97 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| #include <LibFont/Font.h>
 | |
| #include <LibGUI/Widget/TextArea.h>
 | |
| #include <LibGUI/Window.h>
 | |
| 
 | |
| #include <ctype.h>
 | |
| 
 | |
| namespace LibGUI::Widget
 | |
| {
 | |
| 
 | |
| 	BAN::ErrorOr<BAN::RefPtr<TextArea>> TextArea::create(BAN::RefPtr<Widget> parent, BAN::StringView text, Rectangle geometry)
 | |
| 	{
 | |
| 		auto* text_area_ptr = new TextArea(parent, geometry);
 | |
| 		if (text_area_ptr == nullptr)
 | |
| 			return BAN::Error::from_errno(ENOMEM);
 | |
| 		auto text_area = BAN::RefPtr<TextArea>::adopt(text_area_ptr);
 | |
| 		TRY(text_area->initialize(color_invisible));
 | |
| 		TRY(text_area->set_text(text));
 | |
| 		return text_area;
 | |
| 	}
 | |
| 
 | |
| 	BAN::ErrorOr<void> TextArea::set_text(BAN::StringView text)
 | |
| 	{
 | |
| 		m_text.clear();
 | |
| 		TRY(m_text.append(text));
 | |
| 		TRY(wrap_text());
 | |
| 		if (is_shown())
 | |
| 			show();
 | |
| 		return {};
 | |
| 	}
 | |
| 
 | |
| 	uint32_t TextArea::get_required_height() const
 | |
| 	{
 | |
| 		auto& font = default_font();
 | |
| 		return m_wrapped_text.size() * font.height();
 | |
| 	}
 | |
| 
 | |
| 	BAN::ErrorOr<void> TextArea::wrap_text()
 | |
| 	{
 | |
| 		m_wrapped_text.clear();
 | |
| 
 | |
| 		if (width() == 0)
 | |
| 			return {};
 | |
| 
 | |
| 		auto& font = default_font();
 | |
| 
 | |
| 		const uint32_t total_columns = width() / font.width();
 | |
| 		ASSERT(total_columns != 0);
 | |
| 
 | |
| 		TRY(m_wrapped_text.emplace_back());
 | |
| 
 | |
| 		for (size_t i = 0; i < m_text.size(); i++)
 | |
| 		{
 | |
| 			if (m_text[i] == '\n')
 | |
| 				TRY(m_wrapped_text.emplace_back());
 | |
| 			else if (isspace(m_text[i]) && m_wrapped_text.back().size() == 0)
 | |
| 				;
 | |
| 			else
 | |
| 			{
 | |
| 				TRY(m_wrapped_text.back().push_back(m_text[i]));
 | |
| 
 | |
| 				if (i + 1 < m_text.size() && isspace(m_text[i]) && !isspace(m_text[i + 1]))
 | |
| 				{
 | |
| 					size_t word_len = 0;
 | |
| 					for (size_t j = i + 1; j < m_text.size() && !isspace(m_text[j]); j++)
 | |
| 						word_len++;
 | |
| 					if (word_len <= total_columns && m_wrapped_text.back().size() + word_len > total_columns)
 | |
| 						TRY(m_wrapped_text.emplace_back());
 | |
| 				}
 | |
| 
 | |
| 				if (m_wrapped_text.back().size() >= total_columns)
 | |
| 					TRY(m_wrapped_text.emplace_back());
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return {};
 | |
| 	}
 | |
| 
 | |
| 	BAN::ErrorOr<void> TextArea::update_geometry_impl()
 | |
| 	{
 | |
| 		TRY(wrap_text());
 | |
| 		return Widget::update_geometry_impl();
 | |
| 	}
 | |
| 
 | |
| 	void TextArea::show_impl()
 | |
| 	{
 | |
| 		const auto& font = default_font();
 | |
| 
 | |
| 		m_texture.fill(m_style.color_normal);
 | |
| 		for (int32_t row = 0; row < static_cast<int32_t>(m_wrapped_text.size()); row++)
 | |
| 			m_texture.draw_text(m_wrapped_text[row].sv(), font, 0, row * font.height(), m_style.color_text);
 | |
| 
 | |
| 		RoundedWidget::style() = m_style;
 | |
| 		RoundedWidget::show_impl();
 | |
| 	}
 | |
| 
 | |
| }
 |