1 /*
2    Copyright (C) 2006 - 2018 by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
3    wesnoth playturn Copyright (C) 2003 by David White <dave@whitevine.net>
4    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY.
12 
13    See the COPYING file for more details.
14 */
15 
16 #include "floating_textbox.hpp"
17 
18 #include "display_chat_manager.hpp"
19 #include "floating_label.hpp"
20 #include "font/standard_colors.hpp"
21 #include "game_display.hpp"
22 #include "preferences/game.hpp"
23 #include "log.hpp"
24 
25 #include <ctime>
26 
27 static lg::log_domain log_display("display");
28 #define ERR_DP LOG_STREAM(err, log_display)
29 
30 namespace gui{
floating_textbox()31 	floating_textbox::floating_textbox() :
32 		box_(nullptr),
33 		check_(nullptr),
34 		mode_(TEXTBOX_NONE),
35 		label_string_(),
36 		label_(0)
37 	{}
38 
close(game_display & gui)39 	void floating_textbox::close(game_display& gui)
40 	{
41 		if(!active()) {
42 			return;
43 		}
44 		if(check_ != nullptr) {
45 			if(mode_ == TEXTBOX_MESSAGE) {
46 				preferences::set_message_private(check_->checked());
47 			}
48 		}
49 		box_.reset(nullptr);
50 		check_.reset(nullptr);
51 		font::remove_floating_label(label_);
52 		mode_ = TEXTBOX_NONE;
53 		gui.invalidate_all();
54 	}
55 
update_location(game_display & gui)56 	void floating_textbox::update_location(game_display& gui)
57 	{
58 		if (box_ == nullptr)
59 			return;
60 
61 		const SDL_Rect& area = gui.map_outside_area();
62 
63 		const int border_size = 10;
64 
65 		const int ypos = area.y+area.h-30 - (check_ != nullptr ? check_->height() + border_size : 0);
66 
67 		if (label_ != 0)
68 			font::remove_floating_label(label_);
69 
70 		font::floating_label flabel(label_string_);
71 		flabel.set_color(font::YELLOW_COLOR);
72 		flabel.set_position(area.x + border_size, ypos);
73 		flabel.set_alignment(font::LEFT_ALIGN);
74 		flabel.set_clip_rect(area);
75 
76 		label_ = font::add_floating_label(flabel);
77 
78 		if (label_ == 0)
79 			return;
80 
81 		const SDL_Rect& label_area = font::get_floating_label_rect(label_);
82 		const int textbox_width = area.w - label_area.w - border_size*3;
83 
84 		if(textbox_width <= 0) {
85 			font::remove_floating_label(label_);
86 			return;
87 		}
88 
89 		if(box_ != nullptr) {
90 			box_->set_volatile(true);
91 			const SDL_Rect rect {
92 				  area.x + label_area.w + border_size * 2
93 				, ypos
94 				, textbox_width
95 				, box_->height()
96 			};
97 
98 			box_->set_location(rect);
99 		}
100 
101 		if(check_ != nullptr) {
102 			check_->set_volatile(true);
103 			check_->set_location(box_->location().x,box_->location().y + box_->location().h + border_size);
104 		}
105 	}
106 
show(gui::TEXTBOX_MODE mode,const std::string & label,const std::string & check_label,bool checked,game_display & gui)107 	void floating_textbox::show(gui::TEXTBOX_MODE mode, const std::string& label,
108 		const std::string& check_label, bool checked, game_display& gui)
109 	{
110 		close(gui);
111 
112 		label_string_ = label;
113 		mode_ = mode;
114 
115 		if(!check_label.empty()) {
116 			check_.reset(new gui::button(gui.video(),check_label,gui::button::TYPE_CHECK));
117 			check_->set_check(checked);
118 		}
119 
120 
121 		box_.reset(new gui::textbox(gui.video(),100,"",true,256,font::SIZE_PLUS,0.8,0.6));
122 
123 		update_location(gui);
124 	}
125 
tab(const std::set<std::string> & dictionary)126 	void floating_textbox::tab(const std::set<std::string>& dictionary)
127 	{
128 		if(active() == false) {
129 			return;
130 		}
131 
132 		std::string text = box_->text();
133 		std::vector<std::string> matches(dictionary.begin(), dictionary.end());
134 		const bool line_start = utils::word_completion(text, matches);
135 
136 		if (matches.empty()) return;
137 		if (matches.size() == 1 && mode_ == gui::TEXTBOX_MESSAGE) {
138 			text.append(line_start ? ": " : " ");
139 		} else if (matches.size() > 1) {
140 			std::string completion_list = utils::join(matches, " ");
141 			game_display::get_singleton()->get_chat_manager().add_chat_message(time(nullptr), "", 0, completion_list,
142 					events::chat_handler::MESSAGE_PRIVATE, false);
143 		}
144 		box_->set_text(text);
145 	}
146 }
147