Пример #1
0
void textbox::draw_contents()
{
	SDL_Rect const &loc = inner_location();

	surface surf = video().getSurface();
	draw_solid_tinted_rectangle(loc.x,loc.y,loc.w,loc.h,0,0,0,
				    focus(NULL) ? alpha_focus_ : alpha_, surf);

	SDL_Rect src;

	if(text_image_ == NULL) {
		update_text_cache(true);
	}

	if(text_image_ != NULL) {
		src.y = yscroll_;
		src.w = std::min<size_t>(loc.w,text_image_->w);
		src.h = std::min<size_t>(loc.h,text_image_->h);
		src.x = text_pos_;
		SDL_Rect dest = screen_area();
		dest.x = loc.x;
		dest.y = loc.y;

		// Fills the selected area
		if(is_selection()) {
			const int start = std::min<int>(selstart_,selend_);
			const int end = std::max<int>(selstart_,selend_);
			int startx = char_x_[start];
			int starty = char_y_[start];
			const int endx = char_x_[end];
			const int endy = char_y_[end];

			while(starty <= endy) {
				const size_t right = starty == endy ? endx : text_image_->w;
				if(right <= size_t(startx)) {
					break;
				}

				SDL_Rect rect = create_rect(loc.x + startx
						, loc.y + starty - src.y
						, right - startx
						, line_height_);

				const clip_rect_setter clipper(surf, &loc);

				Uint32 color = SDL_MapRGB(surf->format, 0, 0, 160);
				fill_rect_alpha(rect, color, 140, surf);

				starty += int(line_height_);
				startx = 0;
			}
		}

		sdl_blit(text_image_, &src, surf, &dest);
	}

	draw_cursor((cursor_pos_ == 0 ? 0 : cursor_pos_ - 1), video());

	update_rect(loc);
}
Пример #2
0
void textbox::append_text(const std::string& text, bool auto_scroll, const SDL_Color& color)
{
	if(text_image_.get() == NULL) {
		set_text(text, color);
		return;
	}

	//disallow adding multi-line text to a single-line text box
	if(wrap_ == false && std::find_if(text.begin(),text.end(),utils::isnewline) != text.end()) {
		return;
	}
	const bool is_at_bottom = get_position() == get_max_position();
	const wide_string& wtext = utils::string_to_wstring(text);

	const surface new_text = add_text_line(wtext, color);
	const surface new_surface = create_compatible_surface(text_image_,std::max<size_t>(text_image_->w,new_text->w),text_image_->h+new_text->h);

	SDL_SetAlpha(new_text.get(),0,0);
	SDL_SetAlpha(text_image_.get(),0,0);

	SDL_BlitSurface(text_image_,NULL,new_surface,NULL);

	SDL_Rect target = {0,text_image_->h,new_text->w,new_text->h};
	SDL_BlitSurface(new_text,NULL,new_surface,&target);
	text_image_.assign(new_surface);

	text_.resize(text_.size() + wtext.size());
	std::copy(wtext.begin(),wtext.end(),text_.end()-wtext.size());

	set_dirty(true);
	update_text_cache(false);
	if(auto_scroll && is_at_bottom) scroll_to_bottom();
	handle_text_changed(text_);
}
Пример #3
0
void textbox::set_inner_location(SDL_Rect const &rect)
{
	bg_register(rect);
	if (text_image_.null()) return;
	text_pos_ = 0;
	update_text_cache(false);
}
Пример #4
0
void textbox::set_wrap(bool val)
{
	if(wrap_ != val) {
		wrap_ = val;
		update_text_cache(true);
		set_dirty(true);
	}
}
Пример #5
0
// set_text does not respect max_size_
void textbox::set_text(const std::string& text, const SDL_Color& color)
{
	text_ = utils::string_to_wstring(text);
	cursor_ = text_.size();
	text_pos_ = 0;
	selstart_ = -1;
	selend_ = -1;
	set_dirty(true);
	update_text_cache(true, color);
	handle_text_changed(text_);
}
Пример #6
0
void textbox::clear()
{
	text_.clear();
	cursor_ = 0;
	cursor_pos_ = 0;
	text_pos_ = 0;
	selstart_ = -1;
	selend_ = -1;
	set_dirty(true);
	update_text_cache(true);
	handle_text_changed(text_);
}
Пример #7
0
textbox::textbox(CVideo &video, int width, const std::string& text, bool editable, size_t max_size, double alpha, double alpha_focus, const bool auto_join)
	   : scrollarea(video, auto_join), max_size_(max_size), text_(utils::string_to_wstring(text)),
	     cursor_(text_.size()), selstart_(-1), selend_(-1),
	     grabmouse_(false), text_pos_(0), editable_(editable),
	     show_cursor_(true), show_cursor_at_(0), text_image_(NULL),
	     wrap_(false), line_height_(0), yscroll_(0), alpha_(alpha),
		  alpha_focus_(alpha_focus)
{
	// static const SDL_Rect area = d.screen_area();
	// const int height = font::draw_text(NULL,area,font_size,font::NORMAL_COLOUR,"ABCD",0,0).h;
	set_measurements(width, font::get_max_height(font_size));
	set_scroll_rate(font::get_max_height(font_size) / 2);
	update_text_cache(true);
}
Пример #8
0
void textbox::set_cursor_pos(const int cursor_pos)
{
	if (!editable_) {
		return;
	}
	if (cursor_pos < 0 || size_t(cursor_pos) > text_.size()) {
		WRN_DP << "out-of-boundary selection\n";
		return;
	}

	cursor_ = cursor_pos;
	update_text_cache(false);
	set_dirty(true);
}
Пример #9
0
void textbox::handle_event(const SDL_Event& event)
{
	scrollarea::handle_event(event);
	if(hidden())
		return;

	bool changed = false;

	const int old_selstart = selstart_;
	const int old_selend = selend_;

	//Sanity check: verify that selection start and end are within text
	//boundaries
	if(is_selection() && !(size_t(selstart_) <= text_.size() && size_t(selend_) <= text_.size())) {
		WRN_DP << "out-of-boundary selection\n";
		selstart_ = selend_ = -1;
	}

	int mousex, mousey;
	const Uint8 mousebuttons = SDL_GetMouseState(&mousex,&mousey);
	if(!(mousebuttons & SDL_BUTTON(1))) {
		grabmouse_ = false;
	}

	SDL_Rect const &loc = inner_location();
	bool clicked_inside = !mouse_locked() && (event.type == SDL_MOUSEBUTTONDOWN
					   && (mousebuttons & SDL_BUTTON(1))
					   && point_in_rect(mousex, mousey, loc));
	if(clicked_inside) {
		set_focus(true);
	}
	if ((grabmouse_ && (!mouse_locked() && event.type == SDL_MOUSEMOTION)) || clicked_inside) {
		const int x = mousex - loc.x + text_pos_;
		const int y = mousey - loc.y;
		int pos = 0;
		int distance = x;

		for(unsigned int i = 1; i < char_x_.size(); ++i) {
			if(static_cast<int>(yscroll_) + y < char_y_[i]) {
				break;
			}

			// Check individually each distance (if, one day, we support
			// RTL languages, char_x_[c] may not be monotonous.)
			if(abs(x - char_x_[i]) < distance && yscroll_ + y < char_y_[i] + line_height_) {
				pos = i;
				distance = abs(x - char_x_[i]);
			}
		}

		cursor_ = pos;

		if(grabmouse_)
			selend_ = cursor_;

		update_text_cache(false);

		if(!grabmouse_ && mousebuttons & SDL_BUTTON(1)) {
			grabmouse_ = true;
			selstart_ = selend_ = cursor_;
		} else if (! (mousebuttons & SDL_BUTTON(1))) {
			grabmouse_ = false;
		}

		set_dirty();
	}

	if(editable_ == false) {
		return;
	}

	//if we don't have the focus, then see if we gain the focus,
	//otherwise return
	if(focus(&event) == false) {
		if (!mouse_locked() && event.type == SDL_MOUSEMOTION && point_in_rect(mousex, mousey, loc))
			events::focus_handler(this);

		return;
	}

	if(event.type != SDL_KEYDOWN || focus(&event) != true) {
		draw();
		return;
	}

	const SDL_keysym& key = reinterpret_cast<const SDL_KeyboardEvent&>(event).keysym;
	const SDLMod modifiers = SDL_GetModState();

	const int c = key.sym;
	const int old_cursor = cursor_;

	if(c == SDLK_LEFT && cursor_ > 0)
		--cursor_;

	if(c == SDLK_RIGHT && cursor_ < static_cast<int>(text_.size()))
		++cursor_;

	// ctrl-a, ctrl-e and ctrl-u are readline style shortcuts, even on Macs
	if(c == SDLK_END || (c == SDLK_e && (modifiers & KMOD_CTRL)))
		cursor_ = text_.size();

	if(c == SDLK_HOME || (c == SDLK_a && (modifiers & KMOD_CTRL)))
		cursor_ = 0;

	if((old_cursor != cursor_) && (modifiers & KMOD_SHIFT)) {
		if(selstart_ == -1)
			selstart_ = old_cursor;
		selend_ = cursor_;
	}

	if(c == SDLK_BACKSPACE) {
		changed = true;
		if(is_selection()) {
			erase_selection();
		} else if(cursor_ > 0) {
			--cursor_;
			text_.erase(text_.begin()+cursor_);
		}
	}

	if(c == SDLK_u && (modifiers & KMOD_CTRL)) { // clear line
		changed = true;
		cursor_ = 0;
		text_.resize(0);
	}

	if(c == SDLK_DELETE && !text_.empty()) {
		changed = true;
		if(is_selection()) {
			erase_selection();
		} else {
			if(cursor_ < static_cast<int>(text_.size())) {
				text_.erase(text_.begin()+cursor_);
			}
		}
	}

	wchar_t character = key.unicode;

	//movement characters may have a "Unicode" field on some platforms, so ignore it.
	if(!(c == SDLK_UP || c == SDLK_DOWN || c == SDLK_LEFT || c == SDLK_RIGHT ||
	   c == SDLK_DELETE || c == SDLK_BACKSPACE || c == SDLK_END || c == SDLK_HOME ||
	   c == SDLK_PAGEUP || c == SDLK_PAGEDOWN)) {
		if(character != 0) {
			DBG_G << "Char: " << character << ", c = " << c << "\n";
		}
		if(event.key.keysym.mod & copypaste_modifier) {
			switch(c) {
			case SDLK_v: // paste
				{
				changed = true;
				if(is_selection())
					erase_selection();

				std::string str = copy_from_clipboard(false);

				//cut off anything after the first newline
				str.erase(std::find_if(str.begin(),str.end(),utils::isnewline),str.end());

				wide_string s = utils::string_to_wstring(str);

				if(text_.size() < max_size_) {
					if(s.size() + text_.size() > max_size_) {
						s.resize(max_size_ - text_.size());
					}
					text_.insert(text_.begin()+cursor_, s.begin(), s.end());
					cursor_ += s.size();
				}

				}

				break;

			case SDLK_c: // copy
				{
				const size_t beg = std::min<size_t>(size_t(selstart_),size_t(selend_));
				const size_t end = std::max<size_t>(size_t(selstart_),size_t(selend_));

				wide_string ws = wide_string(text_.begin() + beg, text_.begin() + end);
				std::string s = utils::wstring_to_string(ws);
				copy_to_clipboard(s, false);
				}
				break;
			}
		} else {
			if(character >= 32 && character != 127) {
				changed = true;
				if(is_selection())
					erase_selection();

				if(text_.size() + 1 <= max_size_) {
					text_.insert(text_.begin()+cursor_,character);
					++cursor_;
				}
			}
		}
	}

	if(is_selection() && (selend_ != cursor_))
		selstart_ = selend_ = -1;

	//since there has been cursor activity, make the cursor appear for
	//at least the next 500ms.
	show_cursor_ = true;
	show_cursor_at_ = SDL_GetTicks();

	if(changed || old_cursor != cursor_ || old_selstart != selstart_ || old_selend != selend_) {
		text_image_ = NULL;
		handle_text_changed(text_);
	}

	set_dirty(true);
}
Пример #10
0
	void Label::update(Compositor* compositor, float delta_seconds)
	{
		ScrollablePanel::update(compositor, delta_seconds);
		update_text_cache();
	}
Пример #11
0
	void Label::append_text(const char* message)
	{
		text.append(message);
		cache_is_dirty = 1;
		update_text_cache();
	}
Пример #12
0
void textbox::update_location(SDL_Rect const &rect)
{
	scrollarea::update_location(rect);
	update_text_cache(true);
	set_dirty(true);
}
Пример #13
0
void textbox::draw_contents()
{
	SDL_Rect const &loc = inner_location();

	surface surf = video().getSurface();
	draw_solid_tinted_rectangle(loc.x,loc.y,loc.w,loc.h,0,0,0,
				    focus(NULL) ? alpha_focus_ : alpha_, surf);

	SDL_Rect src;

	if(text_image_ == NULL) {
		update_text_cache(true);
	}

	if(text_image_ != NULL) {
		src.y = yscroll_;
		src.w = std::min<size_t>(loc.w,text_image_->w);
		src.h = std::min<size_t>(loc.h,text_image_->h);
		src.x = text_pos_;
		SDL_Rect dest = screen_area();
		dest.x = loc.x;
		dest.y = loc.y;

		// Fills the selected area
		if(enabled() && is_selection()) {
			const int start = std::min<int>(selstart_,selend_);
			const int end = std::max<int>(selstart_,selend_);
			int startx = char_x_[start];
			int starty = char_y_[start];
			const int endx = char_x_[end];
			const int endy = char_y_[end];

			while(starty <= endy) {
				const size_t right = starty == endy ? endx : text_image_->w;
				if(right <= size_t(startx)) {
					break;
				}

				SDL_Rect rect = create_rect(loc.x + startx
						, loc.y + starty - src.y
						, right - startx
						, line_height_);

				const clip_rect_setter clipper(surf, &loc);

				Uint32 color = SDL_MapRGB(surf->format, 0, 0, 160);
				fill_rect_alpha(rect, color, 140, surf);

				starty += int(line_height_);
				startx = 0;
			}
		}

		if(enabled()) {
			sdl_blit(text_image_, &src, surf, &dest);
		} else {
			// HACK: using 30% opacity allows white text to look as though it is grayed out,
			// while not changing any applicable non-grayscale AA. Actual colored text will
			// not look as good, but this is not currently a concern since GUI1 textboxes
			// are not used much nowadays, and they will eventually all go away.
			sdl_blit(adjust_surface_alpha(text_image_, ftofxp(0.3)), &src, surf, &dest);
		}
	}

	draw_cursor((cursor_pos_ == 0 ? 0 : cursor_pos_ - 1), video());

	update_rect(loc);
}